File: infobar_container_view.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (156 lines) | stat: -rw-r--r-- 6,020 bytes parent folder | download | duplicates (5)
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/infobars/infobar_container_view.h"

#include <numeric>

#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_shader.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/color/chrome_color_id.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/infobars/infobar_view.h"
#include "chrome/grit/generated_resources.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/color/color_provider.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/skia_paint_util.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/cascading_property.h"
#include "ui/views/controls/focus_ring.h"

namespace {

class ContentShadow : public views::View {
  METADATA_HEADER(ContentShadow, views::View)

 public:
  ContentShadow();

 protected:
  // views::View:
  gfx::Size CalculatePreferredSize(
      const views::SizeBounds& available_size) const override;
  void OnPaint(gfx::Canvas* canvas) override;
};

ContentShadow::ContentShadow() {
  SetPaintToLayer();
  layer()->SetFillsBoundsOpaquely(false);
}

gfx::Size ContentShadow::CalculatePreferredSize(
    const views::SizeBounds& available_size) const {
  return gfx::Size(0, views::BubbleBorder::GetBorderAndShadowInsets().height());
}

void ContentShadow::OnPaint(gfx::Canvas* canvas) {
  // Outdent the sides to make the shadow appear uniform in the corners.
  gfx::RectF container_bounds(parent()->GetLocalBounds());
  View::ConvertRectToTarget(parent(), this, &container_bounds);
  container_bounds.Inset(
      gfx::InsetsF::VH(0, -views::BubbleBorder::kShadowBlur));

  views::BubbleBorder::DrawBorderAndShadow(gfx::RectFToSkRect(container_bounds),
                                           canvas, GetColorProvider());
}

BEGIN_METADATA(ContentShadow)
END_METADATA

}  // namespace

constexpr int kSeparatorHeightDip = 1;

InfoBarContainerView::InfoBarContainerView(Delegate* delegate)
    : infobars::InfoBarContainer(delegate),
      content_shadow_(new ContentShadow()) {
  SetID(VIEW_ID_INFO_BAR_CONTAINER);
  AddChildViewRaw(content_shadow_.get());
  views::SetCascadingColorProviderColor(this, views::kCascadingBackgroundColor,
                                        kColorToolbar);
  SetBackground(
      views::CreateSolidBackground(kColorInfoBarContentAreaSeparator));

  GetViewAccessibility().SetRole(ax::mojom::Role::kGroup);
  GetViewAccessibility().SetName(
      l10n_util::GetStringUTF8(IDS_ACCNAME_INFOBAR_CONTAINER));
}

InfoBarContainerView::~InfoBarContainerView() {
  RemoveAllInfoBarsForDestruction();
}

bool InfoBarContainerView::IsEmpty() const {
  // NOTE: Can't check if the size IsEmpty() since it's always 0-width.
  return GetPreferredSize().height() == 0;
}

void InfoBarContainerView::Layout(PassKey) {
  const auto set_bounds = [this](int top, View* child) {
    const int height = static_cast<InfoBarView*>(child)->computed_height();
    // Do not add separator dip if it's the first infobar. The first infobar
    // should be flush with the top of InfoBarContainerView.
    int add_separator_height =
        (child == children().front()) ? 0 : kSeparatorHeightDip;
    child->SetBounds(0, top + add_separator_height, width(), height);
    return child->bounds().bottom();
  };
  DCHECK_EQ(content_shadow_, children().back());
  const int top = std::accumulate(children().begin(),
                                  std::prev(children().end()), 0, set_bounds);

  // The shadow is positioned flush with the bottom infobar, with the separator
  // there drawn by the shadow code (so we don't have to extend our bounds out
  // to be able to draw it; see comments in CalculatePreferredSize() on why the
  // shadow is drawn outside the container bounds).
  content_shadow_->SetBounds(0, top, width(),
                             content_shadow_->GetPreferredSize().height());
}

gfx::Size InfoBarContainerView::CalculatePreferredSize(
    const views::SizeBounds& available_size) const {
  const auto enlarge_size = [this](const gfx::Size& size, const View* child) {
    const gfx::Size child_size = child->GetPreferredSize();
    int add_separator_height =
        (child == children().front()) ? 0 : kSeparatorHeightDip;
    return gfx::Size(
        std::max(size.width(), child_size.width()),
        size.height() + child_size.height() + add_separator_height);
  };
  // Don't reserve space for the bottom shadow here.  Because the shadow paints
  // to its own layer and this class doesn't, it can paint outside the size
  // computed here.  Not including the shadow bounds means the browser will
  // automatically lay out web content beginning below the bottom infobar
  // (instead of below the shadow), and clicks in the shadow region will go to
  // the web content instead of the infobars; both of these effects are
  // desirable.  On the other hand, it also means the browser doesn't know the
  // shadow is there and could lay out something atop it or size the window too
  // small for it; but these are unlikely.
  DCHECK_EQ(content_shadow_, children().back());
  return std::accumulate(children().cbegin(), std::prev(children().cend()),
                         gfx::Size(), enlarge_size);
}

void InfoBarContainerView::PlatformSpecificAddInfoBar(
    infobars::InfoBar* infobar,
    size_t position) {
  AddChildViewAt(static_cast<InfoBarView*>(infobar),
                 static_cast<int>(position));
}

void InfoBarContainerView::PlatformSpecificRemoveInfoBar(
    infobars::InfoBar* infobar) {
  RemoveChildView(static_cast<InfoBarView*>(infobar));
}

BEGIN_METADATA(InfoBarContainerView)
END_METADATA