Tips_tutorials   >   Studio104   >   Studio 104 (All Contents)
Introduction
Welcome to the Studio 104 tutorial.
This tutorial is provided to StudioTips Members only. If you are not currently a StudioTips Member please go to www.studiotips.net and click the link provided for becoming a StudioTips Member. The cost of membership is minimal and helps to cover the time and expense of creating these tutorials and maintaining the studiotips.net website.
This tutorial continues from where we left off in the Studio 103 tutorial. In this tutorial we will:
- Create a window with a headed list object.
- Learn about subwindow fields and how they work.
- Create a container window with two subwindows.
- Send messages to and from the subwindows.
This tutorial builds on the Studio 103 library. You must complete Studio 101, 102, and 103 prior to starting this tutorial.
Headed List Subwindow
The headed list object is one of my favorite list objects in Omnis Studio. In this section we will create a window which has a headed list object. The window will be
generic in design, allowing it to be used as a subwindow to present different data lists.
List Object vs. List Variable
One thing we need to clarify when talking about lists is the difference between a list object and a list variable.
- List Variable - A variable with the variable type set to List. The list variable has columns and rows and holds data. The list variable does not present the data to the runtime user. In a window class you normally use an instance variable for any lists you want to display in a list object. For clarity, I normally refer to a list variable as a data list.
- List Object - A window field object that is used to display the contents of a list variable to the user. Omnis Studio has numerous list objects: kCheckList, kComplexGrid, kDataGrid, kDroplist, kHeadedListBox, kStringGrid
Create Headed List Window
To create the headed list window class:
- F2 Browser > select Contacts library > click New Class > click Window.
- Name the window class, wHeadedList.
- Right-click on the window class in the F2 Browser and select Methods... in the context menu.
- Add the following instance variables in the Variables pane:
irDataList - Type - Item Reference - used to point the a list variable in the parent window
irListObj - Type Item Reference - points to the headed list object in this window
irParent - Type Item Reference - points to the parent window instance
- Add a $setParentRef method to the wHeadedList class methods.
- Add the parameter, pfrParent - Type - Field Reference to the $setParentRef method.
- Add the following code to the $setParentRef method.
Set reference irParent to pfrParent.$ref
Quit method kTrue
Later in this tutorial when the wHeadedList is instantiated as a subwindow, the $setParentRef method will be used by the parent window to register itself as the parent of the child subwindow.
- Add a $:ListObjRef property method to the wHeadedList class methods.
- Add the following code to the $:ListObjRef method.
Quit method irListObj
- Add a $setDataListRef property method to the wHeadedList class methods.
- Add the following code to the $setDataListRef method.
Set reference irDataList to pfDataList.$ref
- Press F3 to jump from the method editor to the window class editor of the wHeadedList window class.
- Press F3 again to open the Component Store palette window.
- Drag and drop the Headed List object from the Component Store to the wHeadedList window class.
- With the headed list field object selected press F6 to go to the field's properties.
- Set the headed field list properties as follows:
General tab
$name - HeadedListObj
$dataname - irDataList
$top - 20
$left - 20
Appearance tab
$designcolumns - 1
- Double-click the headed list object to go to the object's methods.
- Add a $construct method to the headed list object and enter the following code in the method:
Set reference irListObj to $cfield
Do $cfield.$edgefloat.$assign(kEFposnClient)
The $construct window class method code will run when the window is instantiated, just prior to it becoming visible in the display.
- Select the $event method of the headed list object and replace the existing code with the following code in the method:
If irParent.$event_HeadedListObj.$cando
Do irParent.$event_HeadedListObj
End If
All headed list events will be forwarded to the registered parent, provided that the parent window class has an $event_HeadedListObj method.
Parent Window
A parent window is a window class which contains one or more subwindow fields. The subwindow is considered a child window of the parent window.
A subwindow field is a special window object which allows you to instantiate a window class inside of another window class instance.
A child window knows nothing about the world outside of itself. The child window doesn't even know who its parent is. The parent is responsible to inform the child who its parent is.
Communication between parent and child window instances is accomplished by sending messages via the public class methods of the parent and child windows.
In this section we will create a parent window class with two subwindows. Each subwindow will be an instance of
wHeadedList. One subwindow will display a list of the countries, the other subwindow class will display a list of states/provs for the selected country.
Create Parent Window
To create the parent window class:
- F2 Browser > select Contacts library > click New Class > click Window.
- Name the window class, wCountryStateprovContainer.
- Right-click on the window class in the F2 Browser and select Methods... in the context menu.
- Add the following instance variables in the Variables pane:
iCountriesList - Type - List
iStateprovsList - Type - List
irswCountries - Type Item Reference - Countries subwindow field
irswStateprovs - Type Item Reference - Stateprovs subwindow field
- Add a constructDefineLists method to the class methods.
- Add the following code to the constructDefineLists method.
Do iCountriesList.$definefromsqlclass('tCountry')
Do iCountriesList.$sessionobject.$assign($ctask.dbsessionobj)
Do iStateprovsList.$definefromsqlclass('tStateprov')
Do iStateprovsList.$sessionobject.$assign(dbsessionobj)
Quit method kTrue
- Add a constructSubWin_Countries method to the class methods.
- Add the following code to the constructSubWin_Countries method.
Do irswCountries.$setParentRef($cinst) Returns FlagOK
If FlagOK
Do irswCountries.$setDataListRef(iCountriesList) Returns FlagOK
If FlagOK
Do irswCountries.$:ListObjRef() Returns rListObj
Do rListObj.$name.$assign('CountriesList')
Do rListObj.$colcount.$assign(1)
Do rListObj.$columnnames.$assign('Country')
Do rListObj.$calculation.$assign('irDataList.CountryName')
End If
End If
Quit method FlagOK
- Add a constructSubWin_Stateprovs method to the class methods.
- Add the following code to the constructSubWin_Stateprovs method.
Do irswStateprovs.$setParentRef($cinst) Returns FlagOK
If FlagOK
Do irswStateprovs.$setDataListRef(iStateprovsList) Returns FlagOK
If FlagOK
Do irswStateprovs.$:ListObjRef() Returns rListObj
Do rListObj.$name.$assign('StateprovsList')
Do rListObj.$colcount.$assign(2)
Do rListObj.$columnnames.$assign('State/Prov,Abbrev')
Do rListObj.$calculation.$assign('con(irDataList.StateProvName,kTab,irDataList.StateProvAbbrev)')
End If
End If
Quit method FlagOK
- Add a buildCountriesList method to the class methods.
- Add the following code to the buildCountriesList method.
Do iCountriesList.$getAllRecords() Returns FlagOK
Quit method FlagOK
- Add a buildStateprovsListForCurrCountry method to the class methods.
- Add the following code to the buildStateprovsListForCurrCountry method.
If iCountriesList.$line
Calculate SQLText as con("WHERE Country_fkey = ",iCountriesList.Country_pkey)
Do iStateprovsList.$select(SQLText) Returns FlagOK
If FlagOK
Do iStateprovsList.$fetch(kFetchAll) Returns FlagOK
End If
Do irswStateprovs.$redraw()
End If
Quit method FlagOK
- Add the following code to the existing $construct class method.
Do method constructDefineLists Returns FlagOK
If FlagOK
Do method constructSubWin_Countries Returns FlagOK
If FlagOK
Do method constructSubWin_Stateprovs Returns FlagOK
If FlagOK
Do method buildCountriesList Returns FlagOK
If FlagOK
Do method buildStateprovsListForCurrCountry Returns FlagOK
End If
End If
End If
End If
If not(FlagOK)
Do errhndlr.$promptonceLastError()
End If
Quit method FlagOK
- Add an $event_HeadedListObj method to the class methods.
- Add the following code to the $event_HeadedListObj method.
Calculate FlagOK as kTrue
Switch low($cobj().$name)
Case 'countrieslist'
If pEventCode=evClick
Do method buildStateprovsListForCurrCountry Returns FlagOK
End If
Case 'stateprovslist'
End Switch
Quit method FlagOK
Add Subwindow Fields
We will now add the subwindow fields to the wCountryStateprovContainer window class.
- If you are still in the window methods editor, press F3 to switch to the window class editor, otherwise double-click on wCountryStateprovContainer in the F2 Browser.
- F3 Component Store > drag the Subwindow field onto the window class.
- With the subwindow field selected press F6 Property Manager and set the following properties:
General tab
$name - swCountries
$classname - wHeadedList
$height - 200
$left - 10
$top - 10
$width - 400
- Dag another Subwindow field from the Component Store onto the window class.
- With the subwindow field selected press F6 Property Manager and set the following properties:
General tab
$name - swStateprov
$classname - wHeadedList
$height - 200
$left - 10
$top - 220
$width - 400
- Double-click the swCountries subwindow field to get to its methods.
- Add a $construct method to the swCountries subwindow field and enter the following code:
Set reference irswCountries to $cfield
- Add a $construct method to the swStateprovs subwindow field and enter the following code:
Set reference irswStateprovs to $cfield
Main Menu
We are just about ready to test the wCountryStateprovContainer window.
In order to open and instance of the window class we will add a menu line to the main menu.
- F2 Browser > double-click mMainMenu.
- Add a menu line to mMainMenu and set its F6 properties as follows:
$name - Countries, States/Provinces Browser
$text - Countries, States/Provinces Browser
- Add the following code to the $event method of the menu line.
Calculate ClassName as 'wCountryStateProvContainer'
Do $clib.$windows.$findname(ClassName) Returns rClass
If isnull(rClass)
OK message [sys(85)] (Icon) {Unable to find the window class '[ClassName]'.}
Else
Do rClass.$openonce('*') Returns rWin
If isnull(rWin)
OK message [sys(85)] (Icon) {Unable to open an instance of the window class [ClassName].}
End If
End If
Quit method rWin
- Close the menu class.
- Close and reopen the Startup_Task to reinstall the main menu. (F2 Browser > right-click Startup_Task > select Close Task, then right-click again and select Open Task.)
Testing the Parent Window
We are now ready to test the parent window.
- Contacts menu > select Counties, States/Provs Browser
- All going well and instance of the wCountyStateprovContainer window will be instantiated. The top subwindow will display a list of the countries and the bottom subwindow will display a list of states/provs for the selected country.
- If you select a different country, the list of states/provs will be rebuilt to display the states and provinces connected to the country.
Parent Window Sequence of Events
The following is an overview of the sequence of events that occur when the parent window is instantiated.
- When the wCountryStateprovContainer window begins to be instantiated, the two subwindow fields are first instantiated in order of the $order field property.
- The subwindows fields each open a separate instance of wHeadedList. When the window is instantiated the $construct methods of the window objects are first run. In this case the HeadedListObj $construct method expands the headed list object to fill the available area and sets the ivar irListObj to point to the headed list object.
- The $construct class method of wHeadedList runs next, but there isn't any code in the method.
- The $construct method of the subwindow fields in wCountryStateprovContainer set the ivars irswCountries and irswStateprovs to point to the respective subwindow fields.
- The $construct class method of wCountryStateprovContainer runs next. This method calls a series of private construct methods.
- constructDefineLists defines the data list variables iCountriesList and iStateprovsList of wCountryStateprovContainer.
- constructSubWin_Countries sends a $setParentRef($cinst) message to the swCountries subwindow field. The subwindow field automatically redirects the message to the window class instance of the subwindow field (wHeadedList). Redirecting messages to the window class instance is a feature of subwindow fields.
- The swCountries instance of wHeadedList sets its ivar irParent to point to the instance of wCountryStateprovContainer.
- constructSubWin_Countries sends a $setDataList(iCountriesList) message to the swCountries subwindow field which is redirected to its instance of wHeadedList.
- The swCountries instance of wHeadedList sets its ivar irDataList to point to the ivar iCountriesList of wCountryStateprovContainer.
- constructSubWin_Countries sends a $:ListObjRef message to the swCountries subwindow field which returns a reference to the headed list object.
- constructSubWin_Countries sets various properties of the headed list object. ($name, $colcount, $calculation, $columnnames) Additional properties could be set as needed.
A better alternative would be to add a public method to wHeadedList for setting the headed list properties. e.g. $setListObjColumns(pDataListColNamesCSV,pColNamesCSV,pColAlignCSV) The method would then parse the CSV strings and set the $colcount, $columnnames, $calculation properties and set the alignment for each column.
- constructSubWin_Stateprovs repeats the steps completed by constructSubWin_Countries but for the swStateprovs subwindow field and the iStateprovsList variable.
- Finally the $construct class method of wCountryStateprovContainer calls the buildCountriesList method and then the buildStateprovsListForCurrCountry method.
- The parent window instance along with its two subwindow instances appears to the user.
- When the user clicks on a different country in the countries list, the $event method of wHeadedList sends an $event_HeadedListObj message to the registered parent.
- The instance of wCountryStateprovContainer receives the $event_HeadedListObj message, figures out that the message came from the countries list instance of wHeadedList and calls the buildStateprovsListForCurrCountry method which then rebuilds the lista and redraws the state/provs list subwindow.
Summary
Well that wraps up the Studio 104 tutorial.
I hope that this tutorial has helped you with:
- Seeing how subwindow fields can be used to open instances of other window classes within a parent window instance.
- Understanding how a parent window can send messages to the subwindow field's window instance.
- Learning how a subwindow field can store a reference to its parent window and then use that reference to send messages to the parent window.
If this tutorial has been helpful please send an emai to doug@vencor.ca. It's always encouraging to hear from developers who have benefited from these tutorials. Be sure to include any suggestions for improvements or additional topics you would like to see covered.
In the Studio 105 tutorial we will delve into the topic of Observers based on the Observer Design Pattern.
The Studio 105 tutorial is only available to StudioTips Members. Omnis Studio developers are encouraged to become StudioTips Members. The cost of membership is well worth the benefits of being a member.
Visit www.studiotips.net to find out more and to become a StudioTips Member. Your support is greatly appreciated!
Happy coding!
Doug Kuyvenhoven
Vencor Software