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 BubbleBorder* border = |
38 new BubbleBorder(BubbleBorder::FLOAT, BubbleBorder::SMALL_SHADOW); | |
39 border->set_background_color(GetNativeTheme()->GetSystemColor( | |
40 ui::NativeTheme::kColorId_DialogBackground)); | |
41 set_border(border); | |
42 // Update the background, which relies on the border. | |
43 set_background(new BubbleBackground(border)); | |
62 | 44 |
63 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 45 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
64 title_font_.reset(new gfx::Font(rb.GetFont(ui::ResourceBundle::MediumFont))); | 46 title_ = new Label(title, rb.GetFont(ui::ResourceBundle::MediumFont)); |
sky
2013/01/07 16:51:03
Can you member initialize these to NULL.
msw
2013/01/07 18:06:32
Done.
| |
65 close_button_ = new views::ImageButton(this); | 47 title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
66 close_button_->SetImage(views::CustomButton::STATE_NORMAL, | 48 AddChildView(title_); |
67 rb.GetImageNamed(IDR_CLOSE_BAR).ToImageSkia()); | 49 |
68 close_button_->SetImage(CustomButton::STATE_HOVERED, | 50 close_ = new LabelButton(this, string16()); |
69 rb.GetImageNamed(IDR_CLOSE_BAR_H).ToImageSkia()); | 51 close_->SetImage(CustomButton::STATE_NORMAL, |
70 close_button_->SetImage(CustomButton::STATE_PRESSED, | 52 *rb.GetImageNamed(IDR_CLOSE_BAR).ToImageSkia()); |
71 rb.GetImageNamed(IDR_CLOSE_BAR_P).ToImageSkia()); | 53 close_->SetImage(CustomButton::STATE_HOVERED, |
72 close_button_->SetImageAlignment(ImageButton::ALIGN_CENTER, | 54 *rb.GetImageNamed(IDR_CLOSE_BAR_H).ToImageSkia()); |
73 ImageButton::ALIGN_MIDDLE); | 55 close_->SetImage(CustomButton::STATE_PRESSED, |
74 AddChildView(close_button_); | 56 *rb.GetImageNamed(IDR_CLOSE_BAR_P).ToImageSkia()); |
57 close_->SetSize(close_->GetPreferredSize()); | |
58 AddChildView(close_); | |
59 | |
60 // Set the margins for the content view. | |
61 content_margins_ = gfx::Insets(2 * kSpacing + title_->font().GetHeight(), | |
62 2 * kSpacing, 2 * kSpacing, 2 * kSpacing); | |
75 } | 63 } |
76 | 64 |
77 DialogFrameView::~DialogFrameView() { | 65 DialogFrameView::~DialogFrameView() { |
78 } | 66 } |
79 | 67 |
80 //////////////////////////////////////////////////////////////////////////////// | 68 //////////////////////////////////////////////////////////////////////////////// |
81 // DialogFrameView, NonClientFrameView: | 69 // DialogFrameView, NonClientFrameView: |
82 | 70 |
83 gfx::Rect DialogFrameView::GetBoundsForClientView() const { | 71 gfx::Rect DialogFrameView::GetBoundsForClientView() const { |
84 gfx::Rect client_bounds = GetLocalBounds(); | 72 gfx::Rect client_bounds = GetLocalBounds(); |
85 client_bounds.Inset(GetClientInsets()); | 73 client_bounds.Inset(GetClientInsets()); |
86 return client_bounds; | 74 return client_bounds; |
87 } | 75 } |
88 | 76 |
89 gfx::Rect DialogFrameView::GetWindowBoundsForClientBounds( | 77 gfx::Rect DialogFrameView::GetWindowBoundsForClientBounds( |
90 const gfx::Rect& client_bounds) const { | 78 const gfx::Rect& client_bounds) const { |
91 gfx::Rect window_bounds = client_bounds; | 79 gfx::Rect window_bounds = client_bounds; |
92 window_bounds.Inset(-GetClientInsets()); | 80 window_bounds.Inset(-GetClientInsets()); |
93 return window_bounds; | 81 return window_bounds; |
94 } | 82 } |
95 | 83 |
96 int DialogFrameView::NonClientHitTest(const gfx::Point& point) { | 84 int DialogFrameView::NonClientHitTest(const gfx::Point& point) { |
97 if (close_button_->GetMirroredBounds().Contains(point)) | 85 if (close_->GetMirroredBounds().Contains(point)) |
98 return HTCLOSE; | 86 return HTCLOSE; |
99 return point.y() < GetClientInsets().top() ? HTCAPTION : HTCLIENT; | 87 return point.y() < GetClientInsets().top() ? HTCAPTION : HTCLIENT; |
100 } | 88 } |
101 | 89 |
102 void DialogFrameView::GetWindowMask(const gfx::Size& size, | 90 void DialogFrameView::GetWindowMask(const gfx::Size& size, |
103 gfx::Path* window_mask) { | 91 gfx::Path* window_mask) { |
104 // Nothing to do. | |
105 } | 92 } |
106 | 93 |
107 void DialogFrameView::ResetWindowControls() { | 94 void DialogFrameView::ResetWindowControls() { |
108 // Nothing to do. | |
109 } | 95 } |
110 | 96 |
111 void DialogFrameView::UpdateWindowIcon() { | 97 void DialogFrameView::UpdateWindowIcon() { |
112 // Nothing to do. | |
113 } | 98 } |
114 | 99 |
115 void DialogFrameView::UpdateWindowTitle() { | 100 void DialogFrameView::UpdateWindowTitle() { |
116 // Nothing to do. | |
117 } | 101 } |
118 | 102 |
119 //////////////////////////////////////////////////////////////////////////////// | 103 //////////////////////////////////////////////////////////////////////////////// |
120 // DialogFrameView, View overrides: | 104 // DialogFrameView, View overrides: |
121 | 105 |
122 std::string DialogFrameView::GetClassName() const { | 106 std::string DialogFrameView::GetClassName() const { |
123 return kViewClassName; | 107 return kViewClassName; |
124 } | 108 } |
125 | 109 |
126 void DialogFrameView::Layout() { | 110 void DialogFrameView::Layout() { |
127 title_display_rect_ = GetLocalBounds(); | 111 gfx::Rect bounds = GetLocalBounds(); |
128 title_display_rect_.Inset(GetPaddingInsets()); | 112 bounds.Inset(border()->GetInsets()); |
129 title_display_rect_.set_height(title_font_->GetHeight()); | 113 close_->SetPosition(gfx::Point(bounds.right() - close_->width(), bounds.y())); |
130 | 114 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 | 115 bounds.set_height(title_->font().GetHeight()); |
132 // dialog. The close button image is smaller, and is centered in the hot rect. | 116 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 } | 117 } |
146 | 118 |
147 //////////////////////////////////////////////////////////////////////////////// | 119 //////////////////////////////////////////////////////////////////////////////// |
148 // DialogFrameView, ButtonListener overrides: | 120 // DialogFrameView, ButtonListener overrides: |
149 | 121 |
150 void DialogFrameView::ButtonPressed(Button* sender, const ui::Event& event) { | 122 void DialogFrameView::ButtonPressed(Button* sender, const ui::Event& event) { |
151 if (sender == close_button_) | 123 if (sender == close_) |
152 GetWidget()->Close(); | 124 GetWidget()->Close(); |
153 } | 125 } |
154 | 126 |
155 //////////////////////////////////////////////////////////////////////////////// | 127 //////////////////////////////////////////////////////////////////////////////// |
156 // DialogFrameView, private: | 128 // DialogFrameView, private: |
157 | 129 |
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 { | 130 gfx::Insets DialogFrameView::GetClientInsets() const { |
177 gfx::Insets insets = GetPaddingInsets(); | 131 gfx::Insets insets = border()->GetInsets(); |
178 // The title should be separated from the client area by 1 em (dialog spec), | 132 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; | 133 return insets; |
187 } | 134 } |
188 | 135 |
189 } // namespace views | 136 } // namespace views |
OLD | NEW |