|
IntroductionThis Technote describes the API used to display and interact with the Font Panel from a Carbon application on Mac OS X. While most Carbon applications allow users to select fonts using a Fonts menu (preferably built and maintained using the Standard Font Menu API), users of Cocoa applications select fonts using the standard Font Panel floating dialog. This dialog is implemented by the NSFontPanel class using Objective C and Cocoa and is not directly accessible from Carbon applications. The Font Panel for Carbon API provides access to the Font Panel for Carbon applications on Mac OS X. This Note is directed at application developers who want to allow their Mac OS X Carbon applications to use the Font Panel as a way for users to specify font family, typeface, and size settings for text. Using the Font Panel in CarbonThis section presents a brief overview of the use of the Font Panel from a Carbon application; detailed information about the API follows. The user opens the Font Panel by selecting an appropriate menu item (such as Font Panel… from a Fonts menu), clicking a button, or via some other mechanism. Your application, in response, should generate a Carbon Event Manager command event with Note: If your application does not generate Carbon Event Manager command events, it can open the Font Panel by calling When a Carbon Event target (typically a control or window) gains the focus, your application calls Whenever the selection changes in the focus, or if the style runs are changed programmatically, your application calls If your application has called As the user selects font settings from the Font Panel, your application receives font selection Carbon Events from the Font Panel. The settings selected by the user in the Font Panel are passed as event parameters in the kEventFontSelection event; your application simply extracts as many of the parameters as it can from the event and applies the font settings as it sees fit. When the user closes the Font Panel, a Carbon event notifies your application that the window has closed. Note: Even if your Carbon application still uses the old WaitNextEvent-style event loop, it must install Carbon Event handlers to support the Font Panel. In particular, it has to handle Font Panel closed and selection events described in more detail below. The Font Panel APISetFontInfoForSelectionYour application calls OSStatus SetFontInfoForSelection( OSType iStyleType, UInt32 iNumStyles, void* iStyles, HIObjectRef iFPEventTarget);
iNumStyles is the number of unique style runs being specified in the function call. If iNumStyles is 0, the Font Panel settings are cleared. iStyles is a pointer to an array of style run information. If iStyleType is iFPEventTarget is a reference to the Carbon Event Manager human interface object to which subsequent Font Panel events will be sent. This should be the window or control holding the current focus, or the application itself. The value can change from one call to another, as the user focus shifts. If this value is NULL, the Font Panel will send events to the application target as returned by GetApplicationEventTarget. The following error conditions are returned: paramErr is returned if iNumStyles is nonzero but iStyles is NULL, or if it is detected that iNumStyles is not equal to the number of style runs specified. fontSelectionStyleErr is returned if any of the supplied style run information elements does not contain the minimum information required for Font Panel selection. If Your application is responsible for releasing any memory associated with the style run information pointed to by iStyles, following return from When you call Note: Currently, the Font Panel selects no items at all if iNumStyles is greater than 1. However, your application should supply information for all style runs so that, if this behavior changes in the future, you will not have to modify your application. You can call ATSUStyleWhen
A pointer to an array of Listing 1: Calling SetFontInfoForSelection using an ATSUStyle. if (FPIsFontPanelVisible()) { OSStatus status; ATSUStyle aStyle; ATSUAttributeTag atsuiTag[] = {kATSUFontTag, kATSUSizeTag}; ByteCount atsuiSize[] = {sizeof(ATSUFontID), sizeof(Fixed)}; ATSUAttributeValuePtr atsuiValue[2]; status = ATSUCreateStyle(aStyle); // Populate the attribute value array with pointers to the attribute values, // in the correct order. atsuiValue[0] = &atsuiFontID; atsuiValue[1] = &atsuiSize; // Set the attributes in the ATSUStyle and send the info to the Font Panel. status = ATSUSetAttributes(aStyle, 2, atsuiTag, atsuiSize, atsuiValue); status = SetFontInfoForSelection(kFontSelectionATSUIType, 1, &aStyle, NULL); // Don't forget to release the ATSUStyle! status = ATSUDisposeStyle(aStyle); } FontSelectionQDStyleIf your application uses Quickdraw-style data types, you may want to specify style run information using typedef struct { UInt32 version; FMFontFamilyInstance instance; FMFontSize size; Boolean hasColor; RGBColor color; } FontSelectionQDStyle; const UInt32 kCurrentFontSelectionQDStyleZero = 0; version is the current version number of the record, which should be set by your application to the appropriate constant defined in the header file, currently kCurrentFontSelectionQDStyleZero. instance and size supply the Quickdraw font family reference, style specification, and typeface size. If hasColor is true, color defines the color of the selected text. Otherwise, color is ignored. Note: Currently, color is not supported by the Font Panel for Carbon applications. When Note: Currently, Quickdraw-specific styles such as outline and shadow are not supported by the Font Panel. Listing 2: Calling SetFontInfoForSelection using a FontSelectionQDStyle. // Notify the Font Panel that the font has changed. qdInfo.version = kFontSelectionQDStyleVersionZero; qdInfo.instance = fontFamilyInstance; qdInfo.size = fontSize; GetFontInfoFromWindow(window, NULL, &(qdInfo.size)); qdInfo.hasColor = false; status = SetFontInfoForSelection(kFontSelectionQDType, 1, &qdInfo, NULL); Handling Change of FocusWhen the user focus shifts, the component relinquishing focus should call Remember that the user focus is the part of your application's HI toward which keyboard input is directed; it can be a window, a control, or any other HI element. In this case, only those HI elements to which you wish Font Panel events to be sent need to know when the user focus shifts. (See the documentation for the Carbon Event Manager for more information on Carbon Events and user focus.) For example, if your application supports multiple windows, you can install a Carbon Event handler for each window that will catch Listing 3: Calling SetFontInfoForSelection from a user focus event handler. // Carbon Event Handler declarations. pascal OSStatus MyEventHandler (EventHandlerCallRef nextHandler, EventRef event, void * userData); EventHandlerUPP gMyEventHandlerUPP = NULL; // This array specifies the events which MyEventHandler() can handle. static const EventTypeSpec sMyEventHandlerEvents[] = { { kEventClassWindow, kEventWindowFocusAcquired }, { kEventClassWindow, kEventWindowFocusRelinquish }, }; // Install Carbon Event Handler on each window to support the Font Panel. gMyEventHandlerUPP = NewEventHandlerUPP(MyEventHandler); InstallWindowEventHandler(window1Ref, gMyEventHandlerUPP, GetEventTypeCount(sMyEventHandlerEvents), sMyEventHandlerEvents, 0, NULL); InstallWindowEventHandler(window2Ref, gMyEventHandlerUPP, GetEventTypeCount(sMyEventHandlerEvents), sMyEventHandlerEvents, 0, NULL); ... pascal OSStatus MyEventHandler (EventHandlerCallRef nextHandler, EventRef event, void * userData) { UInt32 eventClass = GetEventClass(event); HICommand command; WindowRef thisWindow = NULL; OSStatus status = eventNotHandledErr; switch ( eventClass ) { case kEventClassWindow: { switch (GetEventKind(event)) { case kEventWindowFocusRelinquish: { // Clear the Font Panel settings. status = SetFontInfoForSelection(kFontSelectionATSUIType, 0, NULL, NULL); } break; case kEventWindowFocusAcquired: { // Tell the Font Panel that the owner of this event handler // is the new target. status = GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &thisWindow); status = SetFontInfoForSelection( kFontSelectionATSUIType, 0, NULL, GetWindowEventTarget(thisWindow)); } break; } } break; } return (status); } Showing and Hiding the Font PanelIt is your application’s responsibility to provide an interface by which the user can activate and deactivate the Font Panel. Typically this will be a Show Font Panel or Show Fonts… item in a Format or Fonts menu. The keyboard equivalent for this item should be command-T. Your applications may have a button or other mechanism for activating the Font Panel; how you implement Font Panel activation will depend on the needs of your application.
The Carbon Event Manager HICommand Listing 4. Part of an 'xmnu' resource implementing the resource 'xmnu' (131, "Font menu") { versionZero { { /* array ItemExtensions: 5 elements */ ... /* [3] */ dataItem { kHICommandShowHideFontPanel, kMenuNoModifiers, currScript, 0, 0, noHierID, sysFont, naturalGlyph }, ... } } }; The standard Carbon application event handler will detect the event and respond to it, calling This command has no parameters. FPShowHideFontPanelCalling OSStatus Your application can call this function directly, as shown in Listing 5, if it does not support the The following error conditions are returned: fontPanelShowErr is returned if, for unknown reasons, the Font Panel cannot be made visible. Specific error conditions will be returned if the reason can be determined (e.g., memFullErr). Listing 4: Calling FPShowHideFontPanel directly. switch ( eventClass ) { ... case kEventClassCommand: { // Extract the HICommand from the event and handle it. GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command); switch ( command.commandID ) { ... case kHICommandShowHideFontPanel: { // Toggle the Font Panel state. status = FPShowHideFontPanel(); } break; ... } } ... } Closing the Font PanelAfter the user closes the Font Panel, either by clicking on its close button or using an application-supplied human interface element (such as a Hide Font Panel menu item), the Font Panel sends a Carbon event to the event target your application specified in its most recent call to The event has no parameters. The event is of class Note: Even if your application is WaitNextEvent-based, you need to install a Carbon event handler to detect when the Font Panel has closed.
Boolean
Font Panel Selection EventWhen the user selects an item in the Font Panel, the Font Panel sends a Carbon event to the event target your application specified in its most recent call to Note: Even if your application is WaitNextEvent-based, you must install a Carbon event handler to get the settings from the Font Panel. The event is of class The event contains parameters reflecting the current Font Panel settings in all supported formats. Your application can obtain the parameters using the GetEventParameter function: kEventParamATSUFontID, typeATSUFontID: If present, specifies the font ID of the selected font. kEventParamATSUFontSize, typeATSUSize: If present, specifies the size of the font as a Fixed value. kEventParamFMFontFamily, typeFMFontFamily: If present, specifies the font family reference of the font. kEventParamFMFontStyle, typeFMFontStyle: If present, specifies the Quickdraw style of the font. kEventParamFMFontSize, typeFMFontSize: If present, specifies the size of the font as an integer. The Font Panel will send this Carbon event to your application every time the user selects an item in the Font Panel. Note that a selection may not define a complete style specification: the user may select a font family, which need not include a typeface; or he may select a size, which may not specify family or face. Therefore, not all the parameters listed above need be present in the Carbon event. Your application must check for all parameters which it recognizes and be able to apply partial font specifications to the currently selected text or to its current font settings as appropriate. SummaryModifying your Carbon application to use the Font Panel API is not difficult, and enhances the Mac OS X experience by giving your users an interface for font selection that is consistent with Cocoa applications and is easier and often more convenient than a Fonts menu. ReferencesApple Type Services for Unicode ImagingCarbon Event ManagerProgramming Topic: Font Panel Posted: 2006-10-26 Document Revision History
Posted: 2006-10-26 |
|