Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |