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