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

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

added licence block to source files

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