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/panel_drag_controller.h" | 5 #include "chrome/browser/ui/panels/panel_drag_controller.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "chrome/browser/ui/panels/detached_panel_strip.h" |
| 9 #include "chrome/browser/ui/panels/docked_panel_strip.h" |
8 #include "chrome/browser/ui/panels/panel.h" | 10 #include "chrome/browser/ui/panels/panel.h" |
| 11 #include "chrome/browser/ui/panels/panel_manager.h" |
9 #include "chrome/browser/ui/panels/panel_strip.h" | 12 #include "chrome/browser/ui/panels/panel_strip.h" |
10 | 13 |
11 PanelDragController::PanelDragController() | 14 // static |
12 : dragging_panel_(NULL) { | 15 const int PanelDragController::kDetachDockedPanelThreshold = 80; |
| 16 const int PanelDragController::kDockDetachedPanelThreshold = 10; |
| 17 |
| 18 PanelDragController::PanelDragController(PanelManager* panel_manager) |
| 19 : panel_manager_(panel_manager), |
| 20 dragging_panel_(NULL), |
| 21 dragging_panel_original_strip_(NULL) { |
13 } | 22 } |
14 | 23 |
15 PanelDragController::~PanelDragController() { | 24 PanelDragController::~PanelDragController() { |
16 } | 25 } |
17 | 26 |
18 void PanelDragController::StartDragging(Panel* panel, | 27 void PanelDragController::StartDragging(Panel* panel, |
19 const gfx::Point& mouse_location) { | 28 const gfx::Point& mouse_location) { |
20 DCHECK(!dragging_panel_); | 29 DCHECK(!dragging_panel_); |
21 DCHECK(panel->draggable()); | 30 DCHECK(panel->draggable()); |
22 | 31 |
23 last_mouse_location_ = mouse_location; | 32 last_mouse_location_ = mouse_location; |
24 | 33 |
25 dragging_panel_ = panel; | 34 dragging_panel_ = panel; |
26 dragging_panel_original_position_ = panel->GetBounds().origin(); | 35 dragging_panel_->SetPreviewMode(true); |
27 | 36 |
28 dragging_panel_->panel_strip()->StartDraggingPanel(panel); | 37 // Keep track of original strip and placement for the case that the drag is |
| 38 // cancelled. |
| 39 dragging_panel_original_strip_ = dragging_panel_->panel_strip(); |
| 40 dragging_panel_original_strip_->SavePanelPlacement(dragging_panel_); |
| 41 |
| 42 if (dragging_panel_original_strip_->type() == PanelStrip::DOCKED) |
| 43 mouse_location_on_docked_ = last_mouse_location_; |
| 44 dragging_panel_original_strip_->StartDraggingPanelWithinStrip( |
| 45 dragging_panel_); |
29 } | 46 } |
30 | 47 |
31 void PanelDragController::Drag(const gfx::Point& mouse_location) { | 48 void PanelDragController::Drag(const gfx::Point& mouse_location) { |
32 DCHECK(dragging_panel_); | 49 DCHECK(dragging_panel_); |
33 | 50 |
34 dragging_panel_->panel_strip()->DragPanel( | 51 PanelStrip* current_strip = dragging_panel_->panel_strip(); |
| 52 |
| 53 // We also need to compute target panel position together with target strip. |
| 54 // This is because target panel position needs to be computed in special way |
| 55 // when drag leaves docked strip and enters detached strip (see comment in |
| 56 // CanDragToDetachedStrip). |
| 57 gfx::Point target_panel_position; |
| 58 PanelStrip* target_strip = ComputeDragTagetStrip( |
| 59 mouse_location, &target_panel_position); |
| 60 if (target_strip != current_strip) { |
| 61 // End the dragging in old strip. |
| 62 current_strip->EndDraggingPanelWithinStrip(dragging_panel_, true); |
| 63 |
| 64 // Apply new panel position. |
| 65 gfx::Rect new_bounds(dragging_panel_->GetBounds()); |
| 66 new_bounds.set_origin(target_panel_position); |
| 67 dragging_panel_->SetPanelBounds(new_bounds); |
| 68 |
| 69 // Move the panel to new strip. |
| 70 panel_manager_->MovePanelToStrip(dragging_panel_, target_strip->type()); |
| 71 |
| 72 if (target_strip->type() == PanelStrip::DOCKED) |
| 73 mouse_location_on_docked_ = mouse_location; |
| 74 |
| 75 // Start the dragging in new strip. |
| 76 target_strip->StartDraggingPanelWithinStrip(dragging_panel_); |
| 77 } else { |
| 78 current_strip->DragPanelWithinStrip( |
35 dragging_panel_, | 79 dragging_panel_, |
36 mouse_location.x() - last_mouse_location_.x(), | 80 mouse_location.x() - last_mouse_location_.x(), |
37 mouse_location.y() - last_mouse_location_.y()); | 81 mouse_location.y() - last_mouse_location_.y()); |
| 82 } |
38 | 83 |
39 last_mouse_location_ = mouse_location; | 84 last_mouse_location_ = mouse_location; |
40 } | 85 } |
41 | 86 |
42 void PanelDragController::EndDragging(bool cancelled) { | 87 void PanelDragController::EndDragging(bool cancelled) { |
43 DCHECK(dragging_panel_); | 88 DCHECK(dragging_panel_); |
44 | 89 |
45 // The code in PanelStrip::EndDraggingPanel might call DragController to find | 90 PanelStrip* current_strip = dragging_panel_->panel_strip(); |
46 // out if the drag has ended. So we need to reset |dragging_panel_| to reflect | 91 if (cancelled) { |
47 // this. | 92 // Abort the drag in current strip. |
48 Panel* panel = dragging_panel_; | 93 current_strip->EndDraggingPanelWithinStrip(dragging_panel_, true); |
| 94 |
| 95 // Restore the dragging panel to its original strip if needed. |
| 96 if (current_strip != dragging_panel_original_strip_) { |
| 97 panel_manager_->MovePanelToStrip( |
| 98 dragging_panel_, dragging_panel_original_strip_->type()); |
| 99 } |
| 100 |
| 101 // We need to clear the preview mode before restoring to the saved placement |
| 102 // because otherwise the panel will remain as it is. |
| 103 dragging_panel_->SetPreviewMode(false); |
| 104 |
| 105 // Restore the dragging panel to its original placement. |
| 106 dragging_panel_original_strip_->RestorePanelToSavedPlacement(); |
| 107 } else { |
| 108 // We need to clear the preview mode first because in this mode, the panel |
| 109 // will remain as it is. |
| 110 dragging_panel_->SetPreviewMode(false); |
| 111 |
| 112 // End the drag. This will cause the panel to be moved to its finalized |
| 113 // position. |
| 114 current_strip->EndDraggingPanelWithinStrip(dragging_panel_, false); |
| 115 |
| 116 // The saved placement is not needed when the drag ends. |
| 117 dragging_panel_original_strip_->DiscardSavedPanelPlacement(); |
| 118 } |
| 119 |
49 dragging_panel_ = NULL; | 120 dragging_panel_ = NULL; |
50 panel->panel_strip()->EndDraggingPanel(panel, cancelled); | 121 } |
| 122 |
| 123 PanelStrip* PanelDragController::ComputeDragTagetStrip( |
| 124 const gfx::Point& mouse_location, gfx::Point* new_panel_position) const { |
| 125 if (CanDragToDockedStrip(mouse_location, new_panel_position)) |
| 126 return panel_manager_->docked_strip(); |
| 127 else if (CanDragToDetachedStrip(mouse_location, new_panel_position)) |
| 128 return panel_manager_->detached_strip(); |
| 129 else |
| 130 return dragging_panel_->panel_strip(); |
| 131 } |
| 132 |
| 133 bool PanelDragController::CanDragToDockedStrip( |
| 134 const gfx::Point& mouse_location, |
| 135 gfx::Point* new_panel_position) const { |
| 136 // It has to come from the detached strip. |
| 137 if (dragging_panel_->panel_strip()->type() != PanelStrip::DETACHED) |
| 138 return false; |
| 139 |
| 140 // The bottom of the panel should come very close to or fall below the bottom |
| 141 // of the docked area. |
| 142 int new_panel_bottom = dragging_panel_->GetBounds().bottom() + |
| 143 mouse_location.y() - last_mouse_location_.y(); |
| 144 int docked_area_bottom = |
| 145 panel_manager_->docked_strip()->display_area().bottom(); |
| 146 if (docked_area_bottom - new_panel_bottom > kDockDetachedPanelThreshold) |
| 147 return false; |
| 148 |
| 149 *new_panel_position = dragging_panel_->GetBounds().origin(); |
| 150 new_panel_position->Offset( |
| 151 mouse_location.x() - last_mouse_location_.x(), |
| 152 mouse_location.y() - last_mouse_location_.y()); |
| 153 return true; |
| 154 } |
| 155 |
| 156 bool PanelDragController::CanDragToDetachedStrip( |
| 157 const gfx::Point& mouse_location, |
| 158 gfx::Point* new_panel_position) const { |
| 159 // It has to come from the docked strip. |
| 160 if (dragging_panel_->panel_strip()->type() != PanelStrip::DOCKED) |
| 161 return false; |
| 162 |
| 163 // The minimized docked panel is not allowed to detach. |
| 164 if (dragging_panel_->expansion_state() != Panel::EXPANDED) |
| 165 return false; |
| 166 |
| 167 // The panel should be dragged up high enough to pass certain threshold. |
| 168 if (mouse_location.y() >= mouse_location_on_docked_.y() || |
| 169 mouse_location_on_docked_.y() - mouse_location.y() < |
| 170 kDetachDockedPanelThreshold) |
| 171 return false; |
| 172 |
| 173 // When the mouse drags within the docked strip, we only update panel's x |
| 174 // coordinate while keep its y coordinate unchanged. When the panel is |
| 175 // detached, the panel should jump immediately to follow the mouse location. |
| 176 // That is, its new y coordinate should be computed based on the distance |
| 177 // between current mouse location and the mouse location when the drag starts |
| 178 // within the docked strip. |
| 179 *new_panel_position = dragging_panel_->GetBounds().origin(); |
| 180 new_panel_position->Offset( |
| 181 mouse_location.x() - last_mouse_location_.x(), |
| 182 mouse_location.y() - mouse_location_on_docked_.y()); |
| 183 return true; |
51 } | 184 } |
52 | 185 |
53 void PanelDragController::OnPanelClosed(Panel* panel) { | 186 void PanelDragController::OnPanelClosed(Panel* panel) { |
54 if (!dragging_panel_) | 187 if (!dragging_panel_) |
55 return; | 188 return; |
56 | 189 |
57 // If the dragging panel is closed, abort the drag. | 190 // If the dragging panel is closed, abort the drag. |
58 if (dragging_panel_ == panel) | 191 if (dragging_panel_ == panel) |
59 EndDragging(false); | 192 EndDragging(false); |
60 } | 193 } |
OLD | NEW |