Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: chrome/browser/ui/panels/docked_panel_strip.cc

Issue 9546001: Support detaching/attaching panels via inter-strip drags. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/panels/docked_panel_strip.h" 5 #include "chrome/browser/ui/panels/docked_panel_strip.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/message_loop.h" 12 #include "base/message_loop.h"
13 #include "chrome/browser/ui/browser.h" 13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/panels/overflow_panel_strip.h" 14 #include "chrome/browser/ui/panels/overflow_panel_strip.h"
15 #include "chrome/browser/ui/panels/panel_drag_controller.h"
15 #include "chrome/browser/ui/panels/panel_manager.h" 16 #include "chrome/browser/ui/panels/panel_manager.h"
16 #include "chrome/browser/ui/panels/panel_mouse_watcher.h" 17 #include "chrome/browser/ui/panels/panel_mouse_watcher.h"
17 #include "chrome/common/chrome_notification_types.h" 18 #include "chrome/common/chrome_notification_types.h"
18 #include "content/public/browser/notification_service.h" 19 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_source.h" 20 #include "content/public/browser/notification_source.h"
20 21
21 namespace { 22 namespace {
22 // Width to height ratio is used to compute the default width or height 23 // Width to height ratio is used to compute the default width or height
23 // when only one value is provided. 24 // when only one value is provided.
24 const double kPanelDefaultWidthToHeightRatio = 1.62; // golden ratio 25 const double kPanelDefaultWidthToHeightRatio = 1.62; // golden ratio
(...skipping 28 matching lines...) Expand all
53 // static 54 // static
54 const int DockedPanelStrip::kPanelMinWidth = 100; 55 const int DockedPanelStrip::kPanelMinWidth = 100;
55 const int DockedPanelStrip::kPanelMinHeight = 20; 56 const int DockedPanelStrip::kPanelMinHeight = 20;
56 57
57 DockedPanelStrip::DockedPanelStrip(PanelManager* panel_manager) 58 DockedPanelStrip::DockedPanelStrip(PanelManager* panel_manager)
58 : PanelStrip(PanelStrip::DOCKED), 59 : PanelStrip(PanelStrip::DOCKED),
59 panel_manager_(panel_manager), 60 panel_manager_(panel_manager),
60 minimized_panel_count_(0), 61 minimized_panel_count_(0),
61 are_titlebars_up_(false), 62 are_titlebars_up_(false),
62 disable_layout_refresh_(false), 63 disable_layout_refresh_(false),
64 panel_to_restore_after_on_drag_cancelled_(NULL),
63 delayed_titlebar_action_(NO_ACTION), 65 delayed_titlebar_action_(NO_ACTION),
64 titlebar_action_factory_(this) { 66 titlebar_action_factory_(this) {
65 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ = 67 dragging_panel_current_iterator_ = panels_.end();
66 panels_.end();
67 } 68 }
68 69
69 DockedPanelStrip::~DockedPanelStrip() { 70 DockedPanelStrip::~DockedPanelStrip() {
70 DCHECK(panels_.empty()); 71 DCHECK(panels_.empty());
71 DCHECK(panels_in_temporary_layout_.empty()); 72 DCHECK(panels_in_temporary_layout_.empty());
72 DCHECK_EQ(0, minimized_panel_count_); 73 DCHECK_EQ(0, minimized_panel_count_);
73 } 74 }
74 75
75 void DockedPanelStrip::SetDisplayArea(const gfx::Rect& display_area) { 76 void DockedPanelStrip::SetDisplayArea(const gfx::Rect& display_area) {
76 if (display_area_ == display_area) 77 if (display_area_ == display_area)
(...skipping 16 matching lines...) Expand all
93 int max_panel_width = GetMaxPanelWidth(); 94 int max_panel_width = GetMaxPanelWidth();
94 int max_panel_height = GetMaxPanelHeight(); 95 int max_panel_height = GetMaxPanelHeight();
95 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight), 96 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight),
96 gfx::Size(max_panel_width, max_panel_height)); 97 gfx::Size(max_panel_width, max_panel_height));
97 98
98 gfx::Size restored_size = panel->restored_size(); 99 gfx::Size restored_size = panel->restored_size();
99 int height = restored_size.height(); 100 int height = restored_size.height();
100 int width = restored_size.width(); 101 int width = restored_size.width();
101 102
102 if (panel->initialized()) { 103 if (panel->initialized()) {
103 // Bump panels in the strip to make room for this panel. 104 // Make sure we have sufficient space for this panel. We might bump
104 // Prevent layout refresh when panel is removed from this strip. 105 // panels in the strip to make room for this panel.
105 disable_layout_refresh_ = true; 106 EnsureEnoughSpaceForPanel(width);
106 PanelStrip* overflow_strip = panel_manager_->overflow_strip(); 107 int x = GetRightMostAvailablePosition() - width;
107 int x;
108 while ((x = GetRightMostAvailablePosition() - width) < display_area_.x()) {
109 DCHECK(!panels_.empty());
110 panels_.back()->MoveToStrip(overflow_strip);
111 }
112 disable_layout_refresh_ = false;
113 108
114 Panel::ExpansionState expansion_state_to_restore; 109 Panel::ExpansionState expansion_state_to_restore;
115 if (panel->expansion_state() == Panel::EXPANDED) { 110 if (panel->expansion_state() == Panel::EXPANDED) {
116 expansion_state_to_restore = Panel::EXPANDED; 111 expansion_state_to_restore = Panel::EXPANDED;
117 } else { 112 } else {
118 if (are_titlebars_up_ || panel->IsDrawingAttention()) { 113 if (are_titlebars_up_ || panel->IsDrawingAttention()) {
119 expansion_state_to_restore = Panel::TITLE_ONLY; 114 expansion_state_to_restore = Panel::TITLE_ONLY;
120 height = panel->TitleOnlyHeight(); 115 height = panel->TitleOnlyHeight();
121 } else { 116 } else {
122 expansion_state_to_restore = Panel::MINIMIZED; 117 expansion_state_to_restore = Panel::MINIMIZED;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 174
180 // Set panel properties for this strip. 175 // Set panel properties for this strip.
181 panel->SetAppIconVisibility(true); 176 panel->SetAppIconVisibility(true);
182 177
183 if (panel->has_temporary_layout()) 178 if (panel->has_temporary_layout())
184 panels_in_temporary_layout_.insert(panel); 179 panels_in_temporary_layout_.insert(panel);
185 else 180 else
186 panels_.push_back(panel); 181 panels_.push_back(panel);
187 } 182 }
188 183
184 void DockedPanelStrip::AddPanelAtPosition(Panel* panel,
185 const gfx::Point& position) {
186 // First, make sure we have sufficient space for this panel. We might bump
187 // panels in the strip to make room for this panel.
188 EnsureEnoughSpaceForPanel(panel->GetBounds().width());
189
190 // Set panel properties for this strip.
jennb 2012/03/01 00:33:38 Wish this method and AddPanels() could be consolid
jianli 2012/03/02 22:42:43 I agree but it will involve quite a bit of refacto
191 panel->SetAppIconVisibility(true);
192
193 // Then, find and insert this panel to the right position.
194 int x = position.x();
195 Panels::iterator iter = panels_.begin();
196 for (; iter != panels_.end(); ++iter) {
197 Panel* current_panel = *iter;
198 gfx::Rect current_bounds = current_panel->GetBounds();
199 if (x > current_bounds.x())
200 break;
201 }
202 panels_.insert(iter, panel);
203
204 gfx::Rect new_bounds(panel->GetBounds());
jennb 2012/03/01 00:33:38 Won't refresh layout update the panel bounds corre
jianli 2012/03/02 22:42:43 RefreshLayout will not update the dragging panel.
205 new_bounds.set_origin(position);
206 panel->SetPanelBounds(new_bounds);
207
208 // This will automatically update all affected panels due to the insertion.
209 RefreshLayout();
210 }
211
212 void DockedPanelStrip::EnsureEnoughSpaceForPanel(int width) {
213 // Prevent layout refresh when panel is removed from this strip.
214 disable_layout_refresh_ = true;
215 PanelStrip* overflow_strip = panel_manager_->overflow_strip();
216 int x;
217 while ((x = GetRightMostAvailablePosition() - width) < display_area_.x()) {
218 DCHECK(!panels_.empty());
219 panels_.back()->MoveToStrip(overflow_strip);
220 }
221 disable_layout_refresh_ = false;
222 }
223
189 int DockedPanelStrip::GetMaxPanelWidth() const { 224 int DockedPanelStrip::GetMaxPanelWidth() const {
190 return static_cast<int>(display_area_.width() * kPanelMaxWidthFactor); 225 return static_cast<int>(display_area_.width() * kPanelMaxWidthFactor);
191 } 226 }
192 227
193 int DockedPanelStrip::GetMaxPanelHeight() const { 228 int DockedPanelStrip::GetMaxPanelHeight() const {
194 return display_area_.height(); 229 return display_area_.height();
195 } 230 }
196 231
197 int DockedPanelStrip::StartingRightPosition() const { 232 int DockedPanelStrip::StartingRightPosition() const {
198 return display_area_.right(); 233 return display_area_.right();
(...skipping 11 matching lines...) Expand all
210 } 245 }
211 246
212 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel); 247 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel);
213 if (iter == panels_.end()) 248 if (iter == panels_.end())
214 return false; 249 return false;
215 250
216 if (panel->expansion_state() != Panel::EXPANDED) 251 if (panel->expansion_state() != Panel::EXPANDED)
217 DecrementMinimizedPanels(); 252 DecrementMinimizedPanels();
218 253
219 // Removing an element from the list will invalidate the iterator that refers 254 // Removing an element from the list will invalidate the iterator that refers
220 // to it. So we need to check if the dragging panel iterators are affected. 255 // to it. If the dragging panel is being removed, set the dragging iterator to
221 bool update_original_dragging_iterator_after_erase = false; 256 // the end of the list.
222 if (dragging_panel_original_iterator_ != panels_.end()) { 257 if (dragging_panel_current_iterator_ == iter)
223 if (dragging_panel_current_iterator_ == iter) { 258 dragging_panel_current_iterator_ = panels_.end();
224 // If the dragging panel is being removed, set both dragging iterators to
225 // the end of the list.
226 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ =
227 panels_.end();
228 } else if (dragging_panel_original_iterator_ == iter) {
229 // If |dragging_panel_original_iterator_| refers to the element being
230 // removed, set the flag so that the iterator can be updated to next
231 // element.
232 update_original_dragging_iterator_after_erase = true;
233 }
234 }
235 259
236 iter = panels_.erase(iter); 260 iter = panels_.erase(iter);
237 261
238 if (update_original_dragging_iterator_after_erase) 262 // If |panel_to_restore_after_on_drag_cancelled_| is removed, update it to
239 dragging_panel_original_iterator_ = iter; 263 // the next panel after the panel being removed.
264 if (panel == panel_to_restore_after_on_drag_cancelled_) {
265 panel_to_restore_after_on_drag_cancelled_ =
266 (iter == panels_.end()) ? NULL : *iter;
267 }
240 268
241 if (!disable_layout_refresh_) 269 if (!disable_layout_refresh_)
242 RefreshLayout(); 270 RefreshLayout();
243 271
244 return true; 272 return true;
245 } 273 }
246 274
247 bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const { 275 bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const {
248 // Panels with temporary layout cannot be shown as active. 276 // Panels with temporary layout cannot be shown as active.
249 return !panel->has_temporary_layout(); 277 return !panel->has_temporary_layout();
250 } 278 }
251 279
252 bool DockedPanelStrip::CanDragPanel(const Panel* panel) const { 280 bool DockedPanelStrip::CanDragPanel(const Panel* panel) const {
253 // Only the panels having temporary layout can't be dragged. 281 // Only the panels having temporary layout can't be dragged.
254 return !panel->has_temporary_layout(); 282 return !panel->has_temporary_layout();
255 } 283 }
256 284
257 Panel* DockedPanelStrip::dragging_panel() const { 285 Panel* DockedPanelStrip::dragging_panel() const {
258 return dragging_panel_current_iterator_ == panels_.end() ? NULL : 286 Panel* dragging_panel = panel_manager_->drag_controller()->dragging_panel();
259 *dragging_panel_current_iterator_; 287 return (dragging_panel && dragging_panel->panel_strip() == this) ?
288 dragging_panel : NULL;
260 } 289 }
261 290
262 void DockedPanelStrip::StartDraggingPanel(Panel* panel) { 291 void DockedPanelStrip::StartDraggingPanel(Panel* panel) {
263 dragging_panel_current_iterator_ = 292 dragging_panel_current_iterator_ =
264 find(panels_.begin(), panels_.end(), panel); 293 find(panels_.begin(), panels_.end(), panel);
265 DCHECK(dragging_panel_current_iterator_ != panels_.end()); 294 DCHECK(dragging_panel_current_iterator_ != panels_.end());
266 dragging_panel_original_iterator_ = dragging_panel_current_iterator_; 295
296 // Remember the panel to restore after. We only need to do it once when the
297 // dragging panel does not leave the docked strip.
298 if (!panel_manager_->drag_controller()->has_dragged_to_other_strip()) {
299 panel_to_restore_after_on_drag_cancelled_ =
300 GetNextPanel(dragging_panel_current_iterator_);
301 }
267 } 302 }
268 303
269 void DockedPanelStrip::DragPanel(Panel* panel, int delta_x, int delta_y) { 304 void DockedPanelStrip::DragPanel(Panel* panel, int delta_x, int delta_y) {
270 if (!delta_x) 305 if (!delta_x)
271 return; 306 return;
272 307
273 // Moves this panel to the dragging position. 308 // Moves this panel to the dragging position.
274 gfx::Rect new_bounds(panel->GetBounds()); 309 gfx::Rect new_bounds(panel->GetBounds());
275 new_bounds.set_x(new_bounds.x() + delta_x); 310 new_bounds.set_x(new_bounds.x() + delta_x);
276 panel->SetPanelBounds(new_bounds); 311 panel->SetPanelBounds(new_bounds);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 // Swaps the contents and makes |dragging_panel_current_iterator_| refers 369 // Swaps the contents and makes |dragging_panel_current_iterator_| refers
335 // to the new position. 370 // to the new position.
336 *dragging_panel_current_iterator_ = current_panel; 371 *dragging_panel_current_iterator_ = current_panel;
337 *current_panel_iterator = dragging_panel; 372 *current_panel_iterator = dragging_panel;
338 dragging_panel_current_iterator_ = current_panel_iterator; 373 dragging_panel_current_iterator_ = current_panel_iterator;
339 } 374 }
340 } 375 }
341 376
342 void DockedPanelStrip::EndDraggingPanel(Panel* panel, bool cancelled) { 377 void DockedPanelStrip::EndDraggingPanel(Panel* panel, bool cancelled) {
343 if (cancelled) { 378 if (cancelled) {
344 if (dragging_panel_current_iterator_ != dragging_panel_original_iterator_) { 379 Panels::iterator next_iter = dragging_panel_current_iterator_;
345 // Find out if the dragging panel should be moved toward the end/beginning 380 ++next_iter;
346 // of the list. 381 if (panel_to_restore_after_on_drag_cancelled_ !=
347 bool move_towards_end_of_list = true; 382 GetNextPanel(dragging_panel_current_iterator_)) {
348 for (Panels::iterator iter = dragging_panel_original_iterator_; 383 // Remove the dragging panel from current position.
349 iter != panels_.end(); ++iter) { 384 panels_.erase(dragging_panel_current_iterator_);
350 if (iter == dragging_panel_current_iterator_) {
351 move_towards_end_of_list = false;
352 break;
353 }
354 }
355 385
356 // Move the dragging panel back to its original position by swapping it 386 // Insert the dragging panel to the restore position.
357 // with its adjacent element until it reach its original position. 387 if (panel_to_restore_after_on_drag_cancelled_) {
358 while (dragging_panel_current_iterator_ != 388 Panels::iterator iter_to_restore_after = std::find(panels_.begin(),
359 dragging_panel_original_iterator_) { 389 panels_.end(), panel_to_restore_after_on_drag_cancelled_);
360 Panels::iterator next_iter = dragging_panel_current_iterator_; 390 DCHECK(iter_to_restore_after != panels_.end());
361 if (move_towards_end_of_list) 391 panels_.insert(iter_to_restore_after, panel);
362 ++next_iter; 392 } else {
363 else 393 panels_.push_back(panel);
364 --next_iter;
365 iter_swap(dragging_panel_current_iterator_, next_iter);
366 dragging_panel_current_iterator_ = next_iter;
367 } 394 }
368 } 395 }
369 } 396 }
370 397
371 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ = 398 dragging_panel_current_iterator_ = panels_.end();
372 panels_.end();
373 399
374 RefreshLayout(); 400 RefreshLayout();
375 } 401 }
376 402
377 void DockedPanelStrip::OnPanelExpansionStateChanged(Panel* panel) { 403 void DockedPanelStrip::OnPanelExpansionStateChanged(Panel* panel) {
378 gfx::Size size = panel->restored_size(); 404 gfx::Size size = panel->restored_size();
379 Panel::ExpansionState expansion_state = panel->expansion_state(); 405 Panel::ExpansionState expansion_state = panel->expansion_state();
380 Panel::ExpansionState old_state = panel->old_expansion_state(); 406 Panel::ExpansionState old_state = panel->old_expansion_state();
381 switch (expansion_state) { 407 switch (expansion_state) {
382 case Panel::EXPANDED: 408 case Panel::EXPANDED:
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 DCHECK(panels_in_temporary_layout_.empty()); 773 DCHECK(panels_in_temporary_layout_.empty());
748 774
749 // Make a copy of the iterator as closing panels can modify the vector. 775 // Make a copy of the iterator as closing panels can modify the vector.
750 Panels panels_copy = panels_; 776 Panels panels_copy = panels_;
751 777
752 // Start from the bottom to avoid reshuffling. 778 // Start from the bottom to avoid reshuffling.
753 for (Panels::reverse_iterator iter = panels_copy.rbegin(); 779 for (Panels::reverse_iterator iter = panels_copy.rbegin();
754 iter != panels_copy.rend(); ++iter) 780 iter != panels_copy.rend(); ++iter)
755 (*iter)->Close(); 781 (*iter)->Close();
756 } 782 }
783
784 Panel* DockedPanelStrip::GetNextPanel(const Panels::iterator& iter) const {
785 DCHECK(iter != panels_.end());
786 Panels::iterator next_iter = iter;
787 ++next_iter;
788 return (next_iter == panels_.end()) ? NULL : *next_iter;
789 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698