1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_VIEWS_CONTROLS_LINK_FRAGMENT_H_
#define UI_VIEWS_CONTROLS_LINK_FRAGMENT_H_
#include <functional>
#include <type_traits>
#include <utility>
#include "base/memory/raw_ptr.h"
#include "ui/views/controls/link.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/style/typography.h"
namespace views {
// A `LinkFragment` can be used to represent a logical link that spans across
// multiple lines. Connected `LinkFragment`s adjust their style if any single
// one of them is hovered over of focused.
class VIEWS_EXPORT LinkFragment : public Link {
METADATA_HEADER(LinkFragment, Link)
public:
explicit LinkFragment(const std::u16string& title = std::u16string(),
int text_context = style::CONTEXT_LABEL,
int text_style = style::STYLE_LINK,
LinkFragment* other_fragment = nullptr);
~LinkFragment() override;
LinkFragment(const LinkFragment&) = delete;
LinkFragment& operator=(const LinkFragment&) = delete;
private:
// Returns the short-circuiting logical-"or" of invoking `f` on all linked
// fragments, beginning with `initial_fragment`.
template <typename F,
typename Fragment> // Templated to allow const or non-const
// LinkFragments
requires(std::is_invocable_r_v<bool, F, Fragment*>)
static bool InvokeOnFragments(F&& f, Fragment* initial_fragment) {
Fragment* fragment = initial_fragment;
bool result = false;
do {
result = std::invoke(std::forward<F>(f), fragment);
fragment = fragment->next_fragment_;
} while (!result && fragment != initial_fragment);
return result;
}
// Returns whether this fragment indicates that the entire link represented
// by it should be underlined.
bool IsUnderlined() const;
// Connects `this` to the `other_fragment`.
void Connect(LinkFragment* other_fragment);
// Disconnects `this` from any other fragments that it may be connected to.
void Disconnect();
// Recalculates the font style for this link fragment and, if it is changed,
// updates both this fragment and all other that are connected to it.
void RecalculateFont() override;
// Pointers to the previous and the next `LinkFragment` if the logical link
// represented by `this` consists of multiple such fragments (e.g. due to
// line breaks).
// If the logical link is just a single `LinkFragment` component, then these
// pointers point to `this`.
raw_ptr<LinkFragment> prev_fragment_;
raw_ptr<LinkFragment> next_fragment_;
};
} // namespace views
#endif // UI_VIEWS_CONTROLS_LINK_FRAGMENT_H_
|