1 // Copyright (c) 2011 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 #ifndef UI_VIEWS_CONTROLS_SINGLE_SPLIT_VIEW_H_ 6 #define UI_VIEWS_CONTROLS_SINGLE_SPLIT_VIEW_H_ 7 8 #include "base/gtest_prod_util.h" 9 #include "ui/views/view.h" 10 11 namespace views { 12 13 class SingleSplitViewListener; 14 15 // SingleSplitView lays out two views next to each other, either horizontally 16 // or vertically. A splitter exists between the two views that the user can 17 // drag around to resize the views. 18 // SingleSplitViewListener's SplitHandleMoved notification helps to monitor user 19 // initiated layout changes. 20 class VIEWS_EXPORT SingleSplitView : public View { 21 public: 22 enum Orientation { 23 HORIZONTAL_SPLIT, 24 VERTICAL_SPLIT 25 }; 26 27 static const char kViewClassName[]; 28 29 SingleSplitView(View* leading, 30 View* trailing, 31 Orientation orientation, 32 SingleSplitViewListener* listener); 33 34 virtual void Layout() OVERRIDE; 35 virtual const char* GetClassName() const OVERRIDE; 36 37 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; 38 39 // SingleSplitView's preferred size is the sum of the preferred widths 40 // and the max of the heights. 41 virtual gfx::Size GetPreferredSize() OVERRIDE; 42 43 // Overriden to return a resize cursor when over the divider. 44 virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE; 45 46 Orientation orientation() const { 47 return is_horizontal_ ? HORIZONTAL_SPLIT : VERTICAL_SPLIT; 48 } 49 50 void set_orientation(Orientation orientation) { 51 is_horizontal_ = orientation == HORIZONTAL_SPLIT; 52 } 53 54 void set_divider_offset(int divider_offset) { 55 divider_offset_ = divider_offset; 56 } 57 int divider_offset() const { return divider_offset_; } 58 59 int GetDividerSize() const; 60 61 void set_resize_disabled(bool resize_disabled) { 62 resize_disabled_ = resize_disabled; 63 } 64 bool is_resize_disabled() const { return resize_disabled_; } 65 66 // Sets whether the leading component is resized when the split views size 67 // changes. The default is true. A value of false results in the trailing 68 // component resizing on a bounds change. 69 void set_resize_leading_on_bounds_change(bool resize) { 70 resize_leading_on_bounds_change_ = resize; 71 } 72 73 // Calculates ideal leading and trailing view bounds according to the given 74 // split view |bounds|, current divider offset and children visiblity. 75 // Does not change children view bounds. 76 void CalculateChildrenBounds(const gfx::Rect& bounds, 77 gfx::Rect* leading_bounds, 78 gfx::Rect* trailing_bounds) const; 79 80 void SetAccessibleName(const string16& name); 81 82 protected: 83 // View overrides. 84 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 85 virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; 86 virtual void OnMouseCaptureLost() OVERRIDE; 87 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; 88 89 private: 90 // This test calls OnMouse* functions. 91 FRIEND_TEST_ALL_PREFIXES(SingleSplitViewTest, MouseDrag); 92 93 // Returns true if |x| or |y| is over the divider. 94 bool IsPointInDivider(const gfx::Point& p); 95 96 // Calculates the new |divider_offset| based on the changes of split view 97 // bounds. 98 int CalculateDividerOffset(int divider_offset, 99 const gfx::Rect& previous_bounds, 100 const gfx::Rect& new_bounds) const; 101 102 // Returns divider offset within primary axis size range for given split 103 // view |bounds|. 104 int NormalizeDividerOffset(int divider_offset, const gfx::Rect& bounds) const; 105 106 // Returns width in case of horizontal split and height otherwise. 107 int GetPrimaryAxisSize() const { 108 return GetPrimaryAxisSize(width(), height()); 109 } 110 111 int GetPrimaryAxisSize(int h, int v) const { 112 return is_horizontal_ ? h : v; 113 } 114 115 // Used to track drag info. 116 struct DragInfo { 117 // The initial coordinate of the mouse when the user started the drag. 118 int initial_mouse_offset; 119 // The initial position of the divider when the user started the drag. 120 int initial_divider_offset; 121 }; 122 123 DragInfo drag_info_; 124 125 // Orientation of the split view. 126 bool is_horizontal_; 127 128 // Position of the divider. 129 int divider_offset_; 130 131 bool resize_leading_on_bounds_change_; 132 133 // Whether resizing is disabled. 134 bool resize_disabled_; 135 136 // Listener to notify about user initiated handle movements. Not owned. 137 SingleSplitViewListener* listener_; 138 139 // The accessible name of this view. 140 string16 accessible_name_; 141 142 DISALLOW_COPY_AND_ASSIGN(SingleSplitView); 143 }; 144 145 } // namespace views 146 147 #endif // UI_VIEWS_CONTROLS_SINGLE_SPLIT_VIEW_H_ 148