172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/app_panel_browser_frame_view.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/compiler_specific.h"
83f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/utf_string_conversions.h"
972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/browser_frame.h"
1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/browser_view.h"
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_resources.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/font.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/path.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/controls/button/image_button.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window_resources.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX)
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/hit_test.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The frame border is only visible in restored mode and is hardcoded to 1 px on
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// each side regardless of the system window border size.
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kFrameBorderThickness = 1;
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// In the window corners, the resize areas don't actually expand bigger, but the
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 16 px at the end of each edge triggers diagonal resizing.
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kResizeAreaCornerSize = 16;
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The titlebar never shrinks too short to show the caption button plus some
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// padding below it.
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kCaptionButtonHeightWithPadding = 27;
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The titlebar has a 2 px 3D edge along the bottom, and we reserve 2 px (1 for
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// border, 1 for padding) along the top.
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTitlebarTopAndBottomEdgeThickness = 2;
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The icon is inset 6 px from the left frame border.
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kIconLeftSpacing = 6;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The icon never shrinks below 16 px on a side.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kIconMinimumSize = 16;
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There is a 4 px gap between the icon and the title text.
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kIconTitleSpacing = 4;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There is a 5 px gap between the title text and the close button.
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTitleCloseButtonSpacing = 5;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There is a 4 px gap between the close button and the frame border.
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kCloseButtonFrameBorderSpacing = 4;
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, public:
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAppPanelBrowserFrameView::AppPanelBrowserFrameView(BrowserFrame* frame,
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                   BrowserView* browser_view)
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : BrowserNonClientFrameView(),
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ALLOW_THIS_IN_INITIALIZER_LIST(
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          close_button_(new views::ImageButton(this))),
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      window_icon_(NULL),
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      frame_(frame),
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_view_(browser_view) {
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(browser_view->ShouldShowWindowIcon());
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(browser_view->ShouldShowWindowTitle());
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  close_button_->SetImage(views::CustomButton::BS_NORMAL,
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          rb.GetBitmapNamed(IDR_CLOSE_BAR));
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  close_button_->SetImage(views::CustomButton::BS_HOT,
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          rb.GetBitmapNamed(IDR_CLOSE_BAR_H));
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  close_button_->SetImage(views::CustomButton::BS_PUSHED,
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  close_button_->SetAccessibleName(
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE));
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddChildView(close_button_);
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_icon_ = new TabIconView(this);
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_icon_->set_is_light(true);
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddChildView(window_icon_);
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_icon_->Update();
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAppPanelBrowserFrameView::~AppPanelBrowserFrameView() {
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, BrowserNonClientFrameView implementation:
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AppPanelBrowserFrameView::GetBoundsForTabStrip(
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    views::View* tabstrip) const {
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // App panels never show a tab strip.
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTREACHED();
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Rect();
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint AppPanelBrowserFrameView::GetHorizontalTabStripVerticalOffset(
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool restored) const {
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // App panels are not themed and don't need this.
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return 0;
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::UpdateThrobber(bool running) {
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_icon_->Update();
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size AppPanelBrowserFrameView::GetMinimumSize() {
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size min_size(browser_view_->GetMinimumSize());
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int border_thickness = NonClientBorderThickness();
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  min_size.Enlarge(2 * border_thickness,
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NonClientTopBorderHeight() + border_thickness);
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  min_size.set_width(std::max(min_size.width(),
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (2 * FrameBorderThickness()) + kIconLeftSpacing + IconSize() +
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kTitleCloseButtonSpacing + kCloseButtonFrameBorderSpacing));
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return min_size;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, views::NonClientFrameView implementation:
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AppPanelBrowserFrameView::GetBoundsForClientView() const {
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return client_view_bounds_;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AppPanelBrowserFrameView::AlwaysUseCustomFrame() const {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AppPanelBrowserFrameView::AlwaysUseNativeFrame() const {
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return frame_->AlwaysUseNativeFrame();
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AppPanelBrowserFrameView::GetWindowBoundsForClientBounds(
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gfx::Rect& client_bounds) const {
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int top_height = NonClientTopBorderHeight();
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int border_thickness = NonClientBorderThickness();
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Rect(std::max(0, client_bounds.x() - border_thickness),
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   std::max(0, client_bounds.y() - top_height),
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   client_bounds.width() + (2 * border_thickness),
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   client_bounds.height() + top_height + border_thickness);
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::NonClientHitTest(const gfx::Point& point) {
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!bounds().Contains(point))
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return HTNOWHERE;
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int frame_component =
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      frame_->GetWindow()->client_view()->NonClientHitTest(point);
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // See if we're in the sysmenu region.  (We check the ClientView first to be
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // consistent with OpaqueBrowserFrameView; it's not really necessary here.)
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect sysmenu_rect(IconBounds());
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // In maximized mode we extend the rect to the screen corner to take advantage
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // of Fitts' Law.
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (frame_->GetWindow()->IsMaximized())
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sysmenu_rect.SetRect(0, 0, sysmenu_rect.right(), sysmenu_rect.bottom());
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  sysmenu_rect.set_x(GetMirroredXForRect(sysmenu_rect));
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sysmenu_rect.Contains(point))
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return (frame_component == HTCLIENT) ? HTCLIENT : HTSYSMENU;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (frame_component != HTNOWHERE)
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return frame_component;
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Then see if the point is within any of the window controls.
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (close_button_->IsVisible() &&
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      close_button_->GetMirroredBounds().Contains(point))
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return HTCLOSE;
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int window_component = GetHTComponentForFrame(point,
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NonClientBorderThickness(), NonClientBorderThickness(),
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kResizeAreaCornerSize, kResizeAreaCornerSize,
174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      frame_->GetWindow()->window_delegate()->CanResize());
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Fall back to the caption if no other component matches.
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (window_component == HTNOWHERE) ? HTCAPTION : window_component;
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::GetWindowMask(const gfx::Size& size,
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             gfx::Path* window_mask) {
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(window_mask);
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (frame_->GetWindow()->IsMaximized())
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Redefine the window visible region for the new size.
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->moveTo(0, 3);
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(1, 2);
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(1, 1);
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(2, 1);
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(3, 0);
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(SkIntToScalar(size.width() - 3), 0);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(SkIntToScalar(size.width() - 2), 1);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(SkIntToScalar(size.width() - 1), 1);
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(SkIntToScalar(size.width() - 1), 2);
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(SkIntToScalar(size.width()), 3);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(SkIntToScalar(size.width()),
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      SkIntToScalar(size.height()));
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->lineTo(0, SkIntToScalar(size.height()));
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_mask->close();
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::EnableClose(bool enable) {
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  close_button_->SetEnabled(enable);
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::ResetWindowControls() {
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The close button isn't affected by this constraint.
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AppPanelBrowserFrameView::UpdateWindowIcon() {
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  window_icon_->SchedulePaint();
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, views::View overrides:
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AppPanelBrowserFrameView::OnPaint(gfx::Canvas* canvas) {
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  views::Window* window = frame_->GetWindow();
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (window->IsMaximized())
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PaintMaximizedFrameBorder(canvas);
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PaintRestoredFrameBorder(canvas);
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PaintTitleBar(canvas);
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!window->IsMaximized())
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PaintRestoredClientEdge(canvas);
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::Layout() {
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LayoutWindowControls();
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LayoutTitleBar();
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  client_view_bounds_ = CalculateClientAreaBounds(width(), height());
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, views::ButtonListener implementation:
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::ButtonPressed(views::Button* sender,
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             const views::Event& event) {
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sender == close_button_)
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    frame_->GetWindow()->CloseWindow();
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, TabIconView::TabContentsProvider implementation:
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AppPanelBrowserFrameView::ShouldTabIconViewAnimate() const {
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This function is queried during the creation of the window as the
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabIconView we host is initialized, so we need to NULL check the selected
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabContents because in this condition there is not yet a selected tab.
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* current_tab = browser_view_->GetSelectedTabContents();
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return current_tab ? current_tab->is_loading() : false;
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSkBitmap AppPanelBrowserFrameView::GetFaviconForTabIconView() {
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return frame_->GetWindow()->window_delegate()->GetWindowIcon();
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AppPanelBrowserFrameView, private:
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::FrameBorderThickness() const {
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return frame_->GetWindow()->IsMaximized() ? 0 : kFrameBorderThickness;
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::NonClientBorderThickness() const {
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FrameBorderThickness() +
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (frame_->GetWindow()->IsMaximized() ? 0 : kClientEdgeThickness);
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::NonClientTopBorderHeight() const {
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return std::max(FrameBorderThickness() + IconSize(),
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  FrameBorderThickness() + kCaptionButtonHeightWithPadding) +
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      TitlebarBottomThickness();
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::TitlebarBottomThickness() const {
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return kTitlebarTopAndBottomEdgeThickness +
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (frame_->GetWindow()->IsMaximized() ? 0 : kClientEdgeThickness);
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppPanelBrowserFrameView::IconSize() const {
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This metric scales up if either the titlebar height or the titlebar font
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // size are increased.
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GetSystemMetrics(SM_CYSMICON);
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return std::max(BrowserFrame::GetTitleFont().height(), kIconMinimumSize);
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AppPanelBrowserFrameView::IconBounds() const {
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int size = IconSize();
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int frame_thickness = FrameBorderThickness();
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Our frame border has a different "3D look" than Windows'.  Theirs has a
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // more complex gradient on the top that they push their icon/title below;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // then the maximized window cuts this off and the icon/title are centered
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in the remaining space.  Because the apparent shape of our border is
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // simpler, using the same positioning makes things look slightly uncentered
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // with restored windows, so when the window is restored, instead of
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // calculating the remaining space from below the frame border, we calculate
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // from below the top border-plus-padding.
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int unavailable_px_at_top = frame_->GetWindow()->IsMaximized() ?
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      frame_thickness : kTitlebarTopAndBottomEdgeThickness;
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When the icon is shorter than the minimum space we reserve for the caption
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // button, we vertically center it.  We want to bias rounding to put extra
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // space above the icon, since the 3D edge (+ client edge, for restored
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // windows) below looks (to the eye) more like additional space than does the
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // border + padding (or nothing at all, for maximized windows) above; hence
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the +1.
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int y = unavailable_px_at_top + (NonClientTopBorderHeight() -
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      unavailable_px_at_top - size - TitlebarBottomThickness() + 1) / 2;
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Rect(frame_thickness + kIconLeftSpacing, y, size, size);
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) {
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* top_left_corner = rb.GetBitmapNamed(IDR_WINDOW_TOP_LEFT_CORNER);
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* top_right_corner =
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rb.GetBitmapNamed(IDR_WINDOW_TOP_RIGHT_CORNER);
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* top_edge = rb.GetBitmapNamed(IDR_WINDOW_TOP_CENTER);
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* right_edge = rb.GetBitmapNamed(IDR_WINDOW_RIGHT_SIDE);
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* left_edge = rb.GetBitmapNamed(IDR_WINDOW_LEFT_SIDE);
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* bottom_left_corner =
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rb.GetBitmapNamed(IDR_WINDOW_BOTTOM_LEFT_CORNER);
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* bottom_right_corner =
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rb.GetBitmapNamed(IDR_WINDOW_BOTTOM_RIGHT_CORNER);
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* bottom_edge = rb.GetBitmapNamed(IDR_WINDOW_BOTTOM_CENTER);
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Window frame mode and color.
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* theme_frame;
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkColor frame_color;
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ShouldPaintAsActive()) {
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    theme_frame = rb.GetBitmapNamed(IDR_FRAME_APP_PANEL);
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    frame_color = ResourceBundle::frame_color_app_panel;
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    theme_frame = rb.GetBitmapNamed(IDR_FRAME_APP_PANEL);  // TODO
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    frame_color = ResourceBundle::frame_color_app_panel_inactive;
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Fill with the frame color first so we have a constant background for
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // areas not covered by the theme image.
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->FillRectInt(frame_color, 0, 0, width(), theme_frame->height());
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now fill down the sides.
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->FillRectInt(frame_color, 0, theme_frame->height(), left_edge->width(),
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      height() - theme_frame->height());
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->FillRectInt(frame_color, width() - right_edge->width(),
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      theme_frame->height(), right_edge->width(),
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      height() - theme_frame->height());
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now fill the bottom area.
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->FillRectInt(frame_color, left_edge->width(),
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      height() - bottom_edge->height(),
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      width() - left_edge->width() - right_edge->width(),
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      bottom_edge->height());
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw the theme frame.
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*theme_frame, 0, 0, width(), theme_frame->height());
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Top.
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*top_left_corner, 0, 0);
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*top_edge, top_left_corner->width(), 0,
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       width() - top_right_corner->width(), top_edge->height());
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*top_right_corner,
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        width() - top_right_corner->width(), 0);
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Right.
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*right_edge, width() - right_edge->width(),
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      top_right_corner->height(), right_edge->width(),
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      height() - top_right_corner->height() - bottom_right_corner->height());
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Bottom.
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*bottom_right_corner,
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        width() - bottom_right_corner->width(),
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        height() - bottom_right_corner->height());
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*bottom_edge, bottom_left_corner->width(),
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      height() - bottom_edge->height(),
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      width() - bottom_left_corner->width() - bottom_right_corner->width(),
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bottom_edge->height());
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*bottom_left_corner, 0,
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        height() - bottom_left_corner->height());
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Left.
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*left_edge, 0, top_left_corner->height(),
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      left_edge->width(),
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      height() - top_left_corner->height() - bottom_left_corner->height());
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::PaintMaximizedFrameBorder(gfx::Canvas* canvas) {
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* frame_image = rb.GetBitmapNamed(IDR_FRAME_APP_PANEL);
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*frame_image, 0, FrameBorderThickness(), width(),
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       frame_image->height());
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The bottom of the titlebar actually comes from the top of the Client Edge
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // graphic, with the actual client edge clipped off the bottom.
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* titlebar_bottom = rb.GetBitmapNamed(IDR_APP_TOP_CENTER);
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int edge_height = titlebar_bottom->height() - kClientEdgeThickness;
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*titlebar_bottom, 0,
404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       frame_->GetWindow()->client_view()->y() - edge_height,
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       width(), edge_height);
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::PaintTitleBar(gfx::Canvas* canvas) {
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The window icon is painted by the TabIconView.
410dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  views::WindowDelegate* d = frame_->GetWindow()->window_delegate();
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawStringInt(d->GetWindowTitle(), BrowserFrame::GetTitleFont(),
41272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      SK_ColorBLACK, GetMirroredXForRect(title_bounds_), title_bounds_.y(),
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      title_bounds_.width(), title_bounds_.height());
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) {
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height());
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int client_area_top = client_area_bounds.y();
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* top_left = rb.GetBitmapNamed(IDR_APP_TOP_LEFT);
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* top = rb.GetBitmapNamed(IDR_APP_TOP_CENTER);
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* top_right = rb.GetBitmapNamed(IDR_APP_TOP_RIGHT);
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* right = rb.GetBitmapNamed(IDR_CONTENT_RIGHT_SIDE);
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* bottom_right =
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rb.GetBitmapNamed(IDR_CONTENT_BOTTOM_RIGHT_CORNER);
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* bottom = rb.GetBitmapNamed(IDR_CONTENT_BOTTOM_CENTER);
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* bottom_left =
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rb.GetBitmapNamed(IDR_CONTENT_BOTTOM_LEFT_CORNER);
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* left = rb.GetBitmapNamed(IDR_CONTENT_LEFT_SIDE);
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Top.
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int top_edge_y = client_area_top - top->height();
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*top_left, client_area_bounds.x() - top_left->width(),
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        top_edge_y);
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*top, client_area_bounds.x(), top_edge_y,
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       client_area_bounds.width(), top->height());
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*top_right, client_area_bounds.right(), top_edge_y);
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Right.
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int client_area_bottom =
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::max(client_area_top, client_area_bounds.bottom());
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int client_area_height = client_area_bottom - client_area_top;
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*right, client_area_bounds.right(), client_area_top,
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       right->width(), client_area_height);
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Bottom.
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*bottom_right, client_area_bounds.right(),
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        client_area_bottom);
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*bottom, client_area_bounds.x(), client_area_bottom,
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       client_area_bounds.width(), bottom_right->height());
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawBitmapInt(*bottom_left,
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_area_bounds.x() - bottom_left->width(), client_area_bottom);
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Left.
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->TileImageInt(*left, client_area_bounds.x() - left->width(),
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_area_top, left->width(), client_area_height);
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Draw the toolbar color to fill in the edges.
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  canvas->DrawRectInt(ResourceBundle::toolbar_color,
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_area_bounds.x() - kClientEdgeThickness,
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_area_top - kClientEdgeThickness,
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_area_bounds.width() + kClientEdgeThickness,
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      client_area_bottom - client_area_top + kClientEdgeThickness);
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::LayoutWindowControls() {
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  close_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT,
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   views::ImageButton::ALIGN_BOTTOM);
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool is_maximized = frame_->GetWindow()->IsMaximized();
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // There should always be the same number of non-border pixels visible to the
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // side of the close button.  In maximized mode we extend the button to the
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // screen corner to obey Fitts' Law.
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int right_extra_width = is_maximized ? kCloseButtonFrameBorderSpacing : 0;
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size close_button_size = close_button_->GetPreferredSize();
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int close_button_y =
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (NonClientTopBorderHeight() - close_button_size.height()) / 2;
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int top_extra_height = is_maximized ? close_button_y : 0;
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  close_button_->SetBounds(width() - FrameBorderThickness() -
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kCloseButtonFrameBorderSpacing - close_button_size.width(),
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      close_button_y - top_extra_height,
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      close_button_size.width() + right_extra_width,
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      close_button_size.height() + top_extra_height);
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppPanelBrowserFrameView::LayoutTitleBar() {
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Size the icon first; the window title is based on the icon position.
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect icon_bounds(IconBounds());
48972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  window_icon_->SetBoundsRect(icon_bounds);
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Size the title.
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int title_x = icon_bounds.right() + kIconTitleSpacing;
4933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int title_height = BrowserFrame::GetTitleFont().GetHeight();
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We bias the title position so that when the difference between the icon
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // and title heights is odd, the extra pixel of the title is above the
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // vertical midline rather than below.  This compensates for how the icon is
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // already biased downwards (see IconBounds()) and helps prevent descenders
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // on the title from overlapping the 3D edge at the bottom of the titlebar.
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  title_bounds_.SetRect(title_x,
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      icon_bounds.y() + ((icon_bounds.height() - title_height - 1) / 2),
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::max(0, close_button_->x() - kTitleCloseButtonSpacing - title_x),
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      title_height);
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AppPanelBrowserFrameView::CalculateClientAreaBounds(int width,
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int height) const {
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int top_height = NonClientTopBorderHeight();
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int border_thickness = NonClientBorderThickness();
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return gfx::Rect(border_thickness, top_height,
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   std::max(0, width - (2 * border_thickness)),
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   std::max(0, height - top_height - border_thickness));
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
513