• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::AXViewState* 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() const OVERRIDE;
42 
43   // Overriden to return a resize cursor when over the divider.
44   virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE;
45 
orientation()46   Orientation orientation() const {
47     return is_horizontal_ ? HORIZONTAL_SPLIT : VERTICAL_SPLIT;
48   }
49 
set_orientation(Orientation orientation)50   void set_orientation(Orientation orientation) {
51     is_horizontal_ = orientation == HORIZONTAL_SPLIT;
52   }
53 
set_divider_offset(int divider_offset)54   void set_divider_offset(int divider_offset) {
55     divider_offset_ = divider_offset;
56   }
divider_offset()57   int divider_offset() const { return divider_offset_; }
58 
59   int GetDividerSize() const;
60 
set_resize_disabled(bool resize_disabled)61   void set_resize_disabled(bool resize_disabled) {
62     resize_disabled_ = resize_disabled;
63   }
is_resize_disabled()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.
set_resize_leading_on_bounds_change(bool resize)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 base::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.
GetPrimaryAxisSize()107   int GetPrimaryAxisSize() const {
108     return GetPrimaryAxisSize(width(), height());
109   }
110 
GetPrimaryAxisSize(int h,int v)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   base::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