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/docked_panel_strip.h" | 5 #include "chrome/browser/ui/panels/docked_panel_strip.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "chrome/browser/ui/browser.h" | 13 #include "chrome/browser/ui/browser.h" |
14 #include "chrome/browser/ui/panels/overflow_panel_strip.h" | 14 #include "chrome/browser/ui/panels/overflow_panel_strip.h" |
15 #include "chrome/browser/ui/panels/panel_drag_controller.h" | |
15 #include "chrome/browser/ui/panels/panel_manager.h" | 16 #include "chrome/browser/ui/panels/panel_manager.h" |
16 #include "chrome/browser/ui/panels/panel_mouse_watcher.h" | 17 #include "chrome/browser/ui/panels/panel_mouse_watcher.h" |
17 #include "chrome/common/chrome_notification_types.h" | 18 #include "chrome/common/chrome_notification_types.h" |
18 #include "content/public/browser/notification_service.h" | 19 #include "content/public/browser/notification_service.h" |
19 #include "content/public/browser/notification_source.h" | 20 #include "content/public/browser/notification_source.h" |
20 | 21 |
21 namespace { | 22 namespace { |
22 // Width to height ratio is used to compute the default width or height | 23 // Width to height ratio is used to compute the default width or height |
23 // when only one value is provided. | 24 // when only one value is provided. |
24 const double kPanelDefaultWidthToHeightRatio = 1.62; // golden ratio | 25 const double kPanelDefaultWidthToHeightRatio = 1.62; // golden ratio |
(...skipping 28 matching lines...) Expand all Loading... | |
53 // static | 54 // static |
54 const int DockedPanelStrip::kPanelMinWidth = 100; | 55 const int DockedPanelStrip::kPanelMinWidth = 100; |
55 const int DockedPanelStrip::kPanelMinHeight = 20; | 56 const int DockedPanelStrip::kPanelMinHeight = 20; |
56 | 57 |
57 DockedPanelStrip::DockedPanelStrip(PanelManager* panel_manager) | 58 DockedPanelStrip::DockedPanelStrip(PanelManager* panel_manager) |
58 : PanelStrip(PanelStrip::DOCKED), | 59 : PanelStrip(PanelStrip::DOCKED), |
59 panel_manager_(panel_manager), | 60 panel_manager_(panel_manager), |
60 minimized_panel_count_(0), | 61 minimized_panel_count_(0), |
61 are_titlebars_up_(false), | 62 are_titlebars_up_(false), |
62 disable_layout_refresh_(false), | 63 disable_layout_refresh_(false), |
64 panel_to_restore_after_on_drag_cancelled_(NULL), | |
63 delayed_titlebar_action_(NO_ACTION), | 65 delayed_titlebar_action_(NO_ACTION), |
64 titlebar_action_factory_(this) { | 66 titlebar_action_factory_(this) { |
65 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ = | 67 dragging_panel_current_iterator_ = panels_.end(); |
66 panels_.end(); | |
67 } | 68 } |
68 | 69 |
69 DockedPanelStrip::~DockedPanelStrip() { | 70 DockedPanelStrip::~DockedPanelStrip() { |
70 DCHECK(panels_.empty()); | 71 DCHECK(panels_.empty()); |
71 DCHECK(panels_in_temporary_layout_.empty()); | 72 DCHECK(panels_in_temporary_layout_.empty()); |
72 DCHECK_EQ(0, minimized_panel_count_); | 73 DCHECK_EQ(0, minimized_panel_count_); |
73 } | 74 } |
74 | 75 |
75 void DockedPanelStrip::SetDisplayArea(const gfx::Rect& display_area) { | 76 void DockedPanelStrip::SetDisplayArea(const gfx::Rect& display_area) { |
76 if (display_area_ == display_area) | 77 if (display_area_ == display_area) |
(...skipping 16 matching lines...) Expand all Loading... | |
93 int max_panel_width = GetMaxPanelWidth(); | 94 int max_panel_width = GetMaxPanelWidth(); |
94 int max_panel_height = GetMaxPanelHeight(); | 95 int max_panel_height = GetMaxPanelHeight(); |
95 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight), | 96 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight), |
96 gfx::Size(max_panel_width, max_panel_height)); | 97 gfx::Size(max_panel_width, max_panel_height)); |
97 | 98 |
98 gfx::Size restored_size = panel->restored_size(); | 99 gfx::Size restored_size = panel->restored_size(); |
99 int height = restored_size.height(); | 100 int height = restored_size.height(); |
100 int width = restored_size.width(); | 101 int width = restored_size.width(); |
101 | 102 |
102 if (panel->initialized()) { | 103 if (panel->initialized()) { |
103 // Bump panels in the strip to make room for this panel. | 104 // Make sure we have sufficient space for this panel. We might bump |
104 // Prevent layout refresh when panel is removed from this strip. | 105 // panels in the strip to make room for this panel. |
105 disable_layout_refresh_ = true; | 106 EnsureEnoughSpaceForPanel(width); |
106 PanelStrip* overflow_strip = panel_manager_->overflow_strip(); | 107 int x = GetRightMostAvailablePosition() - width; |
107 int x; | |
108 while ((x = GetRightMostAvailablePosition() - width) < display_area_.x()) { | |
109 DCHECK(!panels_.empty()); | |
110 panels_.back()->MoveToStrip(overflow_strip); | |
111 } | |
112 disable_layout_refresh_ = false; | |
113 | 108 |
114 Panel::ExpansionState expansion_state_to_restore; | 109 Panel::ExpansionState expansion_state_to_restore; |
115 if (panel->expansion_state() == Panel::EXPANDED) { | 110 if (panel->expansion_state() == Panel::EXPANDED) { |
116 expansion_state_to_restore = Panel::EXPANDED; | 111 expansion_state_to_restore = Panel::EXPANDED; |
117 } else { | 112 } else { |
118 if (are_titlebars_up_ || panel->IsDrawingAttention()) { | 113 if (are_titlebars_up_ || panel->IsDrawingAttention()) { |
119 expansion_state_to_restore = Panel::TITLE_ONLY; | 114 expansion_state_to_restore = Panel::TITLE_ONLY; |
120 height = panel->TitleOnlyHeight(); | 115 height = panel->TitleOnlyHeight(); |
121 } else { | 116 } else { |
122 expansion_state_to_restore = Panel::MINIMIZED; | 117 expansion_state_to_restore = Panel::MINIMIZED; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 | 174 |
180 // Set panel properties for this strip. | 175 // Set panel properties for this strip. |
181 panel->SetAppIconVisibility(true); | 176 panel->SetAppIconVisibility(true); |
182 | 177 |
183 if (panel->has_temporary_layout()) | 178 if (panel->has_temporary_layout()) |
184 panels_in_temporary_layout_.insert(panel); | 179 panels_in_temporary_layout_.insert(panel); |
185 else | 180 else |
186 panels_.push_back(panel); | 181 panels_.push_back(panel); |
187 } | 182 } |
188 | 183 |
184 void DockedPanelStrip::AddPanelAtPosition(Panel* panel, | |
185 const gfx::Point& position) { | |
186 // First, make sure we have sufficient space for this panel. We might bump | |
187 // panels in the strip to make room for this panel. | |
188 EnsureEnoughSpaceForPanel(panel->GetBounds().width()); | |
189 | |
190 // Set panel properties for this strip. | |
jennb
2012/03/01 00:33:38
Wish this method and AddPanels() could be consolid
jianli
2012/03/02 22:42:43
I agree but it will involve quite a bit of refacto
| |
191 panel->SetAppIconVisibility(true); | |
192 | |
193 // Then, find and insert this panel to the right position. | |
194 int x = position.x(); | |
195 Panels::iterator iter = panels_.begin(); | |
196 for (; iter != panels_.end(); ++iter) { | |
197 Panel* current_panel = *iter; | |
198 gfx::Rect current_bounds = current_panel->GetBounds(); | |
199 if (x > current_bounds.x()) | |
200 break; | |
201 } | |
202 panels_.insert(iter, panel); | |
203 | |
204 gfx::Rect new_bounds(panel->GetBounds()); | |
jennb
2012/03/01 00:33:38
Won't refresh layout update the panel bounds corre
jianli
2012/03/02 22:42:43
RefreshLayout will not update the dragging panel.
| |
205 new_bounds.set_origin(position); | |
206 panel->SetPanelBounds(new_bounds); | |
207 | |
208 // This will automatically update all affected panels due to the insertion. | |
209 RefreshLayout(); | |
210 } | |
211 | |
212 void DockedPanelStrip::EnsureEnoughSpaceForPanel(int width) { | |
213 // Prevent layout refresh when panel is removed from this strip. | |
214 disable_layout_refresh_ = true; | |
215 PanelStrip* overflow_strip = panel_manager_->overflow_strip(); | |
216 int x; | |
217 while ((x = GetRightMostAvailablePosition() - width) < display_area_.x()) { | |
218 DCHECK(!panels_.empty()); | |
219 panels_.back()->MoveToStrip(overflow_strip); | |
220 } | |
221 disable_layout_refresh_ = false; | |
222 } | |
223 | |
189 int DockedPanelStrip::GetMaxPanelWidth() const { | 224 int DockedPanelStrip::GetMaxPanelWidth() const { |
190 return static_cast<int>(display_area_.width() * kPanelMaxWidthFactor); | 225 return static_cast<int>(display_area_.width() * kPanelMaxWidthFactor); |
191 } | 226 } |
192 | 227 |
193 int DockedPanelStrip::GetMaxPanelHeight() const { | 228 int DockedPanelStrip::GetMaxPanelHeight() const { |
194 return display_area_.height(); | 229 return display_area_.height(); |
195 } | 230 } |
196 | 231 |
197 int DockedPanelStrip::StartingRightPosition() const { | 232 int DockedPanelStrip::StartingRightPosition() const { |
198 return display_area_.right(); | 233 return display_area_.right(); |
(...skipping 11 matching lines...) Expand all Loading... | |
210 } | 245 } |
211 | 246 |
212 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel); | 247 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel); |
213 if (iter == panels_.end()) | 248 if (iter == panels_.end()) |
214 return false; | 249 return false; |
215 | 250 |
216 if (panel->expansion_state() != Panel::EXPANDED) | 251 if (panel->expansion_state() != Panel::EXPANDED) |
217 DecrementMinimizedPanels(); | 252 DecrementMinimizedPanels(); |
218 | 253 |
219 // Removing an element from the list will invalidate the iterator that refers | 254 // Removing an element from the list will invalidate the iterator that refers |
220 // to it. So we need to check if the dragging panel iterators are affected. | 255 // to it. If the dragging panel is being removed, set the dragging iterator to |
221 bool update_original_dragging_iterator_after_erase = false; | 256 // the end of the list. |
222 if (dragging_panel_original_iterator_ != panels_.end()) { | 257 if (dragging_panel_current_iterator_ == iter) |
223 if (dragging_panel_current_iterator_ == iter) { | 258 dragging_panel_current_iterator_ = panels_.end(); |
224 // If the dragging panel is being removed, set both dragging iterators to | |
225 // the end of the list. | |
226 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ = | |
227 panels_.end(); | |
228 } else if (dragging_panel_original_iterator_ == iter) { | |
229 // If |dragging_panel_original_iterator_| refers to the element being | |
230 // removed, set the flag so that the iterator can be updated to next | |
231 // element. | |
232 update_original_dragging_iterator_after_erase = true; | |
233 } | |
234 } | |
235 | 259 |
236 iter = panels_.erase(iter); | 260 iter = panels_.erase(iter); |
237 | 261 |
238 if (update_original_dragging_iterator_after_erase) | 262 // If |panel_to_restore_after_on_drag_cancelled_| is removed, update it to |
239 dragging_panel_original_iterator_ = iter; | 263 // the next panel after the panel being removed. |
264 if (panel == panel_to_restore_after_on_drag_cancelled_) { | |
265 panel_to_restore_after_on_drag_cancelled_ = | |
266 (iter == panels_.end()) ? NULL : *iter; | |
267 } | |
240 | 268 |
241 if (!disable_layout_refresh_) | 269 if (!disable_layout_refresh_) |
242 RefreshLayout(); | 270 RefreshLayout(); |
243 | 271 |
244 return true; | 272 return true; |
245 } | 273 } |
246 | 274 |
247 bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const { | 275 bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const { |
248 // Panels with temporary layout cannot be shown as active. | 276 // Panels with temporary layout cannot be shown as active. |
249 return !panel->has_temporary_layout(); | 277 return !panel->has_temporary_layout(); |
250 } | 278 } |
251 | 279 |
252 bool DockedPanelStrip::CanDragPanel(const Panel* panel) const { | 280 bool DockedPanelStrip::CanDragPanel(const Panel* panel) const { |
253 // Only the panels having temporary layout can't be dragged. | 281 // Only the panels having temporary layout can't be dragged. |
254 return !panel->has_temporary_layout(); | 282 return !panel->has_temporary_layout(); |
255 } | 283 } |
256 | 284 |
257 Panel* DockedPanelStrip::dragging_panel() const { | 285 Panel* DockedPanelStrip::dragging_panel() const { |
258 return dragging_panel_current_iterator_ == panels_.end() ? NULL : | 286 Panel* dragging_panel = panel_manager_->drag_controller()->dragging_panel(); |
259 *dragging_panel_current_iterator_; | 287 return (dragging_panel && dragging_panel->panel_strip() == this) ? |
288 dragging_panel : NULL; | |
260 } | 289 } |
261 | 290 |
262 void DockedPanelStrip::StartDraggingPanel(Panel* panel) { | 291 void DockedPanelStrip::StartDraggingPanel(Panel* panel) { |
263 dragging_panel_current_iterator_ = | 292 dragging_panel_current_iterator_ = |
264 find(panels_.begin(), panels_.end(), panel); | 293 find(panels_.begin(), panels_.end(), panel); |
265 DCHECK(dragging_panel_current_iterator_ != panels_.end()); | 294 DCHECK(dragging_panel_current_iterator_ != panels_.end()); |
266 dragging_panel_original_iterator_ = dragging_panel_current_iterator_; | 295 |
296 // Remember the panel to restore after. We only need to do it once when the | |
297 // dragging panel does not leave the docked strip. | |
298 if (!panel_manager_->drag_controller()->has_dragged_to_other_strip()) { | |
299 panel_to_restore_after_on_drag_cancelled_ = | |
300 GetNextPanel(dragging_panel_current_iterator_); | |
301 } | |
267 } | 302 } |
268 | 303 |
269 void DockedPanelStrip::DragPanel(Panel* panel, int delta_x, int delta_y) { | 304 void DockedPanelStrip::DragPanel(Panel* panel, int delta_x, int delta_y) { |
270 if (!delta_x) | 305 if (!delta_x) |
271 return; | 306 return; |
272 | 307 |
273 // Moves this panel to the dragging position. | 308 // Moves this panel to the dragging position. |
274 gfx::Rect new_bounds(panel->GetBounds()); | 309 gfx::Rect new_bounds(panel->GetBounds()); |
275 new_bounds.set_x(new_bounds.x() + delta_x); | 310 new_bounds.set_x(new_bounds.x() + delta_x); |
276 panel->SetPanelBounds(new_bounds); | 311 panel->SetPanelBounds(new_bounds); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 // Swaps the contents and makes |dragging_panel_current_iterator_| refers | 369 // Swaps the contents and makes |dragging_panel_current_iterator_| refers |
335 // to the new position. | 370 // to the new position. |
336 *dragging_panel_current_iterator_ = current_panel; | 371 *dragging_panel_current_iterator_ = current_panel; |
337 *current_panel_iterator = dragging_panel; | 372 *current_panel_iterator = dragging_panel; |
338 dragging_panel_current_iterator_ = current_panel_iterator; | 373 dragging_panel_current_iterator_ = current_panel_iterator; |
339 } | 374 } |
340 } | 375 } |
341 | 376 |
342 void DockedPanelStrip::EndDraggingPanel(Panel* panel, bool cancelled) { | 377 void DockedPanelStrip::EndDraggingPanel(Panel* panel, bool cancelled) { |
343 if (cancelled) { | 378 if (cancelled) { |
344 if (dragging_panel_current_iterator_ != dragging_panel_original_iterator_) { | 379 Panels::iterator next_iter = dragging_panel_current_iterator_; |
345 // Find out if the dragging panel should be moved toward the end/beginning | 380 ++next_iter; |
346 // of the list. | 381 if (panel_to_restore_after_on_drag_cancelled_ != |
347 bool move_towards_end_of_list = true; | 382 GetNextPanel(dragging_panel_current_iterator_)) { |
348 for (Panels::iterator iter = dragging_panel_original_iterator_; | 383 // Remove the dragging panel from current position. |
349 iter != panels_.end(); ++iter) { | 384 panels_.erase(dragging_panel_current_iterator_); |
350 if (iter == dragging_panel_current_iterator_) { | |
351 move_towards_end_of_list = false; | |
352 break; | |
353 } | |
354 } | |
355 | 385 |
356 // Move the dragging panel back to its original position by swapping it | 386 // Insert the dragging panel to the restore position. |
357 // with its adjacent element until it reach its original position. | 387 if (panel_to_restore_after_on_drag_cancelled_) { |
358 while (dragging_panel_current_iterator_ != | 388 Panels::iterator iter_to_restore_after = std::find(panels_.begin(), |
359 dragging_panel_original_iterator_) { | 389 panels_.end(), panel_to_restore_after_on_drag_cancelled_); |
360 Panels::iterator next_iter = dragging_panel_current_iterator_; | 390 DCHECK(iter_to_restore_after != panels_.end()); |
361 if (move_towards_end_of_list) | 391 panels_.insert(iter_to_restore_after, panel); |
362 ++next_iter; | 392 } else { |
363 else | 393 panels_.push_back(panel); |
364 --next_iter; | |
365 iter_swap(dragging_panel_current_iterator_, next_iter); | |
366 dragging_panel_current_iterator_ = next_iter; | |
367 } | 394 } |
368 } | 395 } |
369 } | 396 } |
370 | 397 |
371 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ = | 398 dragging_panel_current_iterator_ = panels_.end(); |
372 panels_.end(); | |
373 | 399 |
374 RefreshLayout(); | 400 RefreshLayout(); |
375 } | 401 } |
376 | 402 |
377 void DockedPanelStrip::OnPanelExpansionStateChanged(Panel* panel) { | 403 void DockedPanelStrip::OnPanelExpansionStateChanged(Panel* panel) { |
378 gfx::Size size = panel->restored_size(); | 404 gfx::Size size = panel->restored_size(); |
379 Panel::ExpansionState expansion_state = panel->expansion_state(); | 405 Panel::ExpansionState expansion_state = panel->expansion_state(); |
380 Panel::ExpansionState old_state = panel->old_expansion_state(); | 406 Panel::ExpansionState old_state = panel->old_expansion_state(); |
381 switch (expansion_state) { | 407 switch (expansion_state) { |
382 case Panel::EXPANDED: | 408 case Panel::EXPANDED: |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
747 DCHECK(panels_in_temporary_layout_.empty()); | 773 DCHECK(panels_in_temporary_layout_.empty()); |
748 | 774 |
749 // Make a copy of the iterator as closing panels can modify the vector. | 775 // Make a copy of the iterator as closing panels can modify the vector. |
750 Panels panels_copy = panels_; | 776 Panels panels_copy = panels_; |
751 | 777 |
752 // Start from the bottom to avoid reshuffling. | 778 // Start from the bottom to avoid reshuffling. |
753 for (Panels::reverse_iterator iter = panels_copy.rbegin(); | 779 for (Panels::reverse_iterator iter = panels_copy.rbegin(); |
754 iter != panels_copy.rend(); ++iter) | 780 iter != panels_copy.rend(); ++iter) |
755 (*iter)->Close(); | 781 (*iter)->Close(); |
756 } | 782 } |
783 | |
784 Panel* DockedPanelStrip::GetNextPanel(const Panels::iterator& iter) const { | |
785 DCHECK(iter != panels_.end()); | |
786 Panels::iterator next_iter = iter; | |
787 ++next_iter; | |
788 return (next_iter == panels_.end()) ? NULL : *next_iter; | |
789 } | |
OLD | NEW |