| 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/window/dialog_frame_view.h" | 5 #include "ui/views/window/dialog_frame_view.h" |
| 6 | 6 |
| 7 #include "grit/ui_resources.h" | 7 #include "grit/ui_resources.h" |
| 8 #include "ui/base/hit_test.h" | 8 #include "ui/base/hit_test.h" |
| 9 #include "ui/base/resource/resource_bundle.h" | 9 #include "ui/base/resource/resource_bundle.h" |
| 10 #include "ui/gfx/canvas.h" | 10 #include "ui/gfx/canvas.h" |
| 11 #include "ui/gfx/font.h" | 11 #include "ui/gfx/font.h" |
| 12 #include "ui/gfx/image/image.h" | 12 #include "ui/gfx/image/image.h" |
| 13 #include "ui/gfx/insets.h" | 13 #include "ui/gfx/insets.h" |
| 14 #include "ui/views/background.h" | 14 #include "ui/views/background.h" |
| 15 #include "ui/views/border.h" | 15 #include "ui/views/bubble/bubble_border.h" |
| 16 #include "ui/views/controls/button/image_button.h" | 16 #include "ui/views/controls/button/label_button.h" |
| 17 #include "ui/views/controls/label.h" |
| 17 #include "ui/views/widget/widget.h" | 18 #include "ui/views/widget/widget.h" |
| 18 #include "ui/views/widget/widget_delegate.h" | 19 #include "ui/views/window/dialog_delegate.h" |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 | 22 |
| 22 // TODO(benrg): Make frame shadow and stroke agree with the spec. | 23 // The base spacing value, multiples of which are used in various places. |
| 24 const int kSpacing = 10; |
| 23 | 25 |
| 24 // TODO(benrg): Title bar text should be #222, not black. Text in the client | 26 // static |
| 25 // area should also be #222, but is currently usually black. Punting on this | 27 const char kViewClassName[] = "ui/views/DialogFrameView"; |
| 26 // until the overhaul of color handling that will be happening Real Soon Now. | |
| 27 const SkColor kDialogTitleColor = SK_ColorBLACK; | |
| 28 const SkColor kDialogBackgroundColor = SK_ColorWHITE; | |
| 29 | |
| 30 // Dialog-size-dependent padding values from the spec, in pixels. | |
| 31 const int kGoogleSmallDialogVPadding = 16; | |
| 32 const int kGoogleSmallDialogHPadding = 20; | |
| 33 const int kGoogleMediumDialogVPadding = 28; | |
| 34 const int kGoogleMediumDialogHPadding = 32; | |
| 35 const int kGoogleLargeDialogVPadding = 30; | |
| 36 const int kGoogleLargeDialogHPadding = 42; | |
| 37 | |
| 38 // Dialog layouts themselves contain some padding, which should be ignored in | |
| 39 // favor of the padding values above. Currently we hack it by nudging the | |
| 40 // client area outward. | |
| 41 const int kDialogHPaddingNudge = 13; | |
| 42 const int kDialogTopPaddingNudge = 5; | |
| 43 const int kDialogBottomPaddingNudge = 10; | |
| 44 | |
| 45 // TODO(benrg): There are no examples in the spec of close boxes on medium- or | |
| 46 // small-size dialogs, and the close button size is not factored into other | |
| 47 // sizing decisions. This value could cause problems with smaller dialogs. | |
| 48 const int kCloseButtonSize = 44; | |
| 49 | 28 |
| 50 } // namespace | 29 } // namespace |
| 51 | 30 |
| 52 namespace views { | 31 namespace views { |
| 53 | 32 |
| 54 // static | |
| 55 const char DialogFrameView::kViewClassName[] = "ui/views/DialogFrameView"; | |
| 56 | |
| 57 //////////////////////////////////////////////////////////////////////////////// | 33 //////////////////////////////////////////////////////////////////////////////// |
| 58 // DialogFrameView, public: | 34 // DialogFrameView, public: |
| 59 | 35 |
| 60 DialogFrameView::DialogFrameView() { | 36 DialogFrameView::DialogFrameView(const string16& title) |
| 61 set_background(Background::CreateSolidBackground(kDialogBackgroundColor)); | 37 : title_(NULL), |
| 38 close_(NULL) { |
| 39 BubbleBorder* border = |
| 40 new BubbleBorder(BubbleBorder::FLOAT, BubbleBorder::SMALL_SHADOW); |
| 41 border->set_background_color(GetNativeTheme()->GetSystemColor( |
| 42 ui::NativeTheme::kColorId_DialogBackground)); |
| 43 set_border(border); |
| 44 // Update the background, which relies on the border. |
| 45 set_background(new BubbleBackground(border)); |
| 62 | 46 |
| 63 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 47 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 64 title_font_.reset(new gfx::Font(rb.GetFont(ui::ResourceBundle::MediumFont))); | 48 title_ = new Label(title, rb.GetFont(ui::ResourceBundle::MediumFont)); |
| 65 close_button_ = new views::ImageButton(this); | 49 title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 66 close_button_->SetImage(views::CustomButton::STATE_NORMAL, | 50 AddChildView(title_); |
| 67 rb.GetImageNamed(IDR_CLOSE_BAR).ToImageSkia()); | 51 |
| 68 close_button_->SetImage(CustomButton::STATE_HOVERED, | 52 close_ = new LabelButton(this, string16()); |
| 69 rb.GetImageNamed(IDR_CLOSE_BAR_H).ToImageSkia()); | 53 close_->SetImage(CustomButton::STATE_NORMAL, |
| 70 close_button_->SetImage(CustomButton::STATE_PRESSED, | 54 *rb.GetImageNamed(IDR_CLOSE_BAR).ToImageSkia()); |
| 71 rb.GetImageNamed(IDR_CLOSE_BAR_P).ToImageSkia()); | 55 close_->SetImage(CustomButton::STATE_HOVERED, |
| 72 close_button_->SetImageAlignment(ImageButton::ALIGN_CENTER, | 56 *rb.GetImageNamed(IDR_CLOSE_BAR_H).ToImageSkia()); |
| 73 ImageButton::ALIGN_MIDDLE); | 57 close_->SetImage(CustomButton::STATE_PRESSED, |
| 74 AddChildView(close_button_); | 58 *rb.GetImageNamed(IDR_CLOSE_BAR_P).ToImageSkia()); |
| 59 close_->SetSize(close_->GetPreferredSize()); |
| 60 AddChildView(close_); |
| 61 |
| 62 // Set the margins for the content view. |
| 63 content_margins_ = gfx::Insets(2 * kSpacing + title_->font().GetHeight(), |
| 64 2 * kSpacing, 2 * kSpacing, 2 * kSpacing); |
| 75 } | 65 } |
| 76 | 66 |
| 77 DialogFrameView::~DialogFrameView() { | 67 DialogFrameView::~DialogFrameView() { |
| 78 } | 68 } |
| 79 | 69 |
| 80 //////////////////////////////////////////////////////////////////////////////// | 70 //////////////////////////////////////////////////////////////////////////////// |
| 81 // DialogFrameView, NonClientFrameView: | 71 // DialogFrameView, NonClientFrameView: |
| 82 | 72 |
| 83 gfx::Rect DialogFrameView::GetBoundsForClientView() const { | 73 gfx::Rect DialogFrameView::GetBoundsForClientView() const { |
| 84 gfx::Rect client_bounds = GetLocalBounds(); | 74 gfx::Rect client_bounds = GetLocalBounds(); |
| 85 client_bounds.Inset(GetClientInsets()); | 75 client_bounds.Inset(GetClientInsets()); |
| 86 return client_bounds; | 76 return client_bounds; |
| 87 } | 77 } |
| 88 | 78 |
| 89 gfx::Rect DialogFrameView::GetWindowBoundsForClientBounds( | 79 gfx::Rect DialogFrameView::GetWindowBoundsForClientBounds( |
| 90 const gfx::Rect& client_bounds) const { | 80 const gfx::Rect& client_bounds) const { |
| 91 gfx::Rect window_bounds = client_bounds; | 81 gfx::Rect window_bounds = client_bounds; |
| 92 window_bounds.Inset(-GetClientInsets()); | 82 window_bounds.Inset(-GetClientInsets()); |
| 93 return window_bounds; | 83 return window_bounds; |
| 94 } | 84 } |
| 95 | 85 |
| 96 int DialogFrameView::NonClientHitTest(const gfx::Point& point) { | 86 int DialogFrameView::NonClientHitTest(const gfx::Point& point) { |
| 97 if (close_button_->GetMirroredBounds().Contains(point)) | 87 if (close_->GetMirroredBounds().Contains(point)) |
| 98 return HTCLOSE; | 88 return HTCLOSE; |
| 99 return point.y() < GetClientInsets().top() ? HTCAPTION : HTCLIENT; | 89 return point.y() < GetClientInsets().top() ? HTCAPTION : HTCLIENT; |
| 100 } | 90 } |
| 101 | 91 |
| 102 void DialogFrameView::GetWindowMask(const gfx::Size& size, | 92 void DialogFrameView::GetWindowMask(const gfx::Size& size, |
| 103 gfx::Path* window_mask) { | 93 gfx::Path* window_mask) { |
| 104 // Nothing to do. | |
| 105 } | 94 } |
| 106 | 95 |
| 107 void DialogFrameView::ResetWindowControls() { | 96 void DialogFrameView::ResetWindowControls() { |
| 108 // Nothing to do. | |
| 109 } | 97 } |
| 110 | 98 |
| 111 void DialogFrameView::UpdateWindowIcon() { | 99 void DialogFrameView::UpdateWindowIcon() { |
| 112 // Nothing to do. | |
| 113 } | 100 } |
| 114 | 101 |
| 115 void DialogFrameView::UpdateWindowTitle() { | 102 void DialogFrameView::UpdateWindowTitle() { |
| 116 // Nothing to do. | |
| 117 } | 103 } |
| 118 | 104 |
| 119 //////////////////////////////////////////////////////////////////////////////// | 105 //////////////////////////////////////////////////////////////////////////////// |
| 120 // DialogFrameView, View overrides: | 106 // DialogFrameView, View overrides: |
| 121 | 107 |
| 122 std::string DialogFrameView::GetClassName() const { | 108 std::string DialogFrameView::GetClassName() const { |
| 123 return kViewClassName; | 109 return kViewClassName; |
| 124 } | 110 } |
| 125 | 111 |
| 126 void DialogFrameView::Layout() { | 112 void DialogFrameView::Layout() { |
| 127 title_display_rect_ = GetLocalBounds(); | 113 gfx::Rect bounds = GetLocalBounds(); |
| 128 title_display_rect_.Inset(GetPaddingInsets()); | 114 bounds.Inset(border()->GetInsets()); |
| 129 title_display_rect_.set_height(title_font_->GetHeight()); | 115 close_->SetPosition(gfx::Point(bounds.right() - close_->width(), bounds.y())); |
| 130 | 116 bounds.Inset(gfx::Insets(kSpacing, 2 * kSpacing, 0, close_->width())); |
| 131 // The hot rectangle for the close button is flush with the upper right of the | 117 bounds.set_height(title_->font().GetHeight()); |
| 132 // dialog. The close button image is smaller, and is centered in the hot rect. | 118 title_->SetBoundsRect(bounds); |
| 133 close_button_->SetBounds( | |
| 134 width() - kCloseButtonSize, | |
| 135 0, kCloseButtonSize, kCloseButtonSize); | |
| 136 } | |
| 137 | |
| 138 void DialogFrameView::OnPaint(gfx::Canvas* canvas) { | |
| 139 View::OnPaint(canvas); | |
| 140 WidgetDelegate* delegate = GetWidget()->widget_delegate(); | |
| 141 if (!delegate) | |
| 142 return; | |
| 143 canvas->DrawStringInt(delegate->GetWindowTitle(), *title_font_.get(), | |
| 144 kDialogTitleColor, title_display_rect_); | |
| 145 } | 119 } |
| 146 | 120 |
| 147 //////////////////////////////////////////////////////////////////////////////// | 121 //////////////////////////////////////////////////////////////////////////////// |
| 148 // DialogFrameView, ButtonListener overrides: | 122 // DialogFrameView, ButtonListener overrides: |
| 149 | 123 |
| 150 void DialogFrameView::ButtonPressed(Button* sender, const ui::Event& event) { | 124 void DialogFrameView::ButtonPressed(Button* sender, const ui::Event& event) { |
| 151 if (sender == close_button_) | 125 if (sender == close_) |
| 152 GetWidget()->Close(); | 126 GetWidget()->Close(); |
| 153 } | 127 } |
| 154 | 128 |
| 155 //////////////////////////////////////////////////////////////////////////////// | 129 //////////////////////////////////////////////////////////////////////////////// |
| 156 // DialogFrameView, private: | 130 // DialogFrameView, private: |
| 157 | 131 |
| 158 gfx::Insets DialogFrameView::GetPaddingInsets() const { | |
| 159 // These three discrete padding sizes come from the spec. If we ever wanted | |
| 160 // our Google-style dialogs to be resizable, we would probably need to | |
| 161 // smoothly interpolate the padding size instead. | |
| 162 int v_padding, h_padding; | |
| 163 if (width() <= 280) { | |
| 164 v_padding = kGoogleSmallDialogVPadding; | |
| 165 h_padding = kGoogleSmallDialogHPadding; | |
| 166 } else if (width() <= 480) { | |
| 167 v_padding = kGoogleMediumDialogVPadding; | |
| 168 h_padding = kGoogleMediumDialogHPadding; | |
| 169 } else { | |
| 170 v_padding = kGoogleLargeDialogVPadding; | |
| 171 h_padding = kGoogleLargeDialogHPadding; | |
| 172 } | |
| 173 return gfx::Insets(v_padding, h_padding, v_padding, h_padding); | |
| 174 } | |
| 175 | |
| 176 gfx::Insets DialogFrameView::GetClientInsets() const { | 132 gfx::Insets DialogFrameView::GetClientInsets() const { |
| 177 gfx::Insets insets = GetPaddingInsets(); | 133 gfx::Insets insets = border()->GetInsets(); |
| 178 // The title should be separated from the client area by 1 em (dialog spec), | 134 insets += content_margins_; |
| 179 // and one em is equal to the font size (CSS spec). | |
| 180 insets += gfx::Insets( | |
| 181 title_font_->GetHeight() + title_font_->GetFontSize() - | |
| 182 kDialogTopPaddingNudge, | |
| 183 -kDialogHPaddingNudge, | |
| 184 -kDialogBottomPaddingNudge, | |
| 185 -kDialogHPaddingNudge); | |
| 186 return insets; | 135 return insets; |
| 187 } | 136 } |
| 188 | 137 |
| 189 } // namespace views | 138 } // namespace views |
| OLD | NEW |