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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/panels/docked_panel_drag_handler.h" 6 7 #include "chrome/browser/ui/panels/docked_panel_collection.h" 8 #include "chrome/browser/ui/panels/panel.h" 9 #include "chrome/browser/ui/panels/panel_manager.h" 10 #include "ui/gfx/point.h" 11 #include "ui/gfx/rect.h" 12 13 // static 14 void DockedPanelDragHandler::HandleDrag(Panel* panel, 15 const gfx::Point& target_position) { 16 DCHECK_EQ(PanelCollection::DOCKED, panel->collection()->type()); 17 18 DockedPanelCollection* collection = 19 static_cast<DockedPanelCollection*>(panel->collection()); 20 21 // Moves this panel to the dragging position. 22 // Note that we still allow the panel to be moved vertically until it gets 23 // aligned to the bottom area. 24 gfx::Rect new_bounds(panel->GetBounds()); 25 new_bounds.set_x(target_position.x()); 26 int delta_x = new_bounds.x() - panel->GetBounds().x(); 27 int bottom = collection->GetBottomPositionForExpansionState( 28 panel->expansion_state()); 29 if (new_bounds.bottom() != bottom) { 30 new_bounds.set_y(target_position.y()); 31 if (new_bounds.bottom() > bottom) 32 new_bounds.set_y(bottom - new_bounds.height()); 33 } 34 panel->SetPanelBoundsInstantly(new_bounds); 35 36 if (delta_x) { 37 // Checks and processes other affected panels. 38 if (delta_x > 0) 39 DragRight(panel); 40 else 41 DragLeft(panel); 42 43 // Layout refresh will automatically recompute the bounds of all affected 44 // panels due to their position changes. 45 collection->RefreshLayout(); 46 } 47 } 48 49 // static 50 void DockedPanelDragHandler::DragLeft(Panel* panel) { 51 DockedPanelCollection* collection = 52 static_cast<DockedPanelCollection*>(panel->collection()); 53 54 // This is the left corner of the dragging panel. We use it to check against 55 // all the panels on its left. 56 int dragging_panel_left_boundary = panel->GetBounds().x(); 57 58 // Checks the panels to the left of the dragging panel. 59 DockedPanelCollection::Panels::iterator dragging_panel_iterator = 60 find(collection->panels_.begin(), collection->panels_.end(), panel); 61 DockedPanelCollection::Panels::iterator current_panel_iterator = 62 dragging_panel_iterator; 63 ++current_panel_iterator; 64 for (; current_panel_iterator != collection->panels_.end(); 65 ++current_panel_iterator) { 66 Panel* current_panel = *current_panel_iterator; 67 68 // Can we swap dragging panel with its left panel? The criterion is that 69 // the left corner of dragging panel should pass the middle position of 70 // its left panel. 71 if (dragging_panel_left_boundary > current_panel->GetBounds().x() + 72 current_panel->GetBounds().width() / 2) 73 break; 74 75 // Swaps the contents and makes |dragging_panel_iterator| refers to the new 76 // position. 77 *dragging_panel_iterator = current_panel; 78 *current_panel_iterator = panel; 79 dragging_panel_iterator = current_panel_iterator; 80 } 81 } 82 83 // static 84 void DockedPanelDragHandler::DragRight(Panel* panel) { 85 DockedPanelCollection* collection = 86 static_cast<DockedPanelCollection*>(panel->collection()); 87 88 // This is the right corner of the dragging panel. We use it to check against 89 // all the panels on its right. 90 int dragging_panel_right_boundary = panel->GetBounds().x() + 91 panel->GetBounds().width() - 1; 92 93 // Checks the panels to the right of the dragging panel. 94 DockedPanelCollection::Panels::iterator dragging_panel_iterator = 95 find(collection->panels_.begin(), collection->panels_.end(), panel); 96 DockedPanelCollection::Panels::iterator current_panel_iterator = 97 dragging_panel_iterator; 98 while (current_panel_iterator != collection->panels_.begin()) { 99 current_panel_iterator--; 100 Panel* current_panel = *current_panel_iterator; 101 102 // Can we swap dragging panel with its right panel? The criterion is that 103 // the left corner of dragging panel should pass the middle position of 104 // its right panel. 105 if (dragging_panel_right_boundary < current_panel->GetBounds().x() + 106 current_panel->GetBounds().width() / 2) 107 break; 108 109 // Swaps the contents and makes |dragging_panel_iterator| refers to the new 110 // position. 111 *dragging_panel_iterator = current_panel; 112 *current_panel_iterator = panel; 113 dragging_panel_iterator = current_panel_iterator; 114 } 115 } 116