| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/ui/panels/panel_browser_frame_view.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/utf_string_conversions.h" | |
| 10 #include "chrome/browser/themes/theme_service.h" | |
| 11 #include "chrome/browser/themes/theme_service_factory.h" | |
| 12 #include "chrome/browser/ui/panels/panel.h" | |
| 13 #include "chrome/browser/ui/panels/panel_browser_view.h" | |
| 14 #include "chrome/browser/ui/panels/panel_manager.h" | |
| 15 #include "chrome/browser/ui/panels/panel_strip.h" | |
| 16 #include "chrome/browser/ui/views/tab_icon_view.h" | |
| 17 #include "chrome/common/extensions/extension.h" | |
| 18 #include "content/public/browser/web_contents.h" | |
| 19 #include "grit/generated_resources.h" | |
| 20 #include "grit/theme_resources.h" | |
| 21 #include "grit/ui_resources.h" | |
| 22 #include "ui/base/accessibility/accessible_view_state.h" | |
| 23 #include "ui/base/hit_test.h" | |
| 24 #include "ui/base/l10n/l10n_util.h" | |
| 25 #include "ui/base/resource/resource_bundle.h" | |
| 26 #include "ui/gfx/canvas.h" | |
| 27 #include "ui/gfx/path.h" | |
| 28 #include "ui/gfx/screen.h" | |
| 29 #include "ui/views/controls/button/image_button.h" | |
| 30 #include "ui/views/controls/label.h" | |
| 31 #include "ui/views/widget/widget_delegate.h" | |
| 32 | |
| 33 #if defined(USE_AURA) && defined(USE_X11) | |
| 34 #include "ui/base/x/x11_util.h" | |
| 35 #endif | |
| 36 | |
| 37 using content::WebContents; | |
| 38 | |
| 39 namespace { | |
| 40 | |
| 41 // The thickness in pixels of the border. | |
| 42 #if defined(USE_AURA) | |
| 43 // No border inside the window frame; see comment in PaintFrameBorder(). | |
| 44 const int kResizableBorderThickness = 0; | |
| 45 const int kNonResizableBorderThickness = 0; | |
| 46 #else | |
| 47 const int kResizableBorderThickness = 4; | |
| 48 const int kNonResizableBorderThickness = 1; | |
| 49 #endif | |
| 50 | |
| 51 // In the window corners, the resize areas don't actually expand bigger, but the | |
| 52 // 16 px at the end of each edge triggers diagonal resizing. | |
| 53 const int kResizeAreaCornerSize = 16; | |
| 54 | |
| 55 // Colors used to draw client edges. These are experimental values. | |
| 56 const SkColor kClientEdgeColor = SkColorSetRGB(210, 225, 246); | |
| 57 const SkColor kContentsBorderShadow = SkColorSetARGB(51, 0, 0, 0); | |
| 58 | |
| 59 // The spacing in pixels between the icon and the left border. | |
| 60 const int kIconAndBorderSpacing = 4; | |
| 61 | |
| 62 // The height and width in pixels of the icon. | |
| 63 const int kIconSize = 16; | |
| 64 | |
| 65 // The font to use to draw the title. | |
| 66 const char* kTitleFontName = "Arial"; | |
| 67 const int kTitleFontSize = 14; | |
| 68 | |
| 69 // The spacing in pixels between the title and the icon on the left, or the | |
| 70 // button on the right. | |
| 71 const int kTitleSpacing = 11; | |
| 72 | |
| 73 // The spacing in pixels between the close button and the right border. | |
| 74 const int kCloseButtonAndBorderSpacing = 11; | |
| 75 | |
| 76 // The spacing in pixels between the close button and the minimize/restore | |
| 77 // button. | |
| 78 const int kMinimizeButtonAndCloseButtonSpacing = 5; | |
| 79 | |
| 80 // Colors used to draw titlebar background under default theme. | |
| 81 const SkColor kActiveBackgroundDefaultColor = SkColorSetRGB(0x3a, 0x3d, 0x3d); | |
| 82 const SkColor kInactiveBackgroundDefaultColor = SkColorSetRGB(0x7a, 0x7c, 0x7c); | |
| 83 const SkColor kAttentionBackgroundDefaultColor = | |
| 84 SkColorSetRGB(0xff, 0xab, 0x57); | |
| 85 | |
| 86 // Color used to draw the minimized panel. | |
| 87 const SkColor kMinimizeBackgroundDefaultColor = SkColorSetRGB(0xf5, 0xf4, 0xf0); | |
| 88 const SkColor kMinimizeBorderDefaultColor = SkColorSetRGB(0xc9, 0xc9, 0xc9); | |
| 89 | |
| 90 // Color used to draw the title text under default theme. | |
| 91 const SkColor kTitleTextDefaultColor = SkColorSetRGB(0xf9, 0xf9, 0xf9); | |
| 92 | |
| 93 // Color used to draw the divider line between the titlebar and the client area. | |
| 94 #if defined(USE_AURA) | |
| 95 const SkColor kDividerColor = SkColorSetRGB(0xb5, 0xb5, 0xb5); | |
| 96 #else | |
| 97 const SkColor kDividerColor = SkColorSetRGB(0x2a, 0x2c, 0x2c); | |
| 98 #endif | |
| 99 | |
| 100 struct ButtonResources { | |
| 101 gfx::ImageSkia* normal_image; | |
| 102 gfx::ImageSkia* hover_image; | |
| 103 gfx::ImageSkia* push_image; | |
| 104 string16 tooltip_text; | |
| 105 | |
| 106 ButtonResources(int normal_image_id, int hover_image_id, int push_image_id, | |
| 107 int tooltip_id) | |
| 108 : normal_image(NULL), | |
| 109 hover_image(NULL), | |
| 110 push_image(NULL) { | |
| 111 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 112 normal_image = rb.GetImageSkiaNamed(normal_image_id); | |
| 113 hover_image = rb.GetImageSkiaNamed(hover_image_id); | |
| 114 push_image = rb.GetImageSkiaNamed(push_image_id); | |
| 115 tooltip_text = l10n_util::GetStringUTF16(tooltip_id); | |
| 116 } | |
| 117 }; | |
| 118 | |
| 119 struct EdgeResources { | |
| 120 gfx::ImageSkia* top_left; | |
| 121 gfx::ImageSkia* top; | |
| 122 gfx::ImageSkia* top_right; | |
| 123 gfx::ImageSkia* right; | |
| 124 gfx::ImageSkia* bottom_right; | |
| 125 gfx::ImageSkia* bottom; | |
| 126 gfx::ImageSkia* bottom_left; | |
| 127 gfx::ImageSkia* left; | |
| 128 | |
| 129 EdgeResources(int top_left_id, int top_id, int top_right_id, int right_id, | |
| 130 int bottom_right_id, int bottom_id, int bottom_left_id, | |
| 131 int left_id) | |
| 132 : top_left(NULL), | |
| 133 top(NULL), | |
| 134 top_right(NULL), | |
| 135 right(NULL), | |
| 136 bottom_right(NULL), | |
| 137 bottom(NULL), | |
| 138 bottom_left(NULL), | |
| 139 left(NULL) { | |
| 140 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
| 141 top_left = rb.GetImageSkiaNamed(top_left_id); | |
| 142 top = rb.GetImageSkiaNamed(top_id); | |
| 143 top_right = rb.GetImageSkiaNamed(top_right_id); | |
| 144 right = rb.GetImageSkiaNamed(right_id); | |
| 145 bottom_right = rb.GetImageSkiaNamed(bottom_right_id); | |
| 146 bottom = rb.GetImageSkiaNamed(bottom_id); | |
| 147 bottom_left = rb.GetImageSkiaNamed(bottom_left_id); | |
| 148 left = rb.GetImageSkiaNamed(left_id); | |
| 149 } | |
| 150 }; | |
| 151 | |
| 152 gfx::ImageSkia* CreateImageForColor(SkColor color) { | |
| 153 gfx::Canvas canvas(gfx::Size(1, 1), ui::SCALE_FACTOR_100P, true); | |
| 154 canvas.DrawColor(color); | |
| 155 return new gfx::ImageSkia(canvas.ExtractImageRep()); | |
| 156 } | |
| 157 | |
| 158 const ButtonResources& GetCloseButtonResources() { | |
| 159 static ButtonResources* buttons = NULL; | |
| 160 if (!buttons) { | |
| 161 buttons = new ButtonResources(IDR_PANEL_CLOSE, | |
| 162 IDR_PANEL_CLOSE_H, | |
| 163 IDR_PANEL_CLOSE_C, | |
| 164 IDS_PANEL_CLOSE_TOOLTIP); | |
| 165 } | |
| 166 return *buttons; | |
| 167 } | |
| 168 | |
| 169 const ButtonResources& GetMinimizeButtonResources() { | |
| 170 static ButtonResources* buttons = NULL; | |
| 171 if (!buttons) { | |
| 172 buttons = new ButtonResources(IDR_PANEL_MINIMIZE, | |
| 173 IDR_PANEL_MINIMIZE_H, | |
| 174 IDR_PANEL_MINIMIZE_C, | |
| 175 IDS_PANEL_MINIMIZE_TOOLTIP); | |
| 176 } | |
| 177 return *buttons; | |
| 178 } | |
| 179 | |
| 180 const ButtonResources& GetRestoreButtonResources() { | |
| 181 static ButtonResources* buttons = NULL; | |
| 182 if (!buttons) { | |
| 183 buttons = new ButtonResources(IDR_PANEL_RESTORE, | |
| 184 IDR_PANEL_RESTORE_H, | |
| 185 IDR_PANEL_RESTORE_C, | |
| 186 IDS_PANEL_RESTORE_TOOLTIP); | |
| 187 } | |
| 188 return *buttons; | |
| 189 } | |
| 190 | |
| 191 const EdgeResources& GetFrameEdges() { | |
| 192 static EdgeResources* edges = NULL; | |
| 193 if (!edges) { | |
| 194 edges = new EdgeResources( | |
| 195 IDR_WINDOW_TOP_LEFT_CORNER, IDR_WINDOW_TOP_CENTER, | |
| 196 IDR_WINDOW_TOP_RIGHT_CORNER, IDR_WINDOW_RIGHT_SIDE, | |
| 197 IDR_PANEL_BOTTOM_RIGHT_CORNER, IDR_WINDOW_BOTTOM_CENTER, | |
| 198 IDR_PANEL_BOTTOM_LEFT_CORNER, IDR_WINDOW_LEFT_SIDE); | |
| 199 } | |
| 200 return *edges; | |
| 201 } | |
| 202 | |
| 203 const EdgeResources& GetClientEdges() { | |
| 204 static EdgeResources* edges = NULL; | |
| 205 if (!edges) { | |
| 206 edges = new EdgeResources( | |
| 207 IDR_APP_TOP_LEFT, IDR_APP_TOP_CENTER, | |
| 208 IDR_APP_TOP_RIGHT, IDR_CONTENT_RIGHT_SIDE, | |
| 209 IDR_CONTENT_BOTTOM_RIGHT_CORNER, IDR_CONTENT_BOTTOM_CENTER, | |
| 210 IDR_CONTENT_BOTTOM_LEFT_CORNER, IDR_CONTENT_LEFT_SIDE); | |
| 211 } | |
| 212 return *edges; | |
| 213 } | |
| 214 | |
| 215 const gfx::Font& GetTitleFont() { | |
| 216 static gfx::Font* font = NULL; | |
| 217 if (!font) | |
| 218 font = new gfx::Font(kTitleFontName, kTitleFontSize); | |
| 219 return *font; | |
| 220 } | |
| 221 | |
| 222 const gfx::ImageSkia* GetActiveBackgroundDefaultImage() { | |
| 223 static gfx::ImageSkia* image = NULL; | |
| 224 if (!image) | |
| 225 image = CreateImageForColor(kActiveBackgroundDefaultColor); | |
| 226 return image; | |
| 227 } | |
| 228 | |
| 229 const gfx::ImageSkia* GetInactiveBackgroundDefaultImage() { | |
| 230 static gfx::ImageSkia* image = NULL; | |
| 231 if (!image) | |
| 232 image = CreateImageForColor(kInactiveBackgroundDefaultColor); | |
| 233 return image; | |
| 234 } | |
| 235 | |
| 236 const gfx::ImageSkia* GetAttentionBackgroundDefaultImage() { | |
| 237 static gfx::ImageSkia* image = NULL; | |
| 238 if (!image) | |
| 239 image = CreateImageForColor(kAttentionBackgroundDefaultColor); | |
| 240 return image; | |
| 241 } | |
| 242 | |
| 243 const gfx::ImageSkia* GetMinimizeBackgroundDefaultImage() { | |
| 244 static gfx::ImageSkia* image = NULL; | |
| 245 if (!image) | |
| 246 image = CreateImageForColor(kMinimizeBackgroundDefaultColor); | |
| 247 return image; | |
| 248 } | |
| 249 | |
| 250 bool IsHitTestValueForResizing(int hc) { | |
| 251 return hc == HTLEFT || hc == HTRIGHT || hc == HTTOP || hc == HTBOTTOM || | |
| 252 hc == HTTOPLEFT || hc == HTTOPRIGHT || hc == HTBOTTOMLEFT || | |
| 253 hc == HTBOTTOMRIGHT; | |
| 254 } | |
| 255 | |
| 256 } // namespace | |
| 257 | |
| 258 PanelBrowserFrameView::PanelBrowserFrameView(BrowserFrame* frame, | |
| 259 PanelBrowserView* browser_view) | |
| 260 : BrowserNonClientFrameView(frame, browser_view), | |
| 261 panel_browser_view_(browser_view), | |
| 262 paint_state_(NOT_PAINTED), | |
| 263 close_button_(NULL), | |
| 264 minimize_button_(NULL), | |
| 265 restore_button_(NULL), | |
| 266 title_icon_(NULL), | |
| 267 title_label_(NULL) { | |
| 268 frame->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM); | |
| 269 | |
| 270 const ButtonResources& close_button_resources = GetCloseButtonResources(); | |
| 271 close_button_ = new views::ImageButton(this); | |
| 272 close_button_->SetImage(views::CustomButton::BS_NORMAL, | |
| 273 close_button_resources.normal_image); | |
| 274 close_button_->SetImage(views::CustomButton::BS_HOT, | |
| 275 close_button_resources.hover_image); | |
| 276 close_button_->SetImage(views::CustomButton::BS_PUSHED, | |
| 277 close_button_resources.push_image); | |
| 278 close_button_->SetTooltipText(close_button_resources.tooltip_text); | |
| 279 close_button_->SetAccessibleName(close_button_resources.tooltip_text); | |
| 280 AddChildView(close_button_); | |
| 281 | |
| 282 const ButtonResources& minimize_button_resources = | |
| 283 GetMinimizeButtonResources(); | |
| 284 minimize_button_ = new views::ImageButton(this); | |
| 285 minimize_button_->SetImage(views::CustomButton::BS_NORMAL, | |
| 286 minimize_button_resources.normal_image); | |
| 287 minimize_button_->SetImage(views::CustomButton::BS_HOT, | |
| 288 minimize_button_resources.hover_image); | |
| 289 minimize_button_->SetImage(views::CustomButton::BS_PUSHED, | |
| 290 minimize_button_resources.push_image); | |
| 291 minimize_button_->SetTooltipText(minimize_button_resources.tooltip_text); | |
| 292 minimize_button_->SetAccessibleName(minimize_button_resources.tooltip_text); | |
| 293 AddChildView(minimize_button_); | |
| 294 | |
| 295 const ButtonResources& restore_button_resources = | |
| 296 GetRestoreButtonResources(); | |
| 297 restore_button_ = new views::ImageButton(this); | |
| 298 restore_button_->SetImage(views::CustomButton::BS_NORMAL, | |
| 299 restore_button_resources.normal_image); | |
| 300 restore_button_->SetImage(views::CustomButton::BS_HOT, | |
| 301 restore_button_resources.hover_image); | |
| 302 restore_button_->SetImage(views::CustomButton::BS_PUSHED, | |
| 303 restore_button_resources.push_image); | |
| 304 restore_button_->SetTooltipText(restore_button_resources.tooltip_text); | |
| 305 restore_button_->SetAccessibleName(restore_button_resources.tooltip_text); | |
| 306 restore_button_->SetVisible(false); // only visible when panel is minimized | |
| 307 AddChildView(restore_button_); | |
| 308 | |
| 309 title_icon_ = new TabIconView(this); | |
| 310 title_icon_->set_is_light(true); | |
| 311 AddChildView(title_icon_); | |
| 312 title_icon_->Update(); | |
| 313 | |
| 314 title_label_ = new views::Label(GetTitleText()); | |
| 315 title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 316 title_label_->SetAutoColorReadabilityEnabled(false); | |
| 317 AddChildView(title_label_); | |
| 318 } | |
| 319 | |
| 320 PanelBrowserFrameView::~PanelBrowserFrameView() { | |
| 321 } | |
| 322 | |
| 323 gfx::Rect PanelBrowserFrameView::GetBoundsForTabStrip( | |
| 324 views::View* tabstrip) const { | |
| 325 // Panels never show a tab strip. | |
| 326 NOTREACHED(); | |
| 327 return gfx::Rect(); | |
| 328 } | |
| 329 | |
| 330 BrowserNonClientFrameView::TabStripInsets | |
| 331 PanelBrowserFrameView::GetTabStripInsets( | |
| 332 bool restored) const { | |
| 333 // This is not needed since we do not show tab strip for the panel. | |
| 334 return TabStripInsets(); | |
| 335 } | |
| 336 | |
| 337 int PanelBrowserFrameView::GetThemeBackgroundXInset() const { | |
| 338 return 0; | |
| 339 } | |
| 340 | |
| 341 void PanelBrowserFrameView::UpdateThrobber(bool running) { | |
| 342 // Tells the title icon to update the throbber when we need to show the | |
| 343 // animation to indicate we're still loading. | |
| 344 title_icon_->Update(); | |
| 345 } | |
| 346 | |
| 347 gfx::Rect PanelBrowserFrameView::GetBoundsForClientView() const { | |
| 348 return client_view_bounds_; | |
| 349 } | |
| 350 | |
| 351 gfx::Rect PanelBrowserFrameView::GetWindowBoundsForClientBounds( | |
| 352 const gfx::Rect& client_bounds) const { | |
| 353 int top_height = NonClientTopBorderHeight(); | |
| 354 int border_thickness = NonClientBorderThickness(); | |
| 355 return gfx::Rect(std::max(0, client_bounds.x() - border_thickness), | |
| 356 std::max(0, client_bounds.y() - top_height), | |
| 357 client_bounds.width() + (2 * border_thickness), | |
| 358 client_bounds.height() + top_height + border_thickness); | |
| 359 } | |
| 360 | |
| 361 int PanelBrowserFrameView::NonClientHitTest(const gfx::Point& point) { | |
| 362 PanelStrip* panel_strip = panel_browser_view_->panel()->panel_strip(); | |
| 363 if (!panel_strip) | |
| 364 return HTNOWHERE; | |
| 365 | |
| 366 if (!bounds().Contains(point)) | |
| 367 return HTNOWHERE; | |
| 368 | |
| 369 int frame_component = | |
| 370 frame()->client_view()->NonClientHitTest(point); | |
| 371 if (frame_component != HTNOWHERE) | |
| 372 return frame_component; | |
| 373 | |
| 374 if (close_button_->visible() && | |
| 375 close_button_->GetMirroredBounds().Contains(point)) | |
| 376 return HTCLOSE; | |
| 377 | |
| 378 if (minimize_button_->visible() && | |
| 379 minimize_button_->GetMirroredBounds().Contains(point)) | |
| 380 return HTMINBUTTON; | |
| 381 | |
| 382 if (restore_button_->visible() && | |
| 383 restore_button_->GetMirroredBounds().Contains(point)) | |
| 384 return HTMAXBUTTON; | |
| 385 | |
| 386 int window_component = GetHTComponentForFrame(point, | |
| 387 NonClientBorderThickness(), NonClientBorderThickness(), | |
| 388 kResizeAreaCornerSize, kResizeAreaCornerSize, | |
| 389 CanResize()); | |
| 390 | |
| 391 // The bottom edge and corners cannot be used to resize in some scenarios, | |
| 392 // i.e docked panels. | |
| 393 panel::Resizability resizability = panel_strip->GetPanelResizability( | |
| 394 panel_browser_view_->panel()); | |
| 395 if (resizability == panel::RESIZABLE_ALL_SIDES_EXCEPT_BOTTOM && | |
| 396 (window_component == HTBOTTOM || | |
| 397 window_component == HTBOTTOMLEFT || | |
| 398 window_component == HTBOTTOMRIGHT)) | |
| 399 return HTNOWHERE; | |
| 400 | |
| 401 // Fall back to the caption if no other component matches. | |
| 402 return (window_component == HTNOWHERE) ? HTCAPTION : window_component; | |
| 403 } | |
| 404 | |
| 405 void PanelBrowserFrameView::GetWindowMask(const gfx::Size& size, | |
| 406 gfx::Path* window_mask) { | |
| 407 window_mask->moveTo(0, 3); | |
| 408 window_mask->lineTo(1, 2); | |
| 409 window_mask->lineTo(1, 1); | |
| 410 window_mask->lineTo(2, 1); | |
| 411 window_mask->lineTo(3, 0); | |
| 412 window_mask->lineTo(SkIntToScalar(size.width() - 3), 0); | |
| 413 window_mask->lineTo(SkIntToScalar(size.width() - 2), 1); | |
| 414 window_mask->lineTo(SkIntToScalar(size.width() - 1), 1); | |
| 415 window_mask->lineTo(SkIntToScalar(size.width() - 1), 2); | |
| 416 window_mask->lineTo(SkIntToScalar(size.width() - 1), 3); | |
| 417 window_mask->lineTo(SkIntToScalar(size.width()), | |
| 418 SkIntToScalar(size.height())); | |
| 419 window_mask->lineTo(0, SkIntToScalar(size.height())); | |
| 420 window_mask->close(); | |
| 421 } | |
| 422 | |
| 423 void PanelBrowserFrameView::ResetWindowControls() { | |
| 424 // The close button isn't affected by this constraint. | |
| 425 } | |
| 426 | |
| 427 void PanelBrowserFrameView::UpdateWindowIcon() { | |
| 428 title_icon_->SchedulePaint(); | |
| 429 } | |
| 430 | |
| 431 void PanelBrowserFrameView::OnPaint(gfx::Canvas* canvas) { | |
| 432 // The font and color need to be updated depending on the panel's state. | |
| 433 PaintState paint_state; | |
| 434 if (panel_browser_view_->panel()->IsDrawingAttention()) | |
| 435 paint_state = PAINT_FOR_ATTENTION; | |
| 436 else if (bounds().height() <= panel::kMinimizedPanelHeight) | |
| 437 paint_state = PAINT_AS_MINIMIZED; | |
| 438 else if (panel_browser_view_->focused() && | |
| 439 !panel_browser_view_->force_to_paint_as_inactive()) | |
| 440 paint_state = PAINT_AS_ACTIVE; | |
| 441 else | |
| 442 paint_state = PAINT_AS_INACTIVE; | |
| 443 | |
| 444 UpdateControlStyles(paint_state); | |
| 445 PaintFrameBackground(canvas); | |
| 446 PaintFrameEdge(canvas); | |
| 447 PaintDivider(canvas); | |
| 448 } | |
| 449 | |
| 450 void PanelBrowserFrameView::OnThemeChanged() { | |
| 451 } | |
| 452 | |
| 453 gfx::Size PanelBrowserFrameView::GetMinimumSize() { | |
| 454 // This makes the panel be able to shrink to very small, like minimized panel. | |
| 455 return gfx::Size(); | |
| 456 } | |
| 457 | |
| 458 gfx::Size PanelBrowserFrameView::GetMaximumSize() { | |
| 459 // When the user resizes the panel, there is no max size limit. | |
| 460 return gfx::Size(); | |
| 461 } | |
| 462 | |
| 463 void PanelBrowserFrameView::Layout() { | |
| 464 Panel* panel = panel_browser_view_->panel(); | |
| 465 PanelStrip* panel_strip = panel->panel_strip(); | |
| 466 if (!panel_strip) | |
| 467 return; | |
| 468 | |
| 469 // Layout the close button. | |
| 470 int right = width(); | |
| 471 gfx::Size close_button_size = close_button_->GetPreferredSize(); | |
| 472 close_button_->SetBounds( | |
| 473 width() - kCloseButtonAndBorderSpacing - close_button_size.width(), | |
| 474 (NonClientTopBorderHeight() - close_button_size.height()) / 2, | |
| 475 close_button_size.width(), | |
| 476 close_button_size.height()); | |
| 477 right = close_button_->x(); | |
| 478 | |
| 479 // Layout the minimize and restore button. Both occupy the same space, | |
| 480 // but at most one is visible at any time. | |
| 481 gfx::Size button_size = minimize_button_->GetPreferredSize(); | |
| 482 minimize_button_->SetBounds( | |
| 483 right - kMinimizeButtonAndCloseButtonSpacing - button_size.width(), | |
| 484 (NonClientTopBorderHeight() - button_size.height()) / 2, | |
| 485 button_size.width(), | |
| 486 button_size.height()); | |
| 487 restore_button_->SetBoundsRect(minimize_button_->bounds()); | |
| 488 right = minimize_button_->x(); | |
| 489 | |
| 490 // Layout the icon. | |
| 491 int icon_y = (NonClientTopBorderHeight() - kIconSize) / 2; | |
| 492 title_icon_->SetBounds( | |
| 493 NonClientBorderThickness() + kIconAndBorderSpacing, | |
| 494 icon_y, | |
| 495 kIconSize, | |
| 496 kIconSize); | |
| 497 | |
| 498 // Layout the title. | |
| 499 int title_x = title_icon_->bounds().right() + kTitleSpacing; | |
| 500 int title_height = GetTitleFont().GetHeight(); | |
| 501 title_label_->SetBounds( | |
| 502 title_x, | |
| 503 icon_y + ((kIconSize - title_height - 1) / 2), | |
| 504 std::max(0, right - kTitleSpacing - title_x), | |
| 505 title_height); | |
| 506 | |
| 507 // Calculate the client area bounds. | |
| 508 int top_height = NonClientTopBorderHeight(); | |
| 509 int border_thickness = NonClientBorderThickness(); | |
| 510 client_view_bounds_.SetRect( | |
| 511 border_thickness, | |
| 512 top_height, | |
| 513 std::max(0, width() - (2 * border_thickness)), | |
| 514 std::max(0, height() - top_height - border_thickness)); | |
| 515 } | |
| 516 | |
| 517 void PanelBrowserFrameView::GetAccessibleState(ui::AccessibleViewState* state) { | |
| 518 state->role = ui::AccessibilityTypes::ROLE_TITLEBAR; | |
| 519 } | |
| 520 | |
| 521 bool PanelBrowserFrameView::OnMousePressed(const ui::MouseEvent& event) { | |
| 522 gfx::Point mouse_location = event.location(); | |
| 523 | |
| 524 if (CanResize() && | |
| 525 IsHitTestValueForResizing(NonClientHitTest(mouse_location))) | |
| 526 return BrowserNonClientFrameView::OnMousePressed(event); | |
| 527 | |
| 528 // |event.location| is in the view's coordinate system. Convert it to the | |
| 529 // screen coordinate system. | |
| 530 views::View::ConvertPointToScreen(this, &mouse_location); | |
| 531 | |
| 532 if (event.IsOnlyLeftMouseButton() && | |
| 533 panel_browser_view_->OnTitlebarMousePressed(mouse_location)) { | |
| 534 return true; | |
| 535 } | |
| 536 return BrowserNonClientFrameView::OnMousePressed(event); | |
| 537 } | |
| 538 | |
| 539 bool PanelBrowserFrameView::OnMouseDragged(const ui::MouseEvent& event) { | |
| 540 // |event.location| is in the view's coordinate system. Convert it to the | |
| 541 // screen coordinate system. | |
| 542 gfx::Point mouse_location = event.location(); | |
| 543 views::View::ConvertPointToScreen(this, &mouse_location); | |
| 544 | |
| 545 if (panel_browser_view_->OnTitlebarMouseDragged(mouse_location)) | |
| 546 return true; | |
| 547 return BrowserNonClientFrameView::OnMouseDragged(event); | |
| 548 } | |
| 549 | |
| 550 void PanelBrowserFrameView::OnMouseReleased(const ui::MouseEvent& event) { | |
| 551 if (panel_browser_view_->OnTitlebarMouseReleased( | |
| 552 event.IsControlDown() ? panel::APPLY_TO_ALL : panel::NO_MODIFIER)) | |
| 553 return; | |
| 554 BrowserNonClientFrameView::OnMouseReleased(event); | |
| 555 } | |
| 556 | |
| 557 void PanelBrowserFrameView::OnMouseCaptureLost() { | |
| 558 if (panel_browser_view_->OnTitlebarMouseCaptureLost()) | |
| 559 return; | |
| 560 BrowserNonClientFrameView::OnMouseCaptureLost(); | |
| 561 } | |
| 562 | |
| 563 void PanelBrowserFrameView::ButtonPressed(views::Button* sender, | |
| 564 const ui::Event& event) { | |
| 565 if (sender == close_button_) { | |
| 566 frame()->Close(); | |
| 567 } else { | |
| 568 panel::ClickModifier modifier = | |
| 569 event.IsControlDown() ? panel::APPLY_TO_ALL : panel::NO_MODIFIER; | |
| 570 if (sender == minimize_button_) | |
| 571 panel_browser_view_->panel()->OnMinimizeButtonClicked(modifier); | |
| 572 else if (sender == restore_button_) | |
| 573 panel_browser_view_->panel()->OnRestoreButtonClicked(modifier); | |
| 574 } | |
| 575 } | |
| 576 | |
| 577 bool PanelBrowserFrameView::ShouldTabIconViewAnimate() const { | |
| 578 // This function is queried during the creation of the window as the | |
| 579 // TabIconView we host is initialized, so we need to NULL check the selected | |
| 580 // WebContents because in this condition there is not yet a selected tab. | |
| 581 WebContents* current_tab = browser_view()->GetActiveWebContents(); | |
| 582 return current_tab ? current_tab->IsLoading() : false; | |
| 583 } | |
| 584 | |
| 585 gfx::ImageSkia PanelBrowserFrameView::GetFaviconForTabIconView() { | |
| 586 return frame()->widget_delegate()->GetWindowIcon(); | |
| 587 } | |
| 588 | |
| 589 int PanelBrowserFrameView::NonClientBorderThickness() const { | |
| 590 if (CanResize()) | |
| 591 return kResizableBorderThickness; | |
| 592 else | |
| 593 return kNonResizableBorderThickness; | |
| 594 } | |
| 595 | |
| 596 int PanelBrowserFrameView::NonClientTopBorderHeight() const { | |
| 597 return panel::kTitlebarHeight; | |
| 598 } | |
| 599 | |
| 600 gfx::Size PanelBrowserFrameView::NonClientAreaSize() const { | |
| 601 return gfx::Size(NonClientBorderThickness() * 2, | |
| 602 NonClientTopBorderHeight() + NonClientBorderThickness()); | |
| 603 } | |
| 604 | |
| 605 int PanelBrowserFrameView::IconOnlyWidth() const { | |
| 606 return NonClientBorderThickness() * 2 + kIconAndBorderSpacing * 2 + kIconSize; | |
| 607 } | |
| 608 | |
| 609 bool PanelBrowserFrameView::UsingDefaultTheme(PaintState paint_state) const { | |
| 610 // No theme is provided for attention painting. | |
| 611 if (paint_state == PAINT_FOR_ATTENTION) | |
| 612 return true; | |
| 613 | |
| 614 ThemeService* theme_service = ThemeServiceFactory::GetForProfile( | |
| 615 panel_browser_view_->panel()->profile()); | |
| 616 return theme_service->UsingDefaultTheme(); | |
| 617 } | |
| 618 | |
| 619 SkColor PanelBrowserFrameView::GetTitleColor(PaintState paint_state) const { | |
| 620 return UsingDefaultTheme(paint_state) ? | |
| 621 GetDefaultTitleColor(paint_state) : | |
| 622 GetThemedTitleColor(paint_state); | |
| 623 } | |
| 624 | |
| 625 SkColor PanelBrowserFrameView::GetDefaultTitleColor( | |
| 626 PaintState paint_state) const { | |
| 627 return kTitleTextDefaultColor; | |
| 628 } | |
| 629 | |
| 630 SkColor PanelBrowserFrameView::GetThemedTitleColor( | |
| 631 PaintState paint_state) const { | |
| 632 return GetThemeProvider()->GetColor(paint_state == PAINT_AS_ACTIVE ? | |
| 633 ThemeService::COLOR_TAB_TEXT : ThemeService::COLOR_BACKGROUND_TAB_TEXT); | |
| 634 } | |
| 635 | |
| 636 const gfx::ImageSkia* PanelBrowserFrameView::GetFrameBackground( | |
| 637 PaintState paint_state) const { | |
| 638 return UsingDefaultTheme(paint_state) ? | |
| 639 GetDefaultFrameBackground(paint_state) : | |
| 640 GetThemedFrameBackground(paint_state); | |
| 641 } | |
| 642 | |
| 643 const gfx::ImageSkia* PanelBrowserFrameView::GetDefaultFrameBackground( | |
| 644 PaintState paint_state) const { | |
| 645 switch (paint_state) { | |
| 646 case PAINT_AS_INACTIVE: | |
| 647 return GetInactiveBackgroundDefaultImage(); | |
| 648 case PAINT_AS_ACTIVE: | |
| 649 return GetActiveBackgroundDefaultImage(); | |
| 650 case PAINT_AS_MINIMIZED: | |
| 651 return GetMinimizeBackgroundDefaultImage(); | |
| 652 case PAINT_FOR_ATTENTION: | |
| 653 return GetAttentionBackgroundDefaultImage(); | |
| 654 default: | |
| 655 NOTREACHED(); | |
| 656 return GetInactiveBackgroundDefaultImage(); | |
| 657 } | |
| 658 } | |
| 659 | |
| 660 const gfx::ImageSkia* PanelBrowserFrameView::GetThemedFrameBackground( | |
| 661 PaintState paint_state) const { | |
| 662 return GetThemeProvider()->GetImageSkiaNamed(paint_state == PAINT_AS_ACTIVE ? | |
| 663 IDR_THEME_TOOLBAR : IDR_THEME_TAB_BACKGROUND); | |
| 664 } | |
| 665 | |
| 666 void PanelBrowserFrameView::UpdateControlStyles(PaintState paint_state) { | |
| 667 DCHECK(paint_state != NOT_PAINTED); | |
| 668 | |
| 669 if (paint_state == paint_state_) | |
| 670 return; | |
| 671 paint_state_ = paint_state; | |
| 672 | |
| 673 SkColor title_color = GetTitleColor(paint_state_); | |
| 674 title_label_->SetEnabledColor(title_color); | |
| 675 title_label_->SetFont(GetTitleFont()); | |
| 676 | |
| 677 close_button_->SetBackground(title_color, | |
| 678 GetCloseButtonResources().normal_image, | |
| 679 NULL); | |
| 680 | |
| 681 minimize_button_->SetBackground(title_color, | |
| 682 GetMinimizeButtonResources().normal_image, | |
| 683 NULL); | |
| 684 | |
| 685 restore_button_->SetBackground(title_color, | |
| 686 GetRestoreButtonResources().normal_image, | |
| 687 NULL); | |
| 688 } | |
| 689 | |
| 690 void PanelBrowserFrameView::PaintFrameBackground(gfx::Canvas* canvas) { | |
| 691 int top_area_height = NonClientTopBorderHeight(); | |
| 692 int thickness = NonClientBorderThickness(); | |
| 693 const gfx::ImageSkia* image = GetFrameBackground(paint_state_); | |
| 694 | |
| 695 // Top area, including title-bar. | |
| 696 canvas->TileImageInt(*image, 0, 0, width(), top_area_height); | |
| 697 | |
| 698 // For all the non-client area below titlebar, we paint it by using the last | |
| 699 // line from the theme image, instead of using the frame color provided | |
| 700 // in the theme because the frame color in some themes is very different from | |
| 701 // the tab colors we use to render the titlebar and it can produce abrupt | |
| 702 // transition which looks bad. | |
| 703 | |
| 704 // Left border, below title-bar. | |
| 705 canvas->DrawImageInt(*image, 0, top_area_height - 1, thickness, 1, | |
| 706 0, top_area_height, thickness, height() - top_area_height, false); | |
| 707 | |
| 708 // Right border, below title-bar. | |
| 709 canvas->DrawImageInt(*image, (width() % image->width()) - thickness, | |
| 710 top_area_height - 1, thickness, 1, | |
| 711 width() - thickness, top_area_height, | |
| 712 thickness, height() - top_area_height, false); | |
| 713 | |
| 714 // Bottom border. | |
| 715 canvas->DrawImageInt(*image, 0, top_area_height - 1, image->width(), 1, | |
| 716 0, height() - thickness, width(), thickness, false); | |
| 717 } | |
| 718 | |
| 719 void PanelBrowserFrameView::PaintFrameEdge(gfx::Canvas* canvas) { | |
| 720 #if !defined(USE_AURA) | |
| 721 // Border is not needed when panel is not shown as minimized. | |
| 722 if (paint_state_ != PAINT_AS_MINIMIZED) | |
| 723 return; | |
| 724 | |
| 725 // Draw the top border. | |
| 726 const EdgeResources& frame_edges = GetFrameEdges(); | |
| 727 canvas->DrawImageInt(*(frame_edges.top_left), 0, 0); | |
| 728 canvas->TileImageInt( | |
| 729 *(frame_edges.top), frame_edges.top_left->width(), 0, | |
| 730 width() - frame_edges.top_right->width(), frame_edges.top->height()); | |
| 731 canvas->DrawImageInt( | |
| 732 *(frame_edges.top_right), | |
| 733 width() - frame_edges.top_right->width(), 0); | |
| 734 | |
| 735 // Draw the right border. | |
| 736 canvas->TileImageInt( | |
| 737 *(frame_edges.right), width() - frame_edges.right->width(), | |
| 738 frame_edges.top_right->height(), frame_edges.right->width(), | |
| 739 height() - frame_edges.top_right->height() - | |
| 740 frame_edges.bottom_right->height()); | |
| 741 | |
| 742 // Draw the bottom border. | |
| 743 canvas->DrawImageInt( | |
| 744 *(frame_edges.bottom_right), | |
| 745 width() - frame_edges.bottom_right->width(), | |
| 746 height() - frame_edges.bottom_right->height()); | |
| 747 canvas->TileImageInt( | |
| 748 *(frame_edges.bottom), frame_edges.bottom_left->width(), | |
| 749 height() - frame_edges.bottom->height(), | |
| 750 width() - frame_edges.bottom_left->width() - | |
| 751 frame_edges.bottom_right->width(), | |
| 752 frame_edges.bottom->height()); | |
| 753 canvas->DrawImageInt( | |
| 754 *(frame_edges.bottom_left), 0, | |
| 755 height() - frame_edges.bottom_left->height()); | |
| 756 | |
| 757 // Draw the left border. | |
| 758 canvas->TileImageInt( | |
| 759 *(frame_edges.left), 0, frame_edges.top_left->height(), | |
| 760 frame_edges.left->width(), | |
| 761 height() - frame_edges.top_left->height() - | |
| 762 frame_edges.bottom_left->height()); | |
| 763 #endif // !defined(USE_AURA) | |
| 764 } | |
| 765 | |
| 766 void PanelBrowserFrameView::PaintDivider(gfx::Canvas* canvas) { | |
| 767 #if defined(USE_AURA) | |
| 768 // Aura recognizes aura::client::WINDOW_TYPE_PANEL and will draw the | |
| 769 // appropriate frame and shadow. See ash/wm/shadow_controller.h. | |
| 770 | |
| 771 // Draw the divider between the titlebar and the client area. | |
| 772 if (!IsShowingTitlebarOnly()) { | |
| 773 canvas->DrawRect(gfx::Rect(0, panel::kTitlebarHeight, width() - 1, 1), | |
| 774 kDividerColor); | |
| 775 } | |
| 776 #else | |
| 777 // Draw the divider between the titlebar and the client area. | |
| 778 if (!IsShowingTitlebarOnly()) { | |
| 779 canvas->DrawLine(gfx::Point(0, panel::kTitlebarHeight - 1), | |
| 780 gfx::Point(width() - 1, panel::kTitlebarHeight - 1), | |
| 781 kDividerColor); | |
| 782 } | |
| 783 #endif // !defined(USE_AURA) | |
| 784 } | |
| 785 | |
| 786 string16 PanelBrowserFrameView::GetTitleText() const { | |
| 787 return frame()->widget_delegate()->GetWindowTitle(); | |
| 788 } | |
| 789 | |
| 790 void PanelBrowserFrameView::UpdateTitleBar() { | |
| 791 title_label_->SetText(GetTitleText()); | |
| 792 } | |
| 793 | |
| 794 void PanelBrowserFrameView::UpdateTitleBarMinimizeRestoreButtonVisibility() { | |
| 795 Panel* panel = panel_browser_view_->panel(); | |
| 796 minimize_button_->SetVisible(panel->CanMinimize()); | |
| 797 restore_button_->SetVisible(panel->CanRestore()); | |
| 798 | |
| 799 // Reset the button states in case that the hover states are not cleared when | |
| 800 // mouse is clicked but not moved. | |
| 801 minimize_button_->SetState(views::CustomButton::BS_NORMAL); | |
| 802 restore_button_->SetState(views::CustomButton::BS_NORMAL); | |
| 803 } | |
| 804 | |
| 805 bool PanelBrowserFrameView::CanResize() const { | |
| 806 return panel_browser_view_->panel()->CanResizeByMouse() != | |
| 807 panel::NOT_RESIZABLE; | |
| 808 } | |
| 809 | |
| 810 bool PanelBrowserFrameView::IsShowingTitlebarOnly() const { | |
| 811 return height() <= panel::kTitlebarHeight; | |
| 812 } | |
| OLD | NEW |