View this PageEdit this PageAttachments to this PageHistory of this PageHomeRecent ChangesSearch the SwikiHelp Guide
Hotspots: Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007

-M7 GUI Coding OOPS

M7: GUI Coding


The M7 is GUI Coding

Comment:
If M6 is done correctly, M7 is one of the easiest (and most tedious) milestones of the project.


Requirements/Grading Criteria:
      o Login Dialog and Error Handling..........................................10
      o Data input screens to populate the model .......................................10
      o Occupancy Report...........................10
      o Morbidity Report and Pie Chart ..............10
      o Disease History ................10
      o Doctor Rounds .................10
      o All other M6 functionality is present and working thru GUI .............................20
      o SUnit tests (for any non-gui classes added)..............................10
      o Good Smalltalk code and style.................................................10

GUI How To

GUI programing can be extremely hard if one doesn't fully understand how it works. It's one part where spray and pray (trial and error) does not work too well.
First it is important to visualize how the GUI and its related classes, methods work.
Following is an example of visualization of a PatientEditDialog and it's related classes.
GUIs generally have models which are domain classes.
It can have multiple models so it is not hard to create a GUI to manage relation or collaborative operation between multiple domain classes.
*** Please refer to the package for HospitalOOPS in the repository for reference.

Think of aspects like instances that belong to the GUI and is tied to the GUI component(widget) with that aspect.
By changing these aspects you can change what your Text Field or List says. You can also retrieve data from those aspects to use as input.

PatientEditDialog (GUI)     |
 instance:                  |
  patientModel              |      Patient (Domain)        |
  hospitalModel             |                              |      Hospital (Domain)
  recordListCopy            |                              |       instance:
  roomList                  |                              |        roomList
 aspects:                   |       instance:              |
  #name                     |        name                  |
  #id                       |        id                    |
  #password                 |        password              |
  #type                     |        type                  |
  #room                     |        room                  |
  #recordList               |        recordList            |
 actions:                   |       message:               |
  #viewRecord               |                              |

(The above layout only includes the instances and messages that are absolutely necessary to understand this example.)


This is initialize message for the PatientEditDialog.

  initialize
	super initialize.
	patientModel := Patient new.
	hospitalModel := Hospital new.
	recordList :=SelectionInList new.
	recordList listHolder: ((UI.AspectAdaptor subject: patientModel sendsUpdates: true) forAspect: #recordList).
	^self

Because the GUI not only needs to know information on the patient, but also information about the list of available rooms(from hospital class), it will have two models.
It will also have a list, so we need to create an AspectAdaptor for the recordList of the patient object.


The following message uses the patient passed in and initializes the aspects of the GUI elements to match data of the model.

  patientModel: aModel
       patientModel := aModel.
	name := aModel name asValue.
	id := aModel id asValue.
	password := aModel password asValue.
	type := aModel type asValue.
	room := aModel room printString asValue.
	recordListCopy := aModel recordList copy.  "this becomes necessary after exiting the dialog, and updating the original object this Dialog is modeled after"
	recordList :=SelectionInList new.
	recordList listHolder: ((UI.AspectAdaptor subject: self sendsUpdates: true) forAspect: #recordListCopy).

It is a good idea to have a copy Collection instance in the GUI that copies the Collection instance in the model (in this case recordList).
This way when the GUI terminates and updates the actual patient it was modeling we can simply clone this copy instance and use that to set the model's instance.
And because we want our GUI to correctly reflect the recordList of our most up-to-date model, we want to set the AspectAdaptor to the copy instance of the GUI class.
***Remember to use asValue and value messages when passing data to and from instance of model from and to aspects of GUI.


The following is pretty straight forward.
Now that we have a model for the hospital we can retrieve the roomList easily by using....

  hospitalModel: aModel
	hospitalModel := aModel.

this code.

  roomList
	roomList := hospitalModel roomList.
	^roomList asValue.



Following is the action #editPatient for AdminUtilDialog.
(The #editPatient is an action tied to a button of AdminUtilDialog.)

  editPatient
	| selection window |
	patientList selection ifNotNil: [             "checks if the user did select a patient"
	selection := patientList selection.
	window := PatientEditDialog new.              "creates new dialog"
	window patientModel: selection.               "sets patientModel"
	window hospitalModel: hospitalModel.	      "sets hospitalModel"
	window open ifTrue: [                         "and opens the dialog, then waits for it to close."
             "this block executes if the window was closed with a button #accept"
		selection name: window name value.             "update name of selection to new name from the Dialog"
		selection id: window id value.                 "update id of selection to new name from the Dialog"
		selection password: window password value.     "so on"
		selection type: window type value.             "so forth"
		selection room: window room value.             "and..."
		selection recordList: window recordListCopy.   "use the copy instance of the Dialog to update the recordList of selection"
	].].
	self changed: #patientList. "now send an update message to the patientList of AdminUtilDialog so that it can update itself"

Pressing the button will create a PatientEditDialog
using current hospital (which AdminUtilDialog has as a hospitalModel)
and Patient selected from the Patient List (obviously checks if nothing's selected)
each as hospitalModel and patientModel.
If "open" message of the Dialog returns True(this happens when you close a window with a button that has #accept as action),
the actual update process begins, otherwise (if the window closed with #cancel button or the close window button 'X')
do nothing.
***Remember to use asValue and value messages when passing data to and from instance of model from and to aspects of GUI.

Link to this Page