12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/docked_panel_drag_handler.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/docked_panel_collection.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/panel.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/panel_manager.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/point.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DockedPanelDragHandler::HandleDrag(Panel* panel,
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        const gfx::Point& target_position) {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(PanelCollection::DOCKED, panel->collection()->type());
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DockedPanelCollection* collection =
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<DockedPanelCollection*>(panel->collection());
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Moves this panel to the dragging position.
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note that we still allow the panel to be moved vertically until it gets
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // aligned to the bottom area.
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect new_bounds(panel->GetBounds());
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_bounds.set_x(target_position.x());
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int delta_x = new_bounds.x() - panel->GetBounds().x();
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int bottom = collection->GetBottomPositionForExpansionState(
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      panel->expansion_state());
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (new_bounds.bottom() != bottom) {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    new_bounds.set_y(target_position.y());
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (new_bounds.bottom() > bottom)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_bounds.set_y(bottom - new_bounds.height());
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panel->SetPanelBoundsInstantly(new_bounds);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (delta_x) {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Checks and processes other affected panels.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (delta_x > 0)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DragRight(panel);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DragLeft(panel);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Layout refresh will automatically recompute the bounds of all affected
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // panels due to their position changes.
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    collection->RefreshLayout();
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DockedPanelDragHandler::DragLeft(Panel* panel) {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DockedPanelCollection* collection =
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<DockedPanelCollection*>(panel->collection());
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is the left corner of the dragging panel. We use it to check against
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // all the panels on its left.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int dragging_panel_left_boundary = panel->GetBounds().x();
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Checks the panels to the left of the dragging panel.
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DockedPanelCollection::Panels::iterator dragging_panel_iterator =
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      find(collection->panels_.begin(), collection->panels_.end(), panel);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DockedPanelCollection::Panels::iterator current_panel_iterator =
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dragging_panel_iterator;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ++current_panel_iterator;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (; current_panel_iterator != collection->panels_.end();
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++current_panel_iterator) {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* current_panel = *current_panel_iterator;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Can we swap dragging panel with its left panel? The criterion is that
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the left corner of dragging panel should pass the middle position of
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // its left panel.
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (dragging_panel_left_boundary > current_panel->GetBounds().x() +
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            current_panel->GetBounds().width() / 2)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Swaps the contents and makes |dragging_panel_iterator| refers to the new
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // position.
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *dragging_panel_iterator = current_panel;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *current_panel_iterator = panel;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dragging_panel_iterator = current_panel_iterator;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DockedPanelDragHandler::DragRight(Panel* panel) {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DockedPanelCollection* collection =
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<DockedPanelCollection*>(panel->collection());
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is the right corner of the dragging panel. We use it to check against
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // all the panels on its right.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int dragging_panel_right_boundary = panel->GetBounds().x() +
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      panel->GetBounds().width() - 1;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Checks the panels to the right of the dragging panel.
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DockedPanelCollection::Panels::iterator dragging_panel_iterator =
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      find(collection->panels_.begin(), collection->panels_.end(), panel);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DockedPanelCollection::Panels::iterator current_panel_iterator =
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dragging_panel_iterator;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (current_panel_iterator != collection->panels_.begin()) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    current_panel_iterator--;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* current_panel = *current_panel_iterator;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Can we swap dragging panel with its right panel? The criterion is that
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the left corner of dragging panel should pass the middle position of
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // its right panel.
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (dragging_panel_right_boundary < current_panel->GetBounds().x() +
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            current_panel->GetBounds().width() / 2)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Swaps the contents and makes |dragging_panel_iterator| refers to the new
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // position.
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *dragging_panel_iterator = current_panel;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *current_panel_iterator = panel;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dragging_panel_iterator = current_panel_iterator;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
116