1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/os2/scrolbar.cpp
3// Purpose:     wxScrollBar
4// Author:      David Webster
5// Modified by:
6// Created:     10/15/99
7// RCS-ID:      $Id: scrolbar.cpp 39476 2006-05-30 13:43:18Z ABX $
8// Copyright:   (c) David Webster
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#include "wx/scrolbar.h"
16
17#ifndef WX_PRECOMP
18    #include "wx/utils.h"
19#endif
20
21#include "wx/os2/private.h"
22
23IMPLEMENT_DYNAMIC_CLASS(wxScrollBar, wxControl)
24
25// Scrollbar
26bool wxScrollBar::Create(wxWindow* pParent,
27                         wxWindowID vId,
28                         const wxPoint& rPos,
29                         const wxSize& rSize,
30                         long lStyle,
31#if wxUSE_VALIDATORS
32                         const wxValidator& rValidator,
33#endif
34                         const wxString& rsName
35                        )
36{
37    int nX = rPos.x;
38    int nY = rPos.y;
39    int nWidth = rSize.x;
40    int nHeight = rSize.y;
41
42    if (!pParent)
43        return false;
44
45    pParent->AddChild(this);
46    SetName(rsName);
47#if wxUSE_VALIDATORS
48    SetValidator(rValidator);
49#endif
50    SetBackgroundColour(pParent->GetBackgroundColour()) ;
51    SetForegroundColour(pParent->GetForegroundColour()) ;
52
53    if (vId == wxID_ANY)
54        m_windowId = (int)NewControlId();
55    else
56        m_windowId = vId;
57
58    if (nWidth == wxDefaultCoord)
59    {
60        if (lStyle & wxHORIZONTAL)
61            nWidth = 140;
62        else
63            nWidth = 14;
64    }
65    if (nHeight == wxDefaultCoord)
66    {
67        if (lStyle & wxVERTICAL)
68            nHeight = 140;
69        else
70            nHeight = 14;
71    }
72
73    DWORD                           dwStyle = WS_VISIBLE;
74
75    if (GetWindowStyleFlag() & wxCLIP_SIBLINGS)
76        dwStyle |= WS_CLIPSIBLINGS;
77
78    DWORD dwDirection = (lStyle & wxHORIZONTAL) ? SBS_HORZ: SBS_VERT;
79
80    HWND hScrollBar = ::WinCreateWindow( (HWND)GetHwndOf(pParent)
81                                         ,WC_SCROLLBAR
82                                         ,(PSZ)NULL
83                                         ,dwDirection | dwStyle
84                                         ,0, 0, 0, 0
85                                         ,(HWND)GetHwndOf(pParent)
86                                         ,HWND_TOP
87                                         ,(HMENU)m_windowId
88                                         ,NULL
89                                         ,NULL
90                                         );
91
92    m_nPageSize = 1;
93    m_nViewSize = 1;
94    m_nObjectSize = 1;
95    ::WinSendMsg( hScrollBar
96                 ,SBM_SETSCROLLBAR
97                 ,(MPARAM)0
98                 ,MPFROM2SHORT(0,1)
99                );
100    ::WinShowWindow( hScrollBar, TRUE );
101    SetFont(*wxSMALL_FONT);
102
103    m_hWnd = hScrollBar;
104
105    //
106    // Subclass again for purposes of dialog editing mode
107    //
108    SubclassWin((WXHWND)hScrollBar);
109    SetSize( nX
110            ,nY
111            ,nWidth
112            ,nHeight
113           );
114    return true;
115} // end of wxScrollBar::Create
116
117wxScrollBar::~wxScrollBar()
118{
119}
120
121bool wxScrollBar::OS2OnScroll ( int    WXUNUSED(nOrientation),
122                                WXWORD wParam,
123                                WXWORD wPos,
124                                WXHWND WXUNUSED(hControl) )
125{
126    int         nPosition;
127    int         nMaxPos;
128    int         nTrackPos = wPos;
129    int         nMinPos;
130    int         nScrollInc;
131    wxEventType vScrollEvent = wxEVT_NULL;
132
133    MRESULT     vRange;
134
135    //
136    // When we're dragging the scrollbar we can't use pos parameter because it
137    // is limited to 16 bits
138    //
139    if (wParam == SB_SLIDERPOSITION || wParam == SB_SLIDERTRACK)
140    {
141        SBCDATA                     vScrollInfo;
142
143        vScrollInfo.sHilite = SB_SLIDERTRACK;
144
145        ::WinSendMsg((HWND)GetHwnd(), WM_QUERYWINDOWPARAMS, (PVOID)&vScrollInfo, NULL);
146
147        nTrackPos = vScrollInfo.posThumb;
148        nPosition = vScrollInfo.posFirst;
149        nMaxPos   = vScrollInfo.posLast;
150    }
151    else
152    {
153        nPosition = (int)(MRESULT)::WinSendMsg((HWND)GetHwnd(), SBM_QUERYPOS, (MPARAM)NULL, (MPARAM)NULL);
154        vRange = ::WinSendMsg((HWND)GetHwnd(), SBM_QUERYRANGE, (MPARAM)NULL, (MPARAM)NULL);
155        nMinPos = SHORT1FROMMR(vRange);
156        nMaxPos = SHORT2FROMMR(vRange);
157    }
158    //
159    // A page size greater than one has the effect of reducing the effective
160    // range, therefore the range has already been boosted artificially - so
161    // reduce it again.
162    //
163    if (m_nPageSize > 1)
164        nMaxPos -= (m_nPageSize - 1);
165    switch (wParam)
166    {
167        case SB_LINEUP:
168            nScrollInc   = -1;
169            vScrollEvent = wxEVT_SCROLL_LINEUP;
170            break;
171
172        case SB_LINEDOWN:
173            nScrollInc   = 1;
174            vScrollEvent = wxEVT_SCROLL_LINEDOWN;
175            break;
176
177        case SB_PAGEUP:
178            nScrollInc   = -GetPageSize();
179            vScrollEvent = wxEVT_SCROLL_PAGEUP;
180            break;
181
182        case SB_PAGEDOWN:
183            nScrollInc   = GetPageSize();
184            vScrollEvent = wxEVT_SCROLL_PAGEDOWN;
185            break;
186
187        case SB_SLIDERTRACK:
188            nScrollInc   = nTrackPos - nPosition;
189            vScrollEvent = wxEVT_SCROLL_THUMBTRACK;
190            break;
191
192        case SB_ENDSCROLL:
193            nScrollInc   = 0;
194            vScrollEvent = wxEVT_SCROLL_CHANGED;
195            break;
196
197        default:
198            nScrollInc = 0;
199    }
200    if (nScrollInc)
201    {
202        nPosition += nScrollInc;
203
204        if (nPosition < 0)
205            nPosition = 0;
206        if (nPosition > nMaxPos)
207            nPosition = nMaxPos;
208        SetThumbPosition(nPosition);
209    }
210    else if ( vScrollEvent != wxEVT_SCROLL_THUMBRELEASE &&
211              vScrollEvent != wxEVT_SCROLL_CHANGED
212            )
213    {
214        //
215        // Don't process the event if there is no displacement,
216        // unless this is a thumb release or end scroll event.
217        //
218        return false;
219    }
220
221    wxScrollEvent                   vEvent( vScrollEvent
222                                           ,m_windowId
223                                          );
224
225    vEvent.SetOrientation(IsVertical() ? wxVERTICAL : wxHORIZONTAL);
226    vEvent.SetPosition(nPosition);
227    vEvent.SetEventObject(this);
228    return GetEventHandler()->ProcessEvent(vEvent);
229} // end of wxScrollBar::OS2OnScroll
230
231void wxScrollBar::SetThumbPosition ( int nViewStart )
232{
233    SBCDATA                        vInfo;
234
235    memset(&vInfo, '\0', sizeof(SBCDATA));
236    vInfo.cb       = sizeof(SBCDATA);
237    vInfo.posThumb = (SHORT)nViewStart;
238
239    ::WinSendMsg((HWND)GetHwnd(), WM_SETWINDOWPARAMS, (MPARAM)&vInfo, (MPARAM)NULL);
240    ::WinSendMsg((HWND)GetHwnd(), SBM_SETPOS, (MPARAM)nViewStart, (MPARAM)NULL);
241} // end of wxScrollBar::SetThumbPosition
242
243int wxScrollBar::GetThumbPosition() const
244{
245    return((int)(MRESULT)::WinSendMsg((HWND)GetHwnd(), SBM_QUERYPOS, (MPARAM)NULL, (MPARAM)NULL));
246} // end of wxScrollBar::GetThumbPosition
247
248void wxScrollBar::SetScrollbar ( int  nPosition,
249                                 int  nThumbSize,
250                                 int  nRange,
251                                 int  nPageSize,
252                                 bool WXUNUSED(bRefresh) )
253{
254    SBCDATA                         vInfo;
255    //
256    // The lRange (number of scroll steps) is the
257    // object length minus the page size.
258    //
259    int                             nRange1 = wxMax((m_nObjectSize - m_nPageSize), 0);
260
261    m_nViewSize   = nPageSize;
262    m_nPageSize   = nThumbSize;
263    m_nObjectSize = nRange;
264
265
266    //
267    // Try to adjust the lRange to cope with page size > 1
268    // (see comment for SetPageLength)
269    //
270    if (m_nPageSize > 1 )
271    {
272        nRange1 += (m_nPageSize - 1);
273    }
274    vInfo.cb = sizeof(SBCDATA);
275    vInfo.cVisible = (SHORT)m_nPageSize;
276    vInfo.posFirst = 0;
277    vInfo.posLast  = (SHORT)nRange1;
278    vInfo.posThumb = (SHORT)nPosition;
279
280    ::WinSendMsg((HWND)GetHwnd(), WM_SETWINDOWPARAMS, (MPARAM)&vInfo, (MPARAM)NULL);
281} // end of wxScrollBar::SetScrollbar
282
283WXHBRUSH wxScrollBar::OnCtlColor ( WXHDC    WXUNUSED(hDC),
284                                   WXHWND   WXUNUSED(hWnd),
285                                   WXUINT   WXUNUSED(uCtlColor),
286                                   WXUINT   WXUNUSED(uMessage),
287                                   WXWPARAM WXUNUSED(wParam),
288                                   WXLPARAM WXUNUSED(lParam) )
289{
290    //
291    // Does nothing under OS/2
292    //
293    return 0;
294} // end of wxScrollBar::OnCtlColor
295
296void wxScrollBar::Command ( wxCommandEvent& rEvent )
297{
298    SetThumbPosition(rEvent.GetInt());
299    ProcessCommand(rEvent);
300} // end of wxScrollBar::Command
301