/********************************************************************** *< FILE: ITabDialog.h DESCRIPTION: Interface for tabbed dialogs CREATED BY: Cleve Ard HISTORY: Created 01 October 2002 24 March 2003 - Updated for R6. This update allows the current renderer to control which tabs are present in the render dialog. *> Copyright (c) 2002, All Rights Reserved. **********************************************************************/ #ifndef __ITABDIALOG_H_ #define __ITABDIALOG_H_ class ITabbedDialog; class ITabPage; class ITabRegister; class ITabDialogProc; class ITabPageProc; class ITabDialogFilter; class IRollupWindow; class ITabDialogPluginTab; /*********************************************************************** * * ITabDialogManager * * This interface is used to create tabbed dialogs and to register * tabs with dialogs that are created by the system or other plugins * **********************************************************************/ class ITabDialogManager : public FPStaticInterface { public: // Create a tabbed dialog. Parent is the parent window of the dialog, // Instance is the instance where the dialog tempate is stored, and dlg // is the name of the dialog template resource. If instance is NULL, // then dlg is a pointer to the dialog template in memory. MainProc is // the object that is used to handle messages for the dialog. Mult is // true if the tab control should be multiline and is only applicable // when tabID is -1. TabID is the ID of a tab control in the dialog // template, that is to be used. If tabID is -1, then a tab control // is created. HelpID is used to bring up context sensitive help // when the F1 key is pressed. virtual ITabbedDialog* CreateTabbedDialog( HWND parent, HINSTANCE instance, LPCTSTR dlg, ITabDialogProc* mainProc, bool multiline, DWORD helpID=0, int tabID = -1, const Class_ID& dialogID = Class_ID(0,0) ) = 0; // Register/UnRegister a tab for a dialog, DialogID is the id of the dialog // this tab is to be used with. Tab is the address of an object that is used // to add the tab when the dialog is created. Tab must remain valid while // it is registered. virtual bool RegisterTab(const Class_ID& dialogID, ITabDialogPluginTab* tab) = 0; virtual void UnRegisterTab(const Class_ID& dialogID, ITabDialogPluginTab* tab) = 0; // Set/Get the current plugin tab filter for a dialog. This filter is // used to determine which tabs will be present when the dialog is created. virtual void SetTabFilter(const Class_ID& dialogID, ITabDialogFilter* filter) = 0; virtual ITabDialogFilter* GetTabFilter(const Class_ID& dialogID) = 0; // Get the ITabbedDialog for the dialog id. Returns NULL if dialog not // present. Assumes that only one dialog is present for a dialog id at a time. // Note: NOTIFY_TABBED_DIALOG_CREATED and NOTIFY_TABBED_DIALOG_DELETED sent when // a tabbed dialog is created or deleted. callparam is point to dialogID virtual ITabbedDialog* GetTabbedDialog(const Class_ID& dialogID) = 0; // The return value can be a combination of TAB_DIALOG_REMOVE_TAB and // TAB_DIALOG_ADD_TAB static int AcceptTab( ITabDialogFilter* filter, ITabDialogPluginTab* tab ); }; // These are some internally defined dialog ids // Preferences dialog #define TAB_DIALOG_PREFERENCES_ID Class_ID(0x16d416fb, 0x1cdd4da5) // Object Properties dialog #define TAB_DIALOG_PROPERTIES_ID Class_ID(0x777f709b, 0x44404554) // Configure Path dilaog #define TAB_DIALOG_PATH_ID Class_ID(0x2c863840, 0x67b1202f) // Render dialogs #define TAB_DIALOG_RENDER_ID Class_ID(0x648636a0, 0xe52086b) #define TAB_DIALOG_VIDEO_POST_ID Class_ID(0x41be0fad, 0x160c099c) // Environment Dialog #if defined(ENVIRONMENT_DIALOG_IN_RENDER_DIALOG) #define TAB_DIALOG_ENVIRONMENT_ID TAB_DIALOG_RENDER_ID #else // defined(environment_dialog_in_render_dialog) #define TAB_DIALOG_ENVIRONMENT_ID Class_ID(0x447f2d77, 0x781268a7) #endif // defined(environment_dialog_in_render_dialog) // These are the results of accepting a tab for a dialog enum { TAB_DIALOG_REMOVE_TAB = 1, TAB_DIALOG_ADD_TAB = 2 }; #define TAB_DIALOG_MANAGER_INTERFACE_ID Interface_ID(0x46465ead, 0x6e3cbb) // This inline will return the ITabDialogManager. inline ITabDialogManager* GetTabDialogManager() { return static_cast( GetCOREInterface(TAB_DIALOG_MANAGER_INTERFACE_ID)); } /*********************************************************************** * * ITabDialogPluginTab * * This interface is used to add plugin tabs to a tabbed dialog. * **********************************************************************/ class ITabDialogPluginTab : public BaseInterface { public: // Add your tab(s) to the dialog. This will only be called if // both this object and the dialog agree that the tab should // be added. Dialog is the address of the dialog. virtual void AddTabToDialog(ITabbedDialog* dialog) = 0; // Accept this tab in this dialog. Dialog is the address of the // dialog. Return true if the tab should be added. Return false // if the tab should not be added or should be removed if it // was added previously. Filter is the dialog filter. virtual int AcceptDialog( ITabDialogFilter* filter ) { return TAB_DIALOG_ADD_TAB; } // These return various information that is likely to be interesting // when deciding whether or not to use this tab. // If this tab is the UI for a ReferenceMaker, return it here. virtual ReferenceMaker* GetReferenceMaker() { return NULL; } // Otherwise, if this tab is the UI for an Animatable, return it here virtual Animatable* GetAnimatable() { return GetReferenceMaker(); } // Otherwise, If this tab has some known class ID and super class ID virtual Class_ID GetClassID() { Animatable* a = GetAnimatable(); return a ? a->ClassID() : Class_ID(0, 0); } virtual SClass_ID GetSuperClassID() { Animatable* a = GetAnimatable(); return a ? a->SuperClassID() : 0; } // Otherwise, you will need to define a special interface virtual BaseInterface* GetInterface(const Interface_ID& id) { return NULL; } }; /*********************************************************************** * * TabDialogFilter * * This interface is used to filter plugin tabs in a tabbed dialog. * **********************************************************************/ class ITabDialogFilter : public BaseInterface { public: // Return true if the tabs added by the ITabDialogPluginTab tab // are acceptable for this dialog. Dialog is the dialog being // filtered. virtual int AcceptTab( ITabDialogPluginTab* tab ) { return TAB_DIALOG_ADD_TAB; } // Launch the dialog for this filter, open the dialog at a specific page virtual int LaunchDialog(const Class_ID& page = Class_ID(0,0)) { return IDOK; } // These return various information that is likely to be interesting // when deciding whether or not to add a tab. // If this dialog is the UI for a ReferenceMaker, return it here. virtual ReferenceMaker* GetReferenceMaker() { return NULL; } // Otherwise, if this dialog is the UI for an Animatable, return it here virtual Animatable* GetAnimatable() { return GetReferenceMaker(); } // Otherwise, If this dialog has some known class ID and super class ID virtual Class_ID GetClassID() { Animatable* a = GetAnimatable(); return a ? a->ClassID() : Class_ID(0, 0); } virtual SClass_ID GetSuperClassID() { Animatable* a = GetAnimatable(); return a ? a->SuperClassID() : 0; } // Otherwise, you will need to define a special interface virtual BaseInterface* GetInterface(const Interface_ID& id) { return NULL; } }; /*********************************************************************** * * TabDialogMessages * * Messages used by the tab dialog class * **********************************************************************/ enum TabDialogMessages { TABDLG_SWITCH_FROM = WM_USER + 1, // Switching from this page TABDLG_SWITCH_TO = WM_USER + 2, // Switching to this page TABDLG_COMMIT = WM_USER + 3, // Commit the page's working values for real TABDLG_PRECOMMIT = WM_USER + 4, // Check your values, but don't close the dialog; // if your page needs to reject an OK, set the // bool* in LPARAM to false. TABDLG_CANCEL = WM_USER + 5, // User is cancelling out of the dialog TABDLG_CLOSE = WM_USER + 6, // User is closing a modeless dialog TABDLG_INVALIDATE = WM_USER + 7, // The underlying data has changed TABDLGNOTIFY_GETINITINFO = WM_USER + 8, // WE need to get init, see struct TABDLG_NMHDR TABDLG_RESIZE_DIALOG= WM_USER + 9 // The tab is too small for the content }; // The address of this struct passed in LPARAM when // you get a WM_NOTIFY, with TABDLGNOTIFY_GETINITINFO // as the notify code. This notification is sent to // the tab dialog before each page is created. hdr.idFrom // is the index of the page about to be created. The // value stored in dwInitParam is passed to the InitPage // method as lparam. struct TABDLG_NMHDR { NMHDR hdr;//the common denominator //we use the LPARAM dwInitParam; //this out param contains the ptr to initialization data for the page. }; /*********************************************************************** * * ITabbedDialog * * This interface is used to manage a tabbed dialog. You can add pages * and either display a modal or modeless dialog. * You can add a rollout page, that can contain MAX rollouts * **********************************************************************/ #define TABBED_DIALOG_INTERFACE_ID Interface_ID(0x4128621b, 0x744d5789) class ITabbedDialog { public: enum { kSystemPage = 20, kNormalPage = 50, kMaxPage = 100 }; static ITabbedDialog* GetPointer(HWND dialog) { return reinterpret_cast(GetWindowLongPtr( dialog, GWLP_USERDATA)); } // Delete yourself virtual void DeleteThis() = 0; // Return the dialogID for this dialog virtual Class_ID GetDialogID() const = 0; // Add a page to the dialog. Text is the tab text. Instance and // tmplt are the instance and resource for the dialog template // for the page. If instance is NULL, the tmplt is a pointer to // the dialog template in memory. Proc is the message handler for // the page. Image is an image for the tab in the image list set // by SetImageList. Order is the order that the tab will appear // in the tabs. Two pages with the same order are ordered // by the order they are added. HelpID is ID used for context // sensitive help. virtual ITabPage* AddPage( LPCTSTR text, HINSTANCE instance, LPCTSTR tmplt, ITabPageProc* proc, const Class_ID& pageID, ITabDialogPluginTab* plugin = NULL, DWORD helpID = 0, int order = kNormalPage, int image = -1 ) = 0; // Add a rollout page to the dialog. Text is the tab text. Proc is // the message handler for the page. The margins give additional // space between the rollout control and the client are of the tab. // Image is an image for the tab in the image list set by SetImageList. // Order is the order that the tab will appear in the tabs. Two // pages with the same order are ordered by the order they are added. // HelpID is ID used for context sensitive help. virtual ITabPage* AddRollout( LPCTSTR text, ITabPageProc* proc, const Class_ID& pageID, ITabDialogPluginTab* plugin = NULL, int controlID = -1, int width = 0, int bottomMargin = 0, DWORD helpID = 0, int order = kNormalPage, int image = -1 ) = 0; // Add and remove registered tabs to the dialog. virtual void SyncRegisteredTabs() = 0; // Get the filter for this dialog virtual ITabDialogFilter* GetTabFilter() const = 0; // Get/Set the dialog proc. The previous // value is returned when setting the proc virtual ITabDialogProc* GetProc() const = 0; virtual ITabDialogProc* SetProc(ITabDialogProc* newProc) = 0; // Display and process modal dialog virtual INT_PTR DoModal(const Class_ID& page) = 0; // Display and process modeless dialog virtual bool DoFloater(const Class_ID& page) = 0; // Switch to the given page. virtual void Switch(const Class_ID& page) = 0; // Invalidate all pages in the dialog. virtual void Invalidate() = 0; // Set the image list for the tab control virtual void SetImageList(HIMAGELIST list) = 0; // Get the index of the current page virtual int CurrentPage() const = 0; // Set the margins for the tab in the dialog. This is // only applicable if the tabCtrl is not part of the // dialog template. If SetTabbedRect is called with // a nonempty rectangle, it is used, otherwise the // margins are used. virtual void SetMargins(int left, int top, int right, int bottom) = 0; virtual void SetTabbedRect(const RECT& rect) = 0; // Convert indices to pages virtual int GetNbPages() const = 0; virtual ITabPage* GetPage(int index) const = 0; virtual ITabPage* GetPage(const Class_ID& id) const = 0; // Get the window for the tabbed dialog virtual HWND GetHWND() const = 0; // Used for modal dialogs with IDOK and IDCANCEL virtual bool OkToCommit() = 0; virtual bool CommitPages() = 0; // Used for modeless dialogs; note that if the user hits the X in the upper right // corner, a cancel message will be sent. virtual void CloseDialog() = 0; virtual void ClosePages() = 0; // Used for both. virtual void CancelDialog() = 0; virtual void CancelPages() =0; // Get the window for the tab control virtual HWND GetTabHWND() const = 0; protected: // Don't allow it to be deleted except through DeleteThis ~ITabbedDialog() {} }; /*********************************************************************** * * TabDialogPointer * * This smart pointer is used to simplify scope management * **********************************************************************/ class TabDialogPointer { public: TabDialogPointer() : mpDlg(NULL) { } explicit TabDialogPointer(ITabbedDialog* dlg) : mpDlg(dlg) { } explicit TabDialogPointer(TabDialogPointer& src) : mpDlg(src.mpDlg) { src.mpDlg = NULL; } TabDialogPointer( HWND parent, HINSTANCE instance, LPCTSTR dlg, ITabDialogProc* mainProc, bool multiline, DWORD helpID = 0, int tabID = -1, const Class_ID& dialogID = Class_ID(0,0) ) : mpDlg(NULL) { ITabDialogManager* i = GetTabDialogManager(); if (i != NULL) { mpDlg = i->CreateTabbedDialog(parent, instance, dlg, mainProc, multiline, helpID, tabID, dialogID); } } ~TabDialogPointer() { free(); mpDlg = NULL; } TabDialogPointer& operator=(ITabbedDialog* dlg) { free(); mpDlg = dlg; return *this; } TabDialogPointer& operator=(TabDialogPointer& src) { free(); mpDlg = src.mpDlg; src.mpDlg = NULL; return *this; } operator ITabbedDialog*() { return mpDlg; } ITabbedDialog& operator*() { return *mpDlg; } ITabbedDialog* get() { return mpDlg; } ITabbedDialog* release() { ITabbedDialog* dlg = mpDlg; mpDlg = NULL; return dlg; } ITabbedDialog* operator->() { return mpDlg; } ITabbedDialog** operator&() { return &mpDlg; } bool Create( HWND parent, HINSTANCE instance, LPCTSTR dlg, ITabDialogProc* mainProc, bool multiline, int tabID = -1, DWORD helpID = 0, const Class_ID& dialogID = Class_ID(0,0) ) { ITabDialogManager* i = GetTabDialogManager(); if (i != NULL) { ITabbedDialog* retVal = i->CreateTabbedDialog(parent, instance, dlg, mainProc, multiline, helpID, tabID, dialogID); if (retVal != NULL) { free(); mpDlg = retVal; return true; } } return false; } private: void free() { if (mpDlg != NULL) mpDlg->DeleteThis(); } ITabbedDialog* mpDlg; }; /*********************************************************************** * * ITabPage * * This interface is used to manage a page in a tabbed dialog. * **********************************************************************/ class ITabPage : public BaseInterface { public: // Get the window for this page virtual HWND GetHWND() const = 0; // Get the pageID for this page virtual Class_ID GetPageID() const = 0; // Get the help ID for the page virtual int GetHelpID() const = 0; // Get the tab dialog containing this page virtual ITabbedDialog* GetTabDialog() const = 0; // Get/Set the tab dialog page proc. The previous // value is returned when setting the proc virtual ITabPageProc* GetProc() const = 0; virtual ITabPageProc* SetProc(ITabPageProc* newProc) = 0; // Get the Plugin that added this page virtual ITabDialogPluginTab* GetPlugin() const = 0; // Convert pages to indices virtual int GetIndex() const = 0; // Refresh your UI. virtual void Invalidate() = 0; // Get the IRollupWindow interface for the rollout // This interface should not be released, because // it is release by this object when the rollout // is destroyed. NULL is returned if the page is // not a rollout. virtual IRollupWindow* GetRollout() = 0; }; /*********************************************************************** * * ITabDialogProc * * This interface is implemented by the code that wants to use the * tab dialog. The implementer can choose whether to respond to * the methods or to messages * **********************************************************************/ class ITabDialogProc : public BaseInterface { public: // Construct ITabDialogProc() : mpDlg(NULL) {} // Set the dialog proc void SetTabDialog(ITabbedDialog* dlg) { mpDlg = dlg; } ITabbedDialog* GetTabDialog() const { return mpDlg; } // Delete this dialog proc. This method does nothing, because most // dialog procs are not scoped by their dialog, but you can override // it if you want your dialog proc deleted when the dialog is deleted. virtual void DeleteThis() {} // Initialize the dialog INT_PTR InitDialog(HWND focus) { return dialogProc(WM_INITDIALOG, reinterpret_cast(focus), 0); } // Invalidate the dialog void Invalidate() { dialogProc(TABDLG_INVALIDATE, 0, 0); } // Used for modal dialogs with IDOK and IDCANCEL bool OkToCommit() { bool commit = true; dialogProc(TABDLG_PRECOMMIT, 0, reinterpret_cast(&commit)); return commit; } void Commit() { dialogProc(TABDLG_COMMIT, 0, 0); } // The dialog is being closed. This is called after // all of the pages have been committed. void Close() { dialogProc(TABDLG_CLOSE, 0, 0); } // The dialog is being canceled void Cancel() { dialogProc(TABDLG_CANCEL, 0, 0); } // Resize the dialog. Delta is the required // change in size. This method is only called // if the size needs to be increased. // Return true if the dialog was resized. // If the dialog was resize, the dialog manager // will resize the tab control and the content. // The dialog proc may change the delta values // to correspond the the amount the dialog was resized. bool ResizeDialog(SIZE* delta) { return dialogProc(TABDLG_RESIZE_DIALOG, 0, reinterpret_cast(delta)) != 0; }; // The general message proc. This proc is like a // dialog proc, not a window proc virtual INT_PTR dialogProc( UINT msg, WPARAM wParam, LPARAM lParam ) { return FALSE; } // Get extension interfaces, if there are any virtual BaseInterface* GetInterface(const Interface_ID& id) { return NULL; } private: ITabbedDialog* mpDlg; }; /*********************************************************************** * * ITabPageProc * * This interface is used to filter plugin tabs in a tabbed dialog. * **********************************************************************/ class ITabPageProc { public: // Construct ITabPageProc() : mpPage(NULL) {} // Set the dialog proc void SetTabPage(ITabPage* page) { mpPage = page; } ITabPage* GetTabPage() const { return mpPage; } // Delete this page proc. This method does nothing, because most // page procs are not scoped by their page, but you can override // it if you want your page proc deleted when the page is deleted. virtual void DeleteThis() {} // Initialize the dialog INT_PTR InitPage(HWND focus, LPARAM lparam) { return dialogProc(WM_INITDIALOG, reinterpret_cast(focus), lparam); } // Invalidate the dialog void Invalidate() { dialogProc(TABDLG_INVALIDATE, 0, 0); } // Used for modal dialogs with IDOK and IDCANCEL bool OkToCommit() { bool commit = true; dialogProc(TABDLG_PRECOMMIT, 0, reinterpret_cast(&commit)); return commit; } void Commit() { dialogProc(TABDLG_COMMIT, 0, 0); } // The dialog is being closed. This is called after // all of the pages have been committed. void Close() { dialogProc(TABDLG_CLOSE, 0, 0); } // The dialog is being canceled void Cancel() { dialogProc(TABDLG_CANCEL, 0, 0); } // Switch from this page void SwitchFrom() { dialogProc(TABDLG_SWITCH_FROM, 0, 0); } // Switch to this page void SwitchTo() { dialogProc(TABDLG_SWITCH_TO, 0, 0); } // The general message proc. This proc is like a // dialog proc, not a window proc virtual INT_PTR dialogProc( UINT msg, WPARAM wParam, LPARAM lParam ) { return FALSE; } private: ITabPage* mpPage; }; /*********************************************************************** * * ITabDialogObject * * This interface is used to allow plugins to interact with a tabbed dialog. * Objects can expose this interface when they want to participate * in tab selection in a tabbed dialog. * * The dialog defines how objects can participate: * * The Render dialog allows the renderer to participate in the dialog tabs. * * If the renderer doesn't expose this interface, a single separate * tab is created for the renderer's paramters, and the renderer is * allowed to create rollouts in this tab. * * If the renderer does expose this interface, its filter is assigned * to the dialog, to allow it to reject tabs that are not applicable * to its user interface, and it is informed of different actions * that are taking place. * **********************************************************************/ class ITabDialogObject : public BaseInterface { public: // Notify the object that the dialog is activated // or deactivated in a tabbed dialog virtual void Activate(ITabbedDialog* dialog) { } virtual void Deactivate(ITabbedDialog* dialog) { } // Add your tab(s) to the dialog. This will only be called if // both this object and the dialog agree that the tab should // be added. Dialog is the address of the dialog. virtual void AddTabToDialog(ITabbedDialog* dialog, ITabDialogPluginTab* tab) { } // Return true if the tabs added by the ITabDialogPluginTab tab // are acceptable for this dialog. Dialog is the dialog being // filtered. virtual int AcceptTab( ITabDialogPluginTab* tab ) { return TAB_DIALOG_ADD_TAB; } }; #define TAB_DIALOG_OBJECT_INTERFACE_ID Interface_ID(0x313c6db9, 0x42890bb3) inline ITabDialogObject* GetTabDialogObject(InterfaceServer* obj) { return static_cast(obj->GetInterface( TAB_DIALOG_OBJECT_INTERFACE_ID)); } inline int ITabDialogManager::AcceptTab( ITabDialogFilter* filter, ITabDialogPluginTab* tab ) { int dlgResult = filter == NULL ? TAB_DIALOG_ADD_TAB : filter->AcceptTab(tab); if (dlgResult & TAB_DIALOG_ADD_TAB) { dlgResult &= ~TAB_DIALOG_ADD_TAB; dlgResult |= tab->AcceptDialog(filter); } return dlgResult; } #endif