Chromium Code Reviews| 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()) - |