source: trunk/Lucide/gui/pmsplitter.cpp @ 399

Last change on this file since 399 was 387, checked in by dmik, 12 years ago

Added SBM_SETSPLITTERSIZE and SBM_GETSPLITTERSIZE to WM_ER_SPLITTER class.

File size: 11.6 KB
Line 
1/*
2 *  PM Splitter implementation.
3 *  by Eugene Romanenko
4 *
5 *  This code is in the public domain and has no copyright.
6 */
7
8#include "os2all.h"
9
10#include "tb_spl.h"
11
12
13#define SPLITTER_WIDTH  5
14
15static LONG lColor[ SPLITTER_WIDTH ] =
16{
17    CLR_PALEGRAY, CLR_WHITE,    CLR_PALEGRAY,
18    CLR_PALEGRAY, CLR_DARKGRAY
19};
20
21struct splitterWndStruct
22{
23    SHORT splitterPos;
24    SHORT splitterWidth;
25    SHORT fixedSize;
26    ULONG style;
27    HWND  firstWindow;
28    HWND  secondWindow;
29    HPOINTER ptrWE;
30    HPOINTER ptrNS;
31};
32
33
34static VOID setWindSize( HWND splitWnd, splitterWndStruct *sws )
35{
36    if ( !WinIsWindowVisible( splitWnd ) ) {
37        return;
38    }
39
40    if ( sws->firstWindow && sws->secondWindow )
41    {
42        if ( !( WinIsWindowVisible( sws->firstWindow ) &&
43             WinIsWindowVisible( sws->secondWindow ) ) ) {
44            return;
45        }
46
47        SWP swp;
48        WinQueryWindowPos( splitWnd, &swp );
49
50        SHORT x, y, cx, cy;
51        if ( sws->style & SBS_VSPLIT )
52        {
53            if ( sws->style & SBS_FIRSTFIXED ) {
54                sws->splitterPos = sws->fixedSize;
55            } else if ( sws->style & SBS_SECONDFIXED ) {
56                sws->splitterPos = swp.cx - sws->fixedSize;
57            }
58
59            if ( sws->splitterPos > ( ( swp.cx - sws->splitterWidth ) - 1 ) ) {
60                sws->splitterPos = ( swp.cx - sws->splitterWidth ) - 1;
61            }
62
63            sws->splitterPos = sws->splitterPos < 0 ? 0 : sws->splitterPos;
64            x = swp.x;
65            y = swp.y;
66            cx = sws->splitterPos;
67            cy = swp.cy;
68            WinSetWindowPos( sws->firstWindow, HWND_TOP,
69                x, y, cx, cy, SWP_ZORDER | SWP_SIZE | SWP_MOVE );
70            x = swp.x + sws->splitterPos + sws->splitterWidth;
71            y = swp.y;
72            cx = ( ( swp.cx - sws->splitterPos ) - sws->splitterWidth );
73            cx = cx < 0 ? 0 : cx;
74            cy = swp.cy;
75            WinSetWindowPos( sws->secondWindow, HWND_TOP,
76                x, y, cx, cy, SWP_ZORDER | SWP_SIZE | SWP_MOVE  );
77        }
78        else if ( sws->style & SBS_HSPLIT )
79        {
80            if ( sws->style & SBS_FIRSTFIXED ) {
81                sws->splitterPos = sws->fixedSize;
82            } else if ( sws->style & SBS_SECONDFIXED ) {
83                sws->splitterPos = swp.cy - sws->fixedSize;
84            }
85
86            if ( sws->splitterPos > ( ( swp.cy - sws->splitterWidth ) - 1 ) ) {
87                sws->splitterPos = ( swp.cy - sws->splitterWidth ) - 1;
88            }
89
90            sws->splitterPos = sws->splitterPos < 0 ? 0 : sws->splitterPos;
91            x = swp.x;
92            y = swp.y;
93            cx = swp.cx;
94            cy = sws->splitterPos;
95            WinSetWindowPos( sws->firstWindow, HWND_TOP,
96                x, y, cx, cy, SWP_ZORDER | SWP_SIZE | SWP_MOVE  );
97            x = swp.x;
98            y = swp.y + sws->splitterPos + sws->splitterWidth;
99            cx = swp.cx;
100            cy = ( ( swp.cy - sws->splitterPos ) - sws->splitterWidth );
101            WinSetWindowPos( sws->secondWindow, HWND_TOP,
102                x, y, cx, cy, SWP_ZORDER | SWP_SIZE | SWP_MOVE  );
103        }
104        WinInvalidateRect( splitWnd, NULL, FALSE );
105        WinInvalidateRect( sws->firstWindow, NULL, TRUE );
106        WinInvalidateRect( sws->secondWindow, NULL, TRUE );
107    }
108}
109
110static VOID getSplitterSize( HWND splitWnd, splitterWndStruct *sws, PRECTL rcl )
111{
112    RECTL rcl1;
113    WinQueryWindowRect( splitWnd, &rcl1 );
114    if ( sws->style & SBS_VSPLIT )
115    {
116        rcl->xLeft   = sws->splitterPos;
117        rcl->yBottom = 0;
118        rcl->xRight  = sws->splitterPos + sws->splitterWidth;
119        rcl->yTop    = ( rcl1.yTop - rcl1.yBottom );
120    }
121    else
122    {
123        rcl->xLeft   = 0;
124        rcl->yBottom = sws->splitterPos;
125        rcl->xRight  = ( rcl1.xRight - rcl1.xLeft );
126        rcl->yTop    = sws->splitterPos + sws->splitterWidth;
127    }
128}
129
130static MRESULT EXPENTRY splitterProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
131{
132    splitterWndStruct *sws = (splitterWndStruct *)WinQueryWindowULong( hwnd, sizeof( ULONG ) );
133    if ( sws == NULL )
134    {
135        sws = new splitterWndStruct;
136        sws->splitterPos = 0;
137        sws->style = WinQueryWindowULong( hwnd, QWL_STYLE );
138        sws->splitterWidth = sws->style & SBS_FIXED ? 0 : SPLITTER_WIDTH;
139        sws->firstWindow = NULLHANDLE;
140        sws->secondWindow = NULLHANDLE;
141        sws->ptrWE = NULLHANDLE;
142        sws->ptrNS = NULLHANDLE;
143        WinSetWindowULong( hwnd, sizeof( ULONG ), (ULONG)sws );
144    }
145
146    switch ( msg )
147    {
148        case SBM_SETWINDOWS:
149            sws->firstWindow = HWNDFROMMP( mp1 );
150            sws->secondWindow = HWNDFROMMP( mp2 );
151            setWindSize( hwnd, sws );
152            return (MRESULT)(TRUE);
153
154        case SBM_SETSPLITTERPOS:
155            sws->splitterPos = sws->fixedSize = SHORT1FROMMP( mp1 );
156            setWindSize( hwnd, sws );
157            return (MRESULT)(TRUE);
158
159        case SBM_GETSPLITTERPOS:
160            return MRFROMSHORT( sws->splitterPos );
161
162        case SBM_SETPOINTERS:
163            sws->ptrWE = (HPOINTER)mp1;
164            sws->ptrNS = (HPOINTER)mp2;
165            return (MRESULT)(TRUE);
166
167        case SBM_SETFIXEDSIZE:
168            sws->fixedSize = SHORT1FROMMP( mp1 );
169            setWindSize( hwnd, sws );
170            return (MRESULT)(TRUE);
171
172        case SBM_SETSPLITTERSIZE:
173            sws->splitterWidth = SHORT1FROMMP( mp1 );
174            if ( sws->splitterWidth < 0 )
175                sws->splitterWidth = SPLITTER_WIDTH;
176            setWindSize( hwnd, sws );
177            return (MRESULT)(TRUE);
178
179        case SBM_GETSPLITTERSIZE:
180            return MRFROMSHORT( sws->splitterWidth );
181
182        case WM_DESTROY:
183            delete sws;
184            break;
185
186        case WM_WINDOWPOSCHANGED:
187        case WM_SHOW:
188            setWindSize( hwnd, sws );
189            break;
190
191        case WM_PAINT:
192            {
193                RECTL rcl;
194                POINTL ptl;
195                WinQueryWindowRect( hwnd, &rcl );
196                HPS hps = WinBeginPaint( hwnd, 0L, 0L );
197
198                if ( !( sws->style & SBS_FIXED ) )
199                {
200                    if ( sws->style & SBS_VSPLIT )
201                    {
202                        ptl.x = sws->splitterPos;
203                        for ( int i = 0; i < sws->splitterWidth; i++ )
204                        {
205                            ptl.y = 0;
206                            GpiMove( hps, &ptl );
207                            ptl.y = ( rcl.yTop - rcl.yBottom );
208                            GpiSetColor( hps, lColor[ i ] );
209                            GpiLine( hps, &ptl );
210                            ptl.x++;
211                        }
212                    }
213                    else if ( sws->style & SBS_HSPLIT )
214                    {
215                        ptl.y = sws->splitterPos;
216                        for ( int i = sws->splitterWidth; i > 0; i-- )
217                        {
218                            ptl.x = 0;
219                            GpiMove( hps, &ptl );
220                            ptl.x = ( rcl.xRight - rcl.xLeft );
221                            GpiSetColor( hps, lColor[ i ] );
222                            GpiLine( hps, &ptl );
223                            ptl.y++;
224                        }
225                    }
226                }
227                WinEndPaint( hps );
228            }
229            return (MRESULT)(FALSE);
230
231        case WM_MOUSEMOVE:
232            {
233                if ( sws->style & SBS_FIXED ) {
234                    return (MRESULT)(FALSE);
235                }
236
237                POINTL ptl = { SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) };
238                RECTL rcl;
239                getSplitterSize( hwnd, sws, &rcl );
240
241                if ( WinPtInRect( WinQueryAnchorBlock( hwnd ), &rcl, &ptl ) )
242                {
243                    if ( sws->style & SBS_VSPLIT )
244                    {
245                        if ( sws->ptrWE == NULLHANDLE )
246                        {
247                            WinSetPointer( HWND_DESKTOP,
248                                WinQuerySysPointer( HWND_DESKTOP,
249                                        SPTR_SIZEWE, FALSE ) );
250                        }
251                        else {
252                            WinSetPointer( HWND_DESKTOP, sws->ptrWE );
253                        }
254                    }
255                    else
256                    {
257                        if ( sws->ptrNS == NULLHANDLE )
258                        {
259                            WinSetPointer( HWND_DESKTOP,
260                                WinQuerySysPointer( HWND_DESKTOP,
261                                        SPTR_SIZENS, FALSE ) );
262                        }
263                        else {
264                            WinSetPointer( HWND_DESKTOP, sws->ptrNS );
265                        }
266                    }
267                }
268                else
269                {
270                    WinSetPointer( HWND_DESKTOP,
271                            WinQuerySysPointer( HWND_DESKTOP,
272                                    SPTR_ARROW, FALSE ) );
273                }
274            }
275            return (MRESULT)(FALSE);
276
277        case WM_BUTTON1DOWN:
278            {
279                if ( sws->style & SBS_FIXED ) {
280                    return (MRESULT)(FALSE);
281                }
282
283                SHORT oldpos = sws->splitterPos;
284
285                POINTL ptl = { SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) };
286                TRACKINFO track;
287
288                track.cxBorder = 2;
289                track.cyBorder = 2;
290                track.cxGrid   = 1;
291                track.cyGrid   = 1;
292                track.cxKeyboard = 8;
293                track.cyKeyboard = 8;
294                WinQueryWindowRect( hwnd, &track.rclBoundary );
295                getSplitterSize( hwnd, sws, &track.rclTrack );
296
297                if ( !WinPtInRect( WinQueryAnchorBlock( hwnd ), &track.rclTrack, &ptl ) ) {
298                    return (MRESULT)FALSE;
299                }
300
301                track.ptlMinTrackSize.x = track.rclTrack.xRight
302                                        - track.rclTrack.xLeft;
303                track.ptlMinTrackSize.y = track.rclTrack.yTop
304                                        - track.rclTrack.yBottom;
305                track.ptlMaxTrackSize.x = track.rclTrack.xRight
306                                        - track.rclTrack.xLeft;
307                track.ptlMaxTrackSize.y = track.rclTrack.yTop
308                                        - track.rclTrack.yBottom;
309
310                track.fs = TF_MOVE | TF_ALLINBOUNDARY;
311
312                if ( WinTrackRect( hwnd, 0, &track ) )
313                {
314                    if ( sws->style & SBS_VSPLIT ) {
315                        sws->splitterPos = track.rclTrack.xLeft;
316                    } else {
317                        sws->splitterPos = track.rclTrack.yBottom;
318                    }
319
320                    setWindSize( hwnd, sws );
321
322                    // notify owner
323                    WinSendMsg( WinQueryWindow( hwnd, QW_OWNER ), WM_CONTROL,
324                                MPFROM2SHORT( WinQueryWindowUShort( hwnd, QWS_ID ),
325                                              SBN_POSITIONCHANGED ),
326                                MPFROM2SHORT( sws->splitterPos, oldpos ) );
327                }
328            }
329            return (MRESULT)(FALSE);
330
331        case WM_ERASEBACKGROUND:
332            return (MRESULT)(FALSE);
333    }
334    return WinDefWindowProc( hwnd, msg, mp1, mp2 );
335}
336
337
338BOOL InitPMSplitterClass( HAB hab )
339{
340    return WinRegisterClass( hab, WC_ER_SPLITTER, splitterProc,
341                             0, sizeof( ULONG ) * 2 );
342}
343
Note: See TracBrowser for help on using the repository browser.