/*! @header AAutoToolbar.h @abstract Header for AAutoToolbar and AAutoToolbarDelegate . @discussion AAutoToolbar and AAutoToolbarDelegate together make it easy to add toolbars to an application. Little programming is required if you're only using simple icon items. The items that the toolbar can have are specified in an XML file, containing the following elements: Sample XML data:
                                <?xml version="1.0" ?>
                                <!DOCTYPE toolbar SYSTEM "atoolbar.dtd">
                                <toolbar>
                                  <item>
                                    <id>com.uncommonplace.accela.sample</id>
                                    <text>Sample</text>
                                    <command>Samp</command>
                                    <iconcreator>ACEL</iconcreator>
                                    <icontype>Samp</icontype>
                                    <attributes>
                                      <allowduplicates />
                                    </attributes>
                                  </item>
                                  <default>
                                    <id>com.uncommonplace.accela.sample</id>
                                    <id>com.apple.hitoolbox.toolbar.flexiblespace</id>
                                    <id>com.apple.hitoolbox.toolbar.customize</id>
                                  </default>
                                  <allowed>
                                    <id>com.uncommonplace.accela.sample</id>
                                    <id>com.apple.hitoolbox.toolbar.separator</id>
                                    <id>com.apple.hitoolbox.toolbar.space</id>
                                    <id>com.apple.hitoolbox.toolbar.flexiblespace</id>
                                    <id>com.apple.hitoolbox.toolbar.customize</id>
                                    <id>com.apple.hitoolbox.toolbar.print</id>
                                  </allowed>
                                </toolbar>
                                
*/ // See the bottom of this file for the plain text version of the XML sample. #pragma once #include "ACFBundle.h" #include "ACFString.h" #include "ACFXMLParser.h" #include "AToolbar.h" class AAutoToolbarDelegate; class ACFURL; // --------------------------------------------------------------------------- /*! @class AAutoToolbar @abstract A toolbar that reads its configuration from an XML file. @discussion The delegate class actually does all the work. If you need to use custom items (like a popup button), you can subclass AAutoToolbarDelegate and specify your subclass as a template parameter for AAutoToolbar. @templatefield Source A class containing the toolbar ID and the file name. @templatefield DelegateClass A subclass of AToolbar::Delegate. Defaults to AAutoToolbarDelegate. Use a subclass of that if you need custom items. */ template class AAutoToolbar : public AToolbar { public: /*! @function AAutoToolbar @abstract Create a toolbar for the given window. @discussion Unlike the AToolbar constructor, the toolbar ID is not specified here; it's in the XML file. Also, this constructor immediately associates the new toolbar with a window. The toolbar ID will also become the class ID of the delegate class. @param inWindow The window. @param inAttributes Valid options so far are kHIToolbarAutoSavesConfig and kHIToolbarIsConfigurable. */ AAutoToolbar( WindowRef inWindow, OptionBits inAttributes) : AToolbar(Source::identifier,inAttributes) { // note that the toolbar id is also the delegate class id if (sDelegateClass == NULL) sDelegateClass = new AHIObjectClassT(Source::identifier); if (sDelegate == NULL) sDelegate = sDelegateClass->MakeObject( (void*)ACFMainBundle().CopyResourceURL(Source::filename,CFSTR("xml"))); SetDelegate(*sDelegate); ::SetWindowToolbar(inWindow,*this); } /*! Destructor function */ virtual ~AAutoToolbar() { std::vector::iterator iter; for (iter = mEnablers.begin(); iter != mEnablers.end(); iter++) delete *iter; } protected: /*! @var mEnablers List of item enablers so they can be properly deleted. */ std::vector mEnablers; /*! @var sDelegateClass The HIObject class for the delegate. */ static AHIObjectClassT *sDelegateClass; /*! @var sDelegate The global delegate object. */ static DelegateClass *sDelegate; }; // --------------------------------------------------------------------------- /*! @defined DeclareAutoToolbar_ @abstract Creates the declaration of a class for use as the template parameter for AAutoToolbar. @discussion The class created by this macro holds the toolbar identifier and the name of the XML settings file. */ #define DeclareAutoToolbar_(_name_) \ class _name_ \ { \ public: \ static const CFStringRef identifier,filename; \ }; /*! @defined DefineAutoToolbar_ @abstract Creates the definitions for the static data members of the class created by DeclareAutoToolbar_ and the instantiation of AAutoToolbar. @discussion The _name_ parameter should be the same one used with DeclareAutoToolbar_. The _id_ parameter is the ID string for your toolbar, and _file_ is the name of the XML settings file. */ #define DefineAutoToolbar_(_name_,_id_,_file_) \ const CFStringRef _name_::identifier = CFSTR(_id_),_name_::filename = CFSTR(_file_); \ AHIObjectClassT *AAutoToolbar<_name_>::sDelegateClass = NULL; \ AAutoToolbarDelegate *AAutoToolbar<_name_>::sDelegate = NULL; /*! @defined DefineCustomAutoToolbar_ @abstract As with DefineAutoToolbar_, but with a custom delegate class for when you need to implement custom items. @discussion The _delegate_ parameter is your subclass of AAutoToolbarDelegate. */ #define DefineCustomAutoToolbar_(_name_,_delegate_,_id_,_file_) \ const CFStringRef _name_::identifier = CFSTR(_id_),_name_::filename = CFSTR(_file_); \ AHIObjectClassT *AAutoToolbar<_name_>::sDelegateClass = NULL; \ _delegate_ *AAutoToolbar<_name_,_delegate_>::sDelegate = NULL; // --------------------------------------------------------------------------- /*! @class AAutoToolbarDelegate @abstract Toolbar delegate whose behavior depends on the contents of an XML settings file. @discussion If you need to implement custom toolbar items, then you should subclass AAutoToolbarDelegate and override CreateItemWithIdentifier. */ class AAutoToolbarDelegate : public AToolbar::Delegate, public AHICustomObject { public: /*! @class AAutoToolbarDelegate::ItemSettings @abstract Holds the settings for a toolbar item. */ class ItemSettings { public: /*! @function ItemSettings @abstract Initialize from a portion of the XML data. @param inTree The XML data subtree defining this item. */ ItemSettings( const ACFXMLTree &inTree); /*! @function ID @abstract Get the item ID @result A reference to the item ID. */ const ACFString& ID() const { return mID; } /*! @function Text @abstract Get the item's title text. @result A reference to the title text. */ const ACFString& Text() const { return mText; } /*! @function Command ID @abstract Get the item's command ID. @result The command ID. */ UInt32 CommandID() const { return mCommandID; } /*! @function IconCreator @abstract Get the item's icon creator. @result The icon creator. A value of 0 means no value was specified. */ UInt32 IconCreator() const { return mIconCreator; } /*! @function IconType @abstract Get the item's icon type. @result The icon type. A value of 0 means no value was specified. */ UInt32 IconType() const { return mIconCreator; } /*! @function Icon @abstract Get the item's icon @result The item's icon. */ IconRef Icon() const; /*! @function Options @abstract Get the item's option flags. @result The item's option flags. */ OptionBits Options() const { return mOptions; } bool CanUseEnabler() const { return mUseEnabler && (mCommandID != 0); } protected: /*! @var mID The item ID. */ ACFString mID; /*! @var mText The item's title text. */ ACFString mText; /*! @var mCommandID The command ID generated when the item is clicked. */ UInt32 mCommandID; /*! @var mIconCreator The creator code for the icon. */ UInt32 mIconCreator; /*! @var mIconCreator The type code for the icon. */ UInt32 mIconType; /*! @var mOptions The option bits. */ OptionBits mOptions; bool mUseEnabler; /*! @function GetFourByteValue @abstract A utility function for turning a four-character string into a four-byte value. @param inString A four-character string. @param outValue The resulting four-byte value. */ static void GetFourByteValue( const ACFString &inString, UInt32 &outValue); }; protected: friend class AHIObjectClassT; typedef std::vector ItemVector; typedef std::vector StringVector; /*! @var mItems The list of item definitions. */ ItemVector mItems; /*! @var mDefaults The list of item IDs in the default configuration. */ StringVector mDefaults; /*! @var mAllowed The list of all item IDs to be shown in the "configure" sheet. */ StringVector mAllowed; AAutoToolbarDelegate( HIObjectRef inObject) : Delegate(::HIObjectGetEventTarget(inObject)), AHICustomObject(inObject) {} /*! @functiongroup Delegate events */ /*! @function GetDefaultIdentifiers @abstract Handle the kEventToolbarGetDefaultIdentifiers event. @discussion This function determines the default item configuration of the toolbar. It is handled automatically by remembering what was in the default tag in the XML file. @result Whether the event was handled. @param ioArray An array to be filled with the default item IDs. */ virtual bool GetDefaultIdentifiers( ACFMutableArray &ioArray); /*! @function GetDefaultIdentifiers @abstract Handle the kEventToolbarGetAllowedIdentifiers event. @discussion This function determines which items will show up in the Configure sheet. It is handled automatically by remembering what was in the allowed tag in the XML file. @result Whether the event was handled. @param ioArray An array to be filled with the default item IDs. */ virtual bool GetAllowedIdentifiers( ACFMutableArray &ioArray); /*! @function CreateItemWithIdentifier @abstract Creat a new toolbar item of a specified type. @param inIdentifier The item ID. @param inConfigData Configuration data that a custom item may need. @param outItem On return, the HIToolbarItemRef of the created item. @result Whether the event was handled. */ virtual bool CreateItemWithIdentifier( const ACFString &inIdentifier, const AEventParameter &inConfigData, AEventParameter &outItem); /*! @functiongroup AHICustomObject overrides */ /*! @function Initialize @abstract Handle the kHIObjectInitialize event. @discussion This is the function that reads the XML file and stores the information for future use. The name of the file is a parameter of the event. @result An OSStatus code. @param inEvent The initialization event. */ OSStatus Initialize( const ACarbonEvent &inEvent); /*! @functiongroup AAutoDelegate utility functions */ /*! @function AddIDs @abstract Add all item IDs in the given XML tree to a vector. @discussion This function is used to process both the default and allowed tags, since they are both lists of item IDs and differ only in their eventual purpose. @param inTree An XML tree containing a list of id elements. @param ioArray An array which will be filled with the item IDs. */ void AddIDs( const ACFXMLTree &inTree, StringVector &inVector); /*! @function GetIdentifiers @abstract Populate an array with the contents of a string vector. @discussion This method is used to respond to both kEventToolbarGetAllowedIdentifiers and kEventToolbarGetDefaultIdentifiers. @param inSource Either mDefaults or mAllowed. @param ioArray The array from the event. */ static void GetIdentifiers( const StringVector &inSource, ACFMutableArray &ioArray); }; // --------------------------------------------------------------------------- /* XML example com.uncommonplace.accela.sample Sample Samp ACEL Samp com.uncommonplace.accela.sample com.apple.hitoolbox.toolbar.flexiblespace com.apple.hitoolbox.toolbar.customize com.uncommonplace.accela.sample com.apple.hitoolbox.toolbar.separator com.apple.hitoolbox.toolbar.space com.apple.hitoolbox.toolbar.flexiblespace com.apple.hitoolbox.toolbar.customize com.apple.hitoolbox.toolbar.print */