panel_resize_controller.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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_resize_controller.h"
6
7#include "base/logging.h"
8#include "chrome/browser/ui/panels/panel.h"
9#include "chrome/browser/ui/panels/panel_manager.h"
10
11namespace {
12  static bool ResizingLeft(panel::ResizingSides sides) {
13    return sides == panel::RESIZE_TOP_LEFT ||
14           sides == panel::RESIZE_LEFT ||
15           sides == panel::RESIZE_BOTTOM_LEFT;
16  }
17
18  static bool ResizingRight(panel::ResizingSides sides) {
19    return sides == panel::RESIZE_TOP_RIGHT ||
20           sides == panel::RESIZE_RIGHT ||
21           sides == panel::RESIZE_BOTTOM_RIGHT;
22  }
23
24  static bool ResizingTop(panel::ResizingSides sides) {
25    return sides == panel::RESIZE_TOP_LEFT ||
26           sides == panel::RESIZE_TOP ||
27           sides == panel::RESIZE_TOP_RIGHT;
28  }
29
30  static bool ResizingBottom(panel::ResizingSides sides) {
31    return sides == panel::RESIZE_BOTTOM_RIGHT ||
32           sides == panel::RESIZE_BOTTOM ||
33           sides == panel::RESIZE_BOTTOM_LEFT;
34  }
35}
36
37PanelResizeController::PanelResizeController(PanelManager* panel_manager)
38  : panel_manager_(panel_manager),
39    resizing_panel_(NULL),
40    sides_resized_(panel::RESIZE_NONE) {
41}
42
43void PanelResizeController::StartResizing(Panel* panel,
44                                          const gfx::Point& mouse_location,
45                                          panel::ResizingSides sides) {
46  DCHECK(!IsResizing());
47  DCHECK_NE(panel::RESIZE_NONE, sides);
48
49  panel::Resizability resizability = panel->CanResizeByMouse();
50  DCHECK_NE(panel::NOT_RESIZABLE, resizability);
51  if (panel::RESIZABLE_ALL_SIDES_EXCEPT_BOTTOM == resizability &&
52      ResizingBottom(sides)) {
53    DLOG(WARNING) << "Resizing from bottom not allowed. Is this a test?";
54    return;
55  }
56
57  mouse_location_at_start_ = mouse_location;
58  bounds_at_start_ = panel->GetBounds();
59  sides_resized_ = sides;
60  resizing_panel_ = panel;
61  resizing_panel_->OnPanelStartUserResizing();
62}
63
64void PanelResizeController::Resize(const gfx::Point& mouse_location) {
65  DCHECK(IsResizing());
66  panel::Resizability resizability = resizing_panel_->CanResizeByMouse();
67  if (panel::NOT_RESIZABLE == resizability) {
68    EndResizing(false);
69    return;
70  }
71  gfx::Rect bounds = resizing_panel_->GetBounds();
72
73  if (ResizingRight(sides_resized_)) {
74    bounds.set_width(std::max(bounds_at_start_.width() +
75                     mouse_location.x() - mouse_location_at_start_.x(), 0));
76  }
77  if (ResizingBottom(sides_resized_)) {
78    DCHECK_EQ(panel::RESIZABLE_ALL_SIDES, resizability);
79    bounds.set_height(std::max(bounds_at_start_.height() +
80                      mouse_location.y() - mouse_location_at_start_.y(), 0));
81  }
82  if (ResizingLeft(sides_resized_)) {
83    bounds.set_width(std::max(bounds_at_start_.width() +
84                     mouse_location_at_start_.x() - mouse_location.x(), 0));
85  }
86  if (ResizingTop(sides_resized_)) {
87    int new_height = std::max(bounds_at_start_.height() +
88                     mouse_location_at_start_.y() - mouse_location.y(), 0);
89    int new_y = bounds_at_start_.bottom() - new_height;
90
91    // If the mouse is within the main screen area, make sure that the top
92    // border of panel cannot go outside the work area. This is to prevent
93    // panel's titlebar from being resized under the taskbar or OSX menu bar
94    // that is aligned to top screen edge.
95    int display_area_top_position = panel_manager_->display_area().y();
96    if (panel_manager_->display_settings_provider()->
97            GetPrimaryScreenArea().Contains(mouse_location) &&
98        new_y < display_area_top_position) {
99      new_height -= display_area_top_position - new_y;
100    }
101
102    bounds.set_height(new_height);
103  }
104
105  resizing_panel_->IncreaseMaxSize(bounds.size());
106
107  // This effectively only clamps using the min size, since the max_size was
108  // updated above.
109  bounds.set_size(resizing_panel_->ClampSize(bounds.size()));
110
111  if (ResizingLeft(sides_resized_))
112    bounds.set_x(bounds_at_start_.right() - bounds.width());
113
114  if (ResizingTop(sides_resized_))
115    bounds.set_y(bounds_at_start_.bottom() - bounds.height());
116
117  if (bounds != resizing_panel_->GetBounds())
118    resizing_panel_->OnWindowResizedByMouse(bounds);
119}
120
121Panel* PanelResizeController::EndResizing(bool cancelled) {
122  DCHECK(IsResizing());
123
124  if (cancelled)
125    resizing_panel_->OnWindowResizedByMouse(bounds_at_start_);
126
127  // Do a thorough cleanup.
128  resizing_panel_->OnPanelEndUserResizing();
129  Panel* resized_panel = resizing_panel_;
130  resizing_panel_ = NULL;
131  sides_resized_ = panel::RESIZE_NONE;
132  bounds_at_start_ = gfx::Rect();
133  mouse_location_at_start_ = gfx::Point();
134  return resized_panel;
135}
136
137void PanelResizeController::OnPanelClosed(Panel* panel) {
138  if (!resizing_panel_)
139    return;
140
141  // If the resizing panel is closed, abort the resize operation.
142  if (resizing_panel_ == panel)
143    EndResizing(false);
144}
145