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