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

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: Fix per feedback 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"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 const int DockedPanelStrip::kPanelMinHeight = 20; 55 const int DockedPanelStrip::kPanelMinHeight = 20;
56 56
57 DockedPanelStrip::DockedPanelStrip(PanelManager* panel_manager) 57 DockedPanelStrip::DockedPanelStrip(PanelManager* panel_manager)
58 : PanelStrip(PanelStrip::DOCKED), 58 : PanelStrip(PanelStrip::DOCKED),
59 panel_manager_(panel_manager), 59 panel_manager_(panel_manager),
60 minimized_panel_count_(0), 60 minimized_panel_count_(0),
61 are_titlebars_up_(false), 61 are_titlebars_up_(false),
62 disable_layout_refresh_(false), 62 disable_layout_refresh_(false),
63 delayed_titlebar_action_(NO_ACTION), 63 delayed_titlebar_action_(NO_ACTION),
64 titlebar_action_factory_(this) { 64 titlebar_action_factory_(this) {
65 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ = 65 dragging_panel_current_iterator_ = panels_.end();
66 panels_.end();
67 } 66 }
68 67
69 DockedPanelStrip::~DockedPanelStrip() { 68 DockedPanelStrip::~DockedPanelStrip() {
70 DCHECK(panels_.empty()); 69 DCHECK(panels_.empty());
71 DCHECK(panels_in_temporary_layout_.empty()); 70 DCHECK(panels_in_temporary_layout_.empty());
72 DCHECK_EQ(0, minimized_panel_count_); 71 DCHECK_EQ(0, minimized_panel_count_);
73 } 72 }
74 73
75 void DockedPanelStrip::SetDisplayArea(const gfx::Rect& display_area) { 74 void DockedPanelStrip::SetDisplayArea(const gfx::Rect& display_area) {
76 if (display_area_ == display_area) 75 if (display_area_ == display_area)
(...skipping 16 matching lines...) Expand all
93 int max_panel_width = GetMaxPanelWidth(); 92 int max_panel_width = GetMaxPanelWidth();
94 int max_panel_height = GetMaxPanelHeight(); 93 int max_panel_height = GetMaxPanelHeight();
95 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight), 94 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight),
96 gfx::Size(max_panel_width, max_panel_height)); 95 gfx::Size(max_panel_width, max_panel_height));
97 96
98 gfx::Size restored_size = panel->restored_size(); 97 gfx::Size restored_size = panel->restored_size();
99 int height = restored_size.height(); 98 int height = restored_size.height();
100 int width = restored_size.width(); 99 int width = restored_size.width();
101 100
102 if (panel->initialized()) { 101 if (panel->initialized()) {
103 // Bump panels in the strip to make room for this panel. 102 // Make sure we have sufficient space for this panel. We might bump
104 // Prevent layout refresh when panel is removed from this strip. 103 // panels in the strip to make room for this panel.
105 disable_layout_refresh_ = true; 104 EnsureAvailableSpace(width);
106 PanelStrip* overflow_strip = panel_manager_->overflow_strip(); 105 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 106
114 Panel::ExpansionState expansion_state_to_restore; 107 Panel::ExpansionState expansion_state_to_restore;
115 if (panel->expansion_state() == Panel::EXPANDED) { 108 if (panel->expansion_state() == Panel::EXPANDED) {
116 expansion_state_to_restore = Panel::EXPANDED; 109 expansion_state_to_restore = Panel::EXPANDED;
117 } else { 110 } else {
118 if (are_titlebars_up_ || panel->IsDrawingAttention()) { 111 if (are_titlebars_up_ || panel->IsDrawingAttention()) {
119 expansion_state_to_restore = Panel::TITLE_ONLY; 112 expansion_state_to_restore = Panel::TITLE_ONLY;
120 height = panel->TitleOnlyHeight(); 113 height = panel->TitleOnlyHeight();
121 } else { 114 } else {
122 expansion_state_to_restore = Panel::MINIMIZED; 115 expansion_state_to_restore = Panel::MINIMIZED;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 FROM_HERE, 163 FROM_HERE,
171 base::Bind(&DockedPanelStrip::DelayedMovePanelToOverflow, 164 base::Bind(&DockedPanelStrip::DelayedMovePanelToOverflow,
172 base::Unretained(this), 165 base::Unretained(this),
173 panel), 166 panel),
174 base::TimeDelta::FromMilliseconds(PanelManager::AdjustTimeInterval( 167 base::TimeDelta::FromMilliseconds(PanelManager::AdjustTimeInterval(
175 kMoveNewPanelToOverflowDelayMs))); 168 kMoveNewPanelToOverflowDelayMs)));
176 } 169 }
177 panel->Initialize(gfx::Rect(x, y, width, height)); 170 panel->Initialize(gfx::Rect(x, y, width, height));
178 } 171 }
179 172
180 // Set panel properties for this strip. 173 // Insert the panel to the end.
174 InsertPanelToCollection(panel, panels_.end());
jennb 2012/03/03 02:19:33 Don't refactor out the insertion logic as no other
jianli 2012/03/07 19:14:31 Done. Added OnPanelAdded.
175 }
176
177 void DockedPanelStrip::InsertPanelToCollection(
178 Panel* panel, Panels::iterator position) {
181 panel->SetAppIconVisibility(true); 179 panel->SetAppIconVisibility(true);
180 panel->SetAlwaysOnTop(true);
182 181
183 if (panel->has_temporary_layout()) 182 if (panel->has_temporary_layout())
184 panels_in_temporary_layout_.insert(panel); 183 panels_in_temporary_layout_.insert(panel);
185 else 184 else
186 panels_.push_back(panel); 185 panels_.insert(position, panel);
186 }
187
188 void DockedPanelStrip::EnsureAvailableSpace(int width) {
189 // Prevent layout refresh when panel is removed from this strip.
190 disable_layout_refresh_ = true;
191 PanelStrip* overflow_strip = panel_manager_->overflow_strip();
192 int x;
193 while ((x = GetRightMostAvailablePosition() - width) < display_area_.x()) {
194 DCHECK(!panels_.empty());
195 panels_.back()->MoveToStrip(overflow_strip);
196 }
197 disable_layout_refresh_ = false;
187 } 198 }
188 199
189 int DockedPanelStrip::GetMaxPanelWidth() const { 200 int DockedPanelStrip::GetMaxPanelWidth() const {
190 return static_cast<int>(display_area_.width() * kPanelMaxWidthFactor); 201 return static_cast<int>(display_area_.width() * kPanelMaxWidthFactor);
191 } 202 }
192 203
193 int DockedPanelStrip::GetMaxPanelHeight() const { 204 int DockedPanelStrip::GetMaxPanelHeight() const {
194 return display_area_.height(); 205 return display_area_.height();
195 } 206 }
196 207
(...skipping 13 matching lines...) Expand all
210 } 221 }
211 222
212 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel); 223 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel);
213 if (iter == panels_.end()) 224 if (iter == panels_.end())
214 return false; 225 return false;
215 226
216 if (panel->expansion_state() != Panel::EXPANDED) 227 if (panel->expansion_state() != Panel::EXPANDED)
217 DecrementMinimizedPanels(); 228 DecrementMinimizedPanels();
218 229
219 // Removing an element from the list will invalidate the iterator that refers 230 // 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. 231 // to it. If the dragging panel is being removed, set the dragging iterator to
221 bool update_original_dragging_iterator_after_erase = false; 232 // the end of the list.
222 if (dragging_panel_original_iterator_ != panels_.end()) { 233 if (dragging_panel_current_iterator_ == iter)
223 if (dragging_panel_current_iterator_ == iter) { 234 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 235
236 iter = panels_.erase(iter); 236 iter = panels_.erase(iter);
237 237
238 if (update_original_dragging_iterator_after_erase) 238 // Update the saved panel placement if needed. This is because we might remove
239 dragging_panel_original_iterator_ = iter; 239 // |saved_panel_placement_.panel_to_place_before_|.
240 if (saved_panel_placement_.panel &&
241 saved_panel_placement_.panel_to_place_before_ == panel) {
242 saved_panel_placement_.panel_to_place_before_ =
243 (iter == panels_.end()) ? NULL : *iter;
244 }
240 245
241 if (!disable_layout_refresh_) 246 if (!disable_layout_refresh_)
242 RefreshLayout(); 247 RefreshLayout();
243 248
244 return true; 249 return true;
245 } 250 }
246 251
247 bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const { 252 bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const {
248 // Panels with temporary layout cannot be shown as active. 253 // Panels with temporary layout cannot be shown as active.
249 return !panel->has_temporary_layout(); 254 return !panel->has_temporary_layout();
250 } 255 }
251 256
257 void DockedPanelStrip::SavePanelPlacement(Panel* panel) {
258 DCHECK(!saved_panel_placement_.panel);
259
260 saved_panel_placement_.panel = panel;
261
262 // To recover panel to its original placement, we only need to track the panel
263 // that is placed after it.
264 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel);
265 DCHECK(iter != panels_.end());
266 ++iter;
267 saved_panel_placement_.panel_to_place_before_ =
268 (iter == panels_.end()) ? NULL : *iter;
269 }
270
271 void DockedPanelStrip::LoadSavedPanelPlacement() {
272 DCHECK(saved_panel_placement_.panel);
273
274 Panel* panel = saved_panel_placement_.panel;
275 saved_panel_placement_.panel = NULL;
jennb 2012/03/03 02:19:33 leave it and call Discard at end of this method.
jianli 2012/03/07 19:14:31 Done.
276
277 // Find next panel after this panel.
278 Panels::iterator iter = std::find(panels_.begin(), panels_.end(), panel);
279 DCHECK(iter != panels_.end());
280 Panels::iterator next_iter = iter;
281 next_iter++;
282 Panel* next_panel = (next_iter == panels_.end()) ? NULL : *iter;
283
284 // If this panel is already in the right position, nothing to do.
285 if (next_panel == saved_panel_placement_.panel_to_place_before_)
286 return;
287
288 // Remove this panel from its current position.
289 panels_.erase(iter);
290
291 // Insert this panel into its previous position.
292 if (saved_panel_placement_.panel_to_place_before_) {
293 Panels::iterator iter_to_insert_before = std::find(panels_.begin(),
294 panels_.end(), saved_panel_placement_.panel_to_place_before_);
295 DCHECK(iter_to_insert_before != panels_.end());
296 panels_.insert(iter_to_insert_before, panel);
297 } else {
298 panels_.push_back(panel);
299 }
300
301 // This will automatically update all affected panels due to the insertion.
302 RefreshLayout();
303 }
304
305 void DockedPanelStrip::DiscardSavedPanelPlacement() {
306 DCHECK(saved_panel_placement_.panel);
307 saved_panel_placement_.panel = NULL;
308 }
309
252 bool DockedPanelStrip::CanDragPanel(const Panel* panel) const { 310 bool DockedPanelStrip::CanDragPanel(const Panel* panel) const {
253 // Only the panels having temporary layout can't be dragged. 311 // Only the panels having temporary layout can't be dragged.
254 return !panel->has_temporary_layout(); 312 return !panel->has_temporary_layout();
255 } 313 }
256 314
257 Panel* DockedPanelStrip::dragging_panel() const { 315 Panel* DockedPanelStrip::dragging_panel() const {
258 return dragging_panel_current_iterator_ == panels_.end() ? NULL : 316 return dragging_panel_current_iterator_ == panels_.end() ? NULL :
259 *dragging_panel_current_iterator_; 317 *dragging_panel_current_iterator_;
260 } 318 }
261 319
262 void DockedPanelStrip::StartDraggingPanel(Panel* panel) { 320 void DockedPanelStrip::StartDraggingPanelLocally(Panel* panel) {
263 dragging_panel_current_iterator_ = 321 dragging_panel_current_iterator_ =
264 find(panels_.begin(), panels_.end(), panel); 322 find(panels_.begin(), panels_.end(), panel);
265 DCHECK(dragging_panel_current_iterator_ != panels_.end()); 323 DCHECK(dragging_panel_current_iterator_ != panels_.end());
266 dragging_panel_original_iterator_ = dragging_panel_current_iterator_;
267 } 324 }
268 325
269 void DockedPanelStrip::DragPanel(Panel* panel, int delta_x, int delta_y) { 326 void DockedPanelStrip::DragPanelLocally(Panel* panel,
327 int delta_x,
328 int delta_y) {
329 DCHECK_EQ(dragging_panel(), panel);
270 if (!delta_x) 330 if (!delta_x)
271 return; 331 return;
272 332
273 // Moves this panel to the dragging position. 333 // Moves this panel to the dragging position.
274 gfx::Rect new_bounds(panel->GetBounds()); 334 gfx::Rect new_bounds(panel->GetBounds());
275 new_bounds.set_x(new_bounds.x() + delta_x); 335 new_bounds.set_x(new_bounds.x() + delta_x);
276 panel->SetPanelBounds(new_bounds); 336 panel->SetPanelBounds(new_bounds);
277 337
278 // Checks and processes other affected panels. 338 // Checks and processes other affected panels.
279 if (delta_x > 0) 339 if (delta_x > 0)
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 break; 392 break;
333 393
334 // Swaps the contents and makes |dragging_panel_current_iterator_| refers 394 // Swaps the contents and makes |dragging_panel_current_iterator_| refers
335 // to the new position. 395 // to the new position.
336 *dragging_panel_current_iterator_ = current_panel; 396 *dragging_panel_current_iterator_ = current_panel;
337 *current_panel_iterator = dragging_panel; 397 *current_panel_iterator = dragging_panel;
338 dragging_panel_current_iterator_ = current_panel_iterator; 398 dragging_panel_current_iterator_ = current_panel_iterator;
339 } 399 }
340 } 400 }
341 401
342 void DockedPanelStrip::EndDraggingPanel(Panel* panel, bool cancelled) { 402 void DockedPanelStrip::EndDraggingPanelLocally(Panel* panel, bool cancelled) {
343 if (cancelled) { 403 DCHECK_EQ(dragging_panel(), panel);
344 if (dragging_panel_current_iterator_ != dragging_panel_original_iterator_) {
345 // Find out if the dragging panel should be moved toward the end/beginning
346 // of the list.
347 bool move_towards_end_of_list = true;
348 for (Panels::iterator iter = dragging_panel_original_iterator_;
349 iter != panels_.end(); ++iter) {
350 if (iter == dragging_panel_current_iterator_) {
351 move_towards_end_of_list = false;
352 break;
353 }
354 }
355 404
356 // Move the dragging panel back to its original position by swapping it 405 dragging_panel_current_iterator_ = panels_.end();
357 // with its adjacent element until it reach its original position. 406
358 while (dragging_panel_current_iterator_ != 407 // If the drag is cancelled, we don't want to move the dragging panel to the
jennb 2012/03/03 02:19:33 Maybe explain a bit about what is expected to happ
jianli 2012/03/07 19:14:31 Done.
359 dragging_panel_original_iterator_) { 408 // finalized position.
360 Panels::iterator next_iter = dragging_panel_current_iterator_; 409 if (!cancelled)
361 if (move_towards_end_of_list) 410 RefreshLayout();
362 ++next_iter; 411 }
363 else 412
364 --next_iter; 413 void DockedPanelStrip::AddDraggingPanel(Panel* panel,
365 iter_swap(dragging_panel_current_iterator_, next_iter); 414 const gfx::Point& position) {
366 dragging_panel_current_iterator_ = next_iter; 415 DCHECK_NE(this, panel->panel_strip());
367 } 416 panel->set_panel_strip(this);
368 } 417
418 gfx::Rect new_bounds(panel->GetBounds());
419 new_bounds.set_origin(position);
420 panel->SetPanelBounds(new_bounds);
421
422 EnsureAvailableSpace(panel->GetBounds().width());
423
424 int x = panel->GetBounds().x();
425 Panels::iterator iter = panels_.begin();
426 for (; iter != panels_.end(); ++iter) {
427 Panel* current_panel = *iter;
jennb 2012/03/03 02:19:33 I was confusing current_panel with the panel you'r
jianli 2012/03/07 19:14:31 Dropped the temporary vars.
428 gfx::Rect current_bounds = current_panel->GetBounds();
429 if (x > current_bounds.x())
430 break;
369 } 431 }
432 InsertPanelToCollection(panel, iter);
370 433
371 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ = 434 StartDraggingPanelLocally(panel);
372 panels_.end();
373 435
436 // This will automatically update all affected panels due to the insertion.
374 RefreshLayout(); 437 RefreshLayout();
375 } 438 }
376 439
377 void DockedPanelStrip::OnPanelExpansionStateChanged(Panel* panel) { 440 void DockedPanelStrip::OnPanelExpansionStateChanged(Panel* panel) {
378 gfx::Size size = panel->restored_size(); 441 gfx::Size size = panel->restored_size();
379 Panel::ExpansionState expansion_state = panel->expansion_state(); 442 Panel::ExpansionState expansion_state = panel->expansion_state();
380 Panel::ExpansionState old_state = panel->old_expansion_state(); 443 Panel::ExpansionState old_state = panel->old_expansion_state();
381 switch (expansion_state) { 444 switch (expansion_state) {
382 case Panel::EXPANDED: 445 case Panel::EXPANDED:
383 if (old_state == Panel::TITLE_ONLY || old_state == Panel::MINIMIZED) 446 if (old_state == Panel::TITLE_ONLY || old_state == Panel::MINIMIZED)
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 DCHECK(panels_in_temporary_layout_.empty()); 810 DCHECK(panels_in_temporary_layout_.empty());
748 811
749 // Make a copy of the iterator as closing panels can modify the vector. 812 // Make a copy of the iterator as closing panels can modify the vector.
750 Panels panels_copy = panels_; 813 Panels panels_copy = panels_;
751 814
752 // Start from the bottom to avoid reshuffling. 815 // Start from the bottom to avoid reshuffling.
753 for (Panels::reverse_iterator iter = panels_copy.rbegin(); 816 for (Panels::reverse_iterator iter = panels_copy.rbegin();
754 iter != panels_copy.rend(); ++iter) 817 iter != panels_copy.rend(); ++iter)
755 (*iter)->Close(); 818 (*iter)->Close();
756 } 819 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698