/* NSSlider.m Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: September 1997 This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "gnustep/gui/config.h" #include #include #include #include #include @implementation NSSlider static Class cellClass; + (void)initialize { if (self == [NSSlider class]) { // Initial version [self setVersion:1]; // Set our cell class to NSSliderCell [self setCellClass:[NSSliderCell class]]; } } + (void)setCellClass:(Class)class { cellClass = class; } + (Class)cellClass { return cellClass; } - initWithFrame:(NSRect)frameRect { NSSliderCell* theCell = [[[isa cellClass] new] autorelease]; [super initWithFrame:frameRect]; // set our cell [self setCell:theCell]; [theCell setState:1]; return self; } - (NSImage *)image { return [[self cell] image]; } - (int)isVertical { return [[self cell] isVertical]; } - (float)knobThickness { return [[self cell] knobThickness]; } - (void)setImage:(NSImage *)backgroundImage { [[self cell] setImage:backgroundImage]; } - (void)setKnobThickness:(float)aFloat { [[self cell] setKnobThickness:aFloat]; } - (void)setTitle:(NSString *)aString { [[self cell] setTitle:aString]; } - (void)setTitleCell:(NSCell *)aCell { [[self cell] setTitleCell:aCell]; } - (void)setTitleColor:(NSColor *)aColor { [[self cell] setTitleColor:aColor]; } - (void)setTitleFont:(NSFont *)fontObject { [[self cell] setTitleFont:fontObject]; } - (NSString *)title { return [[self cell] title]; } - (id)titleCell { return [[self cell] titleCell]; } - (NSColor *)titleColor { return [[self cell] titleColor]; } - (NSFont *)titleFont { return [[self cell] titleFont]; } - (double)maxValue { return [[self cell] maxValue]; } - (double)minValue { return [[self cell] minValue]; } - (void)setMaxValue:(double)aDouble { [[self cell] setMaxValue:aDouble]; } - (void)setMinValue:(double)aDouble { [[self cell] setMinValue:aDouble]; } - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { return YES; } - (void)drawRect:(NSRect)rect { [[self cell] drawWithFrame:rect inView:self]; } - (float)_floatValueForMousePoint:(NSPoint)point knobRect:(NSRect)knobRect { NSSliderCell* theCell = [self cell]; NSRect slotRect = [theCell trackRect]; BOOL isVertical = [theCell isVertical]; float minValue = [theCell minValue]; float maxValue = [theCell maxValue]; float floatValue = 0; float position; if (isVertical) { /* Adjust the point to lie inside the knob slot. We don't have to worry if the view is flipped or not. */ if (point.y < slotRect.origin.y + knobRect.size.height / 2) position = slotRect.origin.y + knobRect.size.height / 2; else if (point.y > slotRect.origin.y + slotRect.size.height - knobRect.size.height / 2) position = slotRect.origin.y + slotRect.size.height - knobRect.size.height / 2; else position = point.y; /* Compute the float value */ floatValue = (position - (slotRect.origin.y + knobRect.size.height/2)) / (slotRect.size.height - knobRect.size.height); if ([self isFlipped]) floatValue = 1 - floatValue; } else { /* Adjust the point to lie inside the knob slot */ if (point.x < slotRect.origin.x + knobRect.size.width / 2) position = slotRect.origin.x + knobRect.size.width / 2; else if (point.x > slotRect.origin.x + slotRect.size.width - knobRect.size.width / 2) position = slotRect.origin.x + slotRect.size.width - knobRect.size.width / 2; else position = point.x; /* Compute the float value considering the knob size */ floatValue = (position - (slotRect.origin.x + knobRect.size.width / 2)) / (slotRect.size.width - knobRect.size.width); } return floatValue * (maxValue - minValue) + minValue; } - (void)trackKnob:(NSEvent*)theEvent knobRect:(NSRect)knobRect { unsigned int eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask | NSLeftMouseDraggedMask | NSMouseMovedMask | NSPeriodicMask; NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSEventType eventType = [theEvent type]; BOOL isContinuous = [self isContinuous]; NSSliderCell* theCell = [self cell]; float oldFloatValue = [theCell floatValue]; id target = [theCell target]; SEL action = [theCell action]; [NSEvent startPeriodicEventsAfterDelay:0.05 withPeriod:0.05]; [[NSRunLoop currentRunLoop] limitDateForMode:NSEventTrackingRunLoopMode]; while (eventType != NSLeftMouseUp) { theEvent = [[NSApplication sharedApplication] nextEventMatchingMask:eventMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES]; eventType = [theEvent type]; if (eventType != NSPeriodic) point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; else if (point.x != knobRect.origin.x || point.y != knobRect.origin.y) { float floatValue = [self _floatValueForMousePoint:point knobRect:knobRect]; if (floatValue != oldFloatValue) { [theCell setFloatValue:floatValue]; #if 0 [theCell drawWithFrame:[self bounds] inView:self]; [[self window] flushWindow]; #else [self setNeedsDisplay:YES]; #endif if (isContinuous) [target performSelector:action withObject:self]; oldFloatValue = floatValue; } knobRect.origin = point; } } /* If the control is not continuous send the action at the end of the drag */ if (!isContinuous) [target performSelector:action withObject:self]; [NSEvent stopPeriodicEvents]; } - (void)mouseDown:(NSEvent *)theEvent { NSPoint location = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSSliderCell* theCell = [self cell]; NSRect rect; [self lockFocus]; rect = [theCell knobRectFlipped:[self isFlipped]]; if (![self mouse:location inRect:rect]) { /* Mouse is not on the knob, move the knob to the mouse position */ float floatValue = [self _floatValueForMousePoint:location knobRect:rect]; [theCell setFloatValue:floatValue]; if ([self isContinuous]) [[theCell target] performSelector:[theCell action] withObject:self]; #if 0 [theCell drawWithFrame:[self bounds] inView:self]; [[self window] flushWindow]; #else [self setNeedsDisplay:YES]; #endif } [self trackKnob:theEvent knobRect:rect]; } @end