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