OLD | NEW |
---|---|
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 "ui/views/bubble/bubble_frame_view.h" | 5 #include "ui/views/bubble/bubble_frame_view.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
11 #include "ui/base/default_style.h" | 11 #include "ui/base/default_style.h" |
12 #include "ui/base/hit_test.h" | 12 #include "ui/base/hit_test.h" |
13 #include "ui/base/l10n/l10n_util.h" | 13 #include "ui/base/l10n/l10n_util.h" |
14 #include "ui/base/material_design/material_design_controller.h" | 14 #include "ui/base/material_design/material_design_controller.h" |
15 #include "ui/base/resource/resource_bundle.h" | 15 #include "ui/base/resource/resource_bundle.h" |
16 #include "ui/compositor/paint_context.h" | 16 #include "ui/compositor/paint_context.h" |
17 #include "ui/compositor/paint_recorder.h" | 17 #include "ui/compositor/paint_recorder.h" |
18 #include "ui/display/display.h" | 18 #include "ui/display/display.h" |
19 #include "ui/display/screen.h" | 19 #include "ui/display/screen.h" |
20 #include "ui/gfx/geometry/vector2d.h" | 20 #include "ui/gfx/geometry/vector2d.h" |
21 #include "ui/gfx/path.h" | 21 #include "ui/gfx/path.h" |
22 #include "ui/gfx/skia_util.h" | 22 #include "ui/gfx/skia_util.h" |
23 #include "ui/native_theme/native_theme.h" | 23 #include "ui/native_theme/native_theme.h" |
24 #include "ui/resources/grit/ui_resources.h" | 24 #include "ui/resources/grit/ui_resources.h" |
25 #include "ui/strings/grit/ui_strings.h" | 25 #include "ui/strings/grit/ui_strings.h" |
26 #include "ui/vector_icons/vector_icons.h" | 26 #include "ui/vector_icons/vector_icons.h" |
27 #include "ui/views/bubble/bubble_border.h" | 27 #include "ui/views/bubble/bubble_border.h" |
28 #include "ui/views/bubble/bubble_dialog_delegate.h" | |
28 #include "ui/views/controls/button/image_button.h" | 29 #include "ui/views/controls/button/image_button.h" |
29 #include "ui/views/controls/button/image_button_factory.h" | 30 #include "ui/views/controls/button/image_button_factory.h" |
30 #include "ui/views/controls/image_view.h" | 31 #include "ui/views/controls/image_view.h" |
31 #include "ui/views/controls/label.h" | |
32 #include "ui/views/layout/box_layout.h" | 32 #include "ui/views/layout/box_layout.h" |
33 #include "ui/views/layout/layout_provider.h" | 33 #include "ui/views/layout/layout_provider.h" |
34 #include "ui/views/resources/grit/views_resources.h" | 34 #include "ui/views/resources/grit/views_resources.h" |
35 #include "ui/views/widget/widget.h" | 35 #include "ui/views/widget/widget.h" |
36 #include "ui/views/widget/widget_delegate.h" | 36 #include "ui/views/widget/widget_delegate.h" |
37 #include "ui/views/window/client_view.h" | 37 #include "ui/views/window/client_view.h" |
38 #include "ui/views/window/dialog_delegate.h" | 38 #include "ui/views/window/dialog_delegate.h" |
39 | 39 |
40 namespace views { | 40 namespace views { |
41 | 41 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 | 74 |
75 // static | 75 // static |
76 const char BubbleFrameView::kViewClassName[] = "BubbleFrameView"; | 76 const char BubbleFrameView::kViewClassName[] = "BubbleFrameView"; |
77 | 77 |
78 BubbleFrameView::BubbleFrameView(const gfx::Insets& title_margins, | 78 BubbleFrameView::BubbleFrameView(const gfx::Insets& title_margins, |
79 const gfx::Insets& content_margins) | 79 const gfx::Insets& content_margins) |
80 : bubble_border_(nullptr), | 80 : bubble_border_(nullptr), |
81 title_margins_(title_margins), | 81 title_margins_(title_margins), |
82 content_margins_(content_margins), | 82 content_margins_(content_margins), |
83 title_icon_(new views::ImageView()), | 83 title_icon_(new views::ImageView()), |
84 title_(nullptr), | 84 delegate_title_(nullptr), |
85 close_(nullptr), | 85 close_(nullptr), |
86 footnote_container_(nullptr), | 86 footnote_container_(nullptr), |
87 close_button_clicked_(false) { | 87 close_button_clicked_(false) { |
88 AddChildView(title_icon_); | 88 AddChildView(title_icon_); |
89 | 89 |
90 title_ = new Label(base::string16(), style::CONTEXT_DIALOG_TITLE); | 90 default_title_ = new Label(base::string16(), style::CONTEXT_DIALOG_TITLE); |
91 title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 91 default_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
92 title_->set_collapse_when_hidden(true); | 92 default_title_->set_collapse_when_hidden(true); |
93 title_->SetVisible(false); | 93 default_title_->SetVisible(false); |
94 title_->SetMultiLine(true); | 94 default_title_->SetMultiLine(true); |
95 AddChildView(title_); | 95 AddChildView(default_title_); |
96 | 96 |
97 close_ = CreateCloseButton(this); | 97 close_ = CreateCloseButton(this); |
98 close_->SetVisible(false); | 98 close_->SetVisible(false); |
99 #if defined(OS_WIN) | 99 #if defined(OS_WIN) |
100 // Windows will automatically create a tooltip for the close button based on | 100 // Windows will automatically create a tooltip for the close button based on |
101 // the HTCLOSE result from NonClientHitTest(). | 101 // the HTCLOSE result from NonClientHitTest(). |
102 close_->SetTooltipText(base::string16()); | 102 close_->SetTooltipText(base::string16()); |
103 #endif | 103 #endif |
104 AddChildView(close_); | 104 AddChildView(close_); |
105 } | 105 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
167 | 167 |
168 // Allow dialogs to show the system menu and be dragged. | 168 // Allow dialogs to show the system menu and be dragged. |
169 if (GetWidget()->widget_delegate()->AsDialogDelegate() && | 169 if (GetWidget()->widget_delegate()->AsDialogDelegate() && |
170 !GetWidget()->widget_delegate()->AsBubbleDialogDelegate()) { | 170 !GetWidget()->widget_delegate()->AsBubbleDialogDelegate()) { |
171 gfx::Rect bounds(GetContentsBounds()); | 171 gfx::Rect bounds(GetContentsBounds()); |
172 bounds.Inset(title_margins_); | 172 bounds.Inset(title_margins_); |
173 gfx::Rect sys_rect(0, 0, bounds.x(), bounds.y()); | 173 gfx::Rect sys_rect(0, 0, bounds.x(), bounds.y()); |
174 sys_rect.set_origin(gfx::Point(GetMirroredXForRect(sys_rect), 0)); | 174 sys_rect.set_origin(gfx::Point(GetMirroredXForRect(sys_rect), 0)); |
175 if (sys_rect.Contains(point)) | 175 if (sys_rect.Contains(point)) |
176 return HTSYSMENU; | 176 return HTSYSMENU; |
177 if (point.y() < title_->bounds().bottom()) | 177 if (point.y() < title()->bounds().bottom()) |
178 return HTCAPTION; | 178 return HTCAPTION; |
179 } | 179 } |
180 | 180 |
181 return GetWidget()->client_view()->NonClientHitTest(point); | 181 return GetWidget()->client_view()->NonClientHitTest(point); |
182 } | 182 } |
183 | 183 |
184 void BubbleFrameView::GetWindowMask(const gfx::Size& size, | 184 void BubbleFrameView::GetWindowMask(const gfx::Size& size, |
185 gfx::Path* window_mask) { | 185 gfx::Path* window_mask) { |
186 if (bubble_border_->shadow() != BubbleBorder::SMALL_SHADOW && | 186 if (bubble_border_->shadow() != BubbleBorder::SMALL_SHADOW && |
187 bubble_border_->shadow() != BubbleBorder::NO_SHADOW_OPAQUE_BORDER && | 187 bubble_border_->shadow() != BubbleBorder::NO_SHADOW_OPAQUE_BORDER && |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 } | 226 } |
227 | 227 |
228 void BubbleFrameView::UpdateWindowIcon() { | 228 void BubbleFrameView::UpdateWindowIcon() { |
229 gfx::ImageSkia image; | 229 gfx::ImageSkia image; |
230 if (GetWidget()->widget_delegate()->ShouldShowWindowIcon()) | 230 if (GetWidget()->widget_delegate()->ShouldShowWindowIcon()) |
231 image = GetWidget()->widget_delegate()->GetWindowIcon(); | 231 image = GetWidget()->widget_delegate()->GetWindowIcon(); |
232 title_icon_->SetImage(&image); | 232 title_icon_->SetImage(&image); |
233 } | 233 } |
234 | 234 |
235 void BubbleFrameView::UpdateWindowTitle() { | 235 void BubbleFrameView::UpdateWindowTitle() { |
236 title_->SetText(GetWidget()->widget_delegate()->GetWindowTitle()); | 236 WidgetDelegate* delegate = GetWidget()->widget_delegate(); |
237 title_->SetVisible(GetWidget()->widget_delegate()->ShouldShowWindowTitle()); | 237 if (delegate_title_) { |
238 default_title_->SetVisible(false); | |
239 BubbleDialogDelegateView* bubble_delegate = | |
240 delegate->AsBubbleDialogDelegate(); | |
241 if (bubble_delegate) | |
242 bubble_delegate->PropagateUpdateTitleView(delegate_title_); | |
sky
2017/06/09 23:49:16
Can you elaborate on why this path is needed? My t
Bret
2017/06/10 00:52:01
Hmm I guess I'm confused about the role of UpdateW
Bret
2017/06/15 22:20:34
Added a SetupTitleView to BubbleDialogDelegateView
sky
2017/06/19 15:19:25
Exactly. I don't think UpdateWindowTitle is at all
Bret
2017/06/21 22:37:54
After playing around with it, I ended up removing
sky
2017/06/22 14:48:48
I tend to think it isn't worth bothering either.
| |
243 } else { | |
244 default_title_->SetVisible(delegate->ShouldShowWindowTitle()); | |
245 default_title_->SetText(delegate->GetWindowTitle()); | |
246 } | |
238 } | 247 } |
239 | 248 |
240 void BubbleFrameView::SizeConstraintsChanged() {} | 249 void BubbleFrameView::SizeConstraintsChanged() {} |
241 | 250 |
242 void BubbleFrameView::SetTitleFontList(const gfx::FontList& font_list) { | 251 void BubbleFrameView::SetTitleFontList(const gfx::FontList& font_list) { |
243 title_->SetFontList(font_list); | 252 // TODO: resolve this |
253 default_title_->SetFontList(font_list); | |
254 } | |
255 | |
256 void BubbleFrameView::SetTitleView(View* title_view) { | |
257 DCHECK(title_view); | |
sky
2017/06/09 23:49:16
Can you delete default_title_ here if title_view i
Bret
2017/06/15 22:20:34
Done.
| |
258 if (delegate_title_) { | |
259 RemoveChildView(delegate_title_); | |
sky
2017/06/09 23:49:16
delete implicitly removes, so no need to call this
Bret
2017/06/15 22:20:34
Done.
| |
260 delete delegate_title_; | |
261 } | |
262 delegate_title_ = title_view; | |
263 AddChildView(delegate_title_); | |
244 } | 264 } |
245 | 265 |
246 const char* BubbleFrameView::GetClassName() const { | 266 const char* BubbleFrameView::GetClassName() const { |
247 return kViewClassName; | 267 return kViewClassName; |
248 } | 268 } |
249 | 269 |
250 gfx::Insets BubbleFrameView::GetInsets() const { | 270 gfx::Insets BubbleFrameView::GetInsets() const { |
251 gfx::Insets insets = content_margins_; | 271 gfx::Insets insets = content_margins_; |
252 | 272 |
253 const int icon_height = title_icon_->GetPreferredSize().height(); | 273 const int icon_height = title_icon_->GetPreferredSize().height(); |
254 const int label_height = title_->GetPreferredSize().height(); | 274 const int label_height = title()->GetPreferredSize().height(); |
255 const bool has_title = icon_height > 0 || label_height > 0; | 275 const bool has_title = icon_height > 0 || label_height > 0; |
256 const int title_padding = has_title ? title_margins_.height() : 0; | 276 const int title_padding = has_title ? title_margins_.height() : 0; |
257 const int title_height = std::max(icon_height, label_height) + title_padding; | 277 const int title_height = std::max(icon_height, label_height) + title_padding; |
258 const int close_height = | 278 const int close_height = |
259 GetWidget()->widget_delegate()->ShouldShowCloseButton() | 279 GetWidget()->widget_delegate()->ShouldShowCloseButton() |
260 ? close_->height() + LayoutProvider::Get()->GetDistanceMetric( | 280 ? close_->height() + LayoutProvider::Get()->GetDistanceMetric( |
261 DISTANCE_CLOSE_BUTTON_MARGIN) | 281 DISTANCE_CLOSE_BUTTON_MARGIN) |
262 : 0; | 282 : 0; |
263 insets += gfx::Insets(std::max(title_height, close_height), 0, 0, 0); | 283 insets += gfx::Insets(std::max(title_height, close_height), 0, 0, 0); |
264 return insets; | 284 return insets; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
297 #endif // OS_MACOSX | 317 #endif // OS_MACOSX |
298 // Non-dialog bubbles should be non-resizable, so its max size is its | 318 // Non-dialog bubbles should be non-resizable, so its max size is its |
299 // preferred size. | 319 // preferred size. |
300 return GetPreferredSize(); | 320 return GetPreferredSize(); |
301 #endif | 321 #endif |
302 } | 322 } |
303 | 323 |
304 void BubbleFrameView::Layout() { | 324 void BubbleFrameView::Layout() { |
305 // The title margins may not be set, but make sure that's only the case when | 325 // The title margins may not be set, but make sure that's only the case when |
306 // there's no title. | 326 // there's no title. |
307 DCHECK(!title_margins_.IsEmpty() || !title_->visible()); | 327 DCHECK(!title_margins_.IsEmpty() || |
328 (!default_title_->visible() && !delegate_title_)); | |
308 | 329 |
309 const gfx::Rect contents_bounds = GetContentsBounds(); | 330 const gfx::Rect contents_bounds = GetContentsBounds(); |
310 gfx::Rect bounds = contents_bounds; | 331 gfx::Rect bounds = contents_bounds; |
311 bounds.Inset(title_margins_); | 332 bounds.Inset(title_margins_); |
312 if (bounds.IsEmpty()) | 333 if (bounds.IsEmpty()) |
313 return; | 334 return; |
314 | 335 |
315 // The close button is positioned somewhat closer to the edge of the bubble. | 336 // The close button is positioned somewhat closer to the edge of the bubble. |
316 const int close_margin = | 337 const int close_margin = |
317 LayoutProvider::Get()->GetDistanceMetric(DISTANCE_CLOSE_BUTTON_MARGIN); | 338 LayoutProvider::Get()->GetDistanceMetric(DISTANCE_CLOSE_BUTTON_MARGIN); |
318 close_->SetPosition( | 339 close_->SetPosition( |
319 gfx::Point(contents_bounds.right() - close_margin - close_->width(), | 340 gfx::Point(contents_bounds.right() - close_margin - close_->width(), |
320 contents_bounds.y() + close_margin)); | 341 contents_bounds.y() + close_margin)); |
321 | 342 |
322 gfx::Size title_icon_pref_size(title_icon_->GetPreferredSize()); | 343 gfx::Size title_icon_pref_size(title_icon_->GetPreferredSize()); |
323 int padding = 0; | 344 const int title_icon_padding = |
324 int title_height = title_icon_pref_size.height(); | 345 title_icon_pref_size.width() > 0 ? title_margins_.left() : 0; |
325 | 346 const int title_label_x = |
326 if (title_->visible() && !title_->text().empty()) { | 347 bounds.x() + title_icon_pref_size.width() + title_icon_padding; |
327 if (title_icon_pref_size.width() > 0) | 348 const int title_available_width = std::max(1, close_->x() - title_label_x); |
328 padding = title_margins_.left(); | 349 const int title_preferred_height = |
329 | 350 title()->GetHeightForWidth(title_available_width); |
330 const int title_label_x = | 351 const int title_height = |
331 bounds.x() + title_icon_pref_size.width() + padding; | 352 std::max(title_icon_pref_size.height(), title_preferred_height); |
332 title_->SizeToFit(std::max(1, close_->x() - title_label_x)); | 353 title()->SetBounds(title_label_x, |
333 title_height = std::max(title_height, title_->height()); | 354 bounds.y() + (title_height - title_preferred_height) / 2, |
334 title_->SetPosition(gfx::Point( | 355 title_available_width, title_height); |
335 title_label_x, bounds.y() + (title_height - title_->height()) / 2)); | |
336 } | |
337 | 356 |
338 title_icon_->SetBounds(bounds.x(), bounds.y(), title_icon_pref_size.width(), | 357 title_icon_->SetBounds(bounds.x(), bounds.y(), title_icon_pref_size.width(), |
339 title_height); | 358 title_height); |
340 bounds.set_width(title_->bounds().right() - bounds.x()); | 359 const int title_right = title()->bounds().right(); |
360 bounds.set_width(title_right - bounds.x()); | |
341 bounds.set_height(title_height); | 361 bounds.set_height(title_height); |
342 | 362 |
343 if (footnote_container_) { | 363 if (footnote_container_) { |
344 const int width = contents_bounds.width(); | 364 const int width = contents_bounds.width(); |
345 const int height = footnote_container_->GetHeightForWidth(width); | 365 const int height = footnote_container_->GetHeightForWidth(width); |
346 footnote_container_->SetBounds( | 366 footnote_container_->SetBounds( |
347 contents_bounds.x(), contents_bounds.bottom() - height, width, height); | 367 contents_bounds.x(), contents_bounds.bottom() - height, width, height); |
348 } | 368 } |
349 } | 369 } |
350 | 370 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
522 bubble_border_->GetArrowOffset(window_bounds.size()) - offscreen_adjust); | 542 bubble_border_->GetArrowOffset(window_bounds.size()) - offscreen_adjust); |
523 if (offscreen_adjust) | 543 if (offscreen_adjust) |
524 SchedulePaint(); | 544 SchedulePaint(); |
525 } | 545 } |
526 | 546 |
527 gfx::Size BubbleFrameView::GetSizeForClientSize( | 547 gfx::Size BubbleFrameView::GetSizeForClientSize( |
528 const gfx::Size& client_size) const { | 548 const gfx::Size& client_size) const { |
529 // Accommodate the width of the title bar elements. | 549 // Accommodate the width of the title bar elements. |
530 int title_bar_width = title_margins_.width() + border()->GetInsets().width(); | 550 int title_bar_width = title_margins_.width() + border()->GetInsets().width(); |
531 gfx::Size title_icon_size = title_icon_->GetPreferredSize(); | 551 gfx::Size title_icon_size = title_icon_->GetPreferredSize(); |
532 gfx::Size title_label_size = title_->GetPreferredSize(); | 552 gfx::Size title_label_size = title()->GetPreferredSize(); |
sky
2017/06/09 23:49:16
In Layout code you use GetHeightForWidth(), and yo
Bret
2017/06/10 00:52:01
I think in practice it matches, because when eithe
Bret
2017/06/15 22:20:34
I investigated this a little more (and wrote a tes
| |
533 if (title_icon_size.width() > 0 && title_label_size.width() > 0) | 553 if (title_icon_size.width() > 0 && title_label_size.width() > 0) |
534 title_bar_width += title_margins_.left(); | 554 title_bar_width += title_margins_.left(); |
535 title_bar_width += title_icon_size.width(); | 555 title_bar_width += title_icon_size.width(); |
536 if (close_->visible()) | 556 if (close_->visible()) |
537 title_bar_width += close_->width() + 1; | 557 title_bar_width += close_->width() + 1; |
538 | 558 |
539 gfx::Size size(client_size); | 559 gfx::Size size(client_size); |
540 gfx::Insets client_insets = GetInsets(); | 560 gfx::Insets client_insets = GetInsets(); |
541 size.Enlarge(client_insets.width(), client_insets.height()); | 561 size.Enlarge(client_insets.width(), client_insets.height()); |
542 size.SetToMax(gfx::Size(title_bar_width, 0)); | 562 size.SetToMax(gfx::Size(title_bar_width, 0)); |
543 | 563 |
544 if (footnote_container_) | 564 if (footnote_container_) |
545 size.Enlarge(0, footnote_container_->GetHeightForWidth(size.width())); | 565 size.Enlarge(0, footnote_container_->GetHeightForWidth(size.width())); |
546 | 566 |
547 DialogDelegate* dialog_delegate = | 567 DialogDelegate* dialog_delegate = |
548 GetWidget()->widget_delegate()->AsDialogDelegate(); | 568 GetWidget()->widget_delegate()->AsDialogDelegate(); |
549 if (dialog_delegate && dialog_delegate->ShouldSnapFrameWidth()) | 569 if (dialog_delegate && dialog_delegate->ShouldSnapFrameWidth()) |
550 size.set_width(LayoutProvider::Get()->GetSnappedDialogWidth(size.width())); | 570 size.set_width(LayoutProvider::Get()->GetSnappedDialogWidth(size.width())); |
551 | 571 |
552 return size; | 572 return size; |
553 } | 573 } |
554 | 574 |
555 } // namespace views | 575 } // namespace views |
OLD | NEW |