User's Guide

Implementing methods for Stopwatch

Now, you must implement one public instance method and fifteen private instance methods for Stopwatch. You can implement them in any order.

Method open

For this example, begin by implementing open, which calls methods that define the user interface:

  1. Ensure that Stopwatch is selected.
  2. Verify that the settings in the browser are for viewing private instance methods. Add the method category Startup.
  3. With Startup highlighted, select New Method Template from the Methods menu.
  4. Revise the displayed template so it includes the following:
    open
       "Public - Create and realize the receiver."
       self
          createShell;
          createWindow;
          realizeWindow.
    
  5. Save the method. If you typed in the text shown above, open is shown in the list of methods.

Now, define the private instance methods. The following two methods go into the Getters & Setters category and are used for displaying the elapsed time:

Method timeElapsedDisplay:

timeElapsedDisplay: aTextWidget
  "Private - Sets the timeElapsedDisplay for the receiver."
  timeElapsedDisplay := aTextWidget.

Method timeElapsedDisplay

timeElapsedDisplay
  "Private - Answers the timeElapsedDisplay for the receiver."
  ^timeElapsedDisplay.

The following eleven methods go into the Window Creation category:

Method createWindow

createWindow
   "Private - Create the stopwatch. The outside window is 'shell.'
    The form that manages layout of widgets is 'widgetManager.'
    The time widgets ('label' and 'timeDisplay') are on the top.
    The buttons ('startButton' and 'stopButton') are on the bottom."
   self createTopLevelShell.
   self createForm.
   self createTimeWidgets.
   self createLabel.
   self createButtons.
   self createStartButton.
   self createStopButton.
   self manageChildren.
   self timeElapsedDisplay: timeDisplay.

Method createTopLevelShell

createTopLevelShell
   "Private - Creates a window."
   shell := CwTopLevelShell
      createApplicationShell: 'shell'
      argBlock: nil.
   shell title: 'Stopwatch'.

Method createShell

createShell
   "Private - Creates a shell for aWidget."
   shell :=
      CwTopLevelShell
         appCreateShell: self class name
         applicationClass: CwAppContext defaultApplicationClass
         display: CgDisplay default
         argBlock: nil.

Method createForm

createForm
   "Private - Creates a form to hold user interface elements."
   widgetManager := shell
      createForm: 'widgetManager'
      argBlock: nil.
   widgetManager manageChild.

Method createTimeWidgets

createTimeWidgets
   "Private - Controls placement of the label and text pane."
   timeWidgets := widgetManager
      createRowColumn: 'timeWidgets'
      argBlock: [:w | w 
         orientation: XmHORIZONTAL;
         marginHeight: 20;
         marginWidth: 5;
         rightAttachment: XmATTACHFORM;
         topAttachment: XmATTACHFORM].

Method createLabel

createLabel
   "Private - Creates a label."
   label := timeWidgets
      createLabel: 'label'
      argBlock: [:w | w labelString: 'Time elapsed:'].
      timeDisplay := timeWidgets "Define a text pane."
      createText: 'timeDisplay'
         argBlock: [:w | w width: 190].
 
   timeDisplay setString: 'Hours:Minutes:Seconds'.

Method createButtons

createButtons
   "Private - Control positioning of the buttons."
   buttons := widgetManager
      createRowColumn: 'buttons'
      argBlock: [:w | w
         orientation: XmHORIZONTAL;
         spacing: 15;
         marginWidth: 12;
         topAttachment: XmATTACHWIDGET;
         topWidget: timeWidgets;
         leftAttachment: XmATTACHFORM;
         rightAttachment: XmATTACHFORM;
         bottomAttachment: XmATTACHFORM].

Method createStartButton

createStartButton
   "Private - Create the Start button."
   startButton := buttons
      createPushButton: '           Start           '
      argBlock: nil.
   startButton
      addEventHandler: ButtonReleaseMask
      receiver: self
      selector: #startButtonMotion:clientData:callData:
      clientData: startButton.

Method createStopButton

createStopButton
   "Private - Create the Stop button."
   stopButton := buttons
      createPushButton: '     Stop/Interval       '
      argBlock: nil.
   stopButton
      addEventHandler: ButtonReleaseMask
      receiver: self
      selector: #stopButtonMotion:clientData:callData:
      clientData: stopButton.

Method manageChildren

manageChildren
   "Private - Places the widgets."
   timeWidgets manageChild.
   label manageChild.
   timeDisplay manageChild.
   buttons manageChild.
   startButton manageChild.
   stopButton manageChild.

Method realizeWindow

realizeWindow
   "Private - Realizes the receiver's widget hierarchy."
   shell realizeWidget.

At this point, you can open an instance of Stopwatch by evaluating the following in a Transcript or Workspace window:

Stopwatch new open

The window should resemble the following:
Stopwatch

Note that when you select a push button, a debugger opens. To change this behavior, finish implementing the methods.The following two methods go into the category Event Handling:

Method startButtonMotion:clientData:callData:

startButtonMotion: aButton clientData: aRowColumn callData: callData
  "Private - The user pressed the Start button. Display the time elapsed."
  startTime := Time now.
  self timeElapsedDisplay
    setString: '            00:00:00'.   "12 spaces between ' and 00"

Implementing this method enables Stopwatch to display the following after you select Start:
Stopwatch

Method stopButtonMotion:clientData:callData:

stopButtonMotion: aButton clientData: aRowColumn callData: callData
  "Private - End timing. Subtract the ending time from the
  starting time to determine the time elapsed."
  | elapsedTime |
  startTime == nil ifTrue: [ ^self ].
  elapsedTime := self calculateTime:
    (Time fromSeconds:
      ( (Time now asSeconds) - startTime asSeconds )).
  self timeElapsedDisplay
    setString: '            ', ((elapsedTime printString) "12 before ,"
    copyFrom: 2 to: 9).

Method calculateTime:

Finally, implement calculateTime: in the category Time Operations:

calculateTime: time
  "Private - Answer the time elapsed in a format that
  displays Hours:Minutes:Seconds."
  | answer |
  answer := WriteStream on: (String new: 8).
  time hours < 10 ifTrue: [answer nextPut: $0].
  time hours printOn: answer.
  answer nextPut: $:.
  time minutes < 10 ifTrue: [answer nextPut: $0].
  time minutes printOn: answer.
  answer nextPut: $:.
  time seconds < 10 ifTrue: [answer nextPut: $0].
  time seconds printOn: answer.
  ^answer contents


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]