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.
5 #include "chrome/browser/ui/views/panels/panel_frame_view.h"
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"
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"
33 #include "ui/aura/window.h"
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;
43 // The height and width in pixels of the icon.
44 const int kIconSize = 16;
46 // The font to use to draw the title.
47 const char* kTitleFontName = "Arial Bold";
48 const int kTitleFontSize = 14;
50 // The extra padding between the button and the top edge.
51 const int kExtraPaddingBetweenButtonAndTop = 1;
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);
59 // Color used to draw the minimized panel.
60 const SkColor kMinimizeBackgroundDefaultColor = SkColorSetRGB(0xf5, 0xf4, 0xf0);
62 // Color used to draw the title text under default theme.
63 const SkColor kTitleTextDefaultColor = SkColorSetRGB(0xf9, 0xf9, 0xf9);
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());
71 const gfx::ImageSkia& GetTopLeftCornerImage(panel::CornerStyle corner_style) {
72 static gfx::ImageSkia* rounded_image = NULL;
73 static gfx::ImageSkia* non_rounded_image = NULL;
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);
79 return (corner_style & panel::TOP_ROUNDED) ? *rounded_image
83 const gfx::ImageSkia& GetTopRightCornerImage(panel::CornerStyle corner_style) {
84 static gfx::ImageSkia* rounded_image = NULL;
85 static gfx::ImageSkia* non_rounded_image = NULL;
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);
91 return (corner_style & panel::TOP_ROUNDED) ? *rounded_image
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;
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);
104 return (corner_style & panel::BOTTOM_ROUNDED) ? *rounded_image
105 : *non_rounded_image;
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);
117 return (corner_style & panel::BOTTOM_ROUNDED) ? *rounded_image
118 : *non_rounded_image;
121 const gfx::ImageSkia& GetTopEdgeImage() {
122 static gfx::ImageSkia* image = NULL;
124 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
125 image = rb.GetImageSkiaNamed(IDR_WINDOW_TOP_CENTER);
130 const gfx::ImageSkia& GetBottomEdgeImage() {
131 static gfx::ImageSkia* image = NULL;
133 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
134 image = rb.GetImageSkiaNamed(IDR_WINDOW_BOTTOM_CENTER);
139 const gfx::ImageSkia& GetLeftEdgeImage() {
140 static gfx::ImageSkia* image = NULL;
142 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
143 image = rb.GetImageSkiaNamed(IDR_WINDOW_LEFT_SIDE);
148 const gfx::ImageSkia& GetRightEdgeImage() {
149 static gfx::ImageSkia* image = NULL;
151 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
152 image = rb.GetImageSkiaNamed(IDR_WINDOW_RIGHT_SIDE);
157 const gfx::Font& GetTitleFont() {
158 static gfx::Font* font = NULL;
160 font = new gfx::Font(kTitleFontName, kTitleFontSize);
164 const gfx::ImageSkia* GetActiveBackgroundDefaultImage() {
165 static gfx::ImageSkia* image = NULL;
167 image = CreateImageForColor(kActiveBackgroundDefaultColor);
171 const gfx::ImageSkia* GetInactiveBackgroundDefaultImage() {
172 static gfx::ImageSkia* image = NULL;
174 image = CreateImageForColor(kInactiveBackgroundDefaultColor);
178 const gfx::ImageSkia* GetAttentionBackgroundDefaultImage() {
179 static gfx::ImageSkia* image = NULL;
181 image = CreateImageForColor(kAttentionBackgroundDefaultColor);
185 const gfx::ImageSkia* GetMinimizeBackgroundDefaultImage() {
186 static gfx::ImageSkia* image = NULL;
188 image = CreateImageForColor(kMinimizeBackgroundDefaultColor);
192 int GetFrameEdgeHitTest(const gfx::Point& point,
193 const gfx::Size& frame_size,
194 int resize_area_size,
195 panel::Resizability resizability) {
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)) {
203 } else if (y >= height - resize_area_size &&
204 (resizability & panel::RESIZABLE_BOTTOM_LEFT)) {
206 } else if (resizability & panel::RESIZABLE_LEFT) {
209 } else if (x >= width - resize_area_size) {
210 if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP_RIGHT)) {
212 } else if (y >= height - resize_area_size &&
213 (resizability & panel::RESIZABLE_BOTTOM_RIGHT)) {
214 return HTBOTTOMRIGHT;
215 } else if (resizability & panel::RESIZABLE_RIGHT) {
220 if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP)) {
222 } else if (y >= height - resize_area_size &&
223 (resizability & panel::RESIZABLE_BOTTOM)) {
230 // Frameless is only supported when Aero is enabled and shadow effect is
232 bool ShouldRenderAsFrameless() {
234 bool is_frameless = ui::win::IsAeroGlassEnabled();
236 BOOL shadow_enabled = FALSE;
237 if (::SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow_enabled, 0) &&
239 is_frameless = false;
250 const char PanelFrameView::kViewClassName[] = "PanelFrameView";
252 PanelFrameView::PanelFrameView(PanelView* panel_view)
253 : is_frameless_(ShouldRenderAsFrameless()),
254 panel_view_(panel_view),
256 minimize_button_(NULL),
257 restore_button_(NULL),
260 corner_style_(panel::ALL_ROUNDED) {
263 PanelFrameView::~PanelFrameView() {
266 void PanelFrameView::Init() {
267 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
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_);
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_);
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_);
309 title_icon_ = new TabIconView(this);
310 title_icon_->set_is_light(true);
311 AddChildView(title_icon_);
312 title_icon_->Update();
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_);
320 #if defined(USE_AURA)
321 // Compute the thickness of the client area that needs to be counted towards
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));
332 void PanelFrameView::UpdateTitle() {
336 void PanelFrameView::UpdateIcon() {
340 void PanelFrameView::UpdateThrobber() {
341 title_icon_->Update();
344 void PanelFrameView::UpdateTitlebarMinimizeRestoreButtonVisibility() {
345 Panel* panel = panel_view_->panel();
346 minimize_button_->SetVisible(panel->CanShowMinimizeButton());
347 restore_button_->SetVisible(panel->CanShowRestoreButton());
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);
355 void PanelFrameView::SetWindowCornerStyle(panel::CornerStyle corner_style) {
356 corner_style_ = corner_style;
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);
365 gfx::Path window_mask;
366 GetWindowMask(size(), &window_mask);
367 base::win::ScopedRegion new_region(gfx::CreateHRGNFromSkPath(window_mask));
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);
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 // +------------------------------+
382 // |-+--------------------------+-|
395 // | +--------------------------+ |
397 // +------------------------------+
398 int titlebar_height = TitlebarHeight();
399 int border_thickness = BorderThickness();
400 return gfx::Rect(border_thickness,
402 std::max(0, width() - border_thickness * 2),
403 std::max(0, height() - titlebar_height - border_thickness));
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);
418 int PanelFrameView::NonClientHitTest(const gfx::Point& point) {
419 panel::Resizability resizability = panel_view_->panel()->CanResizeByMouse();
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);
426 if (frame_component != HTNOWHERE)
427 return frame_component;
429 int client_component =
430 panel_view_->window()->client_view()->NonClientHitTest(point);
431 if (client_component != HTNOWHERE)
432 return client_component;
434 if (close_button_ && close_button_->visible() &&
435 close_button_->GetMirroredBounds().Contains(point))
438 if (minimize_button_ && minimize_button_->visible() &&
439 minimize_button_->GetMirroredBounds().Contains(point))
442 if (restore_button_ && restore_button_->visible() &&
443 restore_button_->GetMirroredBounds().Contains(point))
449 void PanelFrameView::GetWindowMask(const gfx::Size& size,
450 gfx::Path* window_mask) {
451 int width = size.width();
452 int height = size.height();
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);
466 window_mask->moveTo(0, 0);
467 window_mask->lineTo(width, 0);
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));
482 window_mask->lineTo(SkIntToScalar(width), SkIntToScalar(height));
483 window_mask->lineTo(0, SkIntToScalar(height));
486 window_mask->close();
489 void PanelFrameView::ResetWindowControls() {
490 // The controls aren't affected by this constraint.
493 void PanelFrameView::UpdateWindowIcon() {
494 title_icon_->SchedulePaint();
497 void PanelFrameView::UpdateWindowTitle() {
498 title_label_->SetText(panel_view_->panel()->GetWindowTitle());
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();
509 const char* PanelFrameView::GetClassName() const {
510 return kViewClassName;
513 gfx::Size PanelFrameView::GetMinimumSize() {
514 return panel_view_->GetMinimumSize();
517 gfx::Size PanelFrameView::GetMaximumSize() {
518 return panel_view_->GetMaximumSize();
521 void PanelFrameView::Layout() {
522 is_frameless_ = ShouldRenderAsFrameless();
524 // Layout the close button.
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();
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();
546 int icon_y = (TitlebarHeight() - kIconSize) / 2;
547 title_icon_->SetBounds(
548 panel::kTitlebarLeftPadding,
554 int title_x = title_icon_->bounds().right() + panel::kIconAndTitlePadding;
555 int title_height = GetTitleFont().GetHeight();
556 title_label_->SetBounds(
558 icon_y + ((kIconSize - title_height - 1) / 2),
559 std::max(0, right - panel::kTitleAndButtonPadding - title_x),
563 void PanelFrameView::OnPaint(gfx::Canvas* canvas) {
564 UpdateControlStyles(GetPaintState());
565 PaintFrameBackground(canvas);
566 PaintFrameEdge(canvas);
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);
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))
582 return NonClientFrameView::OnMousePressed(event);
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);
591 if (panel_view_->OnTitlebarMouseDragged(mouse_location))
593 return NonClientFrameView::OnMouseDragged(event);
596 void PanelFrameView::OnMouseReleased(const ui::MouseEvent& event) {
597 if (panel_view_->OnTitlebarMouseReleased(
598 event.IsControlDown() ? panel::APPLY_TO_ALL : panel::NO_MODIFIER))
600 NonClientFrameView::OnMouseReleased(event);
603 void PanelFrameView::OnMouseCaptureLost() {
604 if (panel_view_->OnTitlebarMouseCaptureLost())
606 NonClientFrameView::OnMouseCaptureLost();
609 void PanelFrameView::ButtonPressed(views::Button* sender,
610 const ui::Event& event) {
611 if (sender == close_button_) {
612 panel_view_->ClosePanel();
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);
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;
631 gfx::ImageSkia PanelFrameView::GetFaviconForTabIconView() {
632 return panel_view_->window()->widget_delegate()->GetWindowIcon();
635 gfx::Size PanelFrameView::NonClientAreaSize() const {
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);
645 int PanelFrameView::TitlebarHeight() const {
646 return panel::kTitlebarHeight;
649 int PanelFrameView::BorderThickness() const {
650 return is_frameless_ ? 0 : kNonAeroBorderThickness;
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;
664 SkColor PanelFrameView::GetTitleColor(PaintState paint_state) const {
665 return kTitleTextDefaultColor;
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();
681 return GetInactiveBackgroundDefaultImage();
685 void PanelFrameView::UpdateControlStyles(PaintState paint_state) {
686 title_label_->SetEnabledColor(GetTitleColor(paint_state));
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
693 int titlebar_height = TitlebarHeight();
694 const gfx::ImageSkia* image = GetFrameBackground(GetPaintState());
695 canvas->TileImageInt(*image, 0, 0, width(), titlebar_height);
700 // Left border, below title-bar.
701 canvas->TileImageInt(*image, 0, titlebar_height, kNonAeroBorderThickness,
702 height() - titlebar_height);
704 // Right border, below title-bar.
705 canvas->TileImageInt(*image, width() - kNonAeroBorderThickness,
706 titlebar_height, kNonAeroBorderThickness, height() - titlebar_height);
709 canvas->TileImageInt(*image, 0, height() - kNonAeroBorderThickness, width(),
710 kNonAeroBorderThickness);
713 void PanelFrameView::PaintFrameEdge(gfx::Canvas* canvas) {
715 // Border is not needed when panel is not shown as minimized.
716 if (GetPaintState() != PAINT_AS_MINIMIZED)
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();
730 // Draw the top border.
731 canvas->DrawImageInt(top_left_image, 0, 0);
732 canvas->TileImageInt(top_image,
733 top_left_image.width(),
735 width() - top_right_image.width(),
737 canvas->DrawImageInt(top_right_image, width() - top_right_image.width(), 0);
739 // Draw the right border.
740 canvas->TileImageInt(right_image,
741 width() - right_image.width(),
742 top_right_image.height(),
744 height() - top_right_image.height() -
745 bottom_right_image.height());
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,
759 height() - bottom_left_image.height());
761 // Draw the left border.
762 canvas->TileImageInt(left_image,
764 top_left_image.height(),
766 height() - top_left_image.height() -
767 bottom_left_image.height());