source: trunk/Lucide/SOURCE/gui/pmsplitter.cpp @ 33

Last change on this file since 33 was 26, checked in by Eugene Romanenko, 16 years ago

remember nav pane position/visibility

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