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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_VIEWS_CONTROLS_FOCUS_RING_H_
#define UI_VIEWS_CONTROLS_FOCUS_RING_H_
#include "base/scoped_observer.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/controls/focusable_border.h"
#include "ui/views/view.h"
#include "ui/views/view_observer.h"
#include "ui/views/views_export.h"
namespace views {
// FocusRing is a View that is designed to act as an indicator of focus for its
// parent. It is a stand-alone view that paints to a layer which extends beyond
// the bounds of its parent view.
//
// Using FocusRing looks something like this:
//
// class MyView : public View {
// ...
// private:
// std::unique_ptr<FocusRing> focus_ring_;
// };
//
// MyView::MyView() {
// focus_ring_ = FocusRing::Install(this);
// ...
// }
//
// If MyView should show a rounded rectangular focus ring when it has focus and
// hide the ring when it loses focus, no other configuration is necessary. In
// other cases, it might be necessary to use the Set*() functions on FocusRing;
// these take care of repainting it when the state changes.
class VIEWS_EXPORT FocusRing : public View, public ViewObserver {
public:
static const char kViewClassName[];
using ViewPredicate = std::function<bool(View* view)>;
~FocusRing() override;
// Create a FocusRing and adds it to |parent|. The returned focus ring is
// owned by the client (the code calling FocusRing::Install), *not* by
// |parent|.
static std::unique_ptr<FocusRing> Install(View* parent);
// Returns whether this class can draw a focus ring from |path|. Not all paths
// are useable since not all paths can be easily outset.
static bool IsPathUseable(const SkPath& path);
// Sets the path to draw this FocusRing around. This path is in the parent
// view's coordinate system, *not* in the FocusRing's coordinate system.
void SetPath(const SkPath& path);
// Sets whether the FocusRing should show an invalid state for the View it
// encloses.
void SetInvalid(bool invalid);
// Sets the predicate function used to tell when the parent has focus. The
// parent is passed into this predicate; it should return whether the parent
// should be treated as focused. This is useful when, for example, the parent
// wraps an inner view and the inner view is the one that actually receives
// focus, but the FocusRing sits on the parent instead of the inner view.
void SetHasFocusPredicate(const ViewPredicate& predicate);
// View:
const char* GetClassName() const override;
void Layout() override;
void OnPaint(gfx::Canvas* canvas) override;
// ViewObserver:
void OnViewFocused(View* view) override;
void OnViewBlurred(View* view) override;
private:
explicit FocusRing(View* parent);
// Translates the provided SkRect or SkRRect, which is in the parent's
// coordinate system, into this view's coordinate system, then insets it
// appropriately to produce the focus ring "halo" effect. If the supplied rect
// is an SkRect, it will have the default focus ring corner radius applied as
// well.
SkRRect RingRectFromPathRect(const SkRect& rect) const;
SkRRect RingRectFromPathRect(const SkRRect& rect) const;
// The View this focus ring is installed on.
View* view_ = nullptr;
// The path to draw this focus ring around. IsPathUseable(path_) is always
// true.
SkPath path_;
// Whether the enclosed View is in an invalid state, which controls whether
// the focus ring shows an invalid appearance (usually a different color).
bool invalid_ = false;
// The predicate used to determine whether the parent has focus.
ViewPredicate has_focus_predicate_;
DISALLOW_COPY_AND_ASSIGN(FocusRing);
};
} // views
#endif // UI_VIEWS_CONTROLS_FOCUS_RING_H_
|