Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3171)

Unified Diff: chrome/browser/ui/panels/docked_panel_strip.cc

Issue 9546001: Support detaching/attaching panels via inter-strip drags. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Patch to land Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/panels/docked_panel_strip.h ('k') | chrome/browser/ui/panels/native_panel.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
}
« no previous file with comments | « chrome/browser/ui/panels/docked_panel_strip.h ('k') | chrome/browser/ui/panels/native_panel.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698