OSDN Git Service

Add a missing return statement.
[mingw/wtklite.git] / sashctrl.cpp
1 /*
2  * sashctrl.cpp
3  *
4  * ---------------------------------------------------------------------------
5  *
6  * Implementation of a minimal C++ class framework for use with the
7  * Microsoft Windows Application Programming Interface.
8  *
9  * $Id$
10  *
11  * This file provides the implementation for each of the three C++ classes
12  * which are required to implement sash window controls.  It must be compiled
13  * to generate three separate object modules:--
14  *
15  *   c++ -c sashctrl.cpp -o sashctrl.o
16  *   c++ -D HSASH_IMPLEMENTATION -c sashctrl.cpp -o hsashctl.o
17  *   c++ -D VSASH_IMPLEMENTATION -c sashctrl.cpp -o vsashctl.o
18  *
19  * to obtain the implementations of the SashWindowMaker abstract base class,
20  * together with its HorizontalSashWindowMaker and VerticalSashWindowMaker
21  * derived classes, respectively.
22  *
23  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
24  * Copyright (C) 2012, 2015, MinGW.org Project.
25  *
26  * ---------------------------------------------------------------------------
27  *
28  * Permission is hereby granted, free of charge, to any person obtaining a
29  * copy of this software and associated documentation files (the "Software"),
30  * to deal in the Software without restriction, including without limitation
31  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
32  * and/or sell copies of the Software, and to permit persons to whom the
33  * Software is furnished to do so, subject to the following conditions:
34  *
35  * The above copyright notice, this permission notice, and the following
36  * disclaimer shall be included in all copies or substantial portions of
37  * the Software.
38  *
39  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
40  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
42  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
44  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
45  * DEALINGS IN THE SOFTWARE.
46  *
47  * ---------------------------------------------------------------------------
48  *
49  */
50 #define  WIN32_LEAN_AND_MEAN
51
52 #include "wtklite.h"
53
54 /* Identify the class implementation to be compiled; each of
55  * the HSASH_IMPLEMENTATION and VSASH_IMPLEMENTATION must be
56  * explicitly requested.  Initially, we assume that either of
57  * these may have been specified, so we deselect the fallback
58  * case...
59  */
60 #undef CORE_IMPLEMENTATION
61
62 /* ...then...
63  */
64 #ifdef HSASH_IMPLEMENTATION
65  /* ...when the horizontal sash case IS selected, we ensure that
66   * the vertical sash case ISN'T...
67   */
68 # undef  VSASH_IMPLEMENTATION
69
70 /* ...otherwise, when the horizontal sash case ISN'T selected...
71  */
72 #elif !defined VSASH_IMPLEMENTATION
73  /* ...and the vertical sash case ISN'T either, then we reselect
74   * the fallback case.
75   */
76 # define CORE_IMPLEMENTATION
77 #endif
78
79 namespace WTK
80 {
81 # ifdef CORE_IMPLEMENTATION
82   /* Neither the HSASH_IMPLEMENTATION nor the VSASH_IMPLEMENTATION
83    * was selected; implement the SashWindowMaker class.
84    */
85   SashWindowMaker::SashWindowMaker
86   ( HINSTANCE app, double minval, double initval, double maxval ):
87     ChildWindowMaker( app ), MinRangeFactor( minval ), MaxRangeFactor( maxval ),
88     DisplacementFactor( initval ){ ValidateDisplacementFactor(); }
89
90   void SashWindowMaker::RegisterWindowClassName( const char *ClassName )
91   {
92     /* Helper routine, to ensure that an appropriate window class name
93      * is registered, as required for instantiation of any object of the
94      * derived HorizontalSashWindowMaker or VerticalSashWindowMaker class.
95      */
96     WindowClassMaker WindowClassRegistry( AppInstance );
97     WindowClassRegistry.SetCursor( LoadCursor( NULL, CursorStyle() ));
98     WindowClassRegistry.Register( ClassName );
99   }
100
101   long SashWindowMaker::OnLeftButtonDown( void )
102   {
103     /* Capture the mouse over a sash bar, and initiate the drag
104      * operation to resize the adjacent sash panes.
105      */
106     HWND owner;
107     SetCapture( AppWindow );
108
109     /* Establish the viewport region of the owner window, within
110      * which the sash panes are defined.
111      */
112     GetClientRect( (owner = GetParent( AppWindow )), &frame );
113     long width = GetFrameWidth(), height = GetFrameHeight();
114
115     /* Adjust the frame bounds to accommodate the entire extent
116      * of the owner window, then relative to those, establish the
117      * clipping region within which mouse movement is to be confined
118      * while dragging the sash bar.
119      */
120     GetWindowRect( owner, &frame );
121     long border = (GetFrameWidth() - width) / 2;
122     SetClippingRegion( width, height, border );
123     ClipCursor( &frame );
124
125     /* Readjust the frame bounds to the entire extent of the owner
126      * window, (they will have been modified while setting up the
127      * clipping region), then further adjust the top edge and left
128      * side entries, to reflect the offset of the viewport within
129      * the overall window bounds.
130      */
131     GetWindowRect( owner, &frame );
132     frame.top = frame.bottom - border - height;
133     frame.left += border;
134     return EXIT_SUCCESS;
135   }
136
137   long SashWindowMaker::OnMouseMove( WPARAM flags )
138   {
139     /* When the mouse has been captured over a sash bar...
140      */
141     if( flags & MK_LBUTTON )
142     {
143       /* ...compute the position to which it has been dragged,
144        * ensuring that it remains within the permitted bounds...
145        */
146       SetDisplacementFactor( GetMessagePos() );
147       ValidateDisplacementFactor();
148
149       /* ...then dynamically update the owner window display,
150        * to reflect the sash movement.
151        */
152       WindowObjectReference( GetParent( AppWindow ))->AdjustLayout();
153     }
154     return EXIT_SUCCESS;
155   }
156
157   void SashWindowMaker::ValidateDisplacementFactor()
158   {
159     /* Helper routine to ensure that sash bar movement
160      * remains within permitted bounds.
161      */
162     if( DisplacementFactor < MinRangeFactor )
163       DisplacementFactor = MinRangeFactor;
164     else if( DisplacementFactor > MaxRangeFactor )
165       DisplacementFactor = MaxRangeFactor;
166   }
167
168   long SashWindowMaker::OnLeftButtonUp( void )
169   {
170     /* Complete a drag operation on a sash bar; first we
171      * release the mouse from the clipping region...
172      */
173     ReleaseCapture();
174     ClipCursor( NULL );
175
176     /* ...then perform a final update of the owner window,
177      * to clean up any display artefacts which may have been
178      * left behind by dragging the sash bar...
179      */
180     HWND owner = GetParent( AppWindow );
181     InvalidateRect( owner, NULL, TRUE );
182     UpdateWindow( owner );
183
184     /* ...and we are done.
185      */
186     return EXIT_SUCCESS;
187   }
188
189 #else
190   /* When compiling each of the HSASH_IMPLEMENTATION module, and
191    * the VSASH_IMPLEMENTATION module...
192    */
193   class MousePositionMapper
194   {
195     /* This locally declared, all-inline class is used to facilitate 
196      * identification of the co-ordinates of the mouse position.
197      */
198     private:
199       union { unsigned long v; struct { unsigned short x, y; }; } pos;
200
201     public:
202       MousePositionMapper( unsigned long v ){ pos.v = v; }
203       long X(){ return pos.x; }
204       long Y(){ return pos.y; }
205   };
206
207 #endif
208 #ifdef HSASH_IMPLEMENTATION
209   /* This is the case where we are compiling the implementation for
210    * the HorizontalSashWindowMaker class.
211    */
212   const char *HorizontalSashWindowMaker::ClassName = NULL;
213   const char *HorizontalSashWindowMaker::RegisteredClassName( void )
214   {
215     /* Helper routine to ensure that the appropriate window class
216      * name is registered on first instantiation of any class object.
217      */
218     if( ClassName == NULL )
219       RegisterWindowClassName( ClassName = "HSashCtrl" );
220     return ClassName;
221   }
222
223   void HorizontalSashWindowMaker::
224   SetClippingRegion( long width, long height, long border )
225   {
226     /* Helper routine, called by the OnLeftButtonDown() method which is
227      * inherited from the SashWindowMaker base class, to establish left
228      * and right movement bounds for the sash bar, within the frame of
229      * the owner window.
230      */
231     ScaleFactor = (double)(width);
232     frame.right -= border + (long)( (1.0 - MaxRangeFactor) * ScaleFactor );
233     frame.left += border + (long)( MinRangeFactor * ScaleFactor );
234   }
235
236   void HorizontalSashWindowMaker::SetDisplacementFactor( unsigned long pos )
237   {
238     /* Helper routine, called by the OnMouseMove() method which is
239      * inherited from the SashWindowMaker base class, to establish the
240      * offset of the sash bar from the left hand side of the owner
241      * window, as it is dragged by the mouse.
242      */
243     MousePositionMapper locate( pos );
244     DisplacementFactor = (double)(locate.X() - frame.left) / ScaleFactor;
245   }
246
247 # elif defined VSASH_IMPLEMENTATION
248   /* This is the case where we are compiling the implementation for
249    * the VerticalSashWindowMaker class.
250    */
251   const char *VerticalSashWindowMaker::ClassName = NULL;
252   const char *VerticalSashWindowMaker::RegisteredClassName( void )
253   {
254     /* Helper routine to ensure that the appropriate window class
255      * name is registered on first instantiation of any class object.
256      */
257     if( ClassName == NULL )
258       RegisterWindowClassName( ClassName = "VSashCtrl" );
259     return ClassName;
260   }
261
262   void VerticalSashWindowMaker::
263   SetClippingRegion( long width, long height, long border )
264   {
265     /* Helper routine, called by the OnLeftButtonDown() method which is
266      * inherited from the SashWindowMaker base class, to establish upper
267      * and lower movement bounds for the sash bar, within the frame of
268      * the owner window.
269      */
270     ScaleFactor = (double)(height); frame.bottom -= border;
271     frame.top = frame.bottom - (long)( (1.0 - MinRangeFactor) * ScaleFactor );
272     frame.bottom -= (long)( (1.0 - MaxRangeFactor) * ScaleFactor );
273   }
274
275   void VerticalSashWindowMaker::SetDisplacementFactor( unsigned long pos )
276   {
277     /* Helper routine, called by the OnMouseMove() method which is
278      * inherited from the SashWindowMaker base class, to establish the
279      * offset of the sash bar from the top edge of the owner window,
280      * as it is dragged by the mouse.
281      */
282     MousePositionMapper locate( pos );
283     DisplacementFactor = (double)(locate.Y() - frame.top) / ScaleFactor;
284   }
285
286 # endif
287 }
288
289 /* $RCSfile$: end of file */