1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file.
4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/panels/panel_manager.h"
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <algorithm>
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/logging.h"
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/scoped_ptr.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser.h"
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/panels/panel.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/window_sizer.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace {
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Invalid panel index.
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst size_t kInvalidPanelIndex = static_cast<size_t>(-1);
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Minimum width and height of a panel.
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kPanelMinWidthPixels = 64;
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kPanelMinHeightPixels = 24;
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Default width and height of a panel.
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kPanelDefaultWidthPixels = 240;
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kPanelDefaultHeightPixels = 290;
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Maxmium width and height of a panel based on the factor of the working
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// area.
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst double kPanelMaxWidthFactor = 1.0;
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst double kPanelMaxHeightFactor = 0.5;
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Horizontal spacing between two panels.
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kPanelsHorizontalSpacing = 4;
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Single instance of PanelManager.
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenscoped_ptr<PanelManager> panel_instance;
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenPanelManager* PanelManager::GetInstance() {
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!panel_instance.get()) {
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    panel_instance.reset(new PanelManager());
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return panel_instance.get();
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenPanelManager::PanelManager()
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : max_width_(0),
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      max_height_(0),
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      min_x_(0),
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      current_x_(0),
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bottom_edge_y_(0),
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      dragging_panel_index_(kInvalidPanelIndex),
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      dragging_panel_original_x_(0) {
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  OnDisplayChanged();
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenPanelManager::~PanelManager() {
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(active_panels_.empty());
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(pending_panels_.empty());
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(panels_pending_to_remove_.empty());
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::OnDisplayChanged() {
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider(
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      WindowSizer::CreateDefaultMonitorInfoProvider());
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gfx::Rect work_area = info_provider->GetPrimaryMonitorWorkArea();
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  min_x_ = work_area.x();
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  current_x_ = work_area.right();
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bottom_edge_y_ = work_area.bottom();
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  max_width_ = static_cast<int>(work_area.width() * kPanelMaxWidthFactor);
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  max_height_ = static_cast<int>(work_area.height() * kPanelMaxHeightFactor);
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Rearrange(active_panels_.begin());
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenPanel* PanelManager::CreatePanel(Browser* browser) {
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gfx::Rect bounds = browser->override_bounds();
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool is_within_bounds = ComputeBoundsForNextPanel(&bounds, true);
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Panel* panel = new Panel(browser, bounds);
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (is_within_bounds)
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    active_panels_.push_back(panel);
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  else
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    pending_panels_.push_back(panel);
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return panel;
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::ProcessPending() {
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  while (!pending_panels_.empty()) {
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Panel* panel = pending_panels_.front();
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    gfx::Rect bounds = panel->bounds();
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (ComputeBoundsForNextPanel(&bounds, true)) {
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // TODO(jianli): More work to support displaying pending panels.
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      active_panels_.push_back(panel);
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pending_panels_.pop_front();
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::Remove(Panel* panel) {
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // If we're in the process of dragging, delay the removal.
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (dragging_panel_index_ != kInvalidPanelIndex) {
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    panels_pending_to_remove_.push_back(panel);
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DoRemove(panel);
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::DelayedRemove() {
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < panels_pending_to_remove_.size(); ++i)
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DoRemove(panels_pending_to_remove_[i]);
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  panels_pending_to_remove_.clear();
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::DoRemove(Panel* panel) {
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Checks the active panel list.
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ActivePanels::iterator iter =
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      find(active_panels_.begin(), active_panels_.end(), panel);
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (iter == active_panels_.end()) {
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Checks the pending panel list.
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    PendingPanels::iterator iter2 =
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        find(pending_panels_.begin(), pending_panels_.end(), panel);
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (iter2 != pending_panels_.end())
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      pending_panels_.erase(iter2);
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  current_x_ = (*iter)->bounds().x() + (*iter)->bounds().width();
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Rearrange(active_panels_.erase(iter));
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ProcessPending();
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::StartDragging(Panel* panel) {
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (size_t i = 0; i < active_panels_.size(); ++i) {
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (active_panels_[i] == panel) {
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      dragging_panel_index_ = i;
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      dragging_panel_bounds_ = panel->bounds();
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      dragging_panel_original_x_ = dragging_panel_bounds_.x();
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::Drag(int delta_x) {
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(dragging_panel_index_ != kInvalidPanelIndex);
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!delta_x)
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Moves this panel to the dragging position.
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  gfx::Rect new_bounds(active_panels_[dragging_panel_index_]->bounds());
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  new_bounds.set_x(new_bounds.x() + delta_x);
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  active_panels_[dragging_panel_index_]->SetBounds(new_bounds);
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Checks and processes other affected panels.
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (delta_x > 0)
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DragPositive(delta_x);
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  else
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DragNegative(delta_x);
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::DragNegative(int delta_x) {
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(delta_x < 0);
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Panel* dragging_panel = active_panels_[dragging_panel_index_];
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // This is the left corner of the dragging panel. We use it to check against
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // all the panels on its left.
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int dragging_panel_x = dragging_panel->bounds().x() + delta_x;
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // This is the right corner which a panel will be moved to.
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int right_x_to_move_to =
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      dragging_panel_bounds_.x() + dragging_panel_bounds_.width();
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Checks the panels to the left of the dragging panel.
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t i = dragging_panel_index_;
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t j = i + 1;
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (; j < active_panels_.size(); ++j, ++i) {
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Current panel will only be affected if the left corner of dragging
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // panel goes beyond the middle position of the current panel.
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (dragging_panel_x > active_panels_[j]->bounds().x() +
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           active_panels_[j]->bounds().width() / 2)
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Moves current panel to the new position.
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    gfx::Rect bounds(active_panels_[j]->bounds());
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bounds.set_x(right_x_to_move_to - bounds.width());
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    right_x_to_move_to -= bounds.width() + kPanelsHorizontalSpacing;
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    active_panels_[j]->SetBounds(bounds);
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Adjusts the index of current panel.
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    active_panels_[i] = active_panels_[j];
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Adjusts the position and index of dragging panel as the result of moving
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // other affected panels.
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (j != dragging_panel_index_ + 1) {
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    j--;
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    dragging_panel_bounds_.set_x(right_x_to_move_to -
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 dragging_panel_bounds_.width());
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    active_panels_[j] = dragging_panel;
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    dragging_panel_index_ = j;
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::DragPositive(int delta_x) {
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(delta_x > 0);
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Panel* dragging_panel = active_panels_[dragging_panel_index_];
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // This is the right corner of the dragging panel. We use it to check against
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // all the panels on its right.
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int dragging_panel_x = dragging_panel->bounds().x() +
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      dragging_panel->bounds().width() - 1 + delta_x;
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // This is the left corner which a panel will be moved to.
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int left_x_to_move_to = dragging_panel_bounds_.x();
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Checks the panels to the right of the dragging panel.
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int i = static_cast<int>(dragging_panel_index_);
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int j = i - 1;
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (; j >= 0; --j, --i) {
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Current panel will only be affected if the right corner of dragging
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // panel goes beyond the middle position of the current panel.
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (dragging_panel_x < active_panels_[j]->bounds().x() +
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           active_panels_[j]->bounds().width() / 2)
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      break;
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Moves current panel to the new position.
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    gfx::Rect bounds(active_panels_[j]->bounds());
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bounds.set_x(left_x_to_move_to);
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    left_x_to_move_to += bounds.width() + kPanelsHorizontalSpacing;
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    active_panels_[j]->SetBounds(bounds);
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Adjusts the index of current panel.
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    active_panels_[i] = active_panels_[j];
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Adjusts the position and index of dragging panel as the result of moving
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // other affected panels.
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (j != static_cast<int>(dragging_panel_index_) - 1) {
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    j++;
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    dragging_panel_bounds_.set_x(left_x_to_move_to);
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    active_panels_[j] = dragging_panel;
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    dragging_panel_index_ = j;
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::EndDragging(bool cancelled) {
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(dragging_panel_index_ != kInvalidPanelIndex);
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (cancelled) {
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Drag(dragging_panel_original_x_ -
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         active_panels_[dragging_panel_index_]->bounds().x());
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    active_panels_[dragging_panel_index_]->SetBounds(dragging_panel_bounds_);
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  dragging_panel_index_ = kInvalidPanelIndex;
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DelayedRemove();
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::Rearrange(ActivePanels::iterator iter_to_start) {
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (iter_to_start == active_panels_.end())
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (ActivePanels::iterator iter = iter_to_start;
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != active_panels_.end(); ++iter) {
274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    gfx::Rect new_bounds((*iter)->bounds());
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ComputeBoundsForNextPanel(&new_bounds, false);
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (new_bounds != (*iter)->bounds())
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      (*iter)->SetBounds(new_bounds);
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PanelManager::ComputeBoundsForNextPanel(gfx::Rect* bounds,
282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                             bool allow_size_change) {
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int width = bounds->width();
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int height = bounds->height();
285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Update the width and/or height to fit into our constraint.
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (allow_size_change) {
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (width == 0 && height == 0) {
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      width = kPanelDefaultWidthPixels;
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      height = kPanelDefaultHeightPixels;
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (width < kPanelMinWidthPixels)
294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      width = kPanelMinWidthPixels;
295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    else if (width > max_width_)
296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      width = max_width_;
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (height < kPanelMinHeightPixels)
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      height = kPanelMinHeightPixels;
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    else if (height > max_height_)
301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      height = max_height_;
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int x = current_x_ - width;
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int y = bottom_edge_y_ - height;
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (x < min_x_)
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  current_x_ -= width + kPanelsHorizontalSpacing;
311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bounds->SetRect(x, y, width, height);
313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::MinimizeAll() {
317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (ActivePanels::const_iterator iter = active_panels_.begin();
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != active_panels_.end(); ++iter) {
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    (*iter)->Minimize();
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::RestoreAll() {
324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (ActivePanels::const_iterator iter = active_panels_.begin();
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != active_panels_.end(); ++iter) {
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    (*iter)->Restore();
327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid PanelManager::RemoveAllActive() {
331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // This should not be called when we're in the process of dragging.
332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(dragging_panel_index_ == kInvalidPanelIndex);
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Start from the bottom to avoid reshuffling.
335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (int i = static_cast<int>(active_panels_.size()) -1; i >= 0; --i)
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    active_panels_[i]->Close();
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ProcessPending();
339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PanelManager::AreAllMinimized() const {
342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (ActivePanels::const_iterator iter = active_panels_.begin();
343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       iter != active_panels_.end(); ++iter) {
344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!(*iter)->minimized())
345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
349