1. slightly changed how wxControlContainer is used
[wxWidgets.git] / include / wx / generic / splitter.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: splitter.h
3 // Purpose: wxSplitterWindow class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifndef __SPLITTERH_G__
13 #define __SPLITTERH_G__
14
15 #ifdef __GNUG__
16 #pragma interface "splitter.h"
17 #endif
18
19 #include "wx/window.h" // base class declaration
20
21 class WXDLLEXPORT wxSplitterEvent;
22
23 // ---------------------------------------------------------------------------
24 // splitter constants
25 // ---------------------------------------------------------------------------
26
27 enum
28 {
29 wxSPLIT_HORIZONTAL = 1,
30 wxSPLIT_VERTICAL
31 };
32
33 enum
34 {
35 wxSPLIT_DRAG_NONE,
36 wxSPLIT_DRAG_DRAGGING,
37 wxSPLIT_DRAG_LEFT_DOWN
38 };
39
40 class WXDLLEXPORT wxControlContainer;
41
42 // ---------------------------------------------------------------------------
43 // wxSplitterWindow maintains one or two panes, with
44 // an optional vertical or horizontal split which
45 // can be used with the mouse or programmatically.
46 // ---------------------------------------------------------------------------
47
48 // TODO:
49 // 1) Perhaps make the borders sensitive to dragging in order to create a split.
50 // The MFC splitter window manages scrollbars as well so is able to
51 // put sash buttons on the scrollbars, but we probably don't want to go down
52 // this path.
53 // 2) for wxWindows 2.0, we must find a way to set the WS_CLIPCHILDREN style
54 // to prevent flickering. (WS_CLIPCHILDREN doesn't work in all cases so can't be
55 // standard).
56
57 class WXDLLEXPORT wxSplitterWindow: public wxWindow
58 {
59 public:
60
61 ////////////////////////////////////////////////////////////////////////////
62 // Public API
63
64 // Default constructor
65 wxSplitterWindow() : m_container(this)
66 {
67 Init();
68 }
69
70 // Normal constructor
71 wxSplitterWindow(wxWindow *parent, wxWindowID id = -1,
72 const wxPoint& pos = wxDefaultPosition,
73 const wxSize& size = wxDefaultSize,
74 long style = wxSP_3D,
75 const wxString& name = "splitter")
76 : m_container(this)
77 {
78 Init();
79 Create(parent, id, pos, size, style, name);
80 }
81
82 virtual ~wxSplitterWindow();
83
84 bool Create(wxWindow *parent, wxWindowID id = -1,
85 const wxPoint& pos = wxDefaultPosition,
86 const wxSize& size = wxDefaultSize,
87 long style = wxSP_3D,
88 const wxString& name = "splitter");
89
90 // Gets the only or left/top pane
91 wxWindow *GetWindow1() const { return m_windowOne; }
92
93 // Gets the right/bottom pane
94 wxWindow *GetWindow2() const { return m_windowTwo; }
95
96 // Sets the split mode
97 void SetSplitMode(int mode) { m_splitMode = mode; }
98
99 // Gets the split mode
100 int GetSplitMode() const { return m_splitMode; };
101
102 // Initialize with one window
103 void Initialize(wxWindow *window);
104
105 // Associates the given window with window 2, drawing the appropriate sash
106 // and changing the split mode.
107 // Does nothing and returns FALSE if the window is already split.
108 // A sashPosition of 0 means choose a default sash position,
109 // negative sashPosition specifies the size of right/lower pane as it's
110 // absolute value rather than the size of left/upper pane.
111 virtual bool SplitVertically(wxWindow *window1,
112 wxWindow *window2,
113 int sashPosition = 0);
114 virtual bool SplitHorizontally(wxWindow *window1,
115 wxWindow *window2,
116 int sashPosition = 0);
117
118 // Removes the specified (or second) window from the view
119 // Doesn't actually delete the window.
120 bool Unsplit(wxWindow *toRemove = (wxWindow *) NULL);
121
122 // Replaces one of the windows with another one (neither old nor new
123 // parameter should be NULL)
124 bool ReplaceWindow(wxWindow *winOld, wxWindow *winNew);
125
126 // Is the window split?
127 bool IsSplit() const { return (m_windowTwo != NULL); }
128
129 // Sets the sash size
130 void SetSashSize(int width) { m_sashSize = width; }
131
132 // Sets the border size
133 void SetBorderSize(int width) { m_borderSize = width; }
134
135 // Gets the sash size
136 int GetSashSize() const { return m_sashSize; }
137
138 // Gets the border size
139 int GetBorderSize() const { return m_borderSize; }
140
141 // Set the sash position
142 void SetSashPosition(int position, bool redraw = TRUE);
143
144 // Gets the sash position
145 int GetSashPosition() const { return m_sashPosition; }
146
147 // If this is zero, we can remove panes by dragging the sash.
148 void SetMinimumPaneSize(int min) { m_minimumPaneSize = min; }
149 int GetMinimumPaneSize() const { return m_minimumPaneSize; }
150
151 // Called when the sash position is about to be changed, return
152 // FALSE from here to prevent the change from taking place.
153 // Repositions sash to minimum position if pane would be too small.
154 // newSashPosition here is always positive or zero.
155 virtual bool OnSashPositionChange(int WXUNUSED(newSashPosition))
156 { return TRUE; }
157
158 // If the sash is moved to an extreme position, a subwindow
159 // is removed from the splitter window, and the app is
160 // notified. The app should delete or hide the window.
161 virtual void OnUnsplit(wxWindow *WXUNUSED(removed)) { }
162
163 // Called when the sash is double-clicked.
164 // The default behaviour is to remove the sash if the
165 // minimum pane size is zero.
166 virtual void OnDoubleClickSash(int WXUNUSED(x), int WXUNUSED(y)) { }
167
168 ////////////////////////////////////////////////////////////////////////////
169 // Implementation
170
171 // Paints the border and sash
172 void OnPaint(wxPaintEvent& event);
173
174 // Handles mouse events
175 void OnMouseEvent(wxMouseEvent& ev);
176
177 // Adjusts the panes
178 void OnSize(wxSizeEvent& event);
179
180 // In live mode, resize child windows in idle time
181 void OnIdle(wxIdleEvent& event);
182
183 // Draws borders
184 virtual void DrawBorders(wxDC& dc);
185
186 // Draws the sash
187 virtual void DrawSash(wxDC& dc);
188
189 // Draws the sash tracker (for whilst moving the sash)
190 virtual void DrawSashTracker(int x, int y);
191
192 // Tests for x, y over sash
193 virtual bool SashHitTest(int x, int y, int tolerance = 2);
194
195 // Resizes subwindows
196 virtual void SizeWindows();
197
198 // Initialize colours
199 void InitColours();
200
201 void SetNeedUpdating(bool needUpdating) { m_needUpdating = needUpdating; }
202 bool GetNeedUpdating() const { return m_needUpdating ; }
203
204 protected:
205 // our event handlers
206 void OnSashPosChanged(wxSplitterEvent& event);
207 void OnSashPosChanging(wxSplitterEvent& event);
208 void OnDoubleClick(wxSplitterEvent& event);
209 void OnUnsplitEvent(wxSplitterEvent& event);
210 void OnSetCursor(wxSetCursorEvent& event);
211
212 void SendUnsplitEvent(wxWindow *winRemoved);
213
214 protected:
215 // common part of all ctors
216 void Init();
217
218 int m_splitMode;
219 bool m_permitUnsplitAlways;
220 bool m_needUpdating; // when in live mode, set this to TRUE to resize children in idle
221 wxWindow* m_windowOne;
222 wxWindow* m_windowTwo;
223 int m_dragMode;
224 int m_oldX;
225 int m_oldY;
226 int m_borderSize;
227 int m_sashSize; // Sash width or height
228 int m_sashPosition; // Number of pixels from left or top
229 int m_firstX;
230 int m_firstY;
231 int m_minimumPaneSize;
232 wxCursor* m_sashCursorWE;
233 wxCursor* m_sashCursorNS;
234 wxPen* m_sashTrackerPen;
235 wxPen* m_lightShadowPen;
236 wxPen* m_mediumShadowPen;
237 wxPen* m_darkShadowPen;
238 wxPen* m_hilightPen;
239 wxBrush* m_faceBrush;
240 wxPen* m_facePen;
241
242 private:
243 WX_DECLARE_CONTROL_CONTAINER();
244
245 DECLARE_DYNAMIC_CLASS(wxSplitterWindow)
246 DECLARE_EVENT_TABLE()
247 };
248
249 // ----------------------------------------------------------------------------
250 // event class and macros
251 // ----------------------------------------------------------------------------
252
253 // we reuse the same class for all splitter event types because this is the
254 // usual wxWin convention, but the three event types have different kind of
255 // data associated with them, so the accessors can be only used if the real
256 // event type matches with the one for which the accessors make sense
257 class WXDLLEXPORT wxSplitterEvent : public wxCommandEvent
258 {
259 public:
260 wxSplitterEvent(wxEventType type = wxEVT_NULL,
261 wxSplitterWindow *splitter = (wxSplitterWindow *)NULL)
262 : wxCommandEvent(type)
263 {
264 SetEventObject(splitter);
265 if (splitter) m_id = splitter->GetId();
266 }
267
268 // SASH_POS_CHANGED methods
269
270 // setting the sash position to -1 prevents the change from taking place at
271 // all
272 void SetSashPosition(int pos)
273 {
274 wxASSERT( GetEventType() == wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED
275 || GetEventType() == wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING);
276
277 m_data.pos = pos;
278 }
279
280 int GetSashPosition() const
281 {
282 wxASSERT( GetEventType() == wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED
283 || GetEventType() == wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING);
284
285 return m_data.pos;
286 }
287
288 // UNSPLIT event methods
289 wxWindow *GetWindowBeingRemoved() const
290 {
291 wxASSERT( GetEventType() == wxEVT_COMMAND_SPLITTER_UNSPLIT );
292
293 return m_data.win;
294 }
295
296 // DCLICK event methods
297 int GetX() const
298 {
299 wxASSERT( GetEventType() == wxEVT_COMMAND_SPLITTER_DOUBLECLICKED );
300
301 return m_data.pt.x;
302 }
303
304 int GetY() const
305 {
306 wxASSERT( GetEventType() == wxEVT_COMMAND_SPLITTER_DOUBLECLICKED );
307
308 return m_data.pt.y;
309 }
310
311 private:
312 friend class WXDLLEXPORT wxSplitterWindow;
313
314 // data for the different types of event
315 union
316 {
317 int pos; // position for SASH_POS_CHANGED event
318 wxWindow *win; // window being removed for UNSPLIT event
319 struct
320 {
321 int x, y;
322 } pt; // position of double click for DCLICK event
323 } m_data;
324
325 DECLARE_DYNAMIC_CLASS(wxSplitterEvent)
326 };
327
328 typedef void (wxEvtHandler::*wxSplitterEventFunction)(wxSplitterEvent&);
329
330 #define EVT_SPLITTER_SASH_POS_CHANGED(id, fn) \
331 DECLARE_EVENT_TABLE_ENTRY( \
332 wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, \
333 id, \
334 -1, \
335 (wxObjectEventFunction)(wxEventFunction)(wxSplitterEventFunction) &fn, \
336 NULL \
337 ),
338
339 #define EVT_SPLITTER_SASH_POS_CHANGING(id, fn) \
340 DECLARE_EVENT_TABLE_ENTRY( \
341 wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, \
342 id, \
343 -1, \
344 (wxObjectEventFunction)(wxEventFunction)(wxSplitterEventFunction) &fn, \
345 NULL \
346 ),
347
348 #define EVT_SPLITTER_DCLICK(id, fn) \
349 DECLARE_EVENT_TABLE_ENTRY( \
350 wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, \
351 id, \
352 -1, \
353 (wxObjectEventFunction)(wxEventFunction)(wxSplitterEventFunction) &fn, \
354 NULL \
355 ),
356
357 #define EVT_SPLITTER_UNSPLIT(id, fn) \
358 DECLARE_EVENT_TABLE_ENTRY( \
359 wxEVT_COMMAND_SPLITTER_UNSPLIT, \
360 id, \
361 -1, \
362 (wxObjectEventFunction)(wxEventFunction)(wxSplitterEventFunction) &fn, \
363 NULL \
364 ),
365
366 #endif // __SPLITTERH_G__