wxCocoa: Added wxScrollBar
[wxWidgets.git] / src / cocoa / scrolbar.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        cocoa/scrolbar.mm
3 // Purpose:     wxScrollBar
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2004/04/25
7 // RCS-ID:      $Id$
8 // Copyright:   (c) 2004 David Elliott
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13 #if wxUSE_SCROLLBAR
14
15 #ifndef WX_PRECOMP
16     #include "wx/app.h"
17     #include "wx/scrolbar.h"
18 #endif //WX_PRECOMP
19
20 #import <AppKit/NSScroller.h>
21
22 IMPLEMENT_DYNAMIC_CLASS(wxScrollBar, wxControl)
23 BEGIN_EVENT_TABLE(wxScrollBar, wxScrollBarBase)
24 END_EVENT_TABLE()
25 WX_IMPLEMENT_COCOA_OWNER(wxScrollBar,NSScroller,NSControl,NSView)
26
27 bool wxScrollBar::Create(wxWindow *parent, wxWindowID winid,
28             const wxPoint& pos, const wxSize& size, long style,
29             const wxValidator& validator, const wxString& name)
30 {
31     if(!CreateControl(parent,winid,pos,size,style,validator,name))
32         return false;
33     SetNSScroller([[NSScroller alloc] initWithFrame: MakeDefaultNSRect(size)]);
34     [m_cocoaNSView release];
35     if(m_parent)
36         m_parent->CocoaAddChild(this);
37     SetInitialFrameRect(pos,size);
38
39     return true;
40 }
41
42 wxScrollBar::~wxScrollBar()
43 {
44     DisassociateNSScroller(GetNSScroller());
45 }
46
47 /* A word about NSScroller vs. wxScrollbar:
48
49 NSScroller uses two float values to represent the state of the scroller.
50 The floatValue indicates where the knob is positioned on a scale from
51 0.0 to 1.0.  A value of 0.0 indicates the scroller is at the top or left,
52 a value of 1.0 indicates the scroller is at the bottom or right.  A value
53 of 0.5 indicates the scroller is dead center.
54
55 wxScrollBar uses three values.  The position indicates the number of
56 scroll units where 0 is at the top or left.  The range indicates how
57 many scroll units there are in the entire bar and the thumb size indicates
58 how many scroll units the thumb takes.  The scrollbar is at the bottom
59 or right when position == range - thumbSize.
60
61 It may be easier to consider wx position to be the top or left of the thumb.
62 In Cocoa, floatValue can be considered as if it were the center of the
63 thumb and the range is ALWAYS (no matter what the knobProportion is) the
64 distance between the center point of the knob from one extreme to the other.
65 */
66
67 int wxScrollBar::GetThumbPosition() const
68 {
69     return (int)((m_range-m_thumbSize)*[GetNSScroller() floatValue]);
70 }
71
72 void wxScrollBar::SetThumbPosition(int position)
73 {
74     [GetNSScroller() setFloatValue:((float)position)/(m_range-m_thumbSize)];
75 }
76
77 void wxScrollBar::SetScrollbar(int position, int thumbSize,
78             int range, int pageSize, bool refresh)
79 {
80     m_range = range;
81     m_thumbSize = thumbSize;
82     m_pageSize = pageSize;
83     [GetNSScroller() setFloatValue:((float)position)/(m_range-m_thumbSize)
84             knobProportion:((float)m_thumbSize)/m_range];
85 }
86
87 void wxScrollBar::Cocoa_wxNSScrollerAction()
88 {
89     NSScrollerPart hitPart = [GetNSScroller() hitPart];
90     wxEventType command;
91     // Note: the comments about the part that is hit are for OS X, the
92     // constants are sort of a leftover from NeXT.  It makes more sense if
93     // you remember that in NeXT clicking the knob slot used to do what
94     // option-clicking does now.
95     switch(hitPart)
96     {
97     // User dragged knob
98     case NSScrollerKnob:
99         command = wxEVT_SCROLL_THUMBTRACK;
100         break;
101     // User option-clicked slot
102     case NSScrollerKnobSlot:
103         command = wxEVT_SCROLL_THUMBTRACK;
104         break;
105     // User clicked Up/Left button
106     case NSScrollerDecrementLine:
107         command = wxEVT_SCROLL_LINEUP;
108         break;
109     // User option-clicked Up/left or clicked in slot
110     case NSScrollerDecrementPage:
111         command = wxEVT_SCROLL_PAGEUP;
112         break;
113     // User clicked Down/Right button
114     case NSScrollerIncrementLine:
115         command = wxEVT_SCROLL_LINEDOWN;
116         break;
117     // User option-clicked Down/Right or clicked in slot
118     case NSScrollerIncrementPage:
119         command = wxEVT_SCROLL_PAGEDOWN;
120         break;
121     // No-op
122     case NSScrollerNoPart:
123     default:
124         return;
125     }
126     // TODO: When scrolling by pages, readjust the floatValue using the
127     // pageSize (which may be different from thumbSize).
128     wxScrollEvent event(command, GetId(), GetThumbPosition(),
129         HasFlag(wxSB_VERTICAL)?wxVERTICAL:wxHORIZONTAL);
130     event.SetEventObject(this);
131     GetEventHandler()->ProcessEvent(event);
132 }
133
134 #endif // wxUSE_SCROLLBAR