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.
main.c
/* |
File: main.c |
Abstract: A skeleton of modern nib-based and Carbon Events-based Carbon application. |
ComboBoxPrefs maintains a list of recently accessed pictures within its combo box. |
It is a chronological list (CFArray) stored via CFPreferences. We also override |
the standard behavior of the combo box to make it more like an address bar seen in |
web browsers. When an item from the ComboBox list is double-clicked that item is |
loaded. ComboBoxPrefs also demonstrates how to create a CGImageRef from a URL pointing |
to a picture. We use QuickTime Graphics Importers, QTNewDataReferenceFromCFURL, |
for automatic support of a wide variety of image types. |
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 © 2005 Apple Computer, Inc., All Rights Reserved |
*/ |
#include <Carbon/Carbon.h> |
#include <Quicktime/Quicktime.h> |
#include <sys/param.h> |
struct GlobalAppInfo // Application globals |
{ |
IBNibRef mainNibRef; |
SInt32 maxHistory; |
}; |
typedef struct GlobalAppInfo GlobalAppInfo; |
void SendCommandProcessEvent( UInt32 commandID ); |
void SendWindowCloseEvent( WindowRef window ); |
static OSStatus GetControlBySigAndID( WindowRef window, OSType signature, SInt32 id, ControlRef *control ); |
static void InstallAppleEventHandlers( void ); |
static void DisplayPreferencesWindow( void ); |
static pascal OSStatus CommandProcessEventHandler( EventHandlerCallRef nextHandler, EventRef inEvent, void *userData ); // Added kHICommandRevert, kHICommandPageSetup, and kHICommandPrint |
static pascal OSStatus MainWindowEventHandler( EventHandlerCallRef nextHandler, EventRef inEvent, void *userData ); |
static OSStatus DoNewWindow( WindowRef *window ); // Install Event Handler for Text view |
static pascal OSStatus PreferencesWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ); |
SInt16 GetControlValueByID( WindowRef window, OSType signature, SInt32 id ); |
void SetControlValueByID( WindowRef window, OSType signature, SInt32 id, SInt32 value ); |
static OSStatus DisplayImageInWindow( WindowRef window, CFURLRef cfURL ); |
static pascal void LiveAlphaSliderActionProc( ControlRef control, ControlPartCode partCode ); |
static OSStatus HIViewFindBySigAndID( HIViewRef inStartView, OSType signature, SInt32 id, HIViewRef *outControl ); |
static pascal OSStatus ComboBoxEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData ); |
void SaveComboBoxValues( HIViewRef comboBoxView ); |
void RestoreComboBoxValues( HIViewRef comboBoxView ); |
GlobalAppInfo g; |
#pragma mark - |
#pragma mark ¥ Main ¥ |
int main( int argc, char *argv[] ) |
{ |
OSStatus status; |
long response; |
CFNumberRef cfNumber = NULL; |
const EventTypeSpec commandProcessEvents[] = { { kEventClassCommand, kEventCommandProcess } }; |
BlockZero( &g, sizeof(g) ); |
status = Gestalt( gestaltSystemVersion, &response ); |
if ( ! ((status == noErr) && (response >= 0x00001030)) ) // We require Mac OS X 10.3 or greater to run |
{ |
DialogRef alertDialod; |
CreateStandardAlert( kAlertStopAlert, CFSTR("Mac OS X 10.3 (minimum) is required for this application"), NULL, NULL, &alertDialod ); |
RunStandardAlert( alertDialod, NULL, NULL ); |
ExitToShell(); |
} |
EnterMovies(); // Needed for use with QuickTimes Graphics Importers |
// Create a Nib reference passing the name of the nib file (without the .nib extension) CreateNibReference only searches into the application bundle. |
status = CreateNibReference( CFSTR("main"), &g.mainNibRef ); |
require_noerr( status, CantGetNibRef ); |
// Read in our preferences, maximum urls to display in our combo box |
cfNumber = (CFNumberRef) CFPreferencesCopyAppValue( CFSTR("MaxHistory"), kCFPreferencesCurrentApplication ); |
if ( cfNumber != NULL ) |
{ |
(void) CFNumberGetValue( cfNumber, kCFNumberSInt32Type, &g.maxHistory ); |
CFRelease( cfNumber ); |
} |
else |
{ |
g.maxHistory = 10; |
} |
// Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar object. This name is set in InterfaceBuilder when the nib is created. |
status = SetMenuBarFromNib( g.mainNibRef, CFSTR("MenuBar") ); |
require_noerr( status, CantSetMenuBar ); |
EnableMenuCommand( NULL, kHICommandPreferences ); // Enable Preferences menu item |
InstallAppleEventHandlers(); |
InstallApplicationEventHandler( NewEventHandlerUPP(CommandProcessEventHandler), GetEventTypeCount(commandProcessEvents), commandProcessEvents, NULL, NULL ); |
RunApplicationEventLoop(); // Call the event loop |
CantSetMenuBar: |
CantGetNibRef: |
return( status ); |
} |
#pragma mark - |
#pragma mark ¥ AppleEvent Handlers ¥ |
static pascal OSErr HandleAppleEventOapp( const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) |
{ |
SendCommandProcessEvent( kHICommandNew ); // Instantiate an empty window at the beginning so the User sees something |
return( noErr ); |
} |
static pascal OSErr HandleAppleEventRapp( const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) |
{ |
WindowRef window = GetFrontWindowOfClass( kDocumentWindowClass, true ); |
if ( window == NULL ) |
SendCommandProcessEvent( kHICommandNew ); // We were already running but with no windows so we create an empty one. |
return( noErr ); |
} |
static pascal OSErr HandleAppleEventOdoc( const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) |
{ |
return( errAEEventNotHandled ); |
} |
static pascal OSErr HandleAppleEventPdoc( const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon ) |
{ |
return( errAEEventNotHandled ); |
} |
static void InstallAppleEventHandlers( void ) |
{ |
OSErr status; |
status = AEInstallEventHandler( kCoreEventClass, kAEOpenApplication, NewAEEventHandlerUPP(HandleAppleEventOapp), 0, false ); require_noerr( status, CantInstallAppleEventHandler ); |
status = AEInstallEventHandler( kCoreEventClass, kAEReopenApplication, NewAEEventHandlerUPP(HandleAppleEventRapp), 0, false ); require_noerr( status, CantInstallAppleEventHandler ); |
status = AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerUPP(HandleAppleEventOdoc), 0, false ); require_noerr( status, CantInstallAppleEventHandler ); |
status = AEInstallEventHandler( kCoreEventClass, kAEPrintDocuments, NewAEEventHandlerUPP(HandleAppleEventPdoc), 0, false ); require_noerr( status, CantInstallAppleEventHandler ); |
// Note: Since RunApplicationEventLoop installs a Quit AE Handler, there is no need to do it here. |
CantInstallAppleEventHandler: |
return; |
} |
#pragma mark - |
#pragma mark ¥ CarbonEvent Handlers ¥ |
static pascal OSStatus CommandProcessEventHandler( EventHandlerCallRef nextHandler, EventRef inEvent, void *userData ) |
{ |
HICommand command; |
OSStatus status = eventNotHandledErr; |
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); |
switch ( command.commandID ) |
{ |
case kHICommandNew: |
status = DoNewWindow( NULL ); |
break; |
case kHICommandPreferences: |
DisplayPreferencesWindow(); |
break; |
} |
return( status ); |
} |
static pascal OSStatus MainWindowEventHandler( EventHandlerCallRef nextHandler, EventRef inEvent, void *inUserData ) |
{ |
#pragma unused ( inCallRef ) |
HICommand command; |
OSStatus status = eventNotHandledErr; |
UInt32 eventKind = GetEventKind( inEvent ); |
UInt32 eventClass = GetEventClass( inEvent ); |
WindowRef window = (WindowRef) inUserData; |
switch ( eventClass ) |
{ |
case kEventClassWindow: |
//if ( eventKind == kEventWindowClose ) // Dispose extra window storage here |
break; |
case kEventClassCommand: |
if ( eventKind == kEventCommandProcess ) |
{ |
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); |
if ( command.commandID == kHICommandOK ) // OK (Execute) Button was clicked in window |
{ |
HIViewRef comboBoxView; |
CFURLRef urlRef = NULL; |
CFStringRef urlString = NULL; |
status = HIViewFindBySigAndID( HIViewGetRoot(window), 'Cmbo', 0, &comboBoxView ); |
status = GetControlData( comboBoxView, kControlEditTextPart, kControlEditTextCFStringTag, sizeof( CFStringRef ), &urlString, NULL ); // Get the current text as a CFURL from the Combo Box |
urlRef = CFURLCreateWithString( kCFAllocatorDefault, urlString, NULL ); // Create a CFURL from the CFString |
SaveComboBoxValues( comboBoxView ); |
status = DisplayImageInWindow( window, urlRef ); |
if ( urlString != NULL ) CFRelease( urlString ); |
if ( urlRef != NULL ) CFRelease( urlRef ); |
} |
} |
break; |
} |
return( status ); |
} |
#pragma mark - |
#pragma mark ¥ Windows ¥ |
static void DisplayPreferencesWindow( void ) |
{ // Entry point for a preferences window |
WindowRef window; |
OSErr err; |
static EventHandlerUPP preferencesWindowEventHandlerUPP; |
const EventTypeSpec windowEvents[] = { { kEventClassCommand, kEventCommandProcess }, { kEventClassWindow, kEventWindowClose } }; |
err = CreateWindowFromNib( g.mainNibRef, CFSTR("PreferencesWindow"), &window ); |
if ( err != noErr ) goto Bail; |
SetControlValueByID( window, 'PopM', 0, (g.maxHistory / 5) + 1 ); // We use a 5X algorithm. 0, 5, 10, 15, ... |
if ( preferencesWindowEventHandlerUPP == NULL ) preferencesWindowEventHandlerUPP = NewEventHandlerUPP( PreferencesWindowEventHandlerProc ); |
err = InstallWindowEventHandler( window, preferencesWindowEventHandlerUPP, GetEventTypeCount(windowEvents), windowEvents, window, NULL ); |
if ( err == noErr ) |
{ |
ShowWindow( window ); |
(void) RunAppModalLoopForWindow( window ); // Run the preferences window as application modal |
} |
Bail: |
return; |
} |
static pascal OSStatus PreferencesWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ) |
{ |
#pragma unused ( inCallRef ) |
HICommand command; |
CFNumberRef cfNumber = NULL; |
WindowRef window = (WindowRef) inUserData; |
UInt32 eventClass = GetEventClass( inEvent ); |
UInt32 eventKind = GetEventKind( inEvent ); |
switch ( eventClass ) |
{ |
case kEventClassWindow: |
if ( eventKind == kEventWindowClose ) |
{ |
(void) QuitAppModalLoopForWindow( window ); |
} |
break; |
case kEventClassCommand: |
if ( eventKind == kEventCommandProcess ) |
{ |
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); |
if ( command.commandID == kHICommandOK ) |
{ |
g.maxHistory = ( (GetControlValueByID( window, 'PopM', 0 ) - 1) * 5 ); // We use a 5X algorithm. 0, 5, 10, 15, ... |
cfNumber = CFNumberCreate( NULL, kCFNumberSInt32Type, &g.maxHistory ); |
CFPreferencesSetAppValue( CFSTR("MaxHistory"), cfNumber, kCFPreferencesCurrentApplication ); |
if ( cfNumber != NULL ) CFRelease( cfNumber ); |
(void) CFPreferencesAppSynchronize( kCFPreferencesCurrentApplication ); // Write prefs to disk! |
} |
if ( (command.commandID == kHICommandOK) || (command.commandID == kHICommandCancel) ) |
{ |
SendWindowCloseEvent( window ); // Send ourselves a kEventWindowClose event |
} |
} |
break; |
} |
return( eventNotHandledErr ); |
} |
static OSStatus DoNewWindow( WindowRef *outWindow ) |
{ |
OSStatus status; |
HIViewRef comboBoxView; |
static EventHandlerUPP windowEventHandlerUPP; |
static EventHandlerUPP comboBoxEventHandlerUPP; |
WindowRef window = NULL; |
const EventTypeSpec windowEvents[] = { { kEventClassCommand, kEventCommandProcess }, { kEventClassWindow, kEventWindowClose } }; |
const EventTypeSpec comboBoxEvents[] = { { kEventClassControl, kEventControlHiliteChanged } }; |
// Create a window. "MainWindow" is the name of the window object. This name is set in InterfaceBuilder when the nib is created. |
status = CreateWindowFromNib( g.mainNibRef, CFSTR("MainWindow"), &window ); |
require_noerr( status, CantCreateWindow ); |
if ( windowEventHandlerUPP == NULL ) windowEventHandlerUPP = NewEventHandlerUPP( MainWindowEventHandler ); |
status = InstallWindowEventHandler( window, windowEventHandlerUPP, GetEventTypeCount(windowEvents), windowEvents, window, NULL ); |
require_noerr( status, CantInstallWindowEventHandler ); |
status = HIViewFindBySigAndID( HIViewGetRoot(window), 'Cmbo', 0, &comboBoxView ); |
if ( comboBoxEventHandlerUPP == NULL ) comboBoxEventHandlerUPP = NewEventHandlerUPP( ComboBoxEventHandler ); |
status = InstallControlEventHandler( comboBoxView, comboBoxEventHandlerUPP, GetEventTypeCount(comboBoxEvents), comboBoxEvents, comboBoxView, NULL ); |
require_noerr( status, CantInstallWindowEventHandler ); |
RestoreComboBoxValues( comboBoxView ); // Load the saved locations into our ComboBox control list |
// The window was created hidden so show it if the window parameter is NULL, if it's not, it will be the responsibility of the caller to show it. |
if ( outWindow == NULL ) ShowWindow( window ); |
SetWindowModified( window, false ); |
CantInstallWindowEventHandler: |
CantCreateWindow: |
if ( outWindow != NULL ) *outWindow = window; |
return( status ); |
} |
// We modify the behavior of the combo box by making it more interactive, similar to the way the Safari address bar behaves. |
// When an item is double clicked from the combo box list it is automatically loaded. |
static pascal OSStatus ComboBoxEventHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void *inUserData ) |
{ |
ControlPartCode previousPartCode; |
HIViewRef comboBoxView = (HIViewRef) inUserData; |
UInt32 eventClass = GetEventClass( inEvent ); |
UInt32 eventKind = GetEventKind( inEvent ); |
OSStatus status = eventNotHandledErr; |
switch ( eventClass ) |
{ |
case kEventClassControl: |
if ( eventKind == kEventControlHiliteChanged ) |
{ |
CFURLRef urlRef = NULL; |
CFStringRef currentCFString = NULL; |
CFStringRef urlCFString = NULL; |
(void) GetControlProperty( comboBoxView, 'Crnt', 'URL_', sizeof(CFStringRef), NULL, ¤tCFString ); // We store the most recent url as a control property |
(void) GetControlData( comboBoxView, kControlEditTextPart, kControlEditTextCFStringTag, sizeof( CFStringRef ), &urlCFString, NULL ); |
if ( (currentCFString == NULL) || (CFStringCompare( currentCFString, urlCFString, 0 ) != kCFCompareEqualTo) ) // Has the url changed? |
{ |
(void) GetEventParameter( inEvent, kEventParamControlPreviousPart, typeControlPartCode, NULL, sizeof(ControlPartCode), NULL, &previousPartCode ); |
if ( previousPartCode == kHIComboBoxDisclosurePart ) // Tells us an item has been selected from the list |
{ |
CFRetain( urlCFString ); |
SetControlProperty( comboBoxView, 'Crnt', 'URL_', sizeof(CFStringRef), &urlCFString ); // Save the url as a control property for checking later |
SaveComboBoxValues( comboBoxView ); |
urlRef = CFURLCreateWithString( kCFAllocatorDefault, urlCFString, NULL ); |
(void) DisplayImageInWindow( GetControlOwner(comboBoxView), urlRef ); // Display the image pointed to by the url in the window |
if ( urlRef != NULL ) CFRelease( urlRef ); |
if ( urlCFString != NULL ) CFRelease( urlCFString ); |
} |
} |
} |
break; |
} |
return( status ); |
} |
#pragma mark - |
#pragma mark ¥ Save/Open Document ¥ |
#pragma mark - |
#pragma mark ¥ Utilities ¥ |
// Utility routine to synchronously send a basic "kEventClassCommand / kEventCommandProcess" CarbonEvent to the application target |
void SendCommandProcessEvent( UInt32 commandID ) |
{ |
HICommand command; |
EventRef event; |
BlockZero( &command, sizeof(command) ); |
command.commandID = commandID; |
(void) CreateEvent( NULL, kEventClassCommand, kEventCommandProcess, GetCurrentEventTime(), kEventAttributeUserEvent, &event ); |
(void) SetEventParameter( event, kEventParamDirectObject, typeHICommand, sizeof(command), &command ); |
(void) SendEventToApplication( event ); |
(void) ReleaseEvent( event ); |
} |
// Utility routine to synchronously send a basic "kEventClassWindow / kEventWindowClose" CarbonEvent to the window target |
void SendWindowCloseEvent( WindowRef window ) |
{ |
EventRef event; |
(void) CreateEvent( NULL, kEventClassWindow, kEventWindowClose, GetCurrentEventTime(), kEventAttributeUserEvent, &event ); |
(void) SetEventParameter( event, kEventParamDirectObject, typeWindowRef, sizeof(window), &window ); |
(void) SendEventToWindow( event, window ); |
(void) ReleaseEvent( event ); |
} |
static OSStatus HIViewFindBySigAndID( HIViewRef inStartView, OSType signature, SInt32 id, HIViewRef *outControl ) |
{ |
HIViewID hiViewID = { signature, id }; |
return( HIViewFindByID( inStartView, hiViewID, outControl ) ); |
} |
static OSStatus GetControlBySigAndID( WindowRef window, OSType signature, SInt32 id, ControlRef *control ) |
{ |
ControlID controlID = { signature, id }; |
return( GetControlByID( window, &controlID, control ) ); |
} |
void SetControlValueByID( WindowRef window, OSType signature, SInt32 id, SInt32 value ) |
{ |
ControlRef control; |
GetControlBySigAndID( window, signature, id, &control ); |
if ( control == NULL ) goto Bail; |
SetControlValue( control, value ); |
Draw1Control( control ); |
Bail: |
return; |
} |
SInt16 GetControlValueByID( WindowRef window, OSType signature, SInt32 id ) |
{ |
ControlRef control; |
GetControlBySigAndID( window, signature, id, &control ); |
if ( control == NULL ) return( 0 ); |
return( GetControlValue(control) ); |
} |
#pragma mark - |
#pragma mark ¥ Specialized Routines ¥ |
// Given a URL to an image, display it in our HIImageView which is embeded in an HIScrollView. |
static OSStatus DisplayImageInWindow( WindowRef window, CFURLRef cfURL ) |
{ |
OSStatus status; |
HIViewRef hiImageView; |
ControlRef control; |
OSType dataRefType; |
static ControlActionUPP sliderControlActionUPP; |
GraphicsImportComponent ci = NULL; |
CGImageRef cgImageRef = NULL; |
Handle dataRef = NULL; |
require( (cfURL != NULL) && (window != NULL), Bail ); |
// Install a slider action proc to modify the image alpha live |
status = GetControlBySigAndID( window, 'Sldr', 1, &control ); require_noerr( status, Bail ); |
if ( sliderControlActionUPP == NULL ) sliderControlActionUPP = NewControlActionUPP( LiveAlphaSliderActionProc ); |
SetControlAction( control, sliderControlActionUPP ); |
// We use the powerful combination of QTNewDataReferenceFromCFURL, GetGraphicsImporterForDataRef, and GraphicsImportCreateCGImage to create a CGImage |
// From a url which points to any media type supported by QuickTime Graphics Importers. |
status = QTNewDataReferenceFromCFURL( cfURL, 0, &dataRef, &dataRefType ); // Create the DataRef from a URL |
status = GetGraphicsImporterForDataRef( dataRef, dataRefType, &ci ); require( ci != NULL, Bail ); // Get the QT GraphicsImporter for the data ref |
status = GraphicsImportCreateCGImage( ci, &cgImageRef, kGraphicsImportCreateCGImageUsingCurrentSettings ); // Use the GraphicsImporter to create a CGImage |
// Set up the image default characteristics |
status = HIViewFindBySigAndID( HIViewGetRoot(window), 'HIiv', 1, &hiImageView ); require_noerr( status, Bail ); // Get the HIImageView |
status = HIImageViewSetImage( hiImageView, cgImageRef ); require_noerr( status, Bail ); // Set the image of the HIImageView |
status = HIImageViewSetOpaque( hiImageView, false ); require_noerr( status, Bail ); // Image can have transparency |
status = HIImageViewSetAlpha( hiImageView, GetControl32BitValue(control) / 100.0 ); require_noerr( status, Bail ); // Set the image alpha |
status = HIImageViewSetScaleToFit( hiImageView, false ); require_noerr( status, Bail ); // Don't scale the image, it's embeded in an HIScrollView so scaling doesn't make much sense |
status = HIViewSetVisible( hiImageView, true ); require_noerr( status, Bail ); // Make it visible |
Bail: |
if ( ci != NULL ) CloseComponent( ci ); else status = -1; |
if ( dataRef != NULL ) DisposeHandle( dataRef ); else status = -1; |
if ( cgImageRef != NULL ) CFRelease( cgImageRef ); else status = -1; |
return( status ); |
} |
// ControlActionProc for slider to adjust image alpha live. ControlActionProc's are needed for live slider feedback. |
static pascal void LiveAlphaSliderActionProc( ControlRef control, ControlPartCode partCode ) |
{ |
OSStatus status; |
HIViewRef hiImageView; |
float alpha = GetControl32BitValue(control) / 100.0; |
status = HIViewFindBySigAndID( HIViewGetRoot(GetControlOwner(control)), 'HIiv', 1, &hiImageView ); require_noerr( status, Bail ); |
status = HIImageViewSetAlpha( hiImageView, alpha ); require_noerr( status, Bail ); |
Bail: |
return; |
} |
// Given a combo box control, keep it sorted chronologically, and store its current list values in "HistoryEntries" appliocation preference |
// 1) Moves the current combo box entry to the top of its CFArray list |
// 2) Truncates array to contain no more than g.maxHistory entries |
// 3) Saves a CFArray of the list in its "HistoryEntries" preference |
// 4) Updates the combo box entries for display |
void SaveComboBoxValues( HIViewRef comboBoxView ) |
{ |
OSStatus status; |
CFArrayRef cfArray; |
CFIndex count; |
CFStringRef cfString; |
CFMutableArrayRef cfMutableArray = NULL; |
CFStringRef urlString = NULL; |
status = GetControlData( comboBoxView, kHIComboBoxDisclosurePart, kHIComboBoxListTag, sizeof(cfArray), (Ptr)&cfArray, NULL ); // Get the combo box list entries |
cfMutableArray = CFArrayCreateMutableCopy( NULL, g.maxHistory, cfArray ); // Make a mutable copy for modification |
status = GetControlData( comboBoxView, kControlEditTextPart, kControlEditTextCFStringTag, sizeof( CFStringRef ), &urlString, NULL ); // Get the current entry in the text portion |
for ( count = CFArrayGetCount( cfMutableArray ) - 1 ; count >= 0 ; count-- ) // If the current url is in the list, delete it, to add it to the top of the list |
{ |
cfString = (CFStringRef) CFArrayGetValueAtIndex( cfMutableArray, count ); |
if ( CFStringCompare( cfString, urlString, kCFCompareCaseInsensitive ) == kCFCompareEqualTo ) // Compare each list entry to the current text entry |
CFArrayRemoveValueAtIndex( cfMutableArray, count ); // Remove any duplicates |
} |
for ( count = CFArrayGetCount( cfMutableArray ) - 1 ; count >= g.maxHistory - 1 ; count-- ) // Remove extra array values beyond g.maxHistory |
CFArrayRemoveValueAtIndex( cfMutableArray, count ); |
CFArrayInsertValueAtIndex( cfMutableArray, 0, (const void *) urlString ); // Insert our new entry at the top of the list |
CFPreferencesSetAppValue( CFSTR("HistoryEntries"), cfMutableArray, kCFPreferencesCurrentApplication ); |
(void) CFPreferencesAppSynchronize( kCFPreferencesCurrentApplication ); // Save the modified list to our application "HistoryEntries" preferences |
RestoreComboBoxValues( comboBoxView ); // Since the list now contains the text entry and modifications, refresh the combo box list |
if ( cfMutableArray != NULL ) CFRelease( cfMutableArray ); |
} |
// Read in the combo box preferences and populate the combo box with those "HistoryEntries" preferences. |
void RestoreComboBoxValues( HIViewRef comboBoxView ) |
{ |
CFArrayRef cfArray = NULL; |
cfArray = (CFArrayRef) CFPreferencesCopyAppValue( CFSTR("HistoryEntries"), kCFPreferencesCurrentApplication ); |
if ( cfArray != NULL ) |
{ |
(void) SetControlData( comboBoxView, kHIComboBoxDisclosurePart, kHIComboBoxListTag, sizeof(cfArray), &cfArray ); |
CFRelease( cfArray ); |
} |
} |
Copyright © 2005 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2005-10-04