Index: chrome/browser/ui/panels/docked_panel_strip.cc |
diff --git a/chrome/browser/ui/panels/docked_panel_strip.cc b/chrome/browser/ui/panels/docked_panel_strip.cc |
index 57a4bee3e475b948b5a596f5f03c7b7d04b30bc8..ea58d998717fcf0ef9c8c930bfbfcad525656886 100644 |
--- a/chrome/browser/ui/panels/docked_panel_strip.cc |
+++ b/chrome/browser/ui/panels/docked_panel_strip.cc |
@@ -11,6 +11,8 @@ |
#include "base/logging.h" |
#include "base/message_loop.h" |
#include "chrome/browser/ui/browser.h" |
+#include "chrome/browser/ui/panels/overflow_panel_strip.h" |
+#include "chrome/browser/ui/panels/panel_drag_controller.h" |
#include "chrome/browser/ui/panels/panel_manager.h" |
#include "chrome/browser/ui/panels/panel_mouse_watcher.h" |
#include "chrome/common/chrome_notification_types.h" |
@@ -60,8 +62,7 @@ DockedPanelStrip::DockedPanelStrip(PanelManager* panel_manager) |
are_titlebars_up_(false), |
delayed_titlebar_action_(NO_ACTION), |
titlebar_action_factory_(this) { |
- dragging_panel_current_iterator_ = dragging_panel_original_iterator_ = |
- panels_.end(); |
+ dragging_panel_current_iterator_ = panels_.end(); |
} |
DockedPanelStrip::~DockedPanelStrip() { |
@@ -87,6 +88,15 @@ void DockedPanelStrip::AddPanel(Panel* panel) { |
DCHECK_NE(this, panel->panel_strip()); |
panel->set_panel_strip(this); |
+ if (panel->initialized()) { |
+ if (panel->in_preview_mode()) |
+ InsertPreviewedPanel(panel); |
+ else |
+ InsertExistingPanel(panel); |
+ } else { |
+ InsertNewlyCreatedPanel(panel); |
+ } |
+ |
// Always update limits, even on existing panels, in case the limits changed |
// while panel was out of the strip. |
int max_panel_width = GetMaxPanelWidth(); |
@@ -94,80 +104,105 @@ void DockedPanelStrip::AddPanel(Panel* panel) { |
panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight), |
gfx::Size(max_panel_width, max_panel_height)); |
+ panel->SetAppIconVisibility(true); |
+ panel->SetAlwaysOnTop(true); |
+} |
+ |
+ |
+void DockedPanelStrip::InsertPreviewedPanel(Panel* panel) { |
Andrei
2012/03/07 22:55:13
DCHECK panel is in preview mode
jianli
2012/03/08 01:18:26
Done.
|
+ FitPanelWithWidth(panel->GetBounds().width()); |
+ |
+ int x = panel->GetBounds().x(); |
+ Panels::iterator iter = panels_.begin(); |
+ for (; iter != panels_.end(); ++iter) |
+ if (x > (*iter)->GetBounds().x()) |
+ break; |
+ panels_.insert(iter, panel); |
+ |
+ // This will automatically update all affected panels due to the insertion. |
+ if (iter != panels_.end()) |
+ RefreshLayout(); |
+} |
+ |
+void DockedPanelStrip::InsertExistingPanel(Panel* panel) { |
gfx::Size restored_size = panel->restored_size(); |
int height = restored_size.height(); |
int width = restored_size.width(); |
- if (panel->initialized()) { |
- int x = FitPanelWithWidth(width); |
+ int x = FitPanelWithWidth(width); |
- Panel::ExpansionState expansion_state_to_restore; |
- if (panel->expansion_state() == Panel::EXPANDED) { |
- expansion_state_to_restore = Panel::EXPANDED; |
+ Panel::ExpansionState expansion_state_to_restore; |
+ if (panel->expansion_state() == Panel::EXPANDED) { |
+ expansion_state_to_restore = Panel::EXPANDED; |
+ } else { |
+ if (are_titlebars_up_ || panel->IsDrawingAttention()) { |
+ expansion_state_to_restore = Panel::TITLE_ONLY; |
+ height = panel->TitleOnlyHeight(); |
} else { |
- if (are_titlebars_up_ || panel->IsDrawingAttention()) { |
- expansion_state_to_restore = Panel::TITLE_ONLY; |
- height = panel->TitleOnlyHeight(); |
- } else { |
- expansion_state_to_restore = Panel::MINIMIZED; |
- height = Panel::kMinimizedPanelHeight; |
- } |
- IncrementMinimizedPanels(); |
+ expansion_state_to_restore = Panel::MINIMIZED; |
+ height = Panel::kMinimizedPanelHeight; |
} |
- int y = |
- GetBottomPositionForExpansionState(expansion_state_to_restore) - height; |
- panel->SetPanelBounds(gfx::Rect(x, y, width, height)); |
+ IncrementMinimizedPanels(); |
+ } |
+ int y = |
+ GetBottomPositionForExpansionState(expansion_state_to_restore) - height; |
+ panel->SetPanelBounds(gfx::Rect(x, y, width, height)); |
- // Update the minimized state to reflect current titlebar mode. |
- // Do this AFTER setting panel bounds to avoid an extra bounds change. |
- if (panel->expansion_state() != Panel::EXPANDED) |
- panel->SetExpansionState(expansion_state_to_restore); |
+ // Update the minimized state to reflect current titlebar mode. |
+ // Do this AFTER setting panel bounds to avoid an extra bounds change. |
+ if (panel->expansion_state() != Panel::EXPANDED) |
+ panel->SetExpansionState(expansion_state_to_restore); |
- } else { |
- // Initialize the newly created panel. Does not bump any panels from strip. |
- if (height == 0 && width == 0 && panel_manager_->auto_sizing_enabled()) { |
- // Auto resizable is enabled only if no initial size is provided. |
- panel->SetAutoResizable(true); |
- } else { |
- if (height == 0) |
- height = width / kPanelDefaultWidthToHeightRatio; |
- if (width == 0) |
- width = height * kPanelDefaultWidthToHeightRatio; |
- } |
+ panels_.push_back(panel); |
+} |
- // Constrain sizes to limits. |
- if (width < kPanelMinWidth) |
- width = kPanelMinWidth; |
- else if (width > max_panel_width) |
- width = max_panel_width; |
- |
- if (height < kPanelMinHeight) |
- height = kPanelMinHeight; |
- else if (height > max_panel_height) |
- height = max_panel_height; |
- |
- panel->set_restored_size(gfx::Size(width, height)); |
- int x = GetRightMostAvailablePosition() - width; |
- int y = display_area_.bottom() - height; |
- |
- // Keep panel visible in the strip even if overlap would occur. |
- // Panel is moved to overflow from the strip after a delay. |
- if (x < display_area_.x()) { |
- x = display_area_.x(); |
- panel->set_has_temporary_layout(true); |
- MessageLoop::current()->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&DockedPanelStrip::DelayedMovePanelToOverflow, |
- base::Unretained(this), |
- panel), |
- base::TimeDelta::FromMilliseconds(PanelManager::AdjustTimeInterval( |
- kMoveNewPanelToOverflowDelayMs))); |
- } |
- panel->Initialize(gfx::Rect(x, y, width, height)); |
+void DockedPanelStrip::InsertNewlyCreatedPanel(Panel* panel) { |
+ int max_panel_width = GetMaxPanelWidth(); |
Andrei
2012/03/07 22:55:13
DCHECK panel is not initialized
jianli
2012/03/08 01:18:26
Done.
|
+ int max_panel_height = GetMaxPanelHeight(); |
+ gfx::Size restored_size = panel->restored_size(); |
+ int height = restored_size.height(); |
+ int width = restored_size.width(); |
+ |
+ // Initialize the newly created panel. Does not bump any panels from strip. |
+ if (height == 0 && width == 0 && panel_manager_->auto_sizing_enabled()) { |
+ // Auto resizable is enabled only if no initial size is provided. |
+ panel->SetAutoResizable(true); |
+ } else { |
+ if (height == 0) |
+ height = width / kPanelDefaultWidthToHeightRatio; |
+ if (width == 0) |
+ width = height * kPanelDefaultWidthToHeightRatio; |
} |
- // Set panel properties for this strip. |
- panel->SetAppIconVisibility(true); |
+ // Constrain sizes to limits. |
+ if (width < kPanelMinWidth) |
+ width = kPanelMinWidth; |
+ else if (width > max_panel_width) |
+ width = max_panel_width; |
+ |
+ if (height < kPanelMinHeight) |
+ height = kPanelMinHeight; |
+ else if (height > max_panel_height) |
+ height = max_panel_height; |
+ |
+ panel->set_restored_size(gfx::Size(width, height)); |
+ int x = GetRightMostAvailablePosition() - width; |
+ int y = display_area_.bottom() - height; |
+ |
+ // Keep panel visible in the strip even if overlap would occur. |
+ // Panel is moved to overflow from the strip after a delay. |
+ if (x < display_area_.x()) { |
+ x = display_area_.x(); |
+ panel->set_has_temporary_layout(true); |
+ MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&DockedPanelStrip::DelayedMovePanelToOverflow, |
+ base::Unretained(this), |
+ panel), |
+ base::TimeDelta::FromMilliseconds(PanelManager::AdjustTimeInterval( |
+ kMoveNewPanelToOverflowDelayMs))); |
+ } |
+ panel->Initialize(gfx::Rect(x, y, width, height)); |
if (panel->has_temporary_layout()) |
panels_in_temporary_layout_.insert(panel); |
@@ -208,16 +243,18 @@ void DockedPanelStrip::RemovePanel(Panel* panel) { |
// to it. We need to update the iterator in that case. |
DCHECK(dragging_panel_current_iterator_ == panels_.end() || |
*dragging_panel_current_iterator_ != panel); |
- bool update_iterator_after_erase = |
- (dragging_panel_original_iterator_ != panels_.end() && |
- *dragging_panel_original_iterator_ == panel); |
// Optimize for the common case of removing the last panel. |
DCHECK(!panels_.empty()); |
if (panels_.back() == panel) { |
panels_.pop_back(); |
- if (update_iterator_after_erase) |
- dragging_panel_original_iterator_ = panels_.end(); |
+ |
+ // Update the saved panel placement if needed. This is because we might remove |
+ // |saved_panel_placement_.left_panel_|. |
+ if (saved_panel_placement_.panel && |
+ saved_panel_placement_.left_panel_ == panel) |
+ saved_panel_placement_.left_panel_ = NULL; |
Andrei
2012/03/07 22:55:13
saved_panel_placement_.left_panel_ may be simply g
jianli
2012/03/08 01:18:26
Good thought. I think we don't want to deal with i
|
+ |
// No need to refresh layout as the remaining panels are unaffected. |
// Just check if other panels can now fit in the freed up space. |
panel_manager_->MovePanelsOutOfOverflowIfCanFit(); |
@@ -225,8 +262,13 @@ void DockedPanelStrip::RemovePanel(Panel* panel) { |
Panels::iterator iter = find(panels_.begin(), panels_.end(), panel); |
DCHECK(iter != panels_.end()); |
iter = panels_.erase(iter); |
- if (update_iterator_after_erase) |
- dragging_panel_original_iterator_ = iter; |
+ |
+ // Update the saved panel placement if needed. This is because we might remove |
+ // |saved_panel_placement_.left_panel_|. |
+ if (saved_panel_placement_.panel && |
+ saved_panel_placement_.left_panel_ == panel) |
+ saved_panel_placement_.left_panel_ = *iter; |
+ |
RefreshLayout(); |
} |
} |
@@ -236,24 +278,72 @@ bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const { |
return !panel->has_temporary_layout(); |
} |
+void DockedPanelStrip::SavePanelPlacement(Panel* panel) { |
+ DCHECK(!saved_panel_placement_.panel); |
+ |
+ saved_panel_placement_.panel = panel; |
+ |
+ // To recover panel to its original placement, we only need to track the panel |
+ // that is placed after it. |
+ Panels::iterator iter = find(panels_.begin(), panels_.end(), panel); |
+ DCHECK(iter != panels_.end()); |
+ ++iter; |
+ saved_panel_placement_.left_panel_ = |
+ (iter == panels_.end()) ? NULL : *iter; |
+} |
+ |
+void DockedPanelStrip::RestorePanelToSavedPlacement() { |
+ DCHECK(saved_panel_placement_.panel); |
+ |
+ Panel* panel = saved_panel_placement_.panel; |
+ |
+ // Find next panel after this panel. |
+ Panels::iterator iter = std::find(panels_.begin(), panels_.end(), panel); |
+ DCHECK(iter != panels_.end()); |
+ Panels::iterator next_iter = iter; |
+ next_iter++; |
+ Panel* next_panel = (next_iter == panels_.end()) ? NULL : *iter; |
+ |
+ // If this panel is already in the right position, nothing to do. |
+ if (next_panel != saved_panel_placement_.left_panel_) { |
+ // Remove this panel from its current position. |
+ panels_.erase(iter); |
+ |
+ // Insert this panel into its previous position. |
+ if (saved_panel_placement_.left_panel_) { |
+ Panels::iterator iter_to_insert_before = std::find(panels_.begin(), |
+ panels_.end(), saved_panel_placement_.left_panel_); |
+ DCHECK(iter_to_insert_before != panels_.end()); |
+ panels_.insert(iter_to_insert_before, panel); |
+ } else { |
+ panels_.push_back(panel); |
+ } |
+ } |
+ |
+ RefreshLayout(); |
+ |
+ DiscardSavedPanelPlacement(); |
+} |
+ |
+void DockedPanelStrip::DiscardSavedPanelPlacement() { |
+ DCHECK(saved_panel_placement_.panel); |
+ saved_panel_placement_.panel = NULL; |
+} |
+ |
bool DockedPanelStrip::CanDragPanel(const Panel* panel) const { |
// Only the panels having temporary layout can't be dragged. |
return !panel->has_temporary_layout(); |
} |
-Panel* DockedPanelStrip::dragging_panel() const { |
- return dragging_panel_current_iterator_ == panels_.end() ? NULL : |
- *dragging_panel_current_iterator_; |
-} |
- |
-void DockedPanelStrip::StartDraggingPanel(Panel* panel) { |
+void DockedPanelStrip::StartDraggingPanelWithinStrip(Panel* panel) { |
dragging_panel_current_iterator_ = |
find(panels_.begin(), panels_.end(), panel); |
DCHECK(dragging_panel_current_iterator_ != panels_.end()); |
- dragging_panel_original_iterator_ = dragging_panel_current_iterator_; |
} |
-void DockedPanelStrip::DragPanel(Panel* panel, int delta_x, int delta_y) { |
+void DockedPanelStrip::DragPanelWithinStrip(Panel* panel, |
+ int delta_x, |
+ int delta_y) { |
if (!delta_x) |
return; |
@@ -326,39 +416,16 @@ void DockedPanelStrip::DragRight(Panel* dragging_panel) { |
} |
} |
-void DockedPanelStrip::EndDraggingPanel(Panel* panel, bool cancelled) { |
- if (cancelled) { |
- if (dragging_panel_current_iterator_ != dragging_panel_original_iterator_) { |
- // Find out if the dragging panel should be moved toward the end/beginning |
- // of the list. |
- bool move_towards_end_of_list = true; |
- for (Panels::iterator iter = dragging_panel_original_iterator_; |
- iter != panels_.end(); ++iter) { |
- if (iter == dragging_panel_current_iterator_) { |
- move_towards_end_of_list = false; |
- break; |
- } |
- } |
- |
- // Move the dragging panel back to its original position by swapping it |
- // with its adjacent element until it reach its original position. |
- while (dragging_panel_current_iterator_ != |
- dragging_panel_original_iterator_) { |
- Panels::iterator next_iter = dragging_panel_current_iterator_; |
- if (move_towards_end_of_list) |
- ++next_iter; |
- else |
- --next_iter; |
- iter_swap(dragging_panel_current_iterator_, next_iter); |
- dragging_panel_current_iterator_ = next_iter; |
- } |
- } |
- } |
- |
- dragging_panel_current_iterator_ = dragging_panel_original_iterator_ = |
- panels_.end(); |
+void DockedPanelStrip::EndDraggingPanelWithinStrip(Panel* panel, bool aborted) { |
+ dragging_panel_current_iterator_ = panels_.end(); |
- RefreshLayout(); |
+ // Calls RefreshLayout to update the dragging panel to its final position |
+ // when the drag ends normally. Otherwise, the drag within this strip is |
+ // aborted because either the drag enters other strip or the drag is |
+ // cancelled. Either way, we don't need to do anything here and let the drag |
+ // controller handle the inter-strip transition or the drag cancellation. |
+ if (!aborted) |
+ RefreshLayout(); |
} |
void DockedPanelStrip::OnPanelExpansionStateChanged(Panel* panel) { |
@@ -521,7 +588,7 @@ bool DockedPanelStrip::ShouldBringUpTitlebars(int mouse_x, int mouse_y) const { |
// If the panel is showing titlebar only, we want to keep it up when it is |
// being dragged. |
- if (state == Panel::TITLE_ONLY && panel == dragging_panel()) |
+ if (state == Panel::TITLE_ONLY && panel->in_preview_mode()) |
return true; |
// We do not want to bring up other minimized panels if the mouse is over |
@@ -706,8 +773,8 @@ void DockedPanelStrip::RefreshLayout() { |
if (x < display_area_.x()) |
break; |
- // Don't update the docked panel that is currently dragged. |
- if (panel != dragging_panel()) { |
+ // Don't update the docked panel that is in preview mode. |
+ if (!panel->in_preview_mode()) { |
new_bounds.set_x(x); |
new_bounds.set_y( |
GetBottomPositionForExpansionState(panel->expansion_state()) - |