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" |
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" | |
15 #include "chrome/browser/ui/panels/panel_manager.h" | 14 #include "chrome/browser/ui/panels/panel_manager.h" |
16 #include "chrome/browser/ui/panels/panel_mouse_watcher.h" | 15 #include "chrome/browser/ui/panels/panel_mouse_watcher.h" |
17 #include "chrome/common/chrome_notification_types.h" | 16 #include "chrome/common/chrome_notification_types.h" |
18 #include "content/public/browser/notification_service.h" | 17 #include "content/public/browser/notification_service.h" |
19 #include "content/public/browser/notification_source.h" | 18 #include "content/public/browser/notification_source.h" |
20 | 19 |
21 namespace { | 20 namespace { |
22 // Width to height ratio is used to compute the default width or height | 21 // Width to height ratio is used to compute the default width or height |
23 // when only one value is provided. | 22 // when only one value is provided. |
24 const double kPanelDefaultWidthToHeightRatio = 1.62; // golden ratio | 23 const double kPanelDefaultWidthToHeightRatio = 1.62; // golden ratio |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 gfx::Rect old_area = display_area_; | 78 gfx::Rect old_area = display_area_; |
80 display_area_ = display_area; | 79 display_area_ = display_area; |
81 | 80 |
82 if (panels_.empty()) | 81 if (panels_.empty()) |
83 return; | 82 return; |
84 | 83 |
85 RefreshLayout(); | 84 RefreshLayout(); |
86 } | 85 } |
87 | 86 |
88 void DockedPanelStrip::AddPanel(Panel* panel) { | 87 void DockedPanelStrip::AddPanel(Panel* panel) { |
89 DCHECK_EQ(this, panel->panel_strip()); | 88 DCHECK_NE(this, panel->panel_strip()); |
89 panel->set_panel_strip(this); | |
90 | 90 |
91 // Always update limits, even for exiting panels, in case the maximums changed | 91 // Always update limits, even on existing panels, in case the limits changed |
92 // while panel was out of the strip. | 92 // while panel was out of the strip. |
93 int max_panel_width = GetMaxPanelWidth(); | 93 int max_panel_width = GetMaxPanelWidth(); |
94 int max_panel_height = GetMaxPanelHeight(); | 94 int max_panel_height = GetMaxPanelHeight(); |
95 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight), | 95 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight), |
96 gfx::Size(max_panel_width, max_panel_height)); | 96 gfx::Size(max_panel_width, max_panel_height)); |
97 | 97 |
98 gfx::Size restored_size = panel->restored_size(); | 98 gfx::Size restored_size = panel->restored_size(); |
99 int height = restored_size.height(); | 99 int height = restored_size.height(); |
100 int width = restored_size.width(); | 100 int width = restored_size.width(); |
101 | 101 |
102 if (panel->initialized()) { | 102 if (panel->initialized()) { |
103 // Bump panels in the strip to make room for this panel. | 103 EnsureAvailableSpace(width); |
104 // Prevent layout refresh when panel is removed from this strip. | 104 int x = GetRightMostAvailablePosition() - width; |
105 disable_layout_refresh_ = true; | |
106 PanelStrip* overflow_strip = panel_manager_->overflow_strip(); | |
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 | 105 |
114 Panel::ExpansionState expansion_state_to_restore; | 106 Panel::ExpansionState expansion_state_to_restore; |
115 if (panel->expansion_state() == Panel::EXPANDED) { | 107 if (panel->expansion_state() == Panel::EXPANDED) { |
116 expansion_state_to_restore = Panel::EXPANDED; | 108 expansion_state_to_restore = Panel::EXPANDED; |
117 } else { | 109 } else { |
118 if (are_titlebars_up_ || panel->IsDrawingAttention()) { | 110 if (are_titlebars_up_ || panel->IsDrawingAttention()) { |
119 expansion_state_to_restore = Panel::TITLE_ONLY; | 111 expansion_state_to_restore = Panel::TITLE_ONLY; |
120 height = panel->TitleOnlyHeight(); | 112 height = panel->TitleOnlyHeight(); |
121 } else { | 113 } else { |
122 expansion_state_to_restore = Panel::MINIMIZED; | 114 expansion_state_to_restore = Panel::MINIMIZED; |
123 height = Panel::kMinimizedPanelHeight; | 115 height = Panel::kMinimizedPanelHeight; |
124 } | 116 } |
125 IncrementMinimizedPanels(); | 117 IncrementMinimizedPanels(); |
126 } | 118 } |
127 | |
128 int y = | 119 int y = |
129 GetBottomPositionForExpansionState(expansion_state_to_restore) - height; | 120 GetBottomPositionForExpansionState(expansion_state_to_restore) - height; |
130 panel->SetPanelBounds(gfx::Rect(x, y, width, height)); | 121 panel->SetPanelBounds(gfx::Rect(x, y, width, height)); |
131 | 122 |
132 // Update the minimized state to reflect current titlebar mode. | 123 // Update the minimized state to reflect current titlebar mode. |
133 // Do this AFTER setting panel bounds to avoid an extra bounds change. | 124 // Do this AFTER setting panel bounds to avoid an extra bounds change. |
134 if (panel->expansion_state() != Panel::EXPANDED) | 125 if (panel->expansion_state() != Panel::EXPANDED) |
135 panel->SetExpansionState(expansion_state_to_restore); | 126 panel->SetExpansionState(expansion_state_to_restore); |
136 | 127 |
137 } else { | 128 } else { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
196 | 187 |
197 int DockedPanelStrip::StartingRightPosition() const { | 188 int DockedPanelStrip::StartingRightPosition() const { |
198 return display_area_.right(); | 189 return display_area_.right(); |
199 } | 190 } |
200 | 191 |
201 int DockedPanelStrip::GetRightMostAvailablePosition() const { | 192 int DockedPanelStrip::GetRightMostAvailablePosition() const { |
202 return panels_.empty() ? StartingRightPosition() : | 193 return panels_.empty() ? StartingRightPosition() : |
203 (panels_.back()->GetBounds().x() - kPanelsHorizontalSpacing); | 194 (panels_.back()->GetBounds().x() - kPanelsHorizontalSpacing); |
204 } | 195 } |
205 | 196 |
206 bool DockedPanelStrip::RemovePanel(Panel* panel) { | 197 void DockedPanelStrip::RemovePanel(Panel* panel) { |
198 DCHECK_EQ(this, panel->panel_strip()); | |
199 panel->set_panel_strip(NULL); | |
200 | |
207 if (panel->has_temporary_layout()) { | 201 if (panel->has_temporary_layout()) { |
208 panels_in_temporary_layout_.erase(panel); | 202 panels_in_temporary_layout_.erase(panel); |
209 return true; | 203 return; |
210 } | 204 } |
211 | 205 |
212 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel); | 206 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel); |
213 if (iter == panels_.end()) | 207 DCHECK(iter != panels_.end()); |
214 return false; | |
215 | 208 |
216 if (panel->expansion_state() != Panel::EXPANDED) | 209 if (panel->expansion_state() != Panel::EXPANDED) |
217 DecrementMinimizedPanels(); | 210 DecrementMinimizedPanels(); |
218 | 211 |
219 // Removing an element from the list will invalidate the iterator that refers | 212 // 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. | 213 // to it. So we need to update the iterator in that case. |
221 bool update_original_dragging_iterator_after_erase = false; | 214 DCHECK(dragging_panel_current_iterator_ != iter); |
222 if (dragging_panel_original_iterator_ != panels_.end()) { | 215 bool update_iterator_after_erase = |
223 if (dragging_panel_current_iterator_ == iter) { | 216 (dragging_panel_original_iterator_ == iter); |
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 | 217 |
236 iter = panels_.erase(iter); | 218 iter = panels_.erase(iter); |
237 | 219 |
238 if (update_original_dragging_iterator_after_erase) | 220 if (update_iterator_after_erase) |
239 dragging_panel_original_iterator_ = iter; | 221 dragging_panel_original_iterator_ = iter; |
240 | 222 |
241 if (!disable_layout_refresh_) | 223 if (!disable_layout_refresh_) |
242 RefreshLayout(); | 224 RefreshLayout(); |
243 | |
244 return true; | |
245 } | 225 } |
246 | 226 |
247 bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const { | 227 bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const { |
248 // Panels with temporary layout cannot be shown as active. | 228 // Panels with temporary layout cannot be shown as active. |
249 return !panel->has_temporary_layout(); | 229 return !panel->has_temporary_layout(); |
250 } | 230 } |
251 | 231 |
252 bool DockedPanelStrip::CanDragPanel(const Panel* panel) const { | 232 bool DockedPanelStrip::CanDragPanel(const Panel* panel) const { |
253 // Only the panels having temporary layout can't be dragged. | 233 // Only the panels having temporary layout can't be dragged. |
254 return !panel->has_temporary_layout(); | 234 return !panel->has_temporary_layout(); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
436 | 416 |
437 panel->SetExpansionState(panel->IsDrawingAttention() ? | 417 panel->SetExpansionState(panel->IsDrawingAttention() ? |
438 Panel::TITLE_ONLY : Panel::MINIMIZED); | 418 Panel::TITLE_ONLY : Panel::MINIMIZED); |
439 } | 419 } |
440 | 420 |
441 void DockedPanelStrip::RestorePanel(Panel* panel) { | 421 void DockedPanelStrip::RestorePanel(Panel* panel) { |
442 DCHECK_EQ(this, panel->panel_strip()); | 422 DCHECK_EQ(this, panel->panel_strip()); |
443 panel->SetExpansionState(Panel::EXPANDED); | 423 panel->SetExpansionState(Panel::EXPANDED); |
444 } | 424 } |
445 | 425 |
426 bool DockedPanelStrip::IsPanelMinimized(const Panel* panel) const { | |
427 return panel->expansion_state() != Panel::EXPANDED; | |
428 } | |
429 | |
446 void DockedPanelStrip::IncrementMinimizedPanels() { | 430 void DockedPanelStrip::IncrementMinimizedPanels() { |
447 minimized_panel_count_++; | 431 minimized_panel_count_++; |
448 if (minimized_panel_count_ == 1) | 432 if (minimized_panel_count_ == 1) |
449 panel_manager_->mouse_watcher()->AddObserver(this); | 433 panel_manager_->mouse_watcher()->AddObserver(this); |
450 DCHECK_LE(minimized_panel_count_, num_panels()); | 434 DCHECK_LE(minimized_panel_count_, num_panels()); |
451 } | 435 } |
452 | 436 |
453 void DockedPanelStrip::DecrementMinimizedPanels() { | 437 void DockedPanelStrip::DecrementMinimizedPanels() { |
454 minimized_panel_count_--; | 438 minimized_panel_count_--; |
455 DCHECK_GE(minimized_panel_count_, 0); | 439 DCHECK_GE(minimized_panel_count_, 0); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
672 delayed_titlebar_action_ = NO_ACTION; | 656 delayed_titlebar_action_ = NO_ACTION; |
673 } | 657 } |
674 | 658 |
675 void DockedPanelStrip::OnFullScreenModeChanged(bool is_full_screen) { | 659 void DockedPanelStrip::OnFullScreenModeChanged(bool is_full_screen) { |
676 for (Panels::const_iterator iter = panels_.begin(); | 660 for (Panels::const_iterator iter = panels_.begin(); |
677 iter != panels_.end(); ++iter) { | 661 iter != panels_.end(); ++iter) { |
678 (*iter)->FullScreenModeChanged(is_full_screen); | 662 (*iter)->FullScreenModeChanged(is_full_screen); |
679 } | 663 } |
680 } | 664 } |
681 | 665 |
666 bool DockedPanelStrip::CanFitPanel(Panel* panel) { | |
667 int width = panel->GetRestoredBounds().width(); | |
668 return GetRightMostAvailablePosition() - width >= display_area_.x(); | |
669 } | |
670 | |
682 void DockedPanelStrip::RefreshLayout() { | 671 void DockedPanelStrip::RefreshLayout() { |
683 int rightmost_position = StartingRightPosition(); | 672 int rightmost_position = StartingRightPosition(); |
684 | 673 |
685 Panels::const_iterator panel_iter = panels_.begin(); | 674 Panels::const_iterator panel_iter = panels_.begin(); |
686 for (; panel_iter != panels_.end(); ++panel_iter) { | 675 for (; panel_iter != panels_.end(); ++panel_iter) { |
687 Panel* panel = *panel_iter; | 676 Panel* panel = *panel_iter; |
688 gfx::Rect new_bounds(panel->GetBounds()); | 677 gfx::Rect new_bounds(panel->GetBounds()); |
689 int x = rightmost_position - new_bounds.width(); | 678 int x = rightmost_position - new_bounds.width(); |
690 | 679 |
691 if (x < display_area_.x()) | 680 if (x < display_area_.x()) |
692 break; | 681 break; |
693 | 682 |
694 // Don't update the docked panel that is currently dragged. | 683 // Don't update the docked panel that is currently dragged. |
695 if (panel != dragging_panel()) { | 684 if (panel != dragging_panel()) { |
696 new_bounds.set_x(x); | 685 new_bounds.set_x(x); |
697 new_bounds.set_y( | 686 new_bounds.set_y( |
698 GetBottomPositionForExpansionState(panel->expansion_state()) - | 687 GetBottomPositionForExpansionState(panel->expansion_state()) - |
699 new_bounds.height()); | 688 new_bounds.height()); |
700 panel->SetPanelBounds(new_bounds); | 689 panel->SetPanelBounds(new_bounds); |
701 } | 690 } |
702 | 691 |
703 rightmost_position = x - kPanelsHorizontalSpacing; | 692 rightmost_position = x - kPanelsHorizontalSpacing; |
704 } | 693 } |
705 | 694 |
706 // Add/remove panels from/to overflow. A change in work area or the | 695 // Add/remove panels from/to overflow. A change in work area or the |
707 // resize/removal of a panel may affect how many panels fit in the strip. | 696 // resize/removal of a panel may affect how many panels fit in the strip. |
708 OverflowPanelStrip* overflow_strip = panel_manager_->overflow_strip(); | 697 if (panel_iter != panels_.end()) |
709 if (panel_iter != panels_.end()) { | 698 MovePanelsToOverflow(*panel_iter); |
710 // Prevent layout refresh when panel is removed from this strip. | 699 else |
711 disable_layout_refresh_ = true; | 700 panel_manager_->MovePanelsOutOfOverflowIfCanFit(); |
jianli
2012/03/02 00:11:41
MovePanelsToOverflow and panel_manager_->MovePanel
jennb
2012/03/02 01:26:32
Moved the former to PanelManager as well. Adding p
| |
701 } | |
712 | 702 |
713 // Keep track of panels to move to overflow in a separate storage since | 703 void DockedPanelStrip::MovePanelsToOverflow(Panel* overflow_point) { |
714 // removing it from the list will invalidate the iterator. | 704 // Prevent layout refresh when panels are bumped from the strip as |
715 std::vector<Panel*> panels_to_move_to_overflow; | 705 // remaining panels in the strip are not affected. |
716 for (; panel_iter != panels_.end(); ++panel_iter) | 706 // Move panels to overflow in reverse to maintain their order. |
717 panels_to_move_to_overflow.push_back(*panel_iter); | 707 disable_layout_refresh_ = true; |
708 Panel* bumped_panel; | |
709 while (!panels_.empty()) { | |
710 bumped_panel = panels_.back(); | |
711 panel_manager_->ChangePanelLayout(panels_.back(), PanelStrip::IN_OVERFLOW); | |
712 if (bumped_panel == overflow_point) | |
713 break; | |
714 } | |
715 DCHECK(!panels_.empty()); | |
716 disable_layout_refresh_ = false; | |
717 } | |
718 | 718 |
719 // Move panels to overflow in reverse to maintain their order. | 719 void DockedPanelStrip::EnsureAvailableSpace(int width) { |
jianli
2012/03/02 00:11:41
This seems to be quite similar to MovePanelsToOver
jennb
2012/03/02 01:26:32
Not easily. In this one, the stopping point is not
| |
720 for (std::vector<Panel*>::reverse_iterator iter = | 720 // Bump panels out of strip to create the requested space. |
721 panels_to_move_to_overflow.rbegin(); | 721 // Prevent layout refresh wile bumping panels from end of strip as |
722 iter != panels_to_move_to_overflow.rend(); ++iter) { | 722 // remaining panels in the strip are not affected. |
723 (*iter)->MoveToStrip(overflow_strip); | 723 disable_layout_refresh_ = true; |
724 } | 724 while (GetRightMostAvailablePosition() - width < display_area_.x()) { |
725 | 725 DCHECK(!panels_.empty()); |
726 disable_layout_refresh_ = false; | 726 panel_manager_->ChangePanelLayout(panels_.back(), PanelStrip::IN_OVERFLOW); |
727 } else { | |
728 // Attempt to add more panels from overflow to the strip. | |
729 Panel* overflow_panel; | |
730 while ((overflow_panel = overflow_strip->first_panel()) && | |
731 GetRightMostAvailablePosition() >= | |
732 display_area_.x() + overflow_panel->restored_size().width()) { | |
733 overflow_panel->MoveToStrip(this); | |
734 } | |
735 } | 727 } |
728 disable_layout_refresh_ = false; | |
736 } | 729 } |
737 | 730 |
738 void DockedPanelStrip::DelayedMovePanelToOverflow(Panel* panel) { | 731 void DockedPanelStrip::DelayedMovePanelToOverflow(Panel* panel) { |
739 if (panels_in_temporary_layout_.erase(panel)) { | 732 if (panels_in_temporary_layout_.erase(panel)) { |
740 DCHECK(panel->has_temporary_layout()); | 733 DCHECK(panel->has_temporary_layout()); |
741 panel->MoveToStrip(panel_manager_->overflow_strip()); | 734 panel_manager_->ChangePanelLayout(panel, PanelStrip::IN_OVERFLOW); |
742 } | 735 } |
743 } | 736 } |
744 | 737 |
745 void DockedPanelStrip::CloseAll() { | 738 void DockedPanelStrip::CloseAll() { |
746 // This should only be called at the end of tests to clean up. | 739 // This should only be called at the end of tests to clean up. |
747 DCHECK(panels_in_temporary_layout_.empty()); | 740 DCHECK(panels_in_temporary_layout_.empty()); |
748 | 741 |
749 // Make a copy of the iterator as closing panels can modify the vector. | 742 // Make a copy of the iterator as closing panels can modify the vector. |
750 Panels panels_copy = panels_; | 743 Panels panels_copy = panels_; |
751 | 744 |
752 // Start from the bottom to avoid reshuffling. | 745 // Start from the bottom to avoid reshuffling. |
753 for (Panels::reverse_iterator iter = panels_copy.rbegin(); | 746 for (Panels::reverse_iterator iter = panels_copy.rbegin(); |
754 iter != panels_copy.rend(); ++iter) | 747 iter != panels_copy.rend(); ++iter) |
755 (*iter)->Close(); | 748 (*iter)->Close(); |
756 } | 749 } |
OLD | NEW |