Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: ash/common/system/tray/tray_details_view.cc

Issue 2561253002: [ash-md] Adds support for Z-order iteration in views::View (Closed)
Patch Set: [ash-md] Adds support for Z-order iteration in views::View (rebased) Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chromeos/dbus/fake_shill_manager_client.cc » ('j') | ui/views/view_unittest.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/common/system/tray/tray_details_view.h" 5 #include "ash/common/system/tray/tray_details_view.h"
6 6
7 #include "ash/common/ash_view_ids.h" 7 #include "ash/common/ash_view_ids.h"
8 #include "ash/common/material_design/material_design_controller.h" 8 #include "ash/common/material_design/material_design_controller.h"
9 #include "ash/common/system/tray/fixed_sized_scroll_view.h" 9 #include "ash/common/system/tray/fixed_sized_scroll_view.h"
10 #include "ash/common/system/tray/system_menu_button.h" 10 #include "ash/common/system/tray/system_menu_button.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 } 42 }
43 43
44 // The index of the horizontal rule below the title row. 44 // The index of the horizontal rule below the title row.
45 const int kTitleRowSeparatorIndex = 1; 45 const int kTitleRowSeparatorIndex = 1;
46 46
47 // A view that is used as ScrollView contents. It supports designating some of 47 // A view that is used as ScrollView contents. It supports designating some of
48 // the children as sticky header rows. The sticky header rows are not scrolled 48 // the children as sticky header rows. The sticky header rows are not scrolled
49 // above the top of the visible viewport until the next one "pushes" it up and 49 // above the top of the visible viewport until the next one "pushes" it up and
50 // are painted above other children. To indicate that a child is a sticky header 50 // are painted above other children. To indicate that a child is a sticky header
51 // row use set_id(VIEW_ID_STICKY_HEADER). 51 // row use set_id(VIEW_ID_STICKY_HEADER).
52 class ScrollContentsView : public views::View, 52 class ScrollContentsView : public views::View {
53 public views::ViewTargeterDelegate {
54 public: 53 public:
55 ScrollContentsView() 54 ScrollContentsView()
56 : box_layout_(new views::BoxLayout( 55 : box_layout_(new views::BoxLayout(
57 views::BoxLayout::kVertical, 56 views::BoxLayout::kVertical,
58 0, 57 0,
59 0, 58 0,
60 UseMd() ? 0 : kContentsBetweenChildSpacingNonMd)) { 59 UseMd() ? 0 : kContentsBetweenChildSpacingNonMd)) {
61 SetEventTargeter(base::MakeUnique<views::ViewTargeter>(this));
62 SetLayoutManager(box_layout_); 60 SetLayoutManager(box_layout_);
63 } 61 }
64 ~ScrollContentsView() override {} 62 ~ScrollContentsView() override {}
65 63
66 protected: 64 protected:
67 // views::View: 65 // views::View:
68 void OnBoundsChanged(const gfx::Rect& previous_bounds) override { 66 void OnBoundsChanged(const gfx::Rect& previous_bounds) override {
69 PositionHeaderRows(); 67 PositionHeaderRows();
70 } 68 }
71 69
72 void PaintChildren(const ui::PaintContext& context) override { 70 void PaintChildren(const ui::PaintContext& context) override {
73 for (int i = 0; i < child_count(); ++i) { 71 views::View::PaintChildren(context);
74 if (child_at(i)->id() != VIEW_ID_STICKY_HEADER && !child_at(i)->layer())
75 child_at(i)->Paint(context);
76 }
77 bool did_draw_shadow = false; 72 bool did_draw_shadow = false;
78 // Paint header rows above other children in Z-order. 73 // Paint header row separators.
79 for (auto& header : headers_) { 74 for (auto& header : headers_)
80 if (!header.view->layer())
81 header.view->Paint(context);
82 did_draw_shadow = PaintDelineation(header, context) || did_draw_shadow; 75 did_draw_shadow = PaintDelineation(header, context) || did_draw_shadow;
83 }
84 76
85 // Draw a shadow at the top of the viewport when scrolled, but only if a 77 // Draw a shadow at the top of the viewport when scrolled, but only if a
86 // header didn't already draw one. Overlap the shadow with the separator 78 // header didn't already draw one. Overlap the shadow with the separator
87 // that's below the header view so we don't get both a separator and a full 79 // that's below the header view so we don't get both a separator and a full
88 // shadow. 80 // shadow.
89 if (y() != 0 && !did_draw_shadow) 81 if (y() != 0 && !did_draw_shadow)
90 DrawShadow(context, gfx::Rect(0, 0, width(), -y() - kSeparatorWidth)); 82 DrawShadow(context, gfx::Rect(0, 0, width(), -y() - kSeparatorWidth));
91 } 83 }
92 84
93 void Layout() override { 85 void Layout() override {
94 views::View::Layout(); 86 views::View::Layout();
95 headers_.clear(); 87 headers_.clear();
96 for (int i = 0; i < child_count(); ++i) { 88 for (int i = 0; i < child_count(); ++i) {
97 views::View* view = child_at(i); 89 views::View* view = child_at(i);
98 if (view->id() == VIEW_ID_STICKY_HEADER) 90 if (view->id() == VIEW_ID_STICKY_HEADER)
99 headers_.emplace_back(view); 91 headers_.emplace_back(view);
100 } 92 }
101 PositionHeaderRows(); 93 PositionHeaderRows();
102 } 94 }
103 95
104 void ReorderChildLayers(ui::Layer* parent_layer) override { 96 View::Views GetChildrenInZOrder() override {
105 views::View::ReorderChildLayers(parent_layer); 97 View::Views children;
106 ui::Layer* topmost_layer = TopmostLayer(this, parent_layer); 98 // Iterate over regular children and later over the sticky headers to keep
107 if (!topmost_layer) 99 // the sticky headers above in Z-order.
108 return; 100 for (int i = 0; i < child_count(); ++i) {
109 101 if (child_at(i)->id() != VIEW_ID_STICKY_HEADER)
110 // Keep the sticky headers with layers above the rest of the children's 102 children.push_back(child_at(i));
111 // layers. Make sure to avoid changing the stacking order of the layers that
112 // are children of |parent_layer| but do not belong to the same parent view.
113 // Note: this assumes that all views that have id=VIEW_ID_STICKY_HEADER have
114 // a layer.
115 for (int i = child_count() - 1; i >= 0; --i) {
116 View* child = child_at(i);
117 if (child->id() == VIEW_ID_STICKY_HEADER &&
118 child->layer() != topmost_layer) {
119 parent_layer->StackAbove(child->layer(), topmost_layer);
120 }
121 } 103 }
104 for (int i = 0; i < child_count(); ++i) {
105 if (child_at(i)->id() == VIEW_ID_STICKY_HEADER)
106 children.push_back(child_at(i));
107 }
108 DCHECK_EQ(child_count(), static_cast<int>(children.size()));
109 return children;
122 } 110 }
123 111
124 void ViewHierarchyChanged( 112 void ViewHierarchyChanged(
125 const ViewHierarchyChangedDetails& details) override { 113 const ViewHierarchyChangedDetails& details) override {
126 if (!details.is_add && details.parent == this) { 114 if (!details.is_add && details.parent == this) {
127 headers_.erase(std::remove_if(headers_.begin(), headers_.end(), 115 headers_.erase(std::remove_if(headers_.begin(), headers_.end(),
128 [details](const Header& header) { 116 [details](const Header& header) {
129 return header.view == details.child; 117 return header.view == details.child;
130 }), 118 }),
131 headers_.end()); 119 headers_.end());
132 } else if (details.is_add && details.parent == this && 120 } else if (details.is_add && details.parent == this &&
133 details.child == child_at(0)) { 121 details.child == child_at(0)) {
134 // We always want padding on the bottom of the scroll contents. 122 // We always want padding on the bottom of the scroll contents.
135 // We only want padding on the top of the scroll contents if the first 123 // We only want padding on the top of the scroll contents if the first
136 // child is not a header (in that case, the padding is built into the 124 // child is not a header (in that case, the padding is built into the
137 // header). 125 // header).
138 DCHECK_EQ(box_layout_, GetLayoutManager()); 126 DCHECK_EQ(box_layout_, GetLayoutManager());
139 box_layout_->set_inside_border_insets( 127 box_layout_->set_inside_border_insets(
140 gfx::Insets(details.child->id() == VIEW_ID_STICKY_HEADER 128 gfx::Insets(details.child->id() == VIEW_ID_STICKY_HEADER
141 ? 0 129 ? 0
142 : kMenuSeparatorVerticalPadding, 130 : kMenuSeparatorVerticalPadding,
143 0, kMenuSeparatorVerticalPadding, 0)); 131 0, kMenuSeparatorVerticalPadding, 0));
144 } 132 }
145 } 133 }
146 134
147 // views::ViewTargeterDelegate:
148 View* TargetForRect(View* root, const gfx::Rect& rect) override {
149 // Give header rows first dibs on events.
150 for (auto& header : headers_) {
151 views::View* view = header.view;
152 gfx::Rect local_to_header = rect;
153 local_to_header.Offset(-view->x(), -view->y());
154 if (ViewTargeterDelegate::DoesIntersectRect(view, local_to_header))
155 return ViewTargeterDelegate::TargetForRect(view, local_to_header);
156 }
157 return ViewTargeterDelegate::TargetForRect(root, rect);
158 }
159
160 private: 135 private:
161 const SkColor kSeparatorColor = SkColorSetA(SK_ColorBLACK, 0x1F); 136 const SkColor kSeparatorColor = SkColorSetA(SK_ColorBLACK, 0x1F);
162 const int kShadowOffsetY = 2; 137 const int kShadowOffsetY = 2;
163 const int kShadowBlur = 2; 138 const int kShadowBlur = 2;
164 // TODO(fukino): Remove this constant once we stop maintaining pre-MD design. 139 // TODO(fukino): Remove this constant once we stop maintaining pre-MD design.
165 // crbug.com/614453. 140 // crbug.com/614453.
166 const int kContentsBetweenChildSpacingNonMd = 1; 141 const int kContentsBetweenChildSpacingNonMd = 1;
167 142
168 // A structure that keeps the original offset of each header between the 143 // A structure that keeps the original offset of each header between the
169 // calls to Layout() to allow keeping track of which view should be sticky. 144 // calls to Layout() to allow keeping track of which view should be sticky.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 SkPaint paint; 219 SkPaint paint;
245 gfx::ShadowValues shadow; 220 gfx::ShadowValues shadow;
246 shadow.emplace_back(gfx::Vector2d(0, kShadowOffsetY), kShadowBlur, 221 shadow.emplace_back(gfx::Vector2d(0, kShadowOffsetY), kShadowBlur,
247 kSeparatorColor); 222 kSeparatorColor);
248 paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadow)); 223 paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadow));
249 paint.setAntiAlias(true); 224 paint.setAntiAlias(true);
250 canvas->ClipRect(shadowed_area, SkClipOp::kDifference); 225 canvas->ClipRect(shadowed_area, SkClipOp::kDifference);
251 canvas->DrawRect(shadowed_area, paint); 226 canvas->DrawRect(shadowed_area, paint);
252 } 227 }
253 228
254 // Recursively iterates through children to return the child layer that is
255 // stacked at the top. Only considers layers that are direct |parent_layer|'s
256 // children.
257 ui::Layer* TopmostLayer(views::View* view, ui::Layer* parent_layer) {
258 DCHECK(parent_layer);
259 // Iterate backwards through the children to find the topmost layer.
260 for (int i = view->child_count() - 1; i >= 0; --i) {
261 views::View* child = view->child_at(i);
262 ui::Layer* layer = TopmostLayer(child, parent_layer);
263 if (layer)
264 return layer;
265 }
266 if (view->layer() && view->layer() != parent_layer &&
267 view->layer()->parent() == parent_layer) {
268 return view->layer();
269 }
270 return nullptr;
271 }
272
273 views::BoxLayout* box_layout_; 229 views::BoxLayout* box_layout_;
274 230
275 // Header child views that stick to the top of visible viewport when scrolled. 231 // Header child views that stick to the top of visible viewport when scrolled.
276 std::vector<Header> headers_; 232 std::vector<Header> headers_;
277 233
278 DISALLOW_COPY_AND_ASSIGN(ScrollContentsView); 234 DISALLOW_COPY_AND_ASSIGN(ScrollContentsView);
279 }; 235 };
280 236
281 // Constants for the title row in material design. 237 // Constants for the title row in material design.
282 const int kTitleRowVerticalPadding = 4; 238 const int kTitleRowVerticalPadding = 4;
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 if (index < child_count() - 1 && child_at(index + 1) != title_row_) 558 if (index < child_count() - 1 && child_at(index + 1) != title_row_)
603 scroll_border_->set_visible(true); 559 scroll_border_->set_visible(true);
604 else 560 else
605 scroll_border_->set_visible(false); 561 scroll_border_->set_visible(false);
606 } 562 }
607 563
608 views::View::OnPaintBorder(canvas); 564 views::View::OnPaintBorder(canvas);
609 } 565 }
610 566
611 } // namespace ash 567 } // namespace ash
OLDNEW
« no previous file with comments | « no previous file | chromeos/dbus/fake_shill_manager_client.cc » ('j') | ui/views/view_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698