Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / panels / panel_frame_view.cc
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/panels/panel_frame_view.h"
6
7 #include "chrome/browser/ui/panels/panel.h"
8 #include "chrome/browser/ui/panels/panel_constants.h"
9 #include "chrome/browser/ui/views/panels/panel_view.h"
10 #include "chrome/browser/ui/views/tab_icon_view.h"
11 #include "content/public/browser/web_contents.h"
12 #include "grit/generated_resources.h"
13 #include "grit/theme_resources.h"
14 #include "grit/ui_resources.h"
15 #include "ui/base/hit_test.h"
16 #include "ui/base/l10n/l10n_util.h"
17 #include "ui/base/resource/resource_bundle.h"
18 #include "ui/gfx/canvas.h"
19 #include "ui/gfx/font_list.h"
20 #include "ui/gfx/path.h"
21 #include "ui/views/controls/button/image_button.h"
22 #include "ui/views/controls/label.h"
23 #include "ui/views/widget/widget.h"
24 #include "ui/views/widget/widget_delegate.h"
25
26 #if defined(OS_WIN)
27 #include "base/win/scoped_gdi_object.h"
28 #include "ui/base/win/shell.h"
29 #include "ui/gfx/path_win.h"
30 #include "ui/views/win/hwnd_util.h"
31 #endif
32
33 #if defined(USE_AURA)
34 #include "ui/aura/window.h"
35 #endif
36
37 namespace {
38
39 // The thickness of the border when Aero is not enabled. In this case, the
40 // shadow around the window will not be painted by the system and we need to
41 // paint a frame in order to differentiate the client area from the background.
42 const int kNonAeroBorderThickness = 1;
43
44 // The height and width in pixels of the icon.
45 const int kIconSize = 16;
46
47 // The extra padding between the button and the top edge.
48 const int kExtraPaddingBetweenButtonAndTop = 1;
49
50 // Colors used to draw titlebar background under default theme.
51 const SkColor kActiveBackgroundDefaultColor = SkColorSetRGB(0x3a, 0x3d, 0x3d);
52 const SkColor kInactiveBackgroundDefaultColor = SkColorSetRGB(0x7a, 0x7c, 0x7c);
53 const SkColor kAttentionBackgroundDefaultColor =
54     SkColorSetRGB(0x53, 0xa9, 0x3f);
55
56 // Color used to draw the minimized panel.
57 const SkColor kMinimizeBackgroundDefaultColor = SkColorSetRGB(0xf5, 0xf4, 0xf0);
58
59 // Color used to draw the title text under default theme.
60 const SkColor kTitleTextDefaultColor = SkColorSetRGB(0xf9, 0xf9, 0xf9);
61
62 gfx::ImageSkia* CreateImageForColor(SkColor color) {
63   gfx::Canvas canvas(gfx::Size(1, 1), 1.0f, true);
64   canvas.DrawColor(color);
65   return new gfx::ImageSkia(canvas.ExtractImageRep());
66 }
67
68 #if defined(OS_WIN)
69 const gfx::ImageSkia& GetTopLeftCornerImage(panel::CornerStyle corner_style) {
70   static gfx::ImageSkia* rounded_image = NULL;
71   static gfx::ImageSkia* non_rounded_image = NULL;
72   if (!rounded_image) {
73     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
74     rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_TOP_LEFT_CORNER);
75     non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_TOP_LEFT_CORNER);
76   }
77   return (corner_style & panel::TOP_ROUNDED) ? *rounded_image
78                                              : *non_rounded_image;
79 }
80
81 const gfx::ImageSkia& GetTopRightCornerImage(panel::CornerStyle corner_style) {
82   static gfx::ImageSkia* rounded_image = NULL;
83   static gfx::ImageSkia* non_rounded_image = NULL;
84   if (!rounded_image) {
85     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
86     rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_TOP_RIGHT_CORNER);
87     non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_TOP_RIGHT_CORNER);
88   }
89   return (corner_style & panel::TOP_ROUNDED) ? *rounded_image
90                                              : *non_rounded_image;
91 }
92
93 const gfx::ImageSkia& GetBottomLeftCornerImage(
94     panel::CornerStyle corner_style) {
95   static gfx::ImageSkia* rounded_image = NULL;
96   static gfx::ImageSkia* non_rounded_image = NULL;
97   if (!rounded_image) {
98     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
99     rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_BOTTOM_LEFT_CORNER);
100     non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_BOTTOM_LEFT_CORNER);
101   }
102   return (corner_style & panel::BOTTOM_ROUNDED) ? *rounded_image
103                                                 : *non_rounded_image;
104 }
105
106 const gfx::ImageSkia& GetBottomRightCornerImage(
107     panel::CornerStyle corner_style) {
108   static gfx::ImageSkia* rounded_image = NULL;
109   static gfx::ImageSkia* non_rounded_image = NULL;
110   if (!rounded_image) {
111     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
112     rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_BOTTOM_RIGHT_CORNER);
113     non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_BOTTOM_RIGHT_CORNER);
114   }
115   return (corner_style & panel::BOTTOM_ROUNDED) ? *rounded_image
116                                                 : *non_rounded_image;
117 }
118
119 const gfx::ImageSkia& GetTopEdgeImage() {
120   static gfx::ImageSkia* image = NULL;
121   if (!image) {
122     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
123     image = rb.GetImageSkiaNamed(IDR_WINDOW_TOP_CENTER);
124   }
125   return *image;
126 }
127
128 const gfx::ImageSkia& GetBottomEdgeImage() {
129   static gfx::ImageSkia* image = NULL;
130   if (!image) {
131     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
132     image = rb.GetImageSkiaNamed(IDR_WINDOW_BOTTOM_CENTER);
133   }
134   return *image;
135 }
136
137 const gfx::ImageSkia& GetLeftEdgeImage() {
138   static gfx::ImageSkia* image = NULL;
139   if (!image) {
140     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
141     image = rb.GetImageSkiaNamed(IDR_WINDOW_LEFT_SIDE);
142   }
143   return *image;
144 }
145
146 const gfx::ImageSkia& GetRightEdgeImage() {
147   static gfx::ImageSkia* image = NULL;
148   if (!image) {
149     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
150     image = rb.GetImageSkiaNamed(IDR_WINDOW_RIGHT_SIDE);
151   }
152   return *image;
153 }
154 #endif  // defined(OS_WIN)
155
156 const gfx::ImageSkia* GetActiveBackgroundDefaultImage() {
157   static gfx::ImageSkia* image = NULL;
158   if (!image)
159     image = CreateImageForColor(kActiveBackgroundDefaultColor);
160   return image;
161 }
162
163 const gfx::ImageSkia* GetInactiveBackgroundDefaultImage() {
164   static gfx::ImageSkia* image = NULL;
165   if (!image)
166     image = CreateImageForColor(kInactiveBackgroundDefaultColor);
167   return image;
168 }
169
170 const gfx::ImageSkia* GetAttentionBackgroundDefaultImage() {
171   static gfx::ImageSkia* image = NULL;
172   if (!image)
173     image = CreateImageForColor(kAttentionBackgroundDefaultColor);
174   return image;
175 }
176
177 const gfx::ImageSkia* GetMinimizeBackgroundDefaultImage() {
178   static gfx::ImageSkia* image = NULL;
179   if (!image)
180     image = CreateImageForColor(kMinimizeBackgroundDefaultColor);
181   return image;
182 }
183
184 int GetFrameEdgeHitTest(const gfx::Point& point,
185                         const gfx::Size& frame_size,
186                         int resize_area_size,
187                         panel::Resizability resizability) {
188   int x = point.x();
189   int y = point.y();
190   int width = frame_size.width();
191   int height = frame_size.height();
192   if (x < resize_area_size) {
193     if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP_LEFT)) {
194       return HTTOPLEFT;
195     } else if (y >= height - resize_area_size &&
196               (resizability & panel::RESIZABLE_BOTTOM_LEFT)) {
197       return HTBOTTOMLEFT;
198     } else if (resizability & panel::RESIZABLE_LEFT) {
199       return HTLEFT;
200     }
201   } else if (x >= width - resize_area_size) {
202     if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP_RIGHT)) {
203       return HTTOPRIGHT;
204     } else if (y >= height - resize_area_size &&
205               (resizability & panel::RESIZABLE_BOTTOM_RIGHT)) {
206       return HTBOTTOMRIGHT;
207     } else if (resizability & panel::RESIZABLE_RIGHT) {
208       return HTRIGHT;
209     }
210   }
211
212   if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP)) {
213     return HTTOP;
214   } else if (y >= height - resize_area_size &&
215             (resizability & panel::RESIZABLE_BOTTOM)) {
216     return HTBOTTOM;
217   }
218
219   return HTNOWHERE;
220 }
221
222 // Frameless is only supported when Aero is enabled and shadow effect is
223 // present.
224 bool ShouldRenderAsFrameless() {
225 #if defined(OS_WIN)
226   bool is_frameless = ui::win::IsAeroGlassEnabled();
227   if (is_frameless) {
228     BOOL shadow_enabled = FALSE;
229     if (::SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow_enabled, 0) &&
230         !shadow_enabled)
231       is_frameless = false;
232   }
233   return is_frameless;
234 #else
235   return false;
236 #endif
237 }
238
239 }  // namespace
240
241 // static
242 const char PanelFrameView::kViewClassName[] = "PanelFrameView";
243
244 PanelFrameView::PanelFrameView(PanelView* panel_view)
245     : is_frameless_(ShouldRenderAsFrameless()),
246       panel_view_(panel_view),
247       close_button_(NULL),
248       minimize_button_(NULL),
249       restore_button_(NULL),
250       title_icon_(NULL),
251       title_label_(NULL),
252       corner_style_(panel::ALL_ROUNDED) {
253 }
254
255 PanelFrameView::~PanelFrameView() {
256 }
257
258 void PanelFrameView::Init() {
259   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
260
261   close_button_ = new views::ImageButton(this);
262   close_button_->SetImage(views::CustomButton::STATE_NORMAL,
263                           rb.GetImageSkiaNamed(IDR_PANEL_CLOSE));
264   close_button_->SetImage(views::CustomButton::STATE_HOVERED,
265                           rb.GetImageSkiaNamed(IDR_PANEL_CLOSE_H));
266   close_button_->SetImage(views::CustomButton::STATE_PRESSED,
267                           rb.GetImageSkiaNamed(IDR_PANEL_CLOSE_C));
268   close_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
269                                    views::ImageButton::ALIGN_MIDDLE);
270   base::string16 tooltip_text =
271       l10n_util::GetStringUTF16(IDS_PANEL_CLOSE_TOOLTIP);
272   close_button_->SetTooltipText(tooltip_text);
273   AddChildView(close_button_);
274
275   minimize_button_ = new views::ImageButton(this);
276   minimize_button_->SetImage(views::CustomButton::STATE_NORMAL,
277                              rb.GetImageSkiaNamed(IDR_PANEL_MINIMIZE));
278   minimize_button_->SetImage(views::CustomButton::STATE_HOVERED,
279                              rb.GetImageSkiaNamed(IDR_PANEL_MINIMIZE_H));
280   minimize_button_->SetImage(views::CustomButton::STATE_PRESSED,
281                              rb.GetImageSkiaNamed(IDR_PANEL_MINIMIZE_C));
282   tooltip_text = l10n_util::GetStringUTF16(IDS_PANEL_MINIMIZE_TOOLTIP);
283   minimize_button_->SetTooltipText(tooltip_text);
284   minimize_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
285                                       views::ImageButton::ALIGN_MIDDLE);
286   AddChildView(minimize_button_);
287
288   restore_button_ = new views::ImageButton(this);
289   restore_button_->SetImage(views::CustomButton::STATE_NORMAL,
290                             rb.GetImageSkiaNamed(IDR_PANEL_RESTORE));
291   restore_button_->SetImage(views::CustomButton::STATE_HOVERED,
292                             rb.GetImageSkiaNamed(IDR_PANEL_RESTORE_H));
293   restore_button_->SetImage(views::CustomButton::STATE_PRESSED,
294                             rb.GetImageSkiaNamed(IDR_PANEL_RESTORE_C));
295   restore_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
296                                      views::ImageButton::ALIGN_MIDDLE);
297   tooltip_text = l10n_util::GetStringUTF16(IDS_PANEL_RESTORE_TOOLTIP);
298   restore_button_->SetTooltipText(tooltip_text);
299   restore_button_->SetVisible(false);  // only visible when panel is minimized
300   AddChildView(restore_button_);
301
302   title_icon_ = new TabIconView(this, NULL);
303   title_icon_->set_is_light(true);
304   AddChildView(title_icon_);
305   title_icon_->Update();
306
307   title_label_ = new views::Label(
308       panel_view_->panel()->GetWindowTitle(),
309       rb.GetFontList(ui::ResourceBundle::BoldFont));
310   title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
311   title_label_->SetAutoColorReadabilityEnabled(false);
312   AddChildView(title_label_);
313
314 #if defined(USE_AURA)
315   // Compute the thickness of the client area that needs to be counted towards
316   // mouse resizing.
317   int thickness_for_mouse_resizing =
318       PanelView::kResizeInsideBoundsSize - BorderThickness();
319   aura::Window* window = panel_view_->GetNativePanelWindow();
320   window->set_hit_test_bounds_override_inner(
321       gfx::Insets(thickness_for_mouse_resizing, thickness_for_mouse_resizing,
322                   thickness_for_mouse_resizing, thickness_for_mouse_resizing));
323 #endif
324 }
325
326 void PanelFrameView::UpdateTitle() {
327   UpdateWindowTitle();
328 }
329
330 void PanelFrameView::UpdateIcon() {
331   UpdateWindowIcon();
332 }
333
334 void PanelFrameView::UpdateThrobber() {
335   title_icon_->Update();
336 }
337
338 void PanelFrameView::UpdateTitlebarMinimizeRestoreButtonVisibility() {
339   Panel* panel = panel_view_->panel();
340   minimize_button_->SetVisible(panel->CanShowMinimizeButton());
341   restore_button_->SetVisible(panel->CanShowRestoreButton());
342
343   // Reset the button states in case that the hover states are not cleared when
344   // mouse is clicked but not moved.
345   minimize_button_->SetState(views::CustomButton::STATE_NORMAL);
346   restore_button_->SetState(views::CustomButton::STATE_NORMAL);
347 }
348
349 void PanelFrameView::SetWindowCornerStyle(panel::CornerStyle corner_style) {
350   corner_style_ = corner_style;
351
352 #if defined(OS_WIN)
353   // Changing the window region is going to force a paint. Only change the
354   // window region if the region really differs.
355   HWND native_window = views::HWNDForWidget(panel_view_->window());
356   base::win::ScopedRegion current_region(::CreateRectRgn(0, 0, 0, 0));
357   int current_region_result = ::GetWindowRgn(native_window, current_region);
358
359   gfx::Path window_mask;
360   GetWindowMask(size(), &window_mask);
361   base::win::ScopedRegion new_region(gfx::CreateHRGNFromSkPath(window_mask));
362
363   if (current_region_result == ERROR ||
364       !::EqualRgn(current_region, new_region)) {
365     // SetWindowRgn takes ownership of the new_region.
366     ::SetWindowRgn(native_window, new_region.release(), TRUE);
367   }
368 #endif
369 }
370
371 gfx::Rect PanelFrameView::GetBoundsForClientView() const {
372   // The origin of client-area bounds starts after left border and titlebar and
373   // spans until hitting the right and bottom borders.
374   //    +------------------------------+
375   //    |         Top Titlebar         |
376   //    |-+--------------------------+-|
377   //    |L|                          |R|
378   //    |e|                          |i|
379   //    |f|                          |g|
380   //    |t|                          |h|
381   //    | |         Client           |t|
382   //    | |                          | |
383   //    |B|          Area            |B|
384   //    |o|                          |o|
385   //    |r|                          |r|
386   //    |d|                          |d|
387   //    |e|                          |e|
388   //    |r|                          |r|
389   //    | +--------------------------+ |
390   //    |        Bottom Border         |
391   //    +------------------------------+
392   int titlebar_height = TitlebarHeight();
393   int border_thickness = BorderThickness();
394   return gfx::Rect(border_thickness,
395                    titlebar_height,
396                    std::max(0, width() - border_thickness * 2),
397                    std::max(0, height() - titlebar_height - border_thickness));
398 }
399
400 gfx::Rect PanelFrameView::GetWindowBoundsForClientBounds(
401       const gfx::Rect& client_bounds) const {
402   int titlebar_height = TitlebarHeight();
403   int border_thickness = BorderThickness();
404   // The window bounds include both client area and non-client area (titlebar
405   // and left, right and bottom borders).
406   return gfx::Rect(client_bounds.x() - border_thickness,
407                    client_bounds.y() - titlebar_height,
408                    client_bounds.width() + border_thickness * 2,
409                    client_bounds.height() + titlebar_height + border_thickness);
410 }
411
412 int PanelFrameView::NonClientHitTest(const gfx::Point& point) {
413   panel::Resizability resizability = panel_view_->panel()->CanResizeByMouse();
414
415   // Check the frame first, as we allow a small area overlapping the contents
416   // to be used for resize handles.
417   int frame_component = GetFrameEdgeHitTest(
418       point, size(), PanelView::kResizeInsideBoundsSize, resizability);
419
420   if (frame_component != HTNOWHERE)
421     return frame_component;
422
423   int client_component =
424       panel_view_->window()->client_view()->NonClientHitTest(point);
425   if (client_component != HTNOWHERE)
426     return client_component;
427
428   if (close_button_ && close_button_->visible() &&
429       close_button_->GetMirroredBounds().Contains(point))
430     return HTCLOSE;
431
432   if (minimize_button_ && minimize_button_->visible() &&
433       minimize_button_->GetMirroredBounds().Contains(point))
434     return HTMINBUTTON;
435
436   if (restore_button_ && restore_button_->visible() &&
437       restore_button_->GetMirroredBounds().Contains(point))
438     return HTMAXBUTTON;
439
440   return HTNOWHERE;
441 }
442
443 void PanelFrameView::GetWindowMask(const gfx::Size& size,
444                                    gfx::Path* window_mask) {
445   int width = size.width();
446   int height = size.height();
447
448   if (corner_style_ & panel::TOP_ROUNDED) {
449     window_mask->moveTo(0, 3);
450     window_mask->lineTo(1, 2);
451     window_mask->lineTo(1, 1);
452     window_mask->lineTo(2, 1);
453     window_mask->lineTo(3, 0);
454     window_mask->lineTo(SkIntToScalar(width - 3), 0);
455     window_mask->lineTo(SkIntToScalar(width - 2), 1);
456     window_mask->lineTo(SkIntToScalar(width - 1), 1);
457     window_mask->lineTo(SkIntToScalar(width - 1), 2);
458     window_mask->lineTo(SkIntToScalar(width - 1), 3);
459   } else {
460     window_mask->moveTo(0, 0);
461     window_mask->lineTo(width, 0);
462   }
463
464   if (corner_style_ & panel::BOTTOM_ROUNDED) {
465     window_mask->lineTo(SkIntToScalar(width - 1), SkIntToScalar(height - 4));
466     window_mask->lineTo(SkIntToScalar(width - 2), SkIntToScalar(height - 3));
467     window_mask->lineTo(SkIntToScalar(width - 2), SkIntToScalar(height - 2));
468     window_mask->lineTo(SkIntToScalar(width - 3), SkIntToScalar(height - 2));
469     window_mask->lineTo(SkIntToScalar(width - 4), SkIntToScalar(height - 1));
470     window_mask->lineTo(3, SkIntToScalar(height - 1));
471     window_mask->lineTo(2, SkIntToScalar(height - 2));
472     window_mask->lineTo(1, SkIntToScalar(height - 2));
473     window_mask->lineTo(1, SkIntToScalar(height - 3));
474     window_mask->lineTo(0, SkIntToScalar(height - 4));
475   } else {
476     window_mask->lineTo(SkIntToScalar(width), SkIntToScalar(height));
477     window_mask->lineTo(0, SkIntToScalar(height));
478   }
479
480   window_mask->close();
481 }
482
483 void PanelFrameView::ResetWindowControls() {
484   // The controls aren't affected by this constraint.
485 }
486
487 void PanelFrameView::UpdateWindowIcon() {
488   title_icon_->SchedulePaint();
489 }
490
491 void PanelFrameView::UpdateWindowTitle() {
492   title_label_->SetText(panel_view_->panel()->GetWindowTitle());
493 }
494
495 gfx::Size PanelFrameView::GetPreferredSize() {
496   gfx::Size pref_size =
497       panel_view_->window()->client_view()->GetPreferredSize();
498   gfx::Rect bounds(0, 0, pref_size.width(), pref_size.height());
499   return panel_view_->window()->non_client_view()->
500       GetWindowBoundsForClientBounds(bounds).size();
501 }
502
503 const char* PanelFrameView::GetClassName() const {
504   return kViewClassName;
505 }
506
507 gfx::Size PanelFrameView::GetMinimumSize() {
508   return panel_view_->GetMinimumSize();
509 }
510
511 gfx::Size PanelFrameView::GetMaximumSize() {
512   return panel_view_->GetMaximumSize();
513 }
514
515 void PanelFrameView::Layout() {
516   is_frameless_ = ShouldRenderAsFrameless();
517
518   // Layout the close button.
519   int right = width();
520   close_button_->SetBounds(
521       width() - panel::kTitlebarRightPadding - panel::kPanelButtonSize,
522       (TitlebarHeight() - panel::kPanelButtonSize) / 2 +
523           kExtraPaddingBetweenButtonAndTop,
524       panel::kPanelButtonSize,
525       panel::kPanelButtonSize);
526   right = close_button_->x();
527
528   // Layout the minimize and restore button. Both occupy the same space,
529   // but at most one is visible at any time.
530   minimize_button_->SetBounds(
531       right - panel::kButtonPadding - panel::kPanelButtonSize,
532       (TitlebarHeight() - panel::kPanelButtonSize) / 2 +
533           kExtraPaddingBetweenButtonAndTop,
534       panel::kPanelButtonSize,
535       panel::kPanelButtonSize);
536   restore_button_->SetBoundsRect(minimize_button_->bounds());
537   right = minimize_button_->x();
538
539   // Layout the icon.
540   int icon_y = (TitlebarHeight() - kIconSize) / 2;
541   title_icon_->SetBounds(
542       panel::kTitlebarLeftPadding,
543       icon_y,
544       kIconSize,
545       kIconSize);
546
547   // Layout the title.
548   int title_x = title_icon_->bounds().right() + panel::kIconAndTitlePadding;
549   int title_height = title_label_->font_list().GetHeight();
550   title_label_->SetBounds(
551       title_x,
552       icon_y + ((kIconSize - title_height - 1) / 2),
553       std::max(0, right - panel::kTitleAndButtonPadding - title_x),
554       title_height);
555 }
556
557 void PanelFrameView::OnPaint(gfx::Canvas* canvas) {
558   UpdateControlStyles(GetPaintState());
559   PaintFrameBackground(canvas);
560   PaintFrameEdge(canvas);
561 }
562
563 bool PanelFrameView::OnMousePressed(const ui::MouseEvent& event) {
564   if (event.IsOnlyLeftMouseButton()) {
565     // |event.location| is in the view's coordinate system. Convert it to the
566     // screen coordinate system.
567     gfx::Point mouse_location = event.location();
568     views::View::ConvertPointToScreen(this, &mouse_location);
569
570     // If the mouse location falls within the resizing area of the titlebar,
571     // do not handle the event so that the system resizing logic could kick in.
572     if (!panel_view_->IsWithinResizingArea(mouse_location) &&
573         panel_view_->OnTitlebarMousePressed(mouse_location))
574       return true;
575   }
576   return NonClientFrameView::OnMousePressed(event);
577 }
578
579 bool PanelFrameView::OnMouseDragged(const ui::MouseEvent& event) {
580   // |event.location| is in the view's coordinate system. Convert it to the
581   // screen coordinate system.
582   gfx::Point mouse_location = event.location();
583   views::View::ConvertPointToScreen(this, &mouse_location);
584
585   if (panel_view_->OnTitlebarMouseDragged(mouse_location))
586     return true;
587   return NonClientFrameView::OnMouseDragged(event);
588 }
589
590 void PanelFrameView::OnMouseReleased(const ui::MouseEvent& event) {
591   if (panel_view_->OnTitlebarMouseReleased(
592           event.IsControlDown() ? panel::APPLY_TO_ALL : panel::NO_MODIFIER))
593     return;
594   NonClientFrameView::OnMouseReleased(event);
595 }
596
597 void PanelFrameView::OnMouseCaptureLost() {
598   if (panel_view_->OnTitlebarMouseCaptureLost())
599     return;
600   NonClientFrameView::OnMouseCaptureLost();
601 }
602
603 void PanelFrameView::ButtonPressed(views::Button* sender,
604                                    const ui::Event& event) {
605   if (sender == close_button_) {
606     panel_view_->ClosePanel();
607   } else {
608     panel::ClickModifier modifier =
609         event.IsControlDown() ? panel::APPLY_TO_ALL : panel::NO_MODIFIER;
610     if (sender == minimize_button_)
611       panel_view_->panel()->OnMinimizeButtonClicked(modifier);
612     else if (sender == restore_button_)
613       panel_view_->panel()->OnRestoreButtonClicked(modifier);
614   }
615 }
616
617 bool PanelFrameView::ShouldTabIconViewAnimate() const {
618   // This function is queried during the creation of the window as the
619   // TabIconView we host is initialized, so we need to NULL check the selected
620   // WebContents because in this condition there is not yet a selected tab.
621   content::WebContents* contents = panel_view_->panel()->GetWebContents();
622   return contents ? contents->IsLoading() : false;
623 }
624
625 gfx::ImageSkia PanelFrameView::GetFaviconForTabIconView() {
626   return panel_view_->window()->widget_delegate()->GetWindowIcon();
627 }
628
629 gfx::Size PanelFrameView::NonClientAreaSize() const {
630   if (is_frameless_)
631     return gfx::Size(0, TitlebarHeight());
632   // When the frame is present, the width of non-client area consists of
633   // left and right borders, while the height consists of the top area
634   // (titlebar) and the bottom border.
635   return gfx::Size(2 * kNonAeroBorderThickness,
636                    TitlebarHeight() + kNonAeroBorderThickness);
637 }
638
639 int PanelFrameView::TitlebarHeight() const {
640   return panel::kTitlebarHeight;
641 }
642
643 int PanelFrameView::BorderThickness() const {
644   return is_frameless_ ? 0 : kNonAeroBorderThickness;
645 }
646
647 PanelFrameView::PaintState PanelFrameView::GetPaintState() const {
648   if (panel_view_->panel()->IsDrawingAttention())
649     return PAINT_FOR_ATTENTION;
650   if (bounds().height() <= panel::kMinimizedPanelHeight)
651     return PAINT_AS_MINIMIZED;
652   if (panel_view_->IsPanelActive() &&
653            !panel_view_->force_to_paint_as_inactive())
654     return PAINT_AS_ACTIVE;
655   return PAINT_AS_INACTIVE;
656 }
657
658 SkColor PanelFrameView::GetTitleColor(PaintState paint_state) const {
659   return kTitleTextDefaultColor;
660 }
661
662 const gfx::ImageSkia* PanelFrameView::GetFrameBackground(
663     PaintState paint_state) const {
664   switch (paint_state) {
665     case PAINT_AS_INACTIVE:
666       return GetInactiveBackgroundDefaultImage();
667     case PAINT_AS_ACTIVE:
668       return GetActiveBackgroundDefaultImage();
669     case PAINT_AS_MINIMIZED:
670       return GetMinimizeBackgroundDefaultImage();
671     case PAINT_FOR_ATTENTION:
672       return GetAttentionBackgroundDefaultImage();
673     default:
674       NOTREACHED();
675       return GetInactiveBackgroundDefaultImage();
676   }
677 }
678
679 void PanelFrameView::UpdateControlStyles(PaintState paint_state) {
680   title_label_->SetEnabledColor(GetTitleColor(paint_state));
681 }
682
683 void PanelFrameView::PaintFrameBackground(gfx::Canvas* canvas) {
684   // We only need to paint the title-bar since no resizing border is shown.
685   // Instead, we allow part of the inner content area be used to trigger the
686   // mouse resizing.
687   int titlebar_height = TitlebarHeight();
688   const gfx::ImageSkia* image = GetFrameBackground(GetPaintState());
689   canvas->TileImageInt(*image, 0, 0, width(), titlebar_height);
690
691   if (is_frameless_)
692     return;
693
694   // Left border, below title-bar.
695   canvas->TileImageInt(*image, 0, titlebar_height, kNonAeroBorderThickness,
696       height() - titlebar_height);
697
698   // Right border, below title-bar.
699   canvas->TileImageInt(*image, width() - kNonAeroBorderThickness,
700       titlebar_height, kNonAeroBorderThickness, height() - titlebar_height);
701
702   // Bottom border.
703   canvas->TileImageInt(*image, 0, height() - kNonAeroBorderThickness, width(),
704       kNonAeroBorderThickness);
705 }
706
707 void PanelFrameView::PaintFrameEdge(gfx::Canvas* canvas) {
708 #if defined(OS_WIN)
709   // Border is not needed when panel is not shown as minimized.
710   if (GetPaintState() != PAINT_AS_MINIMIZED)
711     return;
712
713   const gfx::ImageSkia& top_left_image = GetTopLeftCornerImage(corner_style_);
714   const gfx::ImageSkia& top_right_image = GetTopRightCornerImage(corner_style_);
715   const gfx::ImageSkia& bottom_left_image =
716       GetBottomLeftCornerImage(corner_style_);
717   const gfx::ImageSkia& bottom_right_image =
718       GetBottomRightCornerImage(corner_style_);
719   const gfx::ImageSkia& top_image = GetTopEdgeImage();
720   const gfx::ImageSkia& bottom_image = GetBottomEdgeImage();
721   const gfx::ImageSkia& left_image = GetLeftEdgeImage();
722   const gfx::ImageSkia& right_image = GetRightEdgeImage();
723
724   // Draw the top border.
725   canvas->DrawImageInt(top_left_image, 0, 0);
726   canvas->TileImageInt(top_image,
727                        top_left_image.width(),
728                        0,
729                        width() - top_right_image.width(),
730                        top_image.height());
731   canvas->DrawImageInt(top_right_image, width() - top_right_image.width(), 0);
732
733   // Draw the right border.
734   canvas->TileImageInt(right_image,
735                        width() - right_image.width(),
736                        top_right_image.height(),
737                        right_image.width(),
738                        height() - top_right_image.height() -
739                            bottom_right_image.height());
740
741   // Draw the bottom border.
742   canvas->DrawImageInt(bottom_right_image,
743                        width() - bottom_right_image.width(),
744                        height() - bottom_right_image.height());
745   canvas->TileImageInt(bottom_image,
746                        bottom_left_image.width(),
747                        height() - bottom_image.height(),
748                        width() - bottom_left_image.width() -
749                            bottom_right_image.width(),
750                        bottom_image.height());
751   canvas->DrawImageInt(bottom_left_image,
752                        0,
753                        height() - bottom_left_image.height());
754
755   // Draw the left border.
756   canvas->TileImageInt(left_image,
757                        0,
758                        top_left_image.height(),
759                        left_image.width(),
760                        height() - top_left_image.height() -
761                            bottom_left_image.height());
762 #endif
763 }