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

Unified Diff: ash/common/system/tray/tray_details_view.cc

Issue 2557333003: [ash-md] Stacks child layers properly for sticky header rows (Closed)
Patch Set: [ash-md] Stacks child layers properly for sticky header rows (separators) Created 4 years 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 side-by-side diff with in-line comments
Download patch
Index: ash/common/system/tray/tray_details_view.cc
diff --git a/ash/common/system/tray/tray_details_view.cc b/ash/common/system/tray/tray_details_view.cc
index d48c0e3608800ba71fd7bb2ba4261fda9c035589..01e7256a91bd4cf42690a0b95f62647bb00f034c 100644
--- a/ash/common/system/tray/tray_details_view.cc
+++ b/ash/common/system/tray/tray_details_view.cc
@@ -100,6 +100,26 @@ class ScrollContentsView : public views::View,
PositionHeaderRows();
}
+ void ReorderChildLayers(ui::Layer* parent_layer) override {
+ views::View::ReorderChildLayers(parent_layer);
+ ui::Layer* topmost_layer = TopmostLayer(this, parent_layer);
+ if (!topmost_layer)
+ return;
+
+ // Keep the sticky headers with layers above the rest of the children's
+ // layers. Make sure to avoid changing the stacking order of the layers that
+ // are children of |parent_layer| but do not belong to the same parent view.
+ // Note: this assumes that all views that have id=VIEW_ID_STICKY_HEADER have
+ // a layer.
+ for (int i = child_count() - 1; i >= 0; --i) {
+ View* child = child_at(i);
+ if (child->id() == VIEW_ID_STICKY_HEADER) {
+ if (child->layer() != topmost_layer)
+ parent_layer->StackAbove(child->layer(), topmost_layer);
+ }
+ }
sadrul 2016/12/14 00:48:29 This is really subtle. Can you look at having a te
varkha 2016/12/14 17:46:42 I will.
+ }
+
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override {
if (!details.is_add && details.parent == this) {
@@ -169,24 +189,31 @@ class ScrollContentsView : public views::View,
Header* previous_header = nullptr;
for (auto& header : base::Reversed(headers_)) {
views::View* header_view = header.view;
- header.draw_separator_below = false;
+ bool draw_separator_below = false;
if (header.natural_offset >= scroll_offset) {
previous_header = &header;
header_view->SetY(header.natural_offset);
- continue;
- }
- if (previous_header &&
- previous_header->view->y() <= scroll_offset + header_view->height()) {
- // Lower header displacing the header above.
- header.draw_separator_below = true;
- header_view->SetY(previous_header->view->y() - header_view->height());
} else {
- // A header becomes sticky.
- header_view->SetY(scroll_offset);
- header_view->Layout();
- header_view->SchedulePaint();
+ if (previous_header &&
+ previous_header->view->y() <=
+ scroll_offset + header_view->height()) {
+ // Lower header displacing the header above.
+ draw_separator_below = true;
+ header_view->SetY(previous_header->view->y() - header_view->height());
+ } else {
+ // A header becomes sticky.
+ header_view->SetY(scroll_offset);
+ header_view->Layout();
+ header_view->SchedulePaint();
+ }
+ }
+ if (header.draw_separator_below != draw_separator_below) {
+ header.draw_separator_below = draw_separator_below;
+ TrayPopupUtils::ShowStickyHeaderSeparator(header_view,
+ draw_separator_below);
}
- break;
+ if (header.natural_offset < scroll_offset)
+ break;
}
}
@@ -197,22 +224,11 @@ class ScrollContentsView : public views::View,
bool PaintDelineation(const Header& header, const ui::PaintContext& context) {
const View* view = header.view;
- // If the header is where it normally belongs, draw nothing.
- if (view->y() == header.natural_offset)
+ // If the header is where it normally belongs or If the header is pushed by
+ // a header directly below it, draw nothing.
+ if (view->y() == header.natural_offset || header.draw_separator_below)
return false;
- // If the header is pushed by a header directly below it, draw a separator.
- if (header.draw_separator_below) {
- // TODO(estade): look better at 1.5x scale.
- ui::PaintRecorder recorder(context, size());
- gfx::Canvas* canvas = recorder.canvas();
- gfx::Rect separator = view->bounds();
- separator.set_y(separator.bottom() - kSeparatorWidth);
- separator.set_height(kSeparatorWidth);
- canvas->FillRect(separator, kSeparatorColor);
- return false;
- }
-
// Otherwise, draw a shadow below.
DrawShadow(context,
gfx::Rect(0, 0, view->width(), view->bounds().bottom()));
@@ -234,6 +250,25 @@ class ScrollContentsView : public views::View,
canvas->DrawRect(shadowed_area, paint);
}
+ // Recursively iterates through children to return the child layer that is
+ // stacked at the top. Only considers layers that are direct |parent_layer|'s
+ // children.
+ ui::Layer* TopmostLayer(views::View* view, ui::Layer* parent_layer) {
+ DCHECK(parent_layer);
+ // Iterate backwards through the children to find the topmost layer.
+ for (int i = view->child_count() - 1; i >= 0; --i) {
+ views::View* child = view->child_at(i);
+ ui::Layer* layer = TopmostLayer(child, parent_layer);
+ if (layer)
+ return layer;
+ }
+ if (view->layer() && view->layer() != parent_layer &&
+ view->layer()->parent() == parent_layer) {
+ return view->layer();
+ }
+ return nullptr;
+ }
+
views::BoxLayout* box_layout_;
// Header child views that stick to the top of visible viewport when scrolled.

Powered by Google App Engine
This is Rietveld 408576698