New Writer Wizard
All the changes added to the original OpenOffice.org source code provided in this page, are :
- Copyright Eric Bachard August 2009
- Under GPL License V2, ( and you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation)
Once this code will be commited on some OpenOffice.org Project repository, or backported in OpenOffice.org, or even proposed in OOo4Kids, it will be relicensed under LGPLv3 license.
Important: If you use this information, don't forget everything you'll find here is under CC by-sa License, and you must mention your sources in what you write ...
Below, you'll find a technical description of the New Writer Wizard feature. It is question of OpenOffice.org source code (mainly C++), e.g. the internal source code organisation in OpenOffice.org framework, and the part concerning Draw part (adapted to Writer, of course), the interaction with the graphical part aka vcl, the use of callbacks for the User Interface part, and timers too .. and so on. Thus, we suppose the reader has the mandatory bases to understand the content of what is proposed.
The pre-requisites to read this article still have to be defined, but if the reader is not used with some notions, we invite him to have a look at the OpenOffice.org wiki to complete his knowledge, and read this article in the best conditions.
The new feature will be based on :
- the existing Start Center, basically : framework/source/services/backingwindow.cxx + associated headers
- the existing Impress Wizard, who basically is sd/source/ui/dlg/dlgass.cxx + the matching .src (for the dialog box)
Just one modification will be made in the Start Center, who will not launch Writer directly, but start a wizard, asking for choose between several possibilities.
The wizard will be a 3 steps max wizard. The start is when you click on the "Text" icon in the Start Center frame. This will launch the Writer Wizard who will propose you to ...
Choose (checkbox) between Empty document or existing document
Example 1 :
- Check A new empty Writer document changes the OK pushbutton in Create pushbutton.
- Check ... something else, changes the Create pushbutton in OK pushbutton.
- If "A new empty Writer document" is checked, and Create clicked-> start writer with a new empty document
- If "...something else" is checked, and OK clicked => Step 2
To quit :
- any click on ESC key quits the Assistant
- any click on Cancel button quits the Assistant
Be able to choose between :
- Text (including predefined styles )
- Poem (including predefined styles )
- Journal (including predefined styles )
- Invitation (including predefined styles )
- Birthday card (including predefined styles )
- Other Existing Template, located in a predefined directory
Comments: when create an existing template is checked the pushbuttons shows Ok, when (e.g.) Birthday card is checked, we have Create instead.
TODO : create documents including predefined styles
- any click on Cancel button quits the assistant
- any click on ESC key quits the assistant
- any click on Back returns at step 1
- if any choice is either Text or Poem or Birthday card or Invitation or Expose, the pushbutton becomes a Create pushbutton.
- if the choice is Other Existing Template, the pushbutton becomes OK pushbutton.
- If choice is Text and Create button is clicked : a new empty document, respecting several styles will be proposed.
- If choice is Poem and Create button is clicked : an new empty poem (predefined styles) will be proposed
- If choice is Invitation and Create button is clicked : an new empty invitation (predefined styles) will be proposed
- If choice is Journal and Create button is clicked : an new empty expose (predefined styles) will be proposed
- If choice is Birthday card and Create button is clicked : an new empty Birthday card (predefined styles) will be proposed
- Else if choice is Other Existing Template and OK button is clicked => Step 3
Step 3 (optional) :
- a dialog box containing pre-installed templates, will open.
IMPORTANT : this is the OOo default template dialog box, and we don't manage it for the moment, but if needed, we'll improve it
- The user will select one, and if OK clicked-> start writer with selected template
IMPORTANT : the folder who will open, will be predefined, but can be modified. No pre-installed templates will be there by default, but the professor will put them at the right place.
The most interesting part stands in the dlgass.cxx. Not to say that the backing window is not interesting, but will only be concerned by new constants, for new URLs to open. Oppositely, the dlgass.cxx does contain lot of things :
- class inheritance
- enormous constructor
- Retrieve a document
- Open a folder
- Open User preferences
- Modify Users preferences
- Check for a file type
- lot of callbacks // syntax, use and coding guidelines
- several timers // what's that / interaction with vcl , how to use them / examples, and test
- specific classes
- does manage a view (transition effect) in a part of it, means a SlideShow
Pedagogicaly, this is a source for a lot of studies and experimentations, and the result is imediately visible, what cannot be bad :)
Important: all this study is born from a severe issue causing a crash, and I'm working on (I'm experimenting a fix). See Issue 104344. Last but not least: even fix the crash is interesting for the students ...
State of the Design
First step will be to describe the needs, like how many different pages will be used to dispaly everything, how many buttons, or what we exactly will need, and then the behavior. Looks now obvious the Model/ View Controller paradigm :
- the view, will be described in the .src . The associated constants will be defined in the .hrc ( + some other in the helpid.h )
Constants defining the view
/* PAGE 1 */ /* Create pushbutton, page 1, when create a new empty Writer document is checked */ #define BUT_PAGE1_CREATE 1 /* OK pushbutton, page 1. Appears when "...something else" is checked */ #define BUT_PAGE1_OK 2 /* cancel pushbutton. Quits the assistant */ #define BUT_PAGE1_CANCEL 3 /* Fixed bitmap Page 1 : create */ #define FB_PAGE1 4 /* Radio button : start with template */ #define RB_PAGE1_TEMPLATE 5 /* Radio button : start with empt Writer document */ #define RB_PAGE1_EMPTY_WRITER_DOC 6 /* PAGE 2 */ /* Control for a preview : nice and usefull */ #define CT_PAGE2_PREVIEW 7 /* Checkbox for a preview : checked means preview */ #define CB_PAGE2_PREVIEW 8 /* previous pushbutton : returns to page 1 */ #define BUT_PAGE2_BACK 9 /* Create pushbutton, page 1, when one model is either Poem, or Text, or Birthday, or Invitation, or Journal is checked */ #define BUT_PAGE2_CREATE 10 /* OK pushbutton, page 2. Appears when "existing template" is checked */ #define BUT_PAGE2_OK 11 /* cancel pushbutton. Quits the assistant */ #define BUT_PAGE2_CANCEL 12 /* Checkbox : start with simple text */ #define CB_PAGE2_STARTWITH_SIMPLE_TEXT 13 /* Checkbox : start with journal */ #define CB_PAGE2_STARTWITH_JOURNAL 14 /* Checkbox : start with Poem */ #define CB_PAGE2_STARTWITH_POEM 15 /* Checkbox : start with birthday */ #define CB_PAGE2_STARTWITH_BIRTHDAY 16 /* Checkbox : start with invitation */ #define CB_PAGE2_STARTWITH_INVITATION 17 /* Checkbox : start with Poem */ #define CB_PAGE2_STARTWITH_EXISTING_TEMPLATE 18 /* Fixed bitmap Page 2 : create */ #define FB_PAGE2 19 /* Fixed bitmap page 2 */ #define FB_PAGE2 20 /* We'll need to associate the string with other things */ #define STR_CREATE 27 /* needed too */ #define STR_OPEN 28 /* the ID of the Assistant */ #define DLG_ASS_WRITER 930 /* usefull ? */ #define FL_PAGE2_LAYOUT 20 /* usefull ? */ #define LB_PAGE2_REGION 21 /* usefull ? */ #define LB_PAGE2_LAYOUT 22 /* Radion button : start with an empty document */ #define RB_PAGE1_EMPTY 23 /* */ #define RB_PAGE2_OPEN 24 /* */ #define LB_PAGE2_OPEN 25 /* */ #define PB_PAGE2_OPEN 26 /* */
FIXME : maybe time to use the new layout ?
- the model will tell us what entities we will use, in runtime, be it visible or not to the user.
- the controller will manage the relationships between both the view and the model to produce the expected results
State of the Implementation
=> based on Unit tests
- Layout Page 1 : use the screenshot, based on Interface Builder from Mac OS X 10.4(important )
- Layout Page 2 : use the screenshot, based on Interface Builder from Mac OS X 10.4(important )
- add a cancel button
- activate the cancel button
- add a check box (radio buttons ? , or a better control (what is the best ?)
- add other choices
- make the new control active
- add a next button
- activate the next button
- create a second page
- create a previous button (same location than the previous one)
- add a previous button on the second page
- activate the previous button
- add the button "existing template" on the second page
- make appear / create a new empty dialog, when clicking on the Writer button in the startcenter
- make the next buttons work
- make the previous buttons work
- verify next/previous ping pong works
- make the "existing template" button work : must open the slot 5500 (template or something like that)
- Test every method at runtime, using a debugger.
- make the cancel button work. Expected: click the button closes the window.
- make the escape button work. Expeted : click the button closes the window.
- verify the checkboxes/radio buttons work: click one should point the right document URL.
How many pages do we need
3 steps (max) -> 2 pages + template window (when using an existing template)
2 choices, means 2 lines containing Text + a checkbox. Depending on the checked case, the finish push button will be either Create or OK.
The choice will be exclusive
- Cancel button
Not sure, because will cause an overload, and the entry is in already in the menu :
- Help button
(several choices) -> Text + radio buttons
+ Cancel Back (or Previous?) and Ok pushbuttons
Back will return at page 1
Ok will either open the choosen document, or open the templates dialog box ( port 5500 or so)
A major change will be made in backingwindow.cxx, because a new UNO slot ID will be created, to launch the assistant when a click on the Writer button will be achieved from the Start Center
Concerned modules :
Open a wizard ( Impress wizard like ) when creating a new Writer document.
After some time playing (not sure the word is the best) with OpenGrok, we'll add the new slot ID interface and implementation somewhere in sfx2 + some changes in sfx2/source/appl
Look at the code: to launch the (already existing) Impress wizard, the "slot id" called is 6686 ( as private/factory/simpress?slot=6686 string )
Unfortunaly, there is no slot id 6686. So what ? In fact after searching a bit (a lot in fact), the solution appears in sfxsids.hrc :
When you read #define SID_SFX_START 5000, you immediately understand, that 6686 means 5000 + 1686 and bingo ! there is a matching entry :-)
#define SID_NEWSD (SID_SFX_START + 1686)
Now, you understand that you'll have the following challenge to win : find a new one for SID_NEWSW
... but after searching a bit, grep 1686 or superior tells you that things are not simple, but finally something great appears, saying that the first free slot id will be 5000 + 1718 :-)
The proof :
#define SID_SFX_free_START (SID_SFX_START + 1718) #define SID_SFX_free_END (SID_SFX_START + 3999)
Contains the framework/source/services/backingwindow.cxx + hxx where we'll add the new slot ID
Will contain new schema and datas for the new slot ID
Contains the model dlgass.cxx ( sd/source/ui/dlg/dlgass.cxx + .src + sd/source/ui/dlg/sddlgfact.cxx and .hxx) for the implementation
We'll have to create the assistant dialog, based on :
- New files :
- sw/inc/swenumdef.hxx : contains enumerations for the document types, and templates state
- sw/source/ui/inc/SwAssistantClass.hxx : contains the generic Assistant interface
- sw/source/ui/inc/SwDialogAssistant.hxx : contains the implemented Dialog Assistant interface
- sw/source/ui/inc/SwDialogAssistant.hrc : contains the Dialog Assistant help and ressource IDs for the dialog
- sw/source/ui/dialog/SwDialogAssistant.cxx : contains the implemented Dialog Assistant implementation
- sw/source/ui/dialog/SwDialogAssistant.src : contains the Implemented Dialog Assistant view description
- Modified files
- sw/source/ui/dialog/swdlgfact.hxx : dialog factory interface
- sw/source/ui/dialog/swdlgfact.cxx : dialog factory implementation
- sw/source/ui/dialog/Makefile.mk ( to build the new SwDialogAssistant object )
In Writer, most of the dialogs are abstracted dialogs, created using the factory design pattern. This lead to add a new abstracted dialog, and implement it like other.
SwAssistantClass.hxx will contain the definition of WriterAssistantDlg (a ModalDialog in fact), and WriterAssistantDlg_Impl classes.
The second one (WriterAssistantDlg_Impl) will be private for the WriterAssistantDlg
And in sw/source/ui/dialog/swdlgfact.cxx, we'll add the instanciation of the abstracted dialog, WriterAssistantDlg_Impl, calling the true WriterAssistantDlgImp, itself encapsulated in WriterAssistantDlg.
The new slot id will be 6718
#define WRITER_WIZARD_URL "private:factory/swriter?slot=6718" // 6718 == 5000 + 1718 == new slot value
- create the .src for page 1
- create the .src for page 2
- create the .hrc containing constants for all .src and .cxx
Unit tests for view
- open a window containing the right view, for every step
- verify everything is well located on the view
- verify all clicks are visible for every view
- verify Cancel works for every view
- verify Ok works for every view
- define the list of every
- push button
- radio button
- Cancel button
- Ok button
- Back button
- assistant class name will be WriterAssistantDlg
FIXME : define all class members, methods, and callbacks
The controller will be based on the existing dlgass controller, but adapted to Writer