/* * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "config.h" #import "PlatformScrollBar.h" #import "BlockExceptions.h" using namespace WebCore; @interface WebCoreScrollBar : NSScroller { PlatformScrollbar* scrollbar; } - (id)initWithPlatformScrollbar:(PlatformScrollbar*)s; - (void)detachPlatformScrollbar; @end @implementation WebCoreScrollBar static NSControlSize NSControlSizeForScrollBarControlSize(ScrollbarControlSize size) { if (size == SmallScrollbar) return NSSmallControlSize; if (size == MiniScrollbar) return NSMiniControlSize; return NSRegularControlSize; } - (id)initWithPlatformScrollbar:(PlatformScrollbar*)s { // Cocoa scrollbars just set their orientation by examining their own // dimensions, so we have to do this unsavory hack. NSRect orientation; NSControlSize controlSize = NSControlSizeForScrollBarControlSize(s->controlSize()); orientation.origin.x = orientation.origin.y = 0; if (s->orientation() == VerticalScrollbar) { orientation.size.width = [NSScroller scrollerWidthForControlSize:controlSize]; orientation.size.height = 100; } else { orientation.size.width = 100; orientation.size.height = [NSScroller scrollerWidthForControlSize:controlSize]; } self = [self initWithFrame:orientation]; scrollbar = s; [self setEnabled:YES]; [self setTarget:self]; [self setAction:@selector(scroll:)]; [self setControlSize:controlSize]; return self; } - (void)detachPlatformScrollbar { [self setTarget:nil]; scrollbar = 0; } - (IBAction)scroll:(NSScroller*)sender { if (scrollbar) scrollbar->scrollbarHit([sender hitPart]); } - (void)mouseDown:(NSEvent *)event { Widget::beforeMouseDown(self, scrollbar); [super mouseDown:event]; Widget::afterMouseDown(self, scrollbar); } @end namespace WebCore { PlatformScrollbar::PlatformScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize) : Scrollbar(client, orientation, controlSize) { BEGIN_BLOCK_OBJC_EXCEPTIONS; WebCoreScrollBar *bar = [[WebCoreScrollBar alloc] initWithPlatformScrollbar:this]; setView(bar); [bar release]; END_BLOCK_OBJC_EXCEPTIONS; } PlatformScrollbar::~PlatformScrollbar() { WebCoreScrollBar* bar = (WebCoreScrollBar*)getView(); [bar detachPlatformScrollbar]; // Widget should probably do this for all widgets. // But we don't need it for form elements, and for frames it doesn't work // well because of the way the NSViews are created in WebKit. So for now, // we'll just do it explictly for Scrollbar. removeFromSuperview(); } void PlatformScrollbar::updateThumbPosition() { BEGIN_BLOCK_OBJC_EXCEPTIONS; WebCoreScrollBar *bar = (WebCoreScrollBar *)getView(); [bar setFloatValue:(float)m_currentPos / (m_totalSize - m_visibleSize) knobProportion:[bar knobProportion]]; END_BLOCK_OBJC_EXCEPTIONS; } void PlatformScrollbar::updateThumbProportion() { float val = (float)m_visibleSize/m_totalSize; BEGIN_BLOCK_OBJC_EXCEPTIONS; WebCoreScrollBar *bar = (WebCoreScrollBar *)getView(); if (!(val == [bar knobProportion] || val < 0.0)) [bar setFloatValue: [bar floatValue] knobProportion: val]; END_BLOCK_OBJC_EXCEPTIONS; } bool PlatformScrollbar::scrollbarHit(NSScrollerPart hitPart) { int maxPos = m_totalSize - m_visibleSize; if (maxPos <= 0) return false; // Impossible to scroll anywhere. WebCoreScrollBar *bar = (WebCoreScrollBar *)getView(); int newPos = value(); switch (hitPart) { case NSScrollerDecrementLine: newPos -= m_lineStep; break; case NSScrollerIncrementLine: newPos += m_lineStep; break; case NSScrollerDecrementPage: newPos -= m_pageStep; break; case NSScrollerIncrementPage: newPos += m_pageStep; break; // If the thumb is hit, then the scrollbar changed its value for us. case NSScrollerKnob: case NSScrollerKnobSlot: newPos = (int)([bar floatValue] * maxPos); break; case NSScrollerNoPart: break; } return setValue(newPos); } int PlatformScrollbar::width() const { return Widget::width(); } int PlatformScrollbar::height() const { return Widget::height(); } void PlatformScrollbar::setRect(const IntRect& rect) { setFrameGeometry(rect); } void PlatformScrollbar::setEnabled(bool enabled) { Widget::setEnabled(enabled); } void PlatformScrollbar::paint(GraphicsContext* graphicsContext, const IntRect& damageRect) { Widget::paint(graphicsContext, damageRect); } }