Subject: Re: How to write a Modeless Dialog.
From: Thomas Fletcher (thomasf@qnx.com)
Date: Fri May 26 2000 - 08:23:58 CDT
Martin,
  Thanks ... I had loosely been following the modeless dialog
discussion and was planning on doing the Photon side of things 
this weekend.  This has cleared up a lot of things for me.  Hopefully
much of this work has been taken care of in XAP/XP land and there
will be very few platform specific things that I have to do to 
make things work.
Thomas
On Fri, 26 May 2000, Martin Sevior wrote:
> HI everyone,
> 
> I thought it would be a good idea to provide some documentation for the
> modeless dialog framework so here it is :-)
> 
> A while ago I thought I had a way to implement a modeless "Insert SYmbol"
> dialog. Paul Rohr then asked the question. "Open 4 windows on your
> desktop, now which window does your symbol go into?" From a UI point of
> view the answer is "The Window Most Recently Focussed". The modeless
> dialog framework makes this happen.
> 
> The basic ideas are as follows:
> 
> hj and Mike provided the unix and Windows code to recognise a change in
> the focus state of the open frames. Upon receiving an a focus_in event a
> method in fv_View is called. Within this method is a call to an xap_App
> method
> 
> XAP_App::rememberFocussedFrame( void * pJustFocussedFrame)
> 
> This records the most recently focussed frame in a protected variable in
> xap_App. xap_App is the bottom most class uniformly accessible to all the
> useful abi classes.
> 
> So now a modeless dialog knows which fv_View to interogate or manipulate.
> All it has to do is look up this frame pointer then call
> "getCurrentFrame". There are a couple of ways to do this but the best
> is via the xap_Dialog_Modeless class method
> 
> xap_Dialog_Modeless::getActiveFrame()
> 
> Which returns the most recently focussed frame to any child class of
> xap_Dialog_Modeless. This method has checks to verify the frame is
> actually present. If it isn't present it returns oldest running frame.
> xap_Dialog_Modeless has a couple of other useful methods available to
> child classes and abi in general. These are:
> 
> isRunning() : UT_TRUE if the dialog is running.
> modeless_cleanup() : Which cleans up the various pointers and tables to do
>                      with the dialog. You run this upon closing the
>                      dialog.
> 
> In addition there is code in xap_App to keep track of currently
> running modeless dialogs. Things we have to watch out for are:
> 
> 1. If the dialog is running just activate it, don't rebuild it.
> 
> The activate() method must be implemented seperately in the platform
> specific code for every modeless dialog via the
> 
> XAP_Dialog_Modeless::activate(void)
> 
> virtual function. The code for this is really easy. Look at either
> Insert_Symbol or WordCount for examples. 
> 
> 2. If abi is closed, gracefully shut down the modeless dialogs.
> 
> This method must also be implemented seperately in the platform specific
> code for every modeless dialog via:
> 
> XAP_Dialog_Modeless::destroy(void)
> 
> 
> In addition these is code in the unix modeless dialogs to make xap_App
> remember the dialog in its tables. This is:
> 
> void XAP_App::rememberModelessId(  UT_sint32 id  ,
> XAP_Dialog_Modeless * pDialog)
> 
> This call should be made within RunModeless immediately after calling the
> dialog for the first time. It should NOT be called more than once for each
> dialog otherwise bad things will happen.
> 
> There is one other magic function needed in every gtk modeless dialog. It
> is
> 
> connectFocusModeless(GTK_WIDGET(mainWindow),m_pApp)
> 
> this function is placed in the unix platform sepefic code just after the
> top level widget (called mainWindow) is created.
> 
> 
> Finally Bruce has implemented a scheme to notify all the running modeless
> dialogs of changes in the active frame. The uses the 
> 
>  setActiveFrame(XAP_Frame *pFrame);
> 
> method. This function must be provided by every modeless dialog and it is
> executed by xap_App upon a change of Active Frame. pFrame is the new
> active frame passed down from xap_App.
> 
> setActiveFrame is useful to enable the modeless dialog to change it's
> behaviour upon receiving notice of a change in the active frame. For
> example "WordCount" changes the statistics displayed to reflect the
> current active frame from the setActiveFrame method.
> 
> In addition the function:
> 
> virtual void	 notifyCloseFrame(XAP_Frame *pFrame);
>  
> Must be present and coded."notifyCloseFrame" is called when the active
> frame is closed. The Windows front end needs this. See Bruce's code in
> Insert_Symbol for examples.
> 
> In summary: 
> ----------------------------------------------------------------------
> In ap_EditMethods you invoke a Modeless dialog like this:
> 
> <Usual stuff about raising frames etc.> then:
> 
> 
> 	AP_Dialog_WordCount * pDialog
> 		= (AP_Dialog_WordCount
> *)(pDialogFactory->requestDialog(AP_DIALOG_ID_WORDCOUNT));
> 	UT_ASSERT(pDialog);
> 
>         if(pDialog->isRunning())  // Check to see if the dialog is running
> 	{
> 		pDialog->activate();  // if so activate it
> 	}
>         else
> 	{
>         	pDialog->setCount(pView->countWords()); // Otherwise
> 	        pDialog->runModeless(pFrame);          // Construct it.
> 	}
> 	UT_Bool bOK = UT_TRUE;
> 	return bOK;
> }
> ---------------------------------------------------------------------------
> You must supply code for the following functions in your modeless dialog.
> 
> 
> 	//------------------------------------------------------------
> 	// All these are needed for a modeless dialog
> 
> 	virtual void     useStart(void);
> 	virtual void     useEnd(void);
> 	virtual void	 runModal(XAP_Frame * pFrame) = 0;
> 	virtual void	 runModeless(XAP_Frame * pFrame) = 0;
>         virtual void     destroy(void)=0;
>         virtual void     activate(void)=0;
> 	void		 setActiveFrame(XAP_Frame *pFrame);
> 	virtual void	 notifyCloseFrame(XAP_Frame *pFrame){};
> 
> The useStart(), useEnd() and runModal() are cruft from the fact 
> XAP_Modeless_Dialog inherits from  XAP_Dialog_AppPersistent. They can be
> stubbed if you want.
> --------------------------------------------------------------------------
> 
> In the runModeless method you must include the code:
> 
> void XAP_App::rememberModelessId(  UT_sint32 id  , XAP_Dialog_Modeless *
> pDialog)
> 
> to register your dialog as running. 
> 
> ---------------------------------------------------------------------------
> Finally  the unix front end must include the code:
> 
> connectFocusModeless(GTK_WIDGET(mainWindow),m_pApp)
> 
> to make the cursor in currently active window show up when the dialog is
> focussed.
> --------------------------------------------------------------------------
> 
> Have a look at "Insert_Symbol" and "WordCount" for more clues and feel
> free to ask questions if you need more info.
> 
> Cheers!
> 
> Martin
> 
> 
> 
> 
-------------------------------------------------------------
Thomas (toe-mah) Fletcher       QNX Software Systems
thomasf@qnx.com                 Neutrino Development Group
(613)-591-0931                  http://www.qnx.com/~thomasf
This archive was generated by hypermail 2b25 : Fri May 26 2000 - 08:23:02 CDT