// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/views/panels/panel_frame_view.h" #include "chrome/browser/ui/panels/panel.h" #include "chrome/browser/ui/panels/panel_constants.h" #include "chrome/browser/ui/views/panels/panel_view.h" #include "chrome/browser/ui/views/tab_icon_view.h" #include "content/public/browser/web_contents.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "grit/ui_resources.h" #include "ui/aura/window.h" #include "ui/base/hit_test.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font_list.h" #include "ui/gfx/path.h" #include "ui/gfx/screen.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/label.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" #if defined(OS_WIN) #include "base/win/scoped_gdi_object.h" #include "ui/base/win/shell.h" #include "ui/gfx/path_win.h" #include "ui/views/win/hwnd_util.h" #endif namespace { // The thickness of the border when Aero is not enabled. In this case, the // shadow around the window will not be painted by the system and we need to // paint a frame in order to differentiate the client area from the background. const int kNonAeroBorderThickness = 1; // The height and width in pixels of the icon. const int kIconSize = 16; // The extra padding between the button and the top edge. const int kExtraPaddingBetweenButtonAndTop = 1; // Colors used to draw titlebar background under default theme. const SkColor kActiveBackgroundDefaultColor = SkColorSetRGB(0x3a, 0x3d, 0x3d); const SkColor kInactiveBackgroundDefaultColor = SkColorSetRGB(0x7a, 0x7c, 0x7c); const SkColor kAttentionBackgroundDefaultColor = SkColorSetRGB(0x53, 0xa9, 0x3f); // Color used to draw the minimized panel. const SkColor kMinimizeBackgroundDefaultColor = SkColorSetRGB(0xf5, 0xf4, 0xf0); // Color used to draw the title text under default theme. const SkColor kTitleTextDefaultColor = SkColorSetRGB(0xf9, 0xf9, 0xf9); gfx::ImageSkia* CreateImageForColor(SkColor color) { gfx::Canvas canvas(gfx::Size(1, 1), 1.0f, true); canvas.DrawColor(color); return new gfx::ImageSkia(canvas.ExtractImageRep()); } #if defined(OS_WIN) const gfx::ImageSkia& GetTopLeftCornerImage(panel::CornerStyle corner_style) { static gfx::ImageSkia* rounded_image = NULL; static gfx::ImageSkia* non_rounded_image = NULL; if (!rounded_image) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_TOP_LEFT_CORNER); non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_TOP_LEFT_CORNER); } return (corner_style & panel::TOP_ROUNDED) ? *rounded_image : *non_rounded_image; } const gfx::ImageSkia& GetTopRightCornerImage(panel::CornerStyle corner_style) { static gfx::ImageSkia* rounded_image = NULL; static gfx::ImageSkia* non_rounded_image = NULL; if (!rounded_image) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_TOP_RIGHT_CORNER); non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_TOP_RIGHT_CORNER); } return (corner_style & panel::TOP_ROUNDED) ? *rounded_image : *non_rounded_image; } const gfx::ImageSkia& GetBottomLeftCornerImage( panel::CornerStyle corner_style) { static gfx::ImageSkia* rounded_image = NULL; static gfx::ImageSkia* non_rounded_image = NULL; if (!rounded_image) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_BOTTOM_LEFT_CORNER); non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_BOTTOM_LEFT_CORNER); } return (corner_style & panel::BOTTOM_ROUNDED) ? *rounded_image : *non_rounded_image; } const gfx::ImageSkia& GetBottomRightCornerImage( panel::CornerStyle corner_style) { static gfx::ImageSkia* rounded_image = NULL; static gfx::ImageSkia* non_rounded_image = NULL; if (!rounded_image) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); rounded_image = rb.GetImageSkiaNamed(IDR_WINDOW_BOTTOM_RIGHT_CORNER); non_rounded_image = rb.GetImageSkiaNamed(IDR_PANEL_BOTTOM_RIGHT_CORNER); } return (corner_style & panel::BOTTOM_ROUNDED) ? *rounded_image : *non_rounded_image; } const gfx::ImageSkia& GetTopEdgeImage() { static gfx::ImageSkia* image = NULL; if (!image) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); image = rb.GetImageSkiaNamed(IDR_WINDOW_TOP_CENTER); } return *image; } const gfx::ImageSkia& GetBottomEdgeImage() { static gfx::ImageSkia* image = NULL; if (!image) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); image = rb.GetImageSkiaNamed(IDR_WINDOW_BOTTOM_CENTER); } return *image; } const gfx::ImageSkia& GetLeftEdgeImage() { static gfx::ImageSkia* image = NULL; if (!image) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); image = rb.GetImageSkiaNamed(IDR_WINDOW_LEFT_SIDE); } return *image; } const gfx::ImageSkia& GetRightEdgeImage() { static gfx::ImageSkia* image = NULL; if (!image) { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); image = rb.GetImageSkiaNamed(IDR_WINDOW_RIGHT_SIDE); } return *image; } #endif // defined(OS_WIN) const gfx::ImageSkia* GetActiveBackgroundDefaultImage() { static gfx::ImageSkia* image = NULL; if (!image) image = CreateImageForColor(kActiveBackgroundDefaultColor); return image; } const gfx::ImageSkia* GetInactiveBackgroundDefaultImage() { static gfx::ImageSkia* image = NULL; if (!image) image = CreateImageForColor(kInactiveBackgroundDefaultColor); return image; } const gfx::ImageSkia* GetAttentionBackgroundDefaultImage() { static gfx::ImageSkia* image = NULL; if (!image) image = CreateImageForColor(kAttentionBackgroundDefaultColor); return image; } const gfx::ImageSkia* GetMinimizeBackgroundDefaultImage() { static gfx::ImageSkia* image = NULL; if (!image) image = CreateImageForColor(kMinimizeBackgroundDefaultColor); return image; } int GetFrameEdgeHitTest(const gfx::Point& point, const gfx::Size& frame_size, int resize_area_size, panel::Resizability resizability) { int x = point.x(); int y = point.y(); int width = frame_size.width(); int height = frame_size.height(); if (x < resize_area_size) { if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP_LEFT)) { return HTTOPLEFT; } else if (y >= height - resize_area_size && (resizability & panel::RESIZABLE_BOTTOM_LEFT)) { return HTBOTTOMLEFT; } else if (resizability & panel::RESIZABLE_LEFT) { return HTLEFT; } } else if (x >= width - resize_area_size) { if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP_RIGHT)) { return HTTOPRIGHT; } else if (y >= height - resize_area_size && (resizability & panel::RESIZABLE_BOTTOM_RIGHT)) { return HTBOTTOMRIGHT; } else if (resizability & panel::RESIZABLE_RIGHT) { return HTRIGHT; } } if (y < resize_area_size && (resizability & panel::RESIZABLE_TOP)) { return HTTOP; } else if (y >= height - resize_area_size && (resizability & panel::RESIZABLE_BOTTOM)) { return HTBOTTOM; } return HTNOWHERE; } // Frameless is only supported when Aero is enabled and shadow effect is // present. bool ShouldRenderAsFrameless() { #if defined(OS_WIN) bool is_frameless = ui::win::IsAeroGlassEnabled(); if (is_frameless) { BOOL shadow_enabled = FALSE; if (::SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow_enabled, 0) && !shadow_enabled) is_frameless = false; } return is_frameless; #else return false; #endif } } // namespace // static const char PanelFrameView::kViewClassName[] = "PanelFrameView"; PanelFrameView::PanelFrameView(PanelView* panel_view) : is_frameless_(ShouldRenderAsFrameless()), panel_view_(panel_view), close_button_(NULL), minimize_button_(NULL), restore_button_(NULL), title_icon_(NULL), title_label_(NULL), corner_style_(panel::ALL_ROUNDED) { } PanelFrameView::~PanelFrameView() { } void PanelFrameView::Init() { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); close_button_ = new views::ImageButton(this); close_button_->SetImage(views::CustomButton::STATE_NORMAL, rb.GetImageSkiaNamed(IDR_PANEL_CLOSE)); close_button_->SetImage(views::CustomButton::STATE_HOVERED, rb.GetImageSkiaNamed(IDR_PANEL_CLOSE_H)); close_button_->SetImage(views::CustomButton::STATE_PRESSED, rb.GetImageSkiaNamed(IDR_PANEL_CLOSE_C)); close_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE); base::string16 tooltip_text = l10n_util::GetStringUTF16(IDS_PANEL_CLOSE_TOOLTIP); close_button_->SetTooltipText(tooltip_text); AddChildView(close_button_); minimize_button_ = new views::ImageButton(this); minimize_button_->SetImage(views::CustomButton::STATE_NORMAL, rb.GetImageSkiaNamed(IDR_PANEL_MINIMIZE)); minimize_button_->SetImage(views::CustomButton::STATE_HOVERED, rb.GetImageSkiaNamed(IDR_PANEL_MINIMIZE_H)); minimize_button_->SetImage(views::CustomButton::STATE_PRESSED, rb.GetImageSkiaNamed(IDR_PANEL_MINIMIZE_C)); tooltip_text = l10n_util::GetStringUTF16(IDS_PANEL_MINIMIZE_TOOLTIP); minimize_button_->SetTooltipText(tooltip_text); minimize_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE); AddChildView(minimize_button_); restore_button_ = new views::ImageButton(this); restore_button_->SetImage(views::CustomButton::STATE_NORMAL, rb.GetImageSkiaNamed(IDR_PANEL_RESTORE)); restore_button_->SetImage(views::CustomButton::STATE_HOVERED, rb.GetImageSkiaNamed(IDR_PANEL_RESTORE_H)); restore_button_->SetImage(views::CustomButton::STATE_PRESSED, rb.GetImageSkiaNamed(IDR_PANEL_RESTORE_C)); restore_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE); tooltip_text = l10n_util::GetStringUTF16(IDS_PANEL_RESTORE_TOOLTIP); restore_button_->SetTooltipText(tooltip_text); restore_button_->SetVisible(false); // only visible when panel is minimized AddChildView(restore_button_); title_icon_ = new TabIconView(this, NULL); title_icon_->set_is_light(true); AddChildView(title_icon_); title_icon_->Update(); title_label_ = new views::Label( panel_view_->panel()->GetWindowTitle(), rb.GetFontList(ui::ResourceBundle::BoldFont)); title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); title_label_->SetAutoColorReadabilityEnabled(false); AddChildView(title_label_); // Compute the thickness of the client area that needs to be counted towards // mouse resizing. // TODO(tdanderson): Remove this if possible (crbug.com/344924). int thickness_for_mouse_resizing = PanelView::kResizeInsideBoundsSize - BorderThickness(); aura::Window* window = panel_view_->GetNativePanelWindow(); window->set_hit_test_bounds_override_inner( gfx::Insets(thickness_for_mouse_resizing, thickness_for_mouse_resizing, thickness_for_mouse_resizing, thickness_for_mouse_resizing)); } void PanelFrameView::UpdateTitle() { UpdateWindowTitle(); } void PanelFrameView::UpdateIcon() { UpdateWindowIcon(); } void PanelFrameView::UpdateThrobber() { title_icon_->Update(); } void PanelFrameView::UpdateTitlebarMinimizeRestoreButtonVisibility() { Panel* panel = panel_view_->panel(); minimize_button_->SetVisible(panel->CanShowMinimizeButton()); restore_button_->SetVisible(panel->CanShowRestoreButton()); // Reset the button states in case that the hover states are not cleared when // mouse is clicked but not moved. minimize_button_->SetState(views::CustomButton::STATE_NORMAL); restore_button_->SetState(views::CustomButton::STATE_NORMAL); } void PanelFrameView::SetWindowCornerStyle(panel::CornerStyle corner_style) { corner_style_ = corner_style; #if defined(OS_WIN) // Changing the window region is going to force a paint. Only change the // window region if the region really differs. HWND native_window = views::HWNDForWidget(panel_view_->window()); base::win::ScopedRegion current_region(::CreateRectRgn(0, 0, 0, 0)); int current_region_result = ::GetWindowRgn(native_window, current_region); gfx::Path window_mask; GetWindowMask(size(), &window_mask); base::win::ScopedRegion new_region(gfx::CreateHRGNFromSkPath(window_mask)); if (current_region_result == ERROR || !::EqualRgn(current_region, new_region)) { // SetWindowRgn takes ownership of the new_region. ::SetWindowRgn(native_window, new_region.release(), TRUE); } #endif } gfx::Rect PanelFrameView::GetBoundsForClientView() const { // The origin of client-area bounds starts after left border and titlebar and // spans until hitting the right and bottom borders. // +------------------------------+ // | Top Titlebar | // |-+--------------------------+-| // |L| |R| // |e| |i| // |f| |g| // |t| |h| // | | Client |t| // | | | | // |B| Area |B| // |o| |o| // |r| |r| // |d| |d| // |e| |e| // |r| |r| // | +--------------------------+ | // | Bottom Border | // +------------------------------+ int titlebar_height = TitlebarHeight(); int border_thickness = BorderThickness(); return gfx::Rect(border_thickness, titlebar_height, std::max(0, width() - border_thickness * 2), std::max(0, height() - titlebar_height - border_thickness)); } gfx::Rect PanelFrameView::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const { int titlebar_height = TitlebarHeight(); int border_thickness = BorderThickness(); // The window bounds include both client area and non-client area (titlebar // and left, right and bottom borders). return gfx::Rect(client_bounds.x() - border_thickness, client_bounds.y() - titlebar_height, client_bounds.width() + border_thickness * 2, client_bounds.height() + titlebar_height + border_thickness); } int PanelFrameView::NonClientHitTest(const gfx::Point& point) { panel::Resizability resizability = panel_view_->panel()->CanResizeByMouse(); // Check the frame first, as we allow a small area overlapping the contents // to be used for resize handles. int frame_component = GetFrameEdgeHitTest( point, size(), PanelView::kResizeInsideBoundsSize, resizability); if (frame_component != HTNOWHERE) return frame_component; int client_component = panel_view_->window()->client_view()->NonClientHitTest(point); if (client_component != HTNOWHERE) return client_component; if (close_button_ && close_button_->visible() && close_button_->GetMirroredBounds().Contains(point)) return HTCLOSE; if (minimize_button_ && minimize_button_->visible() && minimize_button_->GetMirroredBounds().Contains(point)) return HTMINBUTTON; if (restore_button_ && restore_button_->visible() && restore_button_->GetMirroredBounds().Contains(point)) return HTMAXBUTTON; return HTNOWHERE; } void PanelFrameView::GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) { int width = size.width(); int height = size.height(); if (corner_style_ & panel::TOP_ROUNDED) { window_mask->moveTo(0, 3); window_mask->lineTo(1, 2); window_mask->lineTo(1, 1); window_mask->lineTo(2, 1); window_mask->lineTo(3, 0); window_mask->lineTo(SkIntToScalar(width - 3), 0); window_mask->lineTo(SkIntToScalar(width - 2), 1); window_mask->lineTo(SkIntToScalar(width - 1), 1); window_mask->lineTo(SkIntToScalar(width - 1), 2); window_mask->lineTo(SkIntToScalar(width - 1), 3); } else { window_mask->moveTo(0, 0); window_mask->lineTo(width, 0); } if (corner_style_ & panel::BOTTOM_ROUNDED) { window_mask->lineTo(SkIntToScalar(width - 1), SkIntToScalar(height - 4)); window_mask->lineTo(SkIntToScalar(width - 2), SkIntToScalar(height - 3)); window_mask->lineTo(SkIntToScalar(width - 2), SkIntToScalar(height - 2)); window_mask->lineTo(SkIntToScalar(width - 3), SkIntToScalar(height - 2)); window_mask->lineTo(SkIntToScalar(width - 4), SkIntToScalar(height - 1)); window_mask->lineTo(3, SkIntToScalar(height - 1)); window_mask->lineTo(2, SkIntToScalar(height - 2)); window_mask->lineTo(1, SkIntToScalar(height - 2)); window_mask->lineTo(1, SkIntToScalar(height - 3)); window_mask->lineTo(0, SkIntToScalar(height - 4)); } else { window_mask->lineTo(SkIntToScalar(width), SkIntToScalar(height)); window_mask->lineTo(0, SkIntToScalar(height)); } window_mask->close(); } void PanelFrameView::ResetWindowControls() { // The controls aren't affected by this constraint. } void PanelFrameView::UpdateWindowIcon() { title_icon_->SchedulePaint(); } void PanelFrameView::UpdateWindowTitle() { title_label_->SetText(panel_view_->panel()->GetWindowTitle()); } gfx::Size PanelFrameView::GetPreferredSize() const { gfx::Size pref_size = panel_view_->window()->client_view()->GetPreferredSize(); gfx::Rect bounds(0, 0, pref_size.width(), pref_size.height()); return panel_view_->window()->non_client_view()-> GetWindowBoundsForClientBounds(bounds).size(); } const char* PanelFrameView::GetClassName() const { return kViewClassName; } gfx::Size PanelFrameView::GetMinimumSize() const { return panel_view_->GetMinimumSize(); } gfx::Size PanelFrameView::GetMaximumSize() const { return panel_view_->GetMaximumSize(); } void PanelFrameView::Layout() { is_frameless_ = ShouldRenderAsFrameless(); // Layout the close button. int right = width(); close_button_->SetBounds( width() - panel::kTitlebarRightPadding - panel::kPanelButtonSize, (TitlebarHeight() - panel::kPanelButtonSize) / 2 + kExtraPaddingBetweenButtonAndTop, panel::kPanelButtonSize, panel::kPanelButtonSize); right = close_button_->x(); // Layout the minimize and restore button. Both occupy the same space, // but at most one is visible at any time. minimize_button_->SetBounds( right - panel::kButtonPadding - panel::kPanelButtonSize, (TitlebarHeight() - panel::kPanelButtonSize) / 2 + kExtraPaddingBetweenButtonAndTop, panel::kPanelButtonSize, panel::kPanelButtonSize); restore_button_->SetBoundsRect(minimize_button_->bounds()); right = minimize_button_->x(); // Layout the icon. int icon_y = (TitlebarHeight() - kIconSize) / 2; title_icon_->SetBounds( panel::kTitlebarLeftPadding, icon_y, kIconSize, kIconSize); // Layout the title. int title_x = title_icon_->bounds().right() + panel::kIconAndTitlePadding; int title_height = title_label_->font_list().GetHeight(); title_label_->SetBounds( title_x, icon_y + ((kIconSize - title_height - 1) / 2), std::max(0, right - panel::kTitleAndButtonPadding - title_x), title_height); } void PanelFrameView::OnPaint(gfx::Canvas* canvas) { UpdateControlStyles(GetPaintState()); PaintFrameBackground(canvas); PaintFrameEdge(canvas); } bool PanelFrameView::OnMousePressed(const ui::MouseEvent& event) { if (event.IsOnlyLeftMouseButton()) { // |event.location| is in the view's coordinate system. Convert it to the // screen coordinate system. gfx::Point mouse_location = event.location(); views::View::ConvertPointToScreen(this, &mouse_location); // If the mouse location falls within the resizing area of the titlebar, // do not handle the event so that the system resizing logic could kick in. if (!panel_view_->IsWithinResizingArea(mouse_location) && panel_view_->OnTitlebarMousePressed(mouse_location)) return true; } return NonClientFrameView::OnMousePressed(event); } bool PanelFrameView::OnMouseDragged(const ui::MouseEvent& event) { #if defined(OS_LINUX) && !defined(OS_CHROMEOS) // Converting the mouse location to screen coordinates returns an incorrect // location while the panel is moving. See crbug.com/353393 for more details. // TODO(pkotwicz): Fix conversion to screen coordinates gfx::Screen* screen = gfx::Screen::GetNativeScreen(); gfx::Point mouse_location = screen->GetCursorScreenPoint(); #else // |event.location| is in the view's coordinate system. Convert it to the // screen coordinate system. gfx::Point mouse_location = event.location(); views::View::ConvertPointToScreen(this, &mouse_location); #endif if (panel_view_->OnTitlebarMouseDragged(mouse_location)) return true; return NonClientFrameView::OnMouseDragged(event); } void PanelFrameView::OnMouseReleased(const ui::MouseEvent& event) { if (panel_view_->OnTitlebarMouseReleased( event.IsControlDown() ? panel::APPLY_TO_ALL : panel::NO_MODIFIER)) return; NonClientFrameView::OnMouseReleased(event); } void PanelFrameView::OnMouseCaptureLost() { if (panel_view_->OnTitlebarMouseCaptureLost()) return; NonClientFrameView::OnMouseCaptureLost(); } void PanelFrameView::ButtonPressed(views::Button* sender, const ui::Event& event) { if (sender == close_button_) { panel_view_->ClosePanel(); } else { panel::ClickModifier modifier = event.IsControlDown() ? panel::APPLY_TO_ALL : panel::NO_MODIFIER; if (sender == minimize_button_) panel_view_->panel()->OnMinimizeButtonClicked(modifier); else if (sender == restore_button_) panel_view_->panel()->OnRestoreButtonClicked(modifier); } } bool PanelFrameView::ShouldTabIconViewAnimate() const { // This function is queried during the creation of the window as the // TabIconView we host is initialized, so we need to NULL check the selected // WebContents because in this condition there is not yet a selected tab. content::WebContents* contents = panel_view_->panel()->GetWebContents(); return contents ? contents->IsLoading() : false; } gfx::ImageSkia PanelFrameView::GetFaviconForTabIconView() { return panel_view_->window()->widget_delegate()->GetWindowIcon(); } gfx::Size PanelFrameView::NonClientAreaSize() const { if (is_frameless_) return gfx::Size(0, TitlebarHeight()); // When the frame is present, the width of non-client area consists of // left and right borders, while the height consists of the top area // (titlebar) and the bottom border. return gfx::Size(2 * kNonAeroBorderThickness, TitlebarHeight() + kNonAeroBorderThickness); } int PanelFrameView::TitlebarHeight() const { return panel::kTitlebarHeight; } int PanelFrameView::BorderThickness() const { return is_frameless_ ? 0 : kNonAeroBorderThickness; } PanelFrameView::PaintState PanelFrameView::GetPaintState() const { if (panel_view_->panel()->IsDrawingAttention()) return PAINT_FOR_ATTENTION; if (bounds().height() <= panel::kMinimizedPanelHeight) return PAINT_AS_MINIMIZED; if (panel_view_->IsPanelActive() && !panel_view_->force_to_paint_as_inactive()) return PAINT_AS_ACTIVE; return PAINT_AS_INACTIVE; } SkColor PanelFrameView::GetTitleColor(PaintState paint_state) const { return kTitleTextDefaultColor; } const gfx::ImageSkia* PanelFrameView::GetFrameBackground( PaintState paint_state) const { switch (paint_state) { case PAINT_AS_INACTIVE: return GetInactiveBackgroundDefaultImage(); case PAINT_AS_ACTIVE: return GetActiveBackgroundDefaultImage(); case PAINT_AS_MINIMIZED: return GetMinimizeBackgroundDefaultImage(); case PAINT_FOR_ATTENTION: return GetAttentionBackgroundDefaultImage(); default: NOTREACHED(); return GetInactiveBackgroundDefaultImage(); } } void PanelFrameView::UpdateControlStyles(PaintState paint_state) { title_label_->SetEnabledColor(GetTitleColor(paint_state)); } void PanelFrameView::PaintFrameBackground(gfx::Canvas* canvas) { // We only need to paint the title-bar since no resizing border is shown. // Instead, we allow part of the inner content area be used to trigger the // mouse resizing. int titlebar_height = TitlebarHeight(); const gfx::ImageSkia* image = GetFrameBackground(GetPaintState()); canvas->TileImageInt(*image, 0, 0, width(), titlebar_height); if (is_frameless_) return; // Left border, below title-bar. canvas->TileImageInt(*image, 0, titlebar_height, kNonAeroBorderThickness, height() - titlebar_height); // Right border, below title-bar. canvas->TileImageInt(*image, width() - kNonAeroBorderThickness, titlebar_height, kNonAeroBorderThickness, height() - titlebar_height); // Bottom border. canvas->TileImageInt(*image, 0, height() - kNonAeroBorderThickness, width(), kNonAeroBorderThickness); } void PanelFrameView::PaintFrameEdge(gfx::Canvas* canvas) { #if defined(OS_WIN) // Border is not needed when panel is not shown as minimized. if (GetPaintState() != PAINT_AS_MINIMIZED) return; const gfx::ImageSkia& top_left_image = GetTopLeftCornerImage(corner_style_); const gfx::ImageSkia& top_right_image = GetTopRightCornerImage(corner_style_); const gfx::ImageSkia& bottom_left_image = GetBottomLeftCornerImage(corner_style_); const gfx::ImageSkia& bottom_right_image = GetBottomRightCornerImage(corner_style_); const gfx::ImageSkia& top_image = GetTopEdgeImage(); const gfx::ImageSkia& bottom_image = GetBottomEdgeImage(); const gfx::ImageSkia& left_image = GetLeftEdgeImage(); const gfx::ImageSkia& right_image = GetRightEdgeImage(); // Draw the top border. canvas->DrawImageInt(top_left_image, 0, 0); canvas->TileImageInt(top_image, top_left_image.width(), 0, width() - top_right_image.width(), top_image.height()); canvas->DrawImageInt(top_right_image, width() - top_right_image.width(), 0); // Draw the right border. canvas->TileImageInt(right_image, width() - right_image.width(), top_right_image.height(), right_image.width(), height() - top_right_image.height() - bottom_right_image.height()); // Draw the bottom border. canvas->DrawImageInt(bottom_right_image, width() - bottom_right_image.width(), height() - bottom_right_image.height()); canvas->TileImageInt(bottom_image, bottom_left_image.width(), height() - bottom_image.height(), width() - bottom_left_image.width() - bottom_right_image.width(), bottom_image.height()); canvas->DrawImageInt(bottom_left_image, 0, height() - bottom_left_image.height()); // Draw the left border. canvas->TileImageInt(left_image, 0, top_left_image.height(), left_image.width(), height() - top_left_image.height() - bottom_left_image.height()); #endif }