| 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 a46e80c3fee1199a5ec4eeabca44ea051c774ab9..67a31d8e8c4218ccafd2b89553701777fbcc5bac 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() {
|
| @@ -83,10 +84,24 @@ void DockedPanelStrip::SetDisplayArea(const gfx::Rect& display_area) {
|
| RefreshLayout();
|
| }
|
|
|
| -void DockedPanelStrip::AddPanel(Panel* panel) {
|
| +void DockedPanelStrip::AddPanel(Panel* panel,
|
| + PositioningMask positioning_mask) {
|
| DCHECK_NE(this, panel->panel_strip());
|
| panel->SetPanelStrip(this);
|
|
|
| + bool known_position = (positioning_mask & KNOWN_POSITION) != 0;
|
| + bool update_bounds = (positioning_mask & DO_NOT_UPDATE_BOUNDS) == 0;
|
| +
|
| + if (!panel->initialized()) {
|
| + DCHECK(!known_position && update_bounds);
|
| + InsertNewlyCreatedPanel(panel);
|
| + } else if (known_position) {
|
| + DCHECK(update_bounds);
|
| + InsertExistingPanelAtKnownPosition(panel);
|
| + } else {
|
| + InsertExistingPanelAtDefaultPosition(panel, update_bounds);
|
| + }
|
| +
|
| // 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,13 +109,94 @@ 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::InsertNewlyCreatedPanel(Panel* panel) {
|
| + DCHECK(!panel->initialized());
|
| +
|
| + int max_panel_width = GetMaxPanelWidth();
|
| + int max_panel_height = GetMaxPanelHeight();
|
| gfx::Size restored_size = panel->restored_size();
|
| int height = restored_size.height();
|
| int width = restored_size.width();
|
|
|
| - if (panel->initialized()) {
|
| - int x = FitPanelWithWidth(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;
|
| + }
|
| +
|
| + // 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);
|
| + else
|
| + panels_.push_back(panel);
|
| +}
|
| +
|
| +void DockedPanelStrip::InsertExistingPanelAtKnownPosition(Panel* panel) {
|
| + DCHECK(panel->initialized());
|
| +
|
| + 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::InsertExistingPanelAtDefaultPosition(
|
| + Panel* panel, bool update_bounds) {
|
| + DCHECK(panel->initialized());
|
| +
|
| + gfx::Size restored_size = panel->restored_size();
|
| + int height = restored_size.height();
|
| + int width = restored_size.width();
|
| +
|
| + int x = FitPanelWithWidth(width);
|
| +
|
| + if (update_bounds) {
|
| Panel::ExpansionState expansion_state_to_restore;
|
| if (panel->expansion_state() == Panel::EXPANDED) {
|
| expansion_state_to_restore = Panel::EXPANDED;
|
| @@ -122,57 +218,9 @@ void DockedPanelStrip::AddPanel(Panel* panel) {
|
| // 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;
|
| - }
|
| -
|
| - // 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));
|
| }
|
|
|
| - // Set panel properties for this strip.
|
| - panel->SetAppIconVisibility(true);
|
| -
|
| - if (panel->has_temporary_layout())
|
| - panels_in_temporary_layout_.insert(panel);
|
| - else
|
| - panels_.push_back(panel);
|
| + panels_.push_back(panel);
|
| }
|
|
|
| int DockedPanelStrip::GetMaxPanelWidth() const {
|
| @@ -208,16 +256,21 @@ 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|.
|
| + // Note: if |left_panel| moves to overflow and then comes back, it is OK to
|
| + // restore the panel to the end of list since we do not want to deal with
|
| + // this case specially.
|
| + if (saved_panel_placement_.panel &&
|
| + saved_panel_placement_.left_panel == panel)
|
| + saved_panel_placement_.left_panel = NULL;
|
| +
|
| // 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 +278,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 +294,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;
|
| +
|
| + // Restoring is only needed when this panel is not in the right position.
|
| + 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;
|
| + saved_panel_placement_.left_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 +432,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) {
|
| @@ -514,6 +597,8 @@ bool DockedPanelStrip::ShouldBringUpTitlebars(int mouse_x, int mouse_y) const {
|
| return true;
|
|
|
| // Bring up titlebars if any panel needs the titlebar up.
|
| + Panel* dragging_panel = dragging_panel_current_iterator_ == panels_.end() ?
|
| + NULL : *dragging_panel_current_iterator_;
|
| for (Panels::const_iterator iter = panels_.begin();
|
| iter != panels_.end(); ++iter) {
|
| Panel* panel = *iter;
|
| @@ -524,7 +609,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 == dragging_panel)
|
| return true;
|
|
|
| // We do not want to bring up other minimized panels if the mouse is over
|
| @@ -717,8 +802,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()) -
|
| @@ -731,6 +816,8 @@ void DockedPanelStrip::RefreshLayout() {
|
|
|
| // Add/remove panels from/to overflow. A change in work area or the
|
| // resize/removal of a panel may affect how many panels fit in the strip.
|
| + // TODO(jianli): Need to handle the case that panel in preview mode could be
|
| + // moved to overflow. (http://crbug.com/117574)
|
| if (panel_iter != panels_.end())
|
| panel_manager_->MovePanelsToOverflow(*panel_iter);
|
| else
|
| @@ -740,7 +827,9 @@ void DockedPanelStrip::RefreshLayout() {
|
| void DockedPanelStrip::DelayedMovePanelToOverflow(Panel* panel) {
|
| if (panels_in_temporary_layout_.erase(panel)) {
|
| DCHECK(panel->has_temporary_layout());
|
| - panel_manager_->MovePanelToStrip(panel, PanelStrip::IN_OVERFLOW);
|
| + panel_manager_->MovePanelToStrip(panel,
|
| + PanelStrip::IN_OVERFLOW,
|
| + PanelStrip::DEFAULT_POSITION);
|
| }
|
| }
|
|
|
|
|