Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
HIDoubleSlider.cp
/* |
File: HIDoubleSlider.cp |
Contains: Demonstrates creating a double slider using the HIView APIs. |
Version: 1.0 |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. |
("Apple") in consideration of your agreement to the following terms, and your |
use, installation, modification or redistribution of this Apple software |
constitutes acceptance of these terms. If you do not agree with these terms, |
please do not use, install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and subject |
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs |
copyrights in this original Apple software (the "Apple Software"), to use, |
reproduce, modify and redistribute the Apple Software, with or without |
modifications, in source and/or binary forms; provided that if you redistribute |
the Apple Software in its entirety and without modifications, you must retain |
this notice and the following text and disclaimers in all such redistributions of |
the Apple Software. Neither the name, trademarks, service marks or logos of |
Apple Computer, Inc. may be used to endorse or promote products derived from the |
Apple Software without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or implied, |
are granted by Apple herein, including but not limited to any patent rights that |
may be infringed by your derivative works or by other works in which the Apple |
Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT |
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN |
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Copyright © 2002 Apple Computer, Inc., All Rights Reserved |
*/ |
#include <Carbon/Carbon.h> |
#include "HIDoubleSlider.h" |
// structure in which we hold our custom push button's data |
typedef struct |
{ |
HIViewRef view; // the HIViewRef for our button |
SInt32 hiValue; // our settings |
SInt32 loValue; |
ControlRef invisibleHiSlider; |
ControlRef invisibleLoSlider; |
} |
DoubleSliderData; |
pascal OSStatus ViewHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon); |
CFStringRef GetDoubleSliderClass(); |
void SetControlHiLoValue(ControlRef theControl, SInt32 newValue, Boolean hiOrLo); |
/* |
* HICreateDoubleSlider() |
* |
* Summary: |
* Creates a double slider control. |
* |
* Parameters: |
* |
* boundsRect: |
* The bounding box of the control. |
* |
* minimum: |
* maximum: |
* loValue: |
* hiValue: |
* 32 Bits settings. |
* |
* outDoubleSlider: |
* On exit, contains the new control. |
* |
* Availability: |
* Mac OS X: in version 10.2 and later since it needs the HIView APIs |
* CarbonLib: not available |
* Non-Carbon CFM: not available |
*/ |
OSStatus |
HICreateDoubleSlider( |
const HIRect * boundsRect, |
SInt32 minimum, SInt32 maximum, SInt32 loValue, SInt32 hiValue, |
HIViewRef * outDoubleSlider) |
{ |
EventRef theInitializeEvent = NULL; |
HIObjectRef hiObject = NULL; |
OSStatus theStatus = CreateEvent(NULL, kEventClassHIObject, kEventHIObjectInitialize, GetCurrentEventTime(), kEventAttributeUserEvent, &theInitializeEvent); |
if (theStatus != noErr) goto exitCreation; |
// settings |
SetEventParameter(theInitializeEvent, kControlLoValueTag, typeSInt32, sizeof(loValue), &loValue); |
SetEventParameter(theInitializeEvent, kControlHiValueTag, typeSInt32, sizeof(hiValue), &hiValue); |
SetEventParameter(theInitializeEvent, kControlCollectionTagMinimum, typeSInt32, sizeof(minimum), &minimum); |
SetEventParameter(theInitializeEvent, kControlCollectionTagMaximum, typeSInt32, sizeof(maximum), &maximum); |
SetEventParameter(theInitializeEvent, kControlCollectionTagBounds, typeHIRect, sizeof(HIRect), boundsRect); |
theStatus = HIObjectCreate(GetDoubleSliderClass(), theInitializeEvent, &hiObject); |
if (theStatus != noErr) goto exitCreation; |
exitCreation: |
*outDoubleSlider = (HIViewRef)hiObject; |
if (theInitializeEvent != NULL) ReleaseEvent(theInitializeEvent); |
return theStatus; |
} |
UInt32 GetHIToolboxVersion() |
{ |
CFBundleRef bundle; |
CFStringRef versionStr = NULL; |
static UInt32 version = 0; |
if (version != 0) return version; |
bundle = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.HIToolbox") ); |
if ( bundle != NULL ) |
versionStr = (CFStringRef) CFBundleGetValueForInfoDictionaryKey( bundle, CFSTR("CFBundleShortVersionString") ); |
if ( versionStr != NULL && CFGetTypeID( versionStr ) == CFStringGetTypeID() ) |
{ |
int major = 0, minor = 0, bugfix = 0; |
char sz[20]; |
CFStringGetCString( versionStr, sz, sizeof( sz ), kCFStringEncodingUTF8 ); |
sscanf( sz, "%d.%d.%d", &major, &minor, &bugfix ); |
version = ( major << 8 ) + ( minor << 4 ) + bugfix; |
} |
return version; |
} |
/*----------------------------------------------------------------------------------------------------------*/ |
// ¥ GetDoubleSliderClass |
// Registers and returns an HIObject class for a double slider. |
/*----------------------------------------------------------------------------------------------------------*/ |
CFStringRef GetDoubleSliderClass() |
{ |
// following code is pretty much boiler plate. |
static HIObjectClassRef theClass; |
if (theClass == NULL) |
{ |
static EventTypeSpec kFactoryEvents[] = |
{ |
// the next 3 messages are boiler plate |
{ kEventClassHIObject, kEventHIObjectConstruct }, |
{ kEventClassHIObject, kEventHIObjectInitialize }, |
{ kEventClassHIObject, kEventHIObjectDestruct }, |
// the next 2 messages are specific to our class |
{ kEventClassDoubleSlider, kEventControlHiValueFieldChanged }, |
{ kEventClassDoubleSlider, kEventControlLoValueFieldChanged }, |
// the next messages are the minimum messages we need to |
// implement the double slider control. |
{ kEventClassControl, kEventControlInitialize }, |
{ kEventClassControl, kEventControlHitTest }, |
{ kEventClassControl, kEventControlTrack }, |
{ kEventClassControl, kEventControlHiliteChanged }, |
{ kEventClassControl, kEventControlActivate }, |
{ kEventClassControl, kEventControlDeactivate }, |
{ kEventClassControl, kEventControlDraw } |
}; |
HIObjectRegisterSubclass(kDoubleSliderClassID, kHIViewClassID, 0, ViewHandler, |
GetEventTypeCount(kFactoryEvents), kFactoryEvents, 0, &theClass); |
} |
return kDoubleSliderClassID; |
} |
/*----------------------------------------------------------------------------------------------------------*/ |
// ¥ GetLoHiRects |
// returns the Rects of both our indicators. |
/*----------------------------------------------------------------------------------------------------------*/ |
void GetLoHiRects(DoubleSliderData* myData, Rect *loRect, Rect *hiRect) |
{ |
SetControl32BitValue(myData->invisibleLoSlider, myData->loValue); |
SetControl32BitValue(myData->invisibleHiSlider, myData->hiValue); |
RgnHandle theRgn = NewRgn(); |
GetControlRegion(myData->invisibleLoSlider, kControlIndicatorPart, theRgn); |
GetRegionBounds(theRgn, loRect); |
GetControlRegion(myData->invisibleHiSlider, kControlIndicatorPart, theRgn); |
GetRegionBounds(theRgn, hiRect); |
DisposeRgn(theRgn); |
} |
enum |
{ |
kControlHiIndicatorPart = 170, |
kControlLoIndicatorPart = 171 |
}; |
/*----------------------------------------------------------------------------------------------------------*/ |
// ¥ FindPart |
// returns which part the Point (from the EventRef) is in or kControlNoPart if not. |
/*----------------------------------------------------------------------------------------------------------*/ |
ControlPartCode FindPart(EventRef inEvent, DoubleSliderData* myData) |
{ |
ControlPartCode part = kControlNoPart; |
// the point parameter is in view-local coords. |
Point qdPoint; |
GetEventParameter(inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(qdPoint), NULL, &qdPoint); |
Rect loRect, hiRect; |
GetLoHiRects(myData, &loRect, &hiRect); |
if (PtInRect(qdPoint, &loRect)) part = kControlLoIndicatorPart; |
if (PtInRect(qdPoint, &hiRect)) part = kControlHiIndicatorPart; |
// if both values are at the maximum, we need to return the Lo indicator part or nothing will move ever again! |
if (myData->loValue == myData->hiValue) |
{ |
SInt32 max = GetControl32BitMaximum(myData->view); |
if (max == myData->loValue) |
part = kControlLoIndicatorPart; |
} |
return part; |
} |
/*----------------------------------------------------------------------------------------------------------*/ |
// ¥ DrawSlider |
// Draws the bar and both indicators using ONLY Appearance calls. |
/*----------------------------------------------------------------------------------------------------------*/ |
void DrawSliderJaguar(DoubleSliderData* myData) |
{ |
ThemeTrackDrawInfo drawInfo; |
drawInfo.kind = kThemeSlider; |
HIRect hiBounds; |
HIViewGetBounds(myData->view, &hiBounds); |
drawInfo.bounds.left = drawInfo.bounds.top = 0; |
drawInfo.bounds.right = (int)hiBounds.size.width; |
drawInfo.bounds.bottom = (int)hiBounds.size.height; |
drawInfo.min = GetControl32BitMinimum(myData->view); |
drawInfo.max = GetControl32BitMaximum(myData->view); |
drawInfo.enableState = (IsControlActive(myData->view) && IsControlEnabled(myData->view))?kThemeTrackActive:kThemeTrackInactive; |
drawInfo.trackInfo.slider.pressState = 0; |
drawInfo.attributes = kThemeTrackRightToLeft; |
drawInfo.trackInfo.slider.thumbDir = kThemeThumbPlain; |
DrawThemeTrack(&drawInfo, NULL, NULL, NULL); |
Rect loRect, hiRect; |
GetLoHiRects(myData, &loRect, &hiRect); |
drawInfo.attributes = kThemeTrackRightToLeft | kThemeTrackShowThumb; |
drawInfo.bounds.top = loRect.top + 2; |
drawInfo.bounds.bottom = drawInfo.bounds.top + 16; |
drawInfo.value = myData->loValue; |
drawInfo.trackInfo.slider.thumbDir = kThemeThumbUpward; |
if (IsControlHilited(myData->view)) |
if (GetControlHilite(myData->view) == kControlLoIndicatorPart) |
drawInfo.trackInfo.slider.pressState = kThemeThumbPressed; |
DrawThemeTrack(&drawInfo, NULL, NULL, NULL); |
drawInfo.trackInfo.slider.pressState = 0; |
drawInfo.bounds.top = hiRect.top + 2; |
drawInfo.bounds.bottom = drawInfo.bounds.top + 16; |
drawInfo.value = myData->hiValue; |
drawInfo.trackInfo.slider.thumbDir = kThemeThumbDownward; |
if (IsControlHilited(myData->view)) |
if (GetControlHilite(myData->view) == kControlHiIndicatorPart) |
drawInfo.trackInfo.slider.pressState = kThemeThumbPressed; |
DrawThemeTrack(&drawInfo, NULL, NULL, NULL); |
} |
void DrawSliderPanther(DoubleSliderData* myData, CGContextRef context) |
{ |
HIThemeTrackDrawInfo drawInfo; |
drawInfo.version = 0; |
drawInfo.kind = kThemeSlider; |
HIViewGetBounds(myData->view, &drawInfo.bounds); |
drawInfo.min = GetControl32BitMinimum(myData->view); |
drawInfo.max = GetControl32BitMaximum(myData->view); |
drawInfo.enableState = (IsControlActive(myData->view) && IsControlEnabled(myData->view))?kThemeTrackActive:kThemeTrackInactive; |
drawInfo.trackInfo.slider.pressState = 0; |
drawInfo.attributes = kThemeTrackRightToLeft; |
drawInfo.trackInfo.slider.thumbDir = kThemeThumbPlain; |
HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal); |
Rect loRect, hiRect; |
GetLoHiRects(myData, &loRect, &hiRect); |
drawInfo.attributes = kThemeTrackRightToLeft | kThemeTrackShowThumb; |
drawInfo.bounds.origin.y = loRect.top + 2; |
drawInfo.bounds.size.height = 16; |
drawInfo.value = myData->loValue; |
drawInfo.trackInfo.slider.thumbDir = kThemeThumbUpward; |
if (IsControlHilited(myData->view)) |
if (GetControlHilite(myData->view) == kControlLoIndicatorPart) |
drawInfo.trackInfo.slider.pressState = kThemeThumbPressed; |
HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal); |
drawInfo.trackInfo.slider.pressState = 0; |
drawInfo.bounds.origin.y = hiRect.top + 2; |
// drawInfo.bounds.bottom = drawInfo.bounds.top + 16; |
drawInfo.value = myData->hiValue; |
drawInfo.trackInfo.slider.thumbDir = kThemeThumbDownward; |
if (IsControlHilited(myData->view)) |
if (GetControlHilite(myData->view) == kControlHiIndicatorPart) |
drawInfo.trackInfo.slider.pressState = kThemeThumbPressed; |
HIThemeDrawTrack(&drawInfo, NULL, context, kHIThemeOrientationNormal); |
} |
/*----------------------------------------------------------------------------------------------------------*/ |
// ¥ ViewHandler |
// Event handler that implements our double slider. |
/*----------------------------------------------------------------------------------------------------------*/ |
pascal OSStatus ViewHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon) |
{ |
OSStatus result = eventNotHandledErr; |
DoubleSliderData* myData = (DoubleSliderData*)inRefcon; |
switch (GetEventClass(inEvent)) |
{ |
case kEventClassHIObject: |
switch (GetEventKind(inEvent)) |
{ |
case kEventHIObjectConstruct: |
{ |
// allocate some instance data |
myData = (DoubleSliderData*) calloc(1, sizeof(DoubleSliderData)); |
// get our superclass instance |
HIViewRef epView; |
GetEventParameter(inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL, sizeof(epView), NULL, &epView); |
// remember our superclass in our instance data and initialize other fields |
myData->view = epView; |
myData->invisibleHiSlider = NULL; |
myData->invisibleLoSlider = NULL; |
// store our instance data into the event |
result = SetEventParameter(inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof(myData), &myData); |
break; |
} |
case kEventHIObjectDestruct: |
{ |
if (myData->invisibleLoSlider) DisposeControl(myData->invisibleLoSlider); |
if (myData->invisibleHiSlider) DisposeControl(myData->invisibleHiSlider); |
free(myData); |
result = noErr; |
break; |
} |
case kEventHIObjectInitialize: |
{ |
// always begin kEventHIObjectInitialize by calling through to the previous handler |
result = CallNextEventHandler(inCaller, inEvent); |
// if that succeeded, do our own initialization |
if (result == noErr) |
{ |
// settings |
GetEventParameter(inEvent, kControlLoValueTag, typeSInt32, NULL, sizeof(myData->loValue), NULL, &myData->loValue); |
GetEventParameter(inEvent, kControlHiValueTag, typeSInt32, NULL, sizeof(myData->hiValue), NULL, &myData->hiValue); |
SInt32 minimum; |
GetEventParameter(inEvent, kControlCollectionTagMinimum, typeSInt32, NULL, sizeof(minimum), NULL, &minimum); |
SetControl32BitMinimum(myData->view, minimum); |
SInt32 maximum; |
GetEventParameter(inEvent, kControlCollectionTagMaximum, typeSInt32, NULL, sizeof(maximum), NULL, &maximum); |
SetControl32BitMaximum(myData->view, maximum); |
HIRect bounds; |
GetEventParameter(inEvent, kControlCollectionTagBounds, typeHIRect, NULL, sizeof(bounds), NULL, &bounds); |
HIViewSetFrame(myData->view, &bounds); |
Rect cBounds = { 0, 0, (int)bounds.size.height - 1, (int)bounds.size.width }; |
// creating 2 invisible sliders to steal information from when needed. |
CreateSliderControl(NULL, &cBounds, 0, minimum, maximum, kControlSliderPointsDownOrRight, 0, false, NULL, &myData->invisibleLoSlider); |
CreateSliderControl(NULL, &cBounds, 0, minimum, maximum, kControlSliderPointsUpOrLeft, 0, false, NULL, &myData->invisibleHiSlider); |
HIViewSetVisible(myData->invisibleLoSlider, false); |
HIViewSetVisible(myData->invisibleHiSlider, false); |
// we're embedding those invisible sliders in our own view so that they move along |
HIViewAddSubview(myData->view, myData->invisibleLoSlider); |
HIViewAddSubview(myData->view, myData->invisibleHiSlider); |
} |
break; |
} |
default: |
break; |
} |
break; |
case kEventClassDoubleSlider: |
switch (GetEventKind(inEvent)) |
{ |
case kEventControlHiValueFieldChanged: |
case kEventControlLoValueFieldChanged: |
HIViewSetNeedsDisplay(myData->view, true); |
result = noErr; |
break; |
default: |
break; |
} |
break; |
case kEventClassControl: |
switch (GetEventKind(inEvent)) |
{ |
case kEventControlInitialize: |
{ |
CallNextEventHandler(inCaller, inEvent); |
UInt32 features = 0; |
result = GetEventParameter(inEvent, kEventParamControlFeatures, typeUInt32, NULL, sizeof(features), NULL, &features); |
if (result == noErr) |
features |= kControlSupportsEmbedding; |
else |
features = kControlSupportsEmbedding; |
result = SetEventParameter(inEvent, kEventParamControlFeatures, typeUInt32, sizeof features, &features); |
break; |
} |
#pragma mark - |
#pragma mark case kEventControlDraw |
case kEventControlDraw: |
{ |
static bool hiToolboxVersionTested = false; |
static bool canUseHITheme = false; |
if (! hiToolboxVersionTested) |
{ |
hiToolboxVersionTested = true; |
canUseHITheme = (GetHIToolboxVersion() >= 0x130); |
} |
CGContextRef context; |
result = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(context), NULL, &context); |
if (canUseHITheme && (result == noErr) && (context != NULL)) |
DrawSliderPanther(myData, context); |
else |
DrawSliderJaguar(myData); |
result = noErr; |
break; |
} |
#pragma mark case kEventControlHitTest |
case kEventControlHitTest: |
{ |
ControlPartCode part = FindPart(inEvent, myData); |
SetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, sizeof(part), &part); |
result = noErr; |
break; |
} |
#pragma mark case kEventControlTrack |
case kEventControlTrack: |
{ |
ControlPartCode part = FindPart(inEvent, myData); |
// was part clicked hilited before? If not, hilite it. |
if (part != GetControlHilite(myData->view)) |
HiliteControl(myData->view, part); |
ControlRef theControl = NULL; |
if (part == kControlHiIndicatorPart) theControl = myData->invisibleHiSlider; |
if (part == kControlLoIndicatorPart) theControl = myData->invisibleLoSlider; |
if (theControl == NULL) break; |
Rect loRect, hiRect; |
GetLoHiRects(myData, &loRect, &hiRect); |
SInt32 height = hiRect.bottom - hiRect.top; |
SInt32 min = GetControl32BitMinimum(theControl); |
SInt32 max = GetControl32BitMaximum(theControl); |
// we need the location of our invisible sliders in local coordinates of the window (actually the content view) |
HIRect hiFrame; |
HIViewGetFrame(theControl, &hiFrame); |
HIViewRef contentView; |
HIViewFindByID(HIViewGetRoot(GetControlOwner(myData->view)), kHIViewWindowContentID, &contentView); |
HIViewConvertRect(&hiFrame, myData->view, contentView); |
SInt32 fTop = (int)hiFrame.origin.y; |
SInt32 fBottom = fTop + (int)hiFrame.size.height; |
// determining (as best as can be done) the delta value which comes from the fact |
// that we clicked in any point of the indicator, but the value associated with the indicator |
// is for only one line within. |
Point pt; |
GetEventParameter(inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(pt), NULL, &pt); |
pt.v += fTop; |
SInt32 deltaValue = min + ((fBottom - pt.v - (height / 2)) * (max - min)) / (fBottom - fTop - height); |
SInt32 value = (part == kControlHiIndicatorPart)?myData->hiValue:myData->loValue; |
deltaValue -= value; |
// tracking (needs a QD Grafport. Actually it doesn't but it's simpler that way for managing local vs. global coords) |
GrafPtr savePort; |
GetPort(&savePort); |
SetPort(GetWindowPort(GetControlOwner(myData->view))); |
MouseTrackingResult mouse = kMouseTrackingMouseDown; |
for (; mouse != kMouseTrackingMouseUp; ) |
{ |
TrackMouseLocation(NULL, &pt, &mouse); |
if (mouse == kMouseTrackingMouseDragged) |
{ |
SInt32 newValue = min - deltaValue + ((fBottom - pt.v - (height / 2)) * (max - min)) / (fBottom - fTop - height); |
if (part == kControlHiIndicatorPart) SetControlHiValue(myData->view, newValue); |
if (part == kControlLoIndicatorPart) SetControlLoValue(myData->view, newValue); |
} |
} |
SetPort(savePort); |
// let's not forget to un-hilite |
HiliteControl(myData->view, 0); |
SetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, sizeof(part), &part); |
result = noErr; |
break; |
} |
#pragma mark case kEventControlHiliteChanged |
#pragma mark - |
// If anything changed, let's ask for a redraw |
case kEventControlActivate: |
case kEventControlDeactivate: |
case kEventControlHiliteChanged: |
HIViewSetNeedsDisplay(myData->view, true); |
result = noErr; |
break; |
default: |
break; |
} |
break; |
default: |
break; |
} |
return result; |
} |
void SetControlHiLoValue(ControlRef theControl, SInt32 newValue, Boolean hiOrLo) |
{ |
DoubleSliderData* myData = (DoubleSliderData*)HIObjectDynamicCast((HIObjectRef)theControl, kDoubleSliderClassID); |
if (myData == NULL) return; |
SInt32 min = GetControl32BitMinimum(myData->invisibleHiSlider); |
SInt32 max = GetControl32BitMaximum(myData->invisibleHiSlider); |
Boolean hiChanged = false, loChanged = false; |
if (hiOrLo) |
{ |
if (newValue > max) newValue = max; |
if (newValue < myData->loValue) newValue = myData->loValue; |
if (hiChanged = (newValue != myData->hiValue)) myData->hiValue = newValue; |
} |
else |
{ |
if (newValue < min) newValue = min; |
if (newValue > myData->hiValue) newValue = myData->hiValue; |
if (loChanged = (newValue != myData->loValue)) myData->loValue = newValue; |
} |
if (hiChanged || loChanged) |
{ |
EventRef theEvent; |
UInt32 kind = hiChanged?kEventControlHiValueFieldChanged:kEventControlLoValueFieldChanged; |
CreateEvent(NULL, kEventClassDoubleSlider, kind, 0, 0, &theEvent); |
SetEventParameter(theEvent, kEventParamDirectObject, typeControlRef, sizeof(ControlRef), &theControl); |
SendEventToEventTarget(theEvent, GetControlEventTarget(theControl)); |
ReleaseEvent(theEvent); |
} |
} |
// Convenience accessors |
SInt32 |
GetControlLoValue(ControlRef theControl) |
{ |
DoubleSliderData* myData = (DoubleSliderData*)HIObjectDynamicCast((HIObjectRef)theControl, kDoubleSliderClassID); |
if (myData) |
return myData->loValue; |
else |
return 0; |
} |
void |
SetControlLoValue( |
ControlRef theControl, |
SInt32 newLoValue) |
{ |
SetControlHiLoValue(theControl, newLoValue, false); |
} |
SInt32 |
GetControlHiValue(ControlRef theControl) |
{ |
DoubleSliderData* myData = (DoubleSliderData*)HIObjectDynamicCast((HIObjectRef)theControl, kDoubleSliderClassID); |
if (myData) |
return myData->hiValue; |
else |
return 0; |
} |
void |
SetControlHiValue( |
ControlRef theControl, |
SInt32 newHiValue) |
{ |
SetControlHiLoValue(theControl, newHiValue, true); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-27