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 #include "ui/base/hit_test.h" 11 12 namespace { 13 bool ResizingLeft(int component) { 14 return component == HTTOPLEFT || 15 component == HTLEFT || 16 component == HTBOTTOMLEFT; 17 } 18 19 bool ResizingRight(int component) { 20 return component == HTTOPRIGHT || 21 component == HTRIGHT || 22 component == HTBOTTOMRIGHT; 23 } 24 25 bool ResizingTop(int component) { 26 return component == HTTOPLEFT || 27 component == HTTOP || 28 component == HTTOPRIGHT; 29 } 30 31 bool ResizingBottom(int component) { 32 return component == HTBOTTOMRIGHT || 33 component == HTBOTTOM || 34 component == HTBOTTOMLEFT; 35 } 36 } // namespace 37 38 PanelResizeController::PanelResizeController(PanelManager* panel_manager) 39 : panel_manager_(panel_manager), 40 resizing_panel_(NULL), 41 component_(HTNOWHERE) { 42 } 43 44 void PanelResizeController::StartResizing(Panel* panel, 45 const gfx::Point& mouse_location, 46 int component) { 47 DCHECK(!IsResizing()); 48 DCHECK_NE(HTNOWHERE, component); 49 50 panel::Resizability resizability = panel->CanResizeByMouse(); 51 DCHECK_NE(panel::NOT_RESIZABLE, resizability); 52 panel::Resizability resizability_to_test; 53 switch (component) { 54 case HTTOPLEFT: 55 resizability_to_test = panel::RESIZABLE_TOP_LEFT; 56 break; 57 case HTTOP: 58 resizability_to_test = panel::RESIZABLE_TOP; 59 break; 60 case HTTOPRIGHT: 61 resizability_to_test = panel::RESIZABLE_TOP_RIGHT; 62 break; 63 case HTLEFT: 64 resizability_to_test = panel::RESIZABLE_LEFT; 65 break; 66 case HTRIGHT: 67 resizability_to_test = panel::RESIZABLE_RIGHT; 68 break; 69 case HTBOTTOMLEFT: 70 resizability_to_test = panel::RESIZABLE_BOTTOM_LEFT; 71 break; 72 case HTBOTTOM: 73 resizability_to_test = panel::RESIZABLE_BOTTOM; 74 break; 75 case HTBOTTOMRIGHT: 76 resizability_to_test = panel::RESIZABLE_BOTTOM_RIGHT; 77 break; 78 default: 79 resizability_to_test = panel::NOT_RESIZABLE; 80 break; 81 } 82 if ((resizability & resizability_to_test) == 0) { 83 DLOG(WARNING) << "Resizing not allowed. Is this a test?"; 84 return; 85 } 86 87 mouse_location_at_start_ = mouse_location; 88 bounds_at_start_ = panel->GetBounds(); 89 component_ = component; 90 resizing_panel_ = panel; 91 resizing_panel_->OnPanelStartUserResizing(); 92 } 93 94 void PanelResizeController::Resize(const gfx::Point& mouse_location) { 95 DCHECK(IsResizing()); 96 panel::Resizability resizability = resizing_panel_->CanResizeByMouse(); 97 if (panel::NOT_RESIZABLE == resizability) { 98 EndResizing(false); 99 return; 100 } 101 gfx::Rect bounds = resizing_panel_->GetBounds(); 102 103 if (ResizingRight(component_)) { 104 bounds.set_width(std::max(bounds_at_start_.width() + 105 mouse_location.x() - mouse_location_at_start_.x(), 0)); 106 } 107 if (ResizingBottom(component_)) { 108 bounds.set_height(std::max(bounds_at_start_.height() + 109 mouse_location.y() - mouse_location_at_start_.y(), 0)); 110 } 111 if (ResizingLeft(component_)) { 112 bounds.set_width(std::max(bounds_at_start_.width() + 113 mouse_location_at_start_.x() - mouse_location.x(), 0)); 114 } 115 if (ResizingTop(component_)) { 116 int new_height = std::max(bounds_at_start_.height() + 117 mouse_location_at_start_.y() - mouse_location.y(), 0); 118 int new_y = bounds_at_start_.bottom() - new_height; 119 120 // Make sure that the panel's titlebar cannot be resized under the taskbar 121 // or OSX menu bar that is aligned to top screen edge. 122 gfx::Rect display_area = panel_manager_->display_settings_provider()-> 123 GetDisplayAreaMatching(bounds); 124 gfx::Rect work_area = panel_manager_->display_settings_provider()-> 125 GetWorkAreaMatching(bounds); 126 if (display_area.y() <= mouse_location.y() && 127 mouse_location.y() < work_area.y()) { 128 new_height -= work_area.y() - new_y; 129 } 130 131 bounds.set_height(new_height); 132 } 133 134 resizing_panel_->IncreaseMaxSize(bounds.size()); 135 136 // This effectively only clamps using the min size, since the max_size was 137 // updated above. 138 bounds.set_size(resizing_panel_->ClampSize(bounds.size())); 139 140 if (ResizingLeft(component_)) 141 bounds.set_x(bounds_at_start_.right() - bounds.width()); 142 143 if (ResizingTop(component_)) 144 bounds.set_y(bounds_at_start_.bottom() - bounds.height()); 145 146 if (bounds != resizing_panel_->GetBounds()) { 147 resizing_panel_->SetPanelBoundsInstantly(bounds); 148 resizing_panel_->OnWindowResizedByMouse(bounds); 149 } 150 } 151 152 Panel* PanelResizeController::EndResizing(bool cancelled) { 153 DCHECK(IsResizing()); 154 155 if (cancelled) { 156 resizing_panel_->SetPanelBoundsInstantly(bounds_at_start_); 157 resizing_panel_->OnWindowResizedByMouse(bounds_at_start_); 158 } 159 160 // Do a thorough cleanup. 161 resizing_panel_->OnPanelEndUserResizing(); 162 Panel* resized_panel = resizing_panel_; 163 resizing_panel_ = NULL; 164 component_ = HTNOWHERE; 165 bounds_at_start_ = gfx::Rect(); 166 mouse_location_at_start_ = gfx::Point(); 167 return resized_panel; 168 } 169 170 void PanelResizeController::OnPanelClosed(Panel* panel) { 171 if (!resizing_panel_) 172 return; 173 174 // If the resizing panel is closed, abort the resize operation. 175 if (resizing_panel_ == panel) 176 EndResizing(false); 177 } 178