5b2a1701f3ea77123ff8c16bb3f9a4fe337a8c74
[WebKit-https.git] / WebCore / platform / mac / PlatformScrollBarMac.mm
1 /*
2  * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "PlatformScrollBar.h"
28
29 #import "BlockExceptions.h"
30
31 using namespace WebCore;
32
33 @interface WebCoreScrollBar : NSScroller
34 {
35     PlatformScrollbar* scrollbar;
36 }
37
38 - (id)initWithPlatformScrollbar:(PlatformScrollbar*)s;
39 - (void)detachPlatformScrollbar;
40
41 @end
42
43 @implementation WebCoreScrollBar
44
45 static NSControlSize NSControlSizeForScrollBarControlSize(ScrollbarControlSize size)
46 {
47     if (size == SmallScrollbar)
48         return NSSmallControlSize;
49     if (size == MiniScrollbar)
50         return NSMiniControlSize;
51     return NSRegularControlSize;
52 }
53
54 - (id)initWithPlatformScrollbar:(PlatformScrollbar*)s
55 {
56     // Cocoa scrollbars just set their orientation by examining their own
57     // dimensions, so we have to do this unsavory hack.
58     NSRect orientation;
59     NSControlSize controlSize = NSControlSizeForScrollBarControlSize(s->controlSize());
60     orientation.origin.x = orientation.origin.y = 0;
61     if (s->orientation() == VerticalScrollbar) {
62         orientation.size.width = [NSScroller scrollerWidthForControlSize:controlSize];
63         orientation.size.height = 100;
64     } else {
65         orientation.size.width = 100;
66         orientation.size.height = [NSScroller scrollerWidthForControlSize:controlSize];
67     }
68     self = [self initWithFrame:orientation];
69
70     scrollbar = s;
71
72     [self setEnabled:YES];
73     [self setTarget:self];
74     [self setAction:@selector(scroll:)];
75     [self setControlSize:controlSize];
76
77     return self;
78 }
79
80 - (void)detachPlatformScrollbar
81 {
82     [self setTarget:nil];
83     scrollbar = 0;
84 }
85
86 - (IBAction)scroll:(NSScroller*)sender
87 {
88     if (scrollbar)
89         scrollbar->scrollbarHit([sender hitPart]);
90 }
91
92 - (void)mouseDown:(NSEvent *)event
93 {
94     Widget::beforeMouseDown(self, scrollbar);
95     [super mouseDown:event];
96     Widget::afterMouseDown(self, scrollbar);
97 }
98
99 @end
100
101 namespace WebCore
102 {
103
104 PlatformScrollbar::PlatformScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
105     : Scrollbar(client, orientation, controlSize)
106 {
107     BEGIN_BLOCK_OBJC_EXCEPTIONS;
108
109     WebCoreScrollBar *bar = [[WebCoreScrollBar alloc] initWithPlatformScrollbar:this];
110     setView(bar);
111     [bar release];
112
113     END_BLOCK_OBJC_EXCEPTIONS;
114 }
115
116 PlatformScrollbar::~PlatformScrollbar()
117 {
118     WebCoreScrollBar* bar = (WebCoreScrollBar*)getView();
119     [bar detachPlatformScrollbar];
120
121     // Widget should probably do this for all widgets.
122     // But we don't need it for form elements, and for frames it doesn't work
123     // well because of the way the NSViews are created in WebKit. So for now,
124     // we'll just do it explictly for Scrollbar.
125     removeFromSuperview();
126 }
127
128 void PlatformScrollbar::updateThumbPosition()
129 {
130     BEGIN_BLOCK_OBJC_EXCEPTIONS;
131     WebCoreScrollBar *bar = (WebCoreScrollBar *)getView();
132     [bar setFloatValue:(float)m_currentPos / (m_totalSize - m_visibleSize)
133         knobProportion:[bar knobProportion]];
134     END_BLOCK_OBJC_EXCEPTIONS;
135 }
136
137 void PlatformScrollbar::updateThumbProportion()
138 {
139     float val = (float)m_visibleSize/m_totalSize;
140
141     BEGIN_BLOCK_OBJC_EXCEPTIONS;
142     WebCoreScrollBar *bar = (WebCoreScrollBar *)getView();
143     if (!(val == [bar knobProportion] || val < 0.0))
144         [bar setFloatValue: [bar floatValue] knobProportion: val];
145     END_BLOCK_OBJC_EXCEPTIONS;
146 }
147
148 bool PlatformScrollbar::scrollbarHit(NSScrollerPart hitPart)
149 {
150     int maxPos = m_totalSize - m_visibleSize;
151     if (maxPos <= 0)
152         return false; // Impossible to scroll anywhere.
153     
154     WebCoreScrollBar *bar = (WebCoreScrollBar *)getView();
155     int newPos = m_currentPos;
156     switch (hitPart) {
157         case NSScrollerDecrementLine:
158             newPos -= m_lineStep;
159             break;
160         case NSScrollerIncrementLine:
161             newPos += m_lineStep;
162             break;
163         case NSScrollerDecrementPage:
164             newPos -= m_pageStep;
165             break;
166         case NSScrollerIncrementPage:
167             newPos += m_pageStep;
168             break;
169
170             // If the thumb is hit, then the scrollbar changed its value for us.
171         case NSScrollerKnob:
172         case NSScrollerKnobSlot:
173             newPos = (int)([bar floatValue] * maxPos);
174             break;
175
176         case NSScrollerNoPart:
177             break;
178     }
179
180     return setValue(newPos);
181 }
182
183 int PlatformScrollbar::width() const
184 {
185     return Widget::width();
186 }
187
188 int PlatformScrollbar::height() const
189 {
190     return Widget::height();
191 }
192
193 void PlatformScrollbar::setRect(const IntRect& rect)
194 {
195     setFrameGeometry(rect);
196 }
197
198 void PlatformScrollbar::setEnabled(bool enabled)
199 {
200     Widget::setEnabled(enabled);
201 }
202
203 void PlatformScrollbar::paint(GraphicsContext* graphicsContext, const IntRect& damageRect)
204 {
205     Widget::paint(graphicsContext, damageRect);
206 }
207
208 }