OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/ui/views/frame/app_non_client_frame_view_aura.h" | |
6 | |
7 #include "base/debug/stack_trace.h" | |
8 #include "chrome/browser/ui/views/frame/browser_frame.h" | |
9 #include "chrome/browser/ui/views/frame/browser_view.h" | |
10 #include "grit/ash_resources.h" | |
11 #include "grit/generated_resources.h" // Accessibility names | |
12 #include "grit/theme_resources.h" | |
13 #include "ui/aura/window.h" | |
14 #include "ui/base/hit_test.h" | |
15 #include "ui/base/l10n/l10n_util.h" | |
16 #include "ui/base/resource/resource_bundle.h" | |
17 #include "ui/base/theme_provider.h" | |
18 #include "ui/gfx/canvas.h" | |
19 #include "ui/gfx/image/image.h" | |
20 #include "ui/gfx/point.h" | |
21 #include "ui/gfx/rect.h" | |
22 #include "ui/gfx/size.h" | |
23 #include "ui/views/controls/button/image_button.h" | |
24 #include "ui/views/widget/widget.h" | |
25 #include "ui/views/window/non_client_view.h" | |
26 | |
27 #if defined(USE_ASH) | |
28 #include "ash/wm/workspace/frame_maximize_button.h" | |
29 #endif | |
30 | |
31 namespace { | |
32 // The number of pixels within the shadow to draw the buttons. | |
33 const int kShadowStart = 16; | |
34 // The size and close buttons are designed to overlap. | |
35 const int kButtonOverlap = 1; | |
36 | |
37 // TODO(pkotwicz): Remove these constants once the IDR_AURA_FULLSCREEN_SHADOW | |
38 // resource is updated. | |
39 const int kShadowHeightStretch = -1; | |
40 } | |
41 | |
42 class AppNonClientFrameViewAura::ControlView | |
43 : public views::View, public views::ButtonListener { | |
44 public: | |
45 explicit ControlView(AppNonClientFrameViewAura* owner) : | |
46 owner_(owner), | |
47 close_button_(new views::ImageButton(this)), | |
48 #if defined(USE_ASH) | |
49 restore_button_(new ash::FrameMaximizeButton(this, owner_)) | |
50 #else | |
51 restore_button_(new views::ImageButton(this)) | |
52 #endif | |
53 { | |
54 close_button_->SetAccessibleName( | |
55 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); | |
56 restore_button_->SetAccessibleName( | |
57 l10n_util::GetStringUTF16(IDS_ACCNAME_MAXIMIZE)); | |
58 | |
59 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
60 | |
61 int control_base_resource_id = owner->browser_view()->IsOffTheRecord() ? | |
62 IDR_AURA_WINDOW_HEADER_BASE_INCOGNITO_ACTIVE : | |
63 IDR_AURA_WINDOW_HEADER_BASE_ACTIVE; | |
64 control_base_ = rb.GetImageNamed(control_base_resource_id).ToImageSkia(); | |
65 shadow_ = rb.GetImageNamed(IDR_AURA_WINDOW_FULLSCREEN_SHADOW).ToImageSkia(); | |
66 | |
67 AddChildView(close_button_); | |
68 AddChildView(restore_button_); | |
69 } | |
70 | |
71 virtual ~ControlView() {} | |
72 | |
73 virtual void Layout() OVERRIDE { | |
74 restore_button_->SetPosition(gfx::Point(kShadowStart, 0)); | |
75 close_button_->SetPosition(gfx::Point(kShadowStart + | |
76 restore_button_->width() - kButtonOverlap, 0)); | |
77 } | |
78 | |
79 virtual void ViewHierarchyChanged(bool is_add, View* parent, | |
80 View* child) OVERRIDE { | |
81 if (is_add && child == this) { | |
82 SetButtonImages(restore_button_, | |
83 IDR_AURA_WINDOW_FULLSCREEN_RESTORE, | |
84 IDR_AURA_WINDOW_FULLSCREEN_RESTORE_H, | |
85 IDR_AURA_WINDOW_FULLSCREEN_RESTORE_P); | |
86 restore_button_->SizeToPreferredSize(); | |
87 | |
88 SetButtonImages(close_button_, | |
89 IDR_AURA_WINDOW_FULLSCREEN_CLOSE, | |
90 IDR_AURA_WINDOW_FULLSCREEN_CLOSE_H, | |
91 IDR_AURA_WINDOW_FULLSCREEN_CLOSE_P); | |
92 close_button_->SizeToPreferredSize(); | |
93 } | |
94 } | |
95 | |
96 virtual gfx::Size GetPreferredSize() OVERRIDE { | |
97 return gfx::Size(shadow_->width(), | |
98 shadow_->height() + kShadowHeightStretch); | |
99 } | |
100 | |
101 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { | |
102 canvas->TileImageInt(*control_base_, | |
103 restore_button_->x(), | |
104 restore_button_->y(), | |
105 restore_button_->width() - kButtonOverlap + close_button_->width(), | |
106 restore_button_->height()); | |
107 | |
108 views::View::OnPaint(canvas); | |
109 | |
110 canvas->DrawImageInt(*shadow_, 0, kShadowHeightStretch); | |
111 } | |
112 | |
113 virtual void ButtonPressed(views::Button* sender, | |
114 const ui::Event& event) OVERRIDE { | |
115 if (sender == close_button_) { | |
116 owner_->frame()->Close(); | |
117 } else if (sender == restore_button_) { | |
118 restore_button_->SetState(views::CustomButton::BS_NORMAL); | |
119 owner_->frame()->Restore(); | |
120 } | |
121 } | |
122 | |
123 private: | |
124 // Sets images whose ids are passed in for each of the respective states | |
125 // of |button|. | |
126 void SetButtonImages(views::ImageButton* button, int normal_image_id, | |
127 int hot_image_id, int pushed_image_id) { | |
128 ui::ThemeProvider* theme_provider = GetThemeProvider(); | |
129 button->SetImage(views::CustomButton::BS_NORMAL, | |
130 theme_provider->GetImageSkiaNamed(normal_image_id)); | |
131 button->SetImage(views::CustomButton::BS_HOT, | |
132 theme_provider->GetImageSkiaNamed(hot_image_id)); | |
133 button->SetImage(views::CustomButton::BS_PUSHED, | |
134 theme_provider->GetImageSkiaNamed(pushed_image_id)); | |
135 } | |
136 | |
137 AppNonClientFrameViewAura* owner_; | |
138 views::ImageButton* close_button_; | |
139 views::ImageButton* restore_button_; | |
140 const gfx::ImageSkia* control_base_; | |
141 const gfx::ImageSkia* shadow_; | |
142 | |
143 DISALLOW_COPY_AND_ASSIGN(ControlView); | |
144 }; | |
145 | |
146 // Observer to detect when the browser frame widget closes so we can clean | |
147 // up our ControlView. Because we can be closed via a keyboard shortcut we | |
148 // are not guaranteed to run AppNonClientFrameView's Close() or Restore(). | |
149 class AppNonClientFrameViewAura::FrameObserver : public views::WidgetObserver { | |
150 public: | |
151 explicit FrameObserver(AppNonClientFrameViewAura* owner) : owner_(owner) {} | |
152 virtual ~FrameObserver() {} | |
153 | |
154 // views::WidgetObserver: | |
155 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE { | |
156 owner_->CloseControlWidget(); | |
157 } | |
158 | |
159 private: | |
160 AppNonClientFrameViewAura* owner_; | |
161 | |
162 DISALLOW_COPY_AND_ASSIGN(FrameObserver); | |
163 }; | |
164 | |
165 // static | |
166 const char AppNonClientFrameViewAura::kViewClassName[] = | |
167 "AppNonClientFrameViewAura"; | |
168 // static | |
169 const char AppNonClientFrameViewAura::kControlWindowName[] = | |
170 "AppNonClientFrameViewAuraControls"; | |
171 | |
172 AppNonClientFrameViewAura::AppNonClientFrameViewAura( | |
173 BrowserFrame* frame, BrowserView* browser_view) | |
174 : BrowserNonClientFrameView(frame, browser_view), | |
175 control_view_(new ControlView(this)), | |
176 control_widget_(NULL), | |
177 frame_observer_(new FrameObserver(this)) { | |
178 // This FrameView is always maximized so we don't want the window to have | |
179 // resize borders. | |
180 frame->GetNativeView()->set_hit_test_bounds_override_inner(gfx::Insets()); | |
181 // Watch for frame close so we can clean up the control widget. | |
182 frame->AddObserver(frame_observer_.get()); | |
183 set_background(views::Background::CreateSolidBackground(SK_ColorBLACK)); | |
184 // Create the controls. | |
185 control_widget_ = new views::Widget; | |
186 views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); | |
187 params.parent = browser_view->GetNativeWindow(); | |
188 params.transparent = true; | |
189 control_widget_->Init(params); | |
190 control_widget_->SetContentsView(control_view_); | |
191 aura::Window* window = control_widget_->GetNativeView(); | |
192 window->SetName(kControlWindowName); | |
193 gfx::Rect control_bounds = GetControlBounds(); | |
194 window->SetBounds(control_bounds); | |
195 control_widget_->Show(); | |
196 } | |
197 | |
198 AppNonClientFrameViewAura::~AppNonClientFrameViewAura() { | |
199 frame()->RemoveObserver(frame_observer_.get()); | |
200 // This frame view can be replaced (and deleted) if the window is restored | |
201 // via a keyboard shortcut like Alt-[. Ensure we close the control widget. | |
202 CloseControlWidget(); | |
203 } | |
204 | |
205 gfx::Rect AppNonClientFrameViewAura::GetBoundsForClientView() const { | |
206 return GetLocalBounds(); | |
207 } | |
208 | |
209 gfx::Rect AppNonClientFrameViewAura::GetWindowBoundsForClientBounds( | |
210 const gfx::Rect& client_bounds) const { | |
211 return client_bounds; | |
212 } | |
213 | |
214 int AppNonClientFrameViewAura::NonClientHitTest( | |
215 const gfx::Point& point) { | |
216 return HTNOWHERE; | |
217 } | |
218 | |
219 void AppNonClientFrameViewAura::GetWindowMask(const gfx::Size& size, | |
220 gfx::Path* window_mask) { | |
221 } | |
222 | |
223 void AppNonClientFrameViewAura::ResetWindowControls() { | |
224 } | |
225 | |
226 void AppNonClientFrameViewAura::UpdateWindowIcon() { | |
227 } | |
228 | |
229 void AppNonClientFrameViewAura::UpdateWindowTitle() { | |
230 } | |
231 | |
232 gfx::Rect AppNonClientFrameViewAura::GetBoundsForTabStrip( | |
233 views::View* tabstrip) const { | |
234 return gfx::Rect(); | |
235 } | |
236 | |
237 BrowserNonClientFrameView::TabStripInsets | |
238 AppNonClientFrameViewAura::GetTabStripInsets(bool restored) const { | |
239 return TabStripInsets(); | |
240 } | |
241 | |
242 int AppNonClientFrameViewAura::GetThemeBackgroundXInset() const { | |
243 return 0; | |
244 } | |
245 | |
246 void AppNonClientFrameViewAura::UpdateThrobber(bool running) { | |
247 } | |
248 | |
249 std::string AppNonClientFrameViewAura::GetClassName() const { | |
250 return kViewClassName; | |
251 } | |
252 | |
253 void AppNonClientFrameViewAura::OnBoundsChanged( | |
254 const gfx::Rect& previous_bounds) { | |
255 if (control_widget_) | |
256 control_widget_->GetNativeView()->SetBounds(GetControlBounds()); | |
257 } | |
258 | |
259 gfx::Rect AppNonClientFrameViewAura::GetControlBounds() const { | |
260 if (!control_view_) | |
261 return gfx::Rect(); | |
262 gfx::Size preferred = control_view_->GetPreferredSize(); | |
263 return gfx::Rect( | |
264 width() - preferred.width(), 0, | |
265 preferred.width(), preferred.height()); | |
266 } | |
267 | |
268 void AppNonClientFrameViewAura::CloseControlWidget() { | |
269 if (control_widget_) { | |
270 control_widget_->Close(); | |
271 control_widget_ = NULL; | |
272 } | |
273 } | |
OLD | NEW |