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

Last change on this file since 367 was 367, checked in by dmik, 11 years ago

Merged bramches/kmk (r294:365) to trunk.

File size: 11.2 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 WM_DESTROY:
173            delete sws;
174            break;
175
176        case WM_WINDOWPOSCHANGED:
177        case WM_SHOW:
178            setWindSize( hwnd, sws );
179            break;
180
181        case WM_PAINT:
182            {
183                RECTL rcl;
184                POINTL ptl;
185                WinQueryWindowRect( hwnd, &rcl );
186                HPS hps = WinBeginPaint( hwnd, 0L, 0L );
187
188                if ( !( sws->style & SBS_FIXED ) )
189                {
190                    if ( sws->style & SBS_VSPLIT )
191                    {
192                        ptl.x = sws->splitterPos;
193                        for ( int i = 0; i < sws->splitterWidth; i++ )
194                        {
195                            ptl.y = 0;
196                            GpiMove( hps, &ptl );
197                            ptl.y = ( rcl.yTop - rcl.yBottom );
198                            GpiSetColor( hps, lColor[ i ] );
199                            GpiLine( hps, &ptl );
200                            ptl.x++;
201                        }
202                    }
203                    else if ( sws->style & SBS_HSPLIT )
204                    {
205                        ptl.y = sws->splitterPos;
206                        for ( int i = sws->splitterWidth; i > 0; i-- )
207                        {
208                            ptl.x = 0;
209                            GpiMove( hps, &ptl );
210                            ptl.x = ( rcl.xRight - rcl.xLeft );
211                            GpiSetColor( hps, lColor[ i ] );
212                            GpiLine( hps, &ptl );
213                            ptl.y++;
214                        }
215                    }
216                }
217                WinEndPaint( hps );
218            }
219            return (MRESULT)(FALSE);
220
221        case WM_MOUSEMOVE:
222            {
223                if ( sws->style & SBS_FIXED ) {
224                    return (MRESULT)(FALSE);
225                }
226
227                POINTL ptl = { SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) };
228                RECTL rcl;
229                getSplitterSize( hwnd, sws, &rcl );
230
231                if ( WinPtInRect( WinQueryAnchorBlock( hwnd ), &rcl, &ptl ) )
232                {
233                    if ( sws->style & SBS_VSPLIT )
234                    {
235                        if ( sws->ptrWE == NULLHANDLE )
236                        {
237                            WinSetPointer( HWND_DESKTOP,
238                                WinQuerySysPointer( HWND_DESKTOP,
239                                        SPTR_SIZEWE, FALSE ) );
240                        }
241                        else {
242                            WinSetPointer( HWND_DESKTOP, sws->ptrWE );
243                        }
244                    }
245                    else
246                    {
247                        if ( sws->ptrNS == NULLHANDLE )
248                        {
249                            WinSetPointer( HWND_DESKTOP,
250                                WinQuerySysPointer( HWND_DESKTOP,
251                                        SPTR_SIZENS, FALSE ) );
252                        }
253                        else {
254                            WinSetPointer( HWND_DESKTOP, sws->ptrNS );
255                        }
256                    }
257                }
258                else
259                {
260                    WinSetPointer( HWND_DESKTOP,
261                            WinQuerySysPointer( HWND_DESKTOP,
262                                    SPTR_ARROW, FALSE ) );
263                }
264            }
265            return (MRESULT)(FALSE);
266
267        case WM_BUTTON1DOWN:
268            {
269                if ( sws->style & SBS_FIXED ) {
270                    return (MRESULT)(FALSE);
271                }
272
273                SHORT oldpos = sws->splitterPos;
274
275                POINTL ptl = { SHORT1FROMMP( mp1 ), SHORT2FROMMP( mp1 ) };
276                TRACKINFO track;
277
278                track.cxBorder = 2;
279                track.cyBorder = 2;
280                track.cxGrid   = 1;
281                track.cyGrid   = 1;
282                track.cxKeyboard = 8;
283                track.cyKeyboard = 8;
284                WinQueryWindowRect( hwnd, &track.rclBoundary );
285                getSplitterSize( hwnd, sws, &track.rclTrack );
286
287                if ( !WinPtInRect( WinQueryAnchorBlock( hwnd ), &track.rclTrack, &ptl ) ) {
288                    return (MRESULT)FALSE;
289                }
290
291                track.ptlMinTrackSize.x = track.rclTrack.xRight
292                                        - track.rclTrack.xLeft;
293                track.ptlMinTrackSize.y = track.rclTrack.yTop
294                                        - track.rclTrack.yBottom;
295                track.ptlMaxTrackSize.x = track.rclTrack.xRight
296                                        - track.rclTrack.xLeft;
297                track.ptlMaxTrackSize.y = track.rclTrack.yTop
298                                        - track.rclTrack.yBottom;
299
300                track.fs = TF_MOVE | TF_ALLINBOUNDARY;
301
302                if ( WinTrackRect( hwnd, 0, &track ) )
303                {
304                    if ( sws->style & SBS_VSPLIT ) {
305                        sws->splitterPos = track.rclTrack.xLeft;
306                    } else {
307                        sws->splitterPos = track.rclTrack.yBottom;
308                    }
309
310                    setWindSize( hwnd, sws );
311
312                    // notify owner
313                    WinSendMsg( WinQueryWindow( hwnd, QW_OWNER ), WM_CONTROL,
314                                MPFROM2SHORT( WinQueryWindowUShort( hwnd, QWS_ID ),
315                                              SBN_POSITIONCHANGED ),
316                                MPFROM2SHORT( sws->splitterPos, oldpos ) );
317                }
318            }
319            return (MRESULT)(FALSE);
320
321        case WM_ERASEBACKGROUND:
322            return (MRESULT)(FALSE);
323    }
324    return WinDefWindowProc( hwnd, msg, mp1, mp2 );
325}
326
327
328BOOL InitPMSplitterClass( HAB hab )
329{
330    return WinRegisterClass( hab, WC_ER_SPLITTER, splitterProc,
331                             0, sizeof( ULONG ) * 2 );
332}
333
Note: See TracBrowser for help on using the repository browser.