No code changes, fixed various typos.
[wxWidgets.git] / src / cocoa / scrolbar.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/scrolbar.mm
3 // Purpose:     wxScrollBar
4 // Author:      David Elliott
5 // Modified by: Mark Oxenham
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
14 #if wxUSE_SCROLLBAR
15
16 #include "wx/scrolbar.h"
17
18 #ifndef WX_PRECOMP
19     #include "wx/app.h"
20 #endif //WX_PRECOMP
21
22 #import <AppKit/NSScroller.h>
23
24 BEGIN_EVENT_TABLE(wxScrollBar, wxScrollBarBase)
25 END_EVENT_TABLE()
26 WX_IMPLEMENT_COCOA_OWNER(wxScrollBar,NSScroller,NSControl,NSView)
27
28 inline NSControlSize AdjustDimension(
29                 int             &pos,
30                 wxSize          &size,
31                 int             (wxSize::*GetDimension)() const,
32                 void            (wxSize::*SetDimension)(int))
33 {
34     NSControlSize controlSize = NSRegularControlSize;
35     const int dimension = (size.*GetDimension)();
36
37     if ((size.GetHeight() == -1) || (size.GetWidth() == -1) || (dimension >= 15)) 
38     {
39         (size.*SetDimension)(15);
40     }
41     else
42     {
43         (size.*SetDimension)(11);
44         controlSize = NSSmallControlSize;
45     }
46
47     pos += (dimension - (size.*GetDimension)() + 1) / 2;
48
49     return (controlSize);
50 }
51
52 bool wxScrollBar::Create(wxWindow *parent, wxWindowID winid,
53             const wxPoint& pos, const wxSize& size, long style,
54             const wxValidator& validator, const wxString& name)
55 {
56     NSControlSize controlSize = NSRegularControlSize;
57     wxSize adjustedSize(size);
58     wxPoint adjustedPos(pos);
59
60     if ((style & wxSB_HORIZONTAL) && ((size.GetHeight() != wxDefaultCoord) || (size.GetHeight() == -1)))
61     {
62         controlSize = AdjustDimension(adjustedPos.y, adjustedSize, &wxSize::GetHeight, &wxSize::SetHeight);
63     }
64     else if ((style & wxSB_VERTICAL) && (size.GetWidth() != wxDefaultCoord || (size.GetWidth() == -1)))
65     {
66         controlSize = AdjustDimension(adjustedPos.x, adjustedSize, &wxSize::GetWidth, &wxSize::SetWidth);
67     }
68
69     if(!CreateControl(parent,winid,adjustedPos,adjustedSize,style,validator,name))
70         return false;
71     SetNSScroller([[NSScroller alloc] initWithFrame: MakeDefaultNSRect(adjustedSize)]);
72     [m_cocoaNSView release];
73     if(m_parent)
74         m_parent->CocoaAddChild(this);
75     SetInitialFrameRect(adjustedPos,adjustedSize);
76
77     BOOL nsEnabled = [GetNSScroller() isEnabled];
78
79     if (IsEnabled() != (nsEnabled != NO))
80     {
81         [GetNSScroller() setEnabled: !nsEnabled];
82     }
83
84     [GetNSScroller() setControlSize: controlSize];
85
86     return true;
87 }
88
89 wxScrollBar::~wxScrollBar()
90 {
91     DisassociateNSScroller(GetNSScroller());
92 }
93
94 /* A word about NSScroller vs. wxScrollbar:
95
96 NSScroller uses two float values to represent the state of the scroller.
97 The floatValue indicates where the knob is positioned on a scale from
98 0.0 to 1.0.  A value of 0.0 indicates the scroller is at the top or left,
99 a value of 1.0 indicates the scroller is at the bottom or right.  A value
100 of 0.5 indicates the scroller is dead center.
101
102 wxScrollBar uses three values.  The position indicates the number of
103 scroll units where 0 is at the top or left.  The range indicates how
104 many scroll units there are in the entire bar and the thumb size indicates
105 how many scroll units the thumb takes.  The scrollbar is at the bottom
106 or right when position == range - thumbSize.
107
108 It may be easier to consider wx position to be the top or left of the thumb.
109 In Cocoa, floatValue can be considered as if it were the center of the
110 thumb and the range is ALWAYS (no matter what the knobProportion is) the
111 distance between the center point of the knob from one extreme to the other.
112 */
113
114 int wxScrollBar::GetThumbPosition() const
115 {
116     return (int)((m_range-m_thumbSize)*[GetNSScroller() floatValue]);
117 }
118
119 void wxScrollBar::SetThumbPosition(int position)
120 {
121     [GetNSScroller() setFloatValue:((float)position)/(m_range-m_thumbSize)];
122 }
123
124 void wxScrollBar::SetScrollbar(int position, int thumbSize,
125             int range, int pageSize, bool refresh)
126 {
127     m_range = range;
128     m_thumbSize = thumbSize;
129     m_pageSize = pageSize;
130     [GetNSScroller() setFloatValue:((float)position)/(m_range-m_thumbSize)
131             knobProportion:((float)m_thumbSize)/m_range];
132 }
133
134 void wxScrollBar::Cocoa_wxNSScrollerAction()
135 {
136     NSScrollerPart hitPart = [GetNSScroller() hitPart];
137     wxEventType command;
138     // Note: the comments about the part that is hit are for OS X, the
139     // constants are sort of a leftover from NeXT.  It makes more sense if
140     // you remember that in NeXT clicking the knob slot used to do what
141     // option-clicking does now.
142     switch(hitPart)
143     {
144     // User dragged knob
145     case NSScrollerKnob:
146         command = wxEVT_SCROLL_THUMBTRACK;
147         break;
148     // User option-clicked slot
149     case NSScrollerKnobSlot:
150         command = wxEVT_SCROLL_THUMBTRACK;
151         break;
152     // User clicked Up/Left button
153     case NSScrollerDecrementLine:
154         command = wxEVT_SCROLL_LINEUP;
155         break;
156     // User option-clicked Up/left or clicked in slot
157     case NSScrollerDecrementPage:
158         command = wxEVT_SCROLL_PAGEUP;
159         break;
160     // User clicked Down/Right button
161     case NSScrollerIncrementLine:
162         command = wxEVT_SCROLL_LINEDOWN;
163         break;
164     // User option-clicked Down/Right or clicked in slot
165     case NSScrollerIncrementPage:
166         command = wxEVT_SCROLL_PAGEDOWN;
167         break;
168     // No-op
169     case NSScrollerNoPart:
170     default:
171         return;
172     }
173     // TODO: When scrolling by pages, readjust the floatValue using the
174     // pageSize (which may be different from thumbSize).
175     wxScrollEvent event(command, GetId(), GetThumbPosition(),
176         HasFlag(wxSB_VERTICAL)?wxVERTICAL:wxHORIZONTAL);
177     event.SetEventObject(this);
178     HandleWindowEvent(event);
179 }
180
181 #endif // wxUSE_SCROLLBAR