| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "views/window/dialog_client_view.h" | |
| 6 | |
| 7 #include "build/build_config.h" | |
| 8 | |
| 9 #if defined(OS_WIN) | |
| 10 #include <windows.h> | |
| 11 #include <uxtheme.h> | |
| 12 #include <vsstyle.h> | |
| 13 #elif defined(TOOLKIT_USES_GTK) | |
| 14 #include <gtk/gtk.h> | |
| 15 #endif | |
| 16 | |
| 17 #include <algorithm> | |
| 18 | |
| 19 #include "base/utf_string_conversions.h" | |
| 20 #include "grit/ui_strings.h" | |
| 21 #include "ui/base/hit_test.h" | |
| 22 #include "ui/base/keycodes/keyboard_codes.h" | |
| 23 #include "ui/base/l10n/l10n_util.h" | |
| 24 #include "ui/base/resource/resource_bundle.h" | |
| 25 #include "ui/gfx/canvas_skia.h" | |
| 26 #include "ui/gfx/font.h" | |
| 27 #include "views/controls/button/text_button.h" | |
| 28 #include "views/layout/layout_constants.h" | |
| 29 #include "views/widget/root_view.h" | |
| 30 #include "views/widget/widget.h" | |
| 31 #include "views/window/dialog_delegate.h" | |
| 32 | |
| 33 #if defined(OS_WIN) | |
| 34 #include "ui/gfx/native_theme.h" | |
| 35 #else | |
| 36 #include "ui/gfx/skia_utils_gtk.h" | |
| 37 #endif | |
| 38 | |
| 39 namespace views { | |
| 40 namespace { | |
| 41 | |
| 42 // Updates any of the standard buttons according to the delegate. | |
| 43 void UpdateButtonHelper(NativeTextButton* button_view, | |
| 44 DialogDelegate* delegate, | |
| 45 ui::DialogButton button) { | |
| 46 string16 label = delegate->GetDialogButtonLabel(button); | |
| 47 if (!label.empty()) | |
| 48 button_view->SetText(label); | |
| 49 button_view->SetEnabled(delegate->IsDialogButtonEnabled(button)); | |
| 50 button_view->SetVisible(delegate->IsDialogButtonVisible(button)); | |
| 51 } | |
| 52 | |
| 53 #if defined(OS_WIN) | |
| 54 void FillViewWithSysColor(gfx::Canvas* canvas, View* view, COLORREF color) { | |
| 55 SkColor sk_color = | |
| 56 SkColorSetRGB(GetRValue(color), GetGValue(color), GetBValue(color)); | |
| 57 canvas->FillRect(sk_color, view->GetLocalBounds()); | |
| 58 } | |
| 59 #endif | |
| 60 | |
| 61 // DialogButton ---------------------------------------------------------------- | |
| 62 | |
| 63 // DialogButtons is used for the ok/cancel buttons of the window. DialogButton | |
| 64 // forwards AcceleratorPressed to the delegate. | |
| 65 | |
| 66 class DialogButton : public NativeTextButton { | |
| 67 public: | |
| 68 DialogButton(ButtonListener* listener, | |
| 69 Widget* owner, | |
| 70 ui::DialogButton type, | |
| 71 const string16& title, | |
| 72 bool is_default) | |
| 73 : NativeTextButton(listener, title), | |
| 74 owner_(owner), | |
| 75 type_(type) { | |
| 76 SetIsDefault(is_default); | |
| 77 } | |
| 78 | |
| 79 // Overridden to forward to the delegate. | |
| 80 virtual bool AcceleratorPressed(const Accelerator& accelerator) { | |
| 81 if (!owner_->widget_delegate()->AsDialogDelegate()-> | |
| 82 AreAcceleratorsEnabled(type_)) { | |
| 83 return false; | |
| 84 } | |
| 85 return NativeTextButton::AcceleratorPressed(accelerator); | |
| 86 } | |
| 87 | |
| 88 private: | |
| 89 Widget* owner_; | |
| 90 const ui::DialogButton type_; | |
| 91 | |
| 92 DISALLOW_COPY_AND_ASSIGN(DialogButton); | |
| 93 }; | |
| 94 | |
| 95 } // namespace | |
| 96 | |
| 97 // static | |
| 98 gfx::Font* DialogClientView::dialog_button_font_ = NULL; | |
| 99 static const int kDialogMinButtonWidth = 75; | |
| 100 static const int kDialogButtonLabelSpacing = 16; | |
| 101 static const int kDialogButtonContentSpacing = 5; | |
| 102 | |
| 103 // The group used by the buttons. This name is chosen voluntarily big not to | |
| 104 // conflict with other groups that could be in the dialog content. | |
| 105 static const int kButtonGroup = 6666; | |
| 106 | |
| 107 /////////////////////////////////////////////////////////////////////////////// | |
| 108 // DialogClientView, public: | |
| 109 | |
| 110 DialogClientView::DialogClientView(Widget* owner, View* contents_view) | |
| 111 : ClientView(owner, contents_view), | |
| 112 ok_button_(NULL), | |
| 113 cancel_button_(NULL), | |
| 114 default_button_(NULL), | |
| 115 extra_view_(NULL), | |
| 116 size_extra_view_height_to_buttons_(false), | |
| 117 notified_delegate_(false), | |
| 118 listening_to_focus_(false), | |
| 119 saved_focus_manager_(NULL), | |
| 120 bottom_view_(NULL) { | |
| 121 InitClass(); | |
| 122 } | |
| 123 | |
| 124 DialogClientView::~DialogClientView() { | |
| 125 } | |
| 126 | |
| 127 void DialogClientView::ShowDialogButtons() { | |
| 128 DialogDelegate* dd = GetDialogDelegate(); | |
| 129 int buttons = dd->GetDialogButtons(); | |
| 130 if (buttons & ui::DIALOG_BUTTON_OK && !ok_button_) { | |
| 131 string16 label = dd->GetDialogButtonLabel(ui::DIALOG_BUTTON_OK); | |
| 132 if (label.empty()) | |
| 133 label = l10n_util::GetStringUTF16(IDS_APP_OK); | |
| 134 bool is_default_button = | |
| 135 (dd->GetDefaultDialogButton() & ui::DIALOG_BUTTON_OK) != 0; | |
| 136 ok_button_ = new DialogButton(this, | |
| 137 GetWidget(), | |
| 138 ui::DIALOG_BUTTON_OK, | |
| 139 label, | |
| 140 is_default_button); | |
| 141 ok_button_->SetGroup(kButtonGroup); | |
| 142 if (is_default_button) | |
| 143 default_button_ = ok_button_; | |
| 144 if (!(buttons & ui::DIALOG_BUTTON_CANCEL)) | |
| 145 ok_button_->AddAccelerator(Accelerator(ui::VKEY_ESCAPE, | |
| 146 false, false, false)); | |
| 147 AddChildView(ok_button_); | |
| 148 } | |
| 149 if (buttons & ui::DIALOG_BUTTON_CANCEL && !cancel_button_) { | |
| 150 string16 label = | |
| 151 dd->GetDialogButtonLabel(ui::DIALOG_BUTTON_CANCEL); | |
| 152 if (label.empty()) { | |
| 153 if (buttons & ui::DIALOG_BUTTON_OK) { | |
| 154 label = l10n_util::GetStringUTF16(IDS_APP_CANCEL); | |
| 155 } else { | |
| 156 label = l10n_util::GetStringUTF16(IDS_APP_CLOSE); | |
| 157 } | |
| 158 } | |
| 159 bool is_default_button = | |
| 160 (dd->GetDefaultDialogButton() & ui::DIALOG_BUTTON_CANCEL) | |
| 161 != 0; | |
| 162 cancel_button_ = new DialogButton(this, | |
| 163 GetWidget(), | |
| 164 ui::DIALOG_BUTTON_CANCEL, | |
| 165 label, | |
| 166 is_default_button); | |
| 167 cancel_button_->SetGroup(kButtonGroup); | |
| 168 cancel_button_->AddAccelerator(Accelerator(ui::VKEY_ESCAPE, | |
| 169 false, false, false)); | |
| 170 if (is_default_button) | |
| 171 default_button_ = ok_button_; | |
| 172 AddChildView(cancel_button_); | |
| 173 } | |
| 174 if (!buttons) { | |
| 175 // Register the escape key as an accelerator which will close the window | |
| 176 // if there are no dialog buttons. | |
| 177 AddAccelerator(Accelerator(ui::VKEY_ESCAPE, false, false, false)); | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 void DialogClientView::SetDefaultButton(NativeTextButton* new_default_button) { | |
| 182 if (default_button_ && default_button_ != new_default_button) { | |
| 183 default_button_->SetIsDefault(false); | |
| 184 default_button_ = NULL; | |
| 185 } | |
| 186 | |
| 187 if (new_default_button) { | |
| 188 default_button_ = new_default_button; | |
| 189 default_button_->SetIsDefault(true); | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 void DialogClientView::OnWillChangeFocus(View* focused_before, | |
| 194 View* focused_now) { | |
| 195 NativeTextButton* new_default_button = NULL; | |
| 196 if (focused_now && | |
| 197 focused_now->GetClassName() == NativeTextButton::kViewClassName) { | |
| 198 new_default_button = static_cast<NativeTextButton*>(focused_now); | |
| 199 } else { | |
| 200 // The focused view is not a button, get the default button from the | |
| 201 // delegate. | |
| 202 DialogDelegate* dd = GetDialogDelegate(); | |
| 203 if ((dd->GetDefaultDialogButton() & ui::DIALOG_BUTTON_OK) != 0) | |
| 204 new_default_button = ok_button_; | |
| 205 if ((dd->GetDefaultDialogButton() & ui::DIALOG_BUTTON_CANCEL) | |
| 206 != 0) | |
| 207 new_default_button = cancel_button_; | |
| 208 } | |
| 209 SetDefaultButton(new_default_button); | |
| 210 } | |
| 211 | |
| 212 void DialogClientView::OnDidChangeFocus(View* focused_before, | |
| 213 View* focused_now) { | |
| 214 } | |
| 215 | |
| 216 // Changing dialog labels will change button widths. | |
| 217 void DialogClientView::UpdateDialogButtons() { | |
| 218 DialogDelegate* dd = GetDialogDelegate(); | |
| 219 int buttons = dd->GetDialogButtons(); | |
| 220 | |
| 221 if (buttons & ui::DIALOG_BUTTON_OK) | |
| 222 UpdateButtonHelper(ok_button_, dd, ui::DIALOG_BUTTON_OK); | |
| 223 | |
| 224 if (buttons & ui::DIALOG_BUTTON_CANCEL) { | |
| 225 UpdateButtonHelper(cancel_button_, dd, ui::DIALOG_BUTTON_CANCEL); | |
| 226 } | |
| 227 | |
| 228 LayoutDialogButtons(); | |
| 229 SchedulePaint(); | |
| 230 } | |
| 231 | |
| 232 void DialogClientView::AcceptWindow() { | |
| 233 if (notified_delegate_) { | |
| 234 // Only notify the delegate once. See comment in header above | |
| 235 // notified_delegate_ for details. | |
| 236 return; | |
| 237 } | |
| 238 if (GetDialogDelegate()->Accept(false)) { | |
| 239 notified_delegate_ = true; | |
| 240 Close(); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 void DialogClientView::CancelWindow() { | |
| 245 // Call the standard Close handler, which checks with the delegate before | |
| 246 // proceeding. This checking _isn't_ done here, but in the WM_CLOSE handler, | |
| 247 // so that the close box on the window also shares this code path. | |
| 248 Close(); | |
| 249 } | |
| 250 | |
| 251 void DialogClientView::SetBottomView(View* bottom_view) { | |
| 252 if (bottom_view_) { | |
| 253 RemoveChildView(bottom_view_); | |
| 254 delete bottom_view_; | |
| 255 } | |
| 256 bottom_view_ = bottom_view; | |
| 257 if (bottom_view_) | |
| 258 AddChildView(bottom_view_); | |
| 259 } | |
| 260 | |
| 261 /////////////////////////////////////////////////////////////////////////////// | |
| 262 // DialogClientView, View overrides: | |
| 263 | |
| 264 void DialogClientView::NativeViewHierarchyChanged( | |
| 265 bool attached, | |
| 266 gfx::NativeView native_view, | |
| 267 internal::RootView* root_view) { | |
| 268 if (attached) { | |
| 269 UpdateFocusListener(); | |
| 270 } | |
| 271 } | |
| 272 | |
| 273 /////////////////////////////////////////////////////////////////////////////// | |
| 274 // DialogClientView, ClientView overrides: | |
| 275 | |
| 276 bool DialogClientView::CanClose() { | |
| 277 if (notified_delegate_) | |
| 278 return true; | |
| 279 | |
| 280 DialogDelegate* dd = GetDialogDelegate(); | |
| 281 int buttons = dd->GetDialogButtons(); | |
| 282 bool close = true; | |
| 283 if (buttons & ui::DIALOG_BUTTON_CANCEL) | |
| 284 close = dd->Cancel(); | |
| 285 else if (buttons & ui::DIALOG_BUTTON_OK) | |
| 286 close = dd->Accept(true); | |
| 287 notified_delegate_ = close; | |
| 288 return close; | |
| 289 } | |
| 290 | |
| 291 void DialogClientView::WidgetClosing() { | |
| 292 if (listening_to_focus_) { | |
| 293 DCHECK(saved_focus_manager_); | |
| 294 if (saved_focus_manager_) | |
| 295 saved_focus_manager_->RemoveFocusChangeListener(this); | |
| 296 } | |
| 297 } | |
| 298 | |
| 299 int DialogClientView::NonClientHitTest(const gfx::Point& point) { | |
| 300 if (size_box_bounds_.Contains(point.x() - x(), point.y() - y())) | |
| 301 return HTBOTTOMRIGHT; | |
| 302 return ClientView::NonClientHitTest(point); | |
| 303 } | |
| 304 | |
| 305 DialogClientView* DialogClientView::AsDialogClientView() { | |
| 306 return this; | |
| 307 } | |
| 308 | |
| 309 const DialogClientView* DialogClientView::AsDialogClientView() const { | |
| 310 return this; | |
| 311 } | |
| 312 | |
| 313 //////////////////////////////////////////////////////////////////////////////// | |
| 314 // DialogClientView, View overrides: | |
| 315 | |
| 316 void DialogClientView::OnPaint(gfx::Canvas* canvas) { | |
| 317 #if defined(OS_WIN) | |
| 318 FillViewWithSysColor(canvas, this, GetSysColor(COLOR_3DFACE)); | |
| 319 #elif defined(USE_WAYLAND) || defined(USE_AURA) | |
| 320 SkColor sk_color = SkColorSetARGB(200, 255, 255, 255); | |
| 321 canvas->FillRect(sk_color, GetLocalBounds()); | |
| 322 #else | |
| 323 GtkWidget* widget = GetWidget()->GetNativeView(); | |
| 324 if (GTK_IS_WINDOW(widget)) { | |
| 325 GtkStyle* window_style = gtk_widget_get_style(widget); | |
| 326 canvas->FillRect(gfx::GdkColorToSkColor(window_style->bg[GTK_STATE_NORMAL]), | |
| 327 GetLocalBounds()); | |
| 328 } | |
| 329 #endif | |
| 330 } | |
| 331 | |
| 332 void DialogClientView::PaintChildren(gfx::Canvas* canvas) { | |
| 333 View::PaintChildren(canvas); | |
| 334 if (!GetWidget()->IsMaximized() && !GetWidget()->IsMinimized()) | |
| 335 PaintSizeBox(canvas); | |
| 336 } | |
| 337 | |
| 338 void DialogClientView::Layout() { | |
| 339 if (has_dialog_buttons()) | |
| 340 LayoutDialogButtons(); | |
| 341 if (bottom_view_) { | |
| 342 gfx::Rect bounds = GetContentsBounds(); | |
| 343 gfx::Size pref = bottom_view_->GetPreferredSize(); | |
| 344 bottom_view_->SetBounds(bounds.x(), | |
| 345 bounds.bottom() - pref.height() - kButtonVEdgeMargin, | |
| 346 bounds.width(), pref.height()); | |
| 347 } | |
| 348 LayoutContentsView(); | |
| 349 } | |
| 350 | |
| 351 void DialogClientView::ViewHierarchyChanged(bool is_add, View* parent, | |
| 352 View* child) { | |
| 353 if (is_add && child == this) { | |
| 354 // Can only add and update the dialog buttons _after_ they are added to the | |
| 355 // view hierarchy since they are native controls and require the | |
| 356 // Container's HWND. | |
| 357 ShowDialogButtons(); | |
| 358 ClientView::ViewHierarchyChanged(is_add, parent, child); | |
| 359 | |
| 360 UpdateFocusListener(); | |
| 361 | |
| 362 // The "extra view" must be created and installed after the contents view | |
| 363 // has been inserted into the view hierarchy. | |
| 364 CreateExtraView(); | |
| 365 UpdateDialogButtons(); | |
| 366 Layout(); | |
| 367 } | |
| 368 } | |
| 369 | |
| 370 gfx::Size DialogClientView::GetPreferredSize() { | |
| 371 gfx::Size prefsize = contents_view()->GetPreferredSize(); | |
| 372 int button_height = 0; | |
| 373 if (has_dialog_buttons()) { | |
| 374 if (cancel_button_) | |
| 375 button_height = cancel_button_->height(); | |
| 376 else | |
| 377 button_height = ok_button_->height(); | |
| 378 // Account for padding above and below the button. | |
| 379 button_height += kDialogButtonContentSpacing + kButtonVEdgeMargin; | |
| 380 | |
| 381 // Make sure the view is sized to the buttons's width if they are wider than | |
| 382 // the contents. | |
| 383 int width = 0; | |
| 384 if (cancel_button_) | |
| 385 width += GetButtonWidth(ui::DIALOG_BUTTON_CANCEL); | |
| 386 if (ok_button_) { | |
| 387 width += GetButtonWidth(ui::DIALOG_BUTTON_OK); | |
| 388 if (cancel_button_) | |
| 389 width += kRelatedButtonHSpacing; | |
| 390 } | |
| 391 if (extra_view_) { | |
| 392 width += extra_view_->GetPreferredSize().width(); | |
| 393 if (cancel_button_ || ok_button_) | |
| 394 width += kRelatedButtonHSpacing; | |
| 395 } | |
| 396 if (width > 0) { | |
| 397 width += 2 * kButtonHEdgeMargin; | |
| 398 prefsize.set_width(std::max(prefsize.width(), width)); | |
| 399 } | |
| 400 } | |
| 401 if (bottom_view_) { | |
| 402 gfx::Size bottom_pref = bottom_view_->GetPreferredSize(); | |
| 403 prefsize.Enlarge(0, bottom_pref.height() + kButtonVEdgeMargin); | |
| 404 } | |
| 405 prefsize.Enlarge(0, button_height); | |
| 406 return prefsize; | |
| 407 } | |
| 408 | |
| 409 bool DialogClientView::AcceleratorPressed(const Accelerator& accelerator) { | |
| 410 // We only expect Escape key. | |
| 411 DCHECK(accelerator.key_code() == ui::VKEY_ESCAPE); | |
| 412 Close(); | |
| 413 return true; | |
| 414 } | |
| 415 | |
| 416 //////////////////////////////////////////////////////////////////////////////// | |
| 417 // DialogClientView, ButtonListener implementation: | |
| 418 | |
| 419 void DialogClientView::ButtonPressed( | |
| 420 Button* sender, const views::Event& event) { | |
| 421 // We NULL check the delegate here since the buttons can receive WM_COMMAND | |
| 422 // messages even after they (and the window containing us) are destroyed. | |
| 423 if (!GetDialogDelegate()) | |
| 424 return; | |
| 425 | |
| 426 if (sender == ok_button_) { | |
| 427 AcceptWindow(); | |
| 428 } else if (sender == cancel_button_) { | |
| 429 CancelWindow(); | |
| 430 } else { | |
| 431 NOTREACHED(); | |
| 432 } | |
| 433 } | |
| 434 | |
| 435 //////////////////////////////////////////////////////////////////////////////// | |
| 436 // DialogClientView, private: | |
| 437 | |
| 438 void DialogClientView::PaintSizeBox(gfx::Canvas* canvas) { | |
| 439 if (GetWidget()->widget_delegate()->CanResize() || | |
| 440 GetWidget()->widget_delegate()->CanMaximize()) { | |
| 441 #if defined(OS_WIN) | |
| 442 gfx::NativeTheme::ExtraParams extra; | |
| 443 gfx::Size gripper_size = gfx::NativeTheme::instance()->GetPartSize( | |
| 444 gfx::NativeTheme::kWindowResizeGripper, gfx::NativeTheme::kNormal, | |
| 445 extra); | |
| 446 | |
| 447 // TODO(beng): (http://b/1085509) In "classic" rendering mode, there isn't | |
| 448 // a theme-supplied gripper. We should probably improvise | |
| 449 // something, which would also require changing |gripper_size| | |
| 450 // to have different default values, too... | |
| 451 size_box_bounds_ = GetContentsBounds(); | |
| 452 size_box_bounds_.set_x(size_box_bounds_.right() - gripper_size.width()); | |
| 453 size_box_bounds_.set_y(size_box_bounds_.bottom() - gripper_size.height()); | |
| 454 | |
| 455 gfx::NativeTheme::instance()->Paint(canvas->GetSkCanvas(), | |
| 456 gfx::NativeTheme::kWindowResizeGripper, | |
| 457 gfx::NativeTheme::kNormal, | |
| 458 size_box_bounds_, | |
| 459 extra); | |
| 460 #else | |
| 461 NOTIMPLEMENTED(); | |
| 462 // TODO(port): paint size box | |
| 463 #endif | |
| 464 } | |
| 465 } | |
| 466 | |
| 467 int DialogClientView::GetButtonWidth(int button) const { | |
| 468 DialogDelegate* dd = GetDialogDelegate(); | |
| 469 string16 button_label = dd->GetDialogButtonLabel( | |
| 470 static_cast<ui::DialogButton>(button)); | |
| 471 int string_width = dialog_button_font_->GetStringWidth(button_label); | |
| 472 return std::max(string_width + kDialogButtonLabelSpacing, | |
| 473 kDialogMinButtonWidth); | |
| 474 } | |
| 475 | |
| 476 int DialogClientView::GetButtonsHeight() const { | |
| 477 if (has_dialog_buttons()) { | |
| 478 if (cancel_button_) | |
| 479 return cancel_button_->height() + kDialogButtonContentSpacing; | |
| 480 return ok_button_->height() + kDialogButtonContentSpacing; | |
| 481 } | |
| 482 return 0; | |
| 483 } | |
| 484 | |
| 485 void DialogClientView::LayoutDialogButtons() { | |
| 486 gfx::Rect lb = GetContentsBounds(); | |
| 487 gfx::Rect extra_bounds; | |
| 488 int bottom_y = lb.bottom() - kButtonVEdgeMargin; | |
| 489 int button_height = 0; | |
| 490 if (bottom_view_) { | |
| 491 gfx::Size bottom_pref = bottom_view_->GetPreferredSize(); | |
| 492 bottom_y -= bottom_pref.height() + kButtonVEdgeMargin + kButtonVEdgeMargin; | |
| 493 } | |
| 494 if (cancel_button_) { | |
| 495 gfx::Size ps = cancel_button_->GetPreferredSize(); | |
| 496 int button_width = std::max( | |
| 497 GetButtonWidth(ui::DIALOG_BUTTON_CANCEL), ps.width()); | |
| 498 int button_x = lb.right() - button_width - kButtonHEdgeMargin; | |
| 499 int button_y = bottom_y - ps.height(); | |
| 500 cancel_button_->SetBounds(button_x, button_y, button_width, ps.height()); | |
| 501 // The extra view bounds are dependent on this button. | |
| 502 extra_bounds.set_width(std::max(0, cancel_button_->x())); | |
| 503 extra_bounds.set_y(cancel_button_->y()); | |
| 504 button_height = std::max(button_height, ps.height()); | |
| 505 } | |
| 506 if (ok_button_) { | |
| 507 gfx::Size ps = ok_button_->GetPreferredSize(); | |
| 508 int button_width = std::max( | |
| 509 GetButtonWidth(ui::DIALOG_BUTTON_OK), ps.width()); | |
| 510 int ok_button_right = lb.right() - kButtonHEdgeMargin; | |
| 511 if (cancel_button_) | |
| 512 ok_button_right = cancel_button_->x() - kRelatedButtonHSpacing; | |
| 513 int button_x = ok_button_right - button_width; | |
| 514 int button_y = bottom_y - ps.height(); | |
| 515 ok_button_->SetBounds(button_x, button_y, ok_button_right - button_x, | |
| 516 ps.height()); | |
| 517 // The extra view bounds are dependent on this button. | |
| 518 extra_bounds.set_width(std::max(0, ok_button_->x())); | |
| 519 extra_bounds.set_y(ok_button_->y()); | |
| 520 button_height = std::max(button_height, ps.height()); | |
| 521 } | |
| 522 if (extra_view_) { | |
| 523 gfx::Size ps = extra_view_->GetPreferredSize(); | |
| 524 extra_bounds.set_x(lb.x() + kButtonHEdgeMargin); | |
| 525 int height = size_extra_view_height_to_buttons_ ? | |
| 526 std::max(ps.height(), button_height) : ps.height(); | |
| 527 extra_bounds.set_height(height); | |
| 528 extra_view_->SetBoundsRect(extra_bounds); | |
| 529 } | |
| 530 } | |
| 531 | |
| 532 void DialogClientView::LayoutContentsView() { | |
| 533 gfx::Rect lb = GetContentsBounds(); | |
| 534 lb.set_height(std::max(0, lb.height() - GetButtonsHeight())); | |
| 535 contents_view()->SetBoundsRect(lb); | |
| 536 contents_view()->Layout(); | |
| 537 } | |
| 538 | |
| 539 void DialogClientView::CreateExtraView() { | |
| 540 View* extra_view = GetDialogDelegate()->GetExtraView(); | |
| 541 if (extra_view && !extra_view_) { | |
| 542 extra_view_ = extra_view; | |
| 543 extra_view_->SetGroup(kButtonGroup); | |
| 544 AddChildView(extra_view_); | |
| 545 size_extra_view_height_to_buttons_ = | |
| 546 GetDialogDelegate()->GetSizeExtraViewHeightToButtons(); | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 DialogDelegate* DialogClientView::GetDialogDelegate() const { | |
| 551 return GetWidget()->widget_delegate()->AsDialogDelegate(); | |
| 552 } | |
| 553 | |
| 554 void DialogClientView::Close() { | |
| 555 GetWidget()->Close(); | |
| 556 GetDialogDelegate()->OnClose(); | |
| 557 } | |
| 558 | |
| 559 void DialogClientView::UpdateFocusListener() { | |
| 560 FocusManager* focus_manager = GetFocusManager(); | |
| 561 // Listen for focus change events so we can update the default button. | |
| 562 // focus_manager can be NULL when the dialog is created on un-shown view. | |
| 563 // We start listening for focus changes when the page is visible. | |
| 564 // Focus manager could also change if window host changes a parent. | |
| 565 if (listening_to_focus_) { | |
| 566 if (saved_focus_manager_ == focus_manager) | |
| 567 return; | |
| 568 DCHECK(saved_focus_manager_); | |
| 569 if (saved_focus_manager_) | |
| 570 saved_focus_manager_->RemoveFocusChangeListener(this); | |
| 571 listening_to_focus_ = false; | |
| 572 } | |
| 573 saved_focus_manager_ = focus_manager; | |
| 574 // Listen for focus change events so we can update the default button. | |
| 575 if (focus_manager) { | |
| 576 focus_manager->AddFocusChangeListener(this); | |
| 577 listening_to_focus_ = true; | |
| 578 } | |
| 579 } | |
| 580 | |
| 581 // static | |
| 582 void DialogClientView::InitClass() { | |
| 583 static bool initialized = false; | |
| 584 if (!initialized) { | |
| 585 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 586 dialog_button_font_ = new gfx::Font(rb.GetFont(ResourceBundle::BaseFont)); | |
| 587 initialized = true; | |
| 588 } | |
| 589 } | |
| 590 | |
| 591 } // namespace views | |
| OLD | NEW |