User's Guide

Implementing the private instance methods

TextEditor has 49 private instance methods. Fortunately, many of the methods have only a few lines of code. Though you can implement them in any order, begin with getter and setter methods.

Private methods for category Getters & Setters

Method fileName

fileName
   "Private - Answers the value of fileName."
   ^fileName

Method fileName:

fileName: value
   "Private - Sets the value of fileName."
   fileName := value.

Method mainWindow

mainWindow
   "Private - Answers the value for mainWindow."
   ^mainWindow

Method modified

modified
   "Private - Answers the value for modified."
   ^modified

Method popup

popup
   "Private - Answers the value for popup."
   ^popup

Method shell

shell
   "Private - Answers the value for shell."
   ^shell

Method text

text
	"Private - Answers the receiver's text widget."
   ^text

Method workRegion:

workRegion: aWidget
   "Private - Sets the work region to aWidget."
   workRegion := aWidget

Private methods for category Initialization & Startup

Method initialize

initialize
   "Private - Initializes the receiver."
   modified := false.   "Text has not changed since last save."

Private methods for category Window Creation

Method createWindow

createWindow
   "Private - Creates a window for the text editor."
   self
      createMainWindow;
      createMenuBar;
      createWorkRegion;
      createPulldownMenus.
   self createTopLevelShell.
   self createPopupMenu.
   self addPopupMenu.

Method createMainWindow

createMainWindow
   "Private - Creates a window."
   mainWindow :=
      CwMainWindow
         createWidget: 'mainWindow'
         parent: self shell
         argBlock: nil

Method createTopLevelShell

createTopLevelShell
   "Private - Creates a form to hold user interface elements."
   self shell width: 600; height: 400.
   self shell
      addCallback: XmNwindowCloseCallback
      receiver: self
      selector: #windowClose:clientData:callData:
      clientData: nil.

Method createShell

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

Method createMenuBar

createMenuBar
   "Private - Creates a menu bar for the window."
   menuBar :=
      (mainWindow
         createMenuBar: 'menuBar'
         argBlock: nil) manageChild

Method createWorkRegion

createWorkRegion
   "Private - Creates a work region."
   (text := self mainWindow createScrolledText: 'text' argBlock: [:w | w
      editMode: XmMULTILINEEDIT])
   manageChild.
   self workRegion: self text parent.
   self addValueChangedCallback.

Method createPulldownMenus

createPulldownMenus
   "Private - Creates pulldown menus."
   self createFileMenu.
   self createEditMenuForTextWidget: self text.

Method addPulldownMenu:

addPulldownMenu: label
   "Private - Adds a pulldown menu to the menu bar."
   ^self addMenuTo: menuBar label: label

Method addMenuTo:label:

addMenuTo: aParent label: labelString
   "Private - Adds a menu."
   | rowColumn labelButton |
   rowColumn := aParent
      createPulldownMenu: 'RowColumn',labelString
      argBlock: nil.
   labelButton := aParent
      createCascadeButton: labelString
      argBlock: nil.
   labelButton
      subMenuId: rowColumn;
      manageChild.
   ^labelButton

Method addMenuEntryTo:label:selector:

addMenuEntryTo: aParent label: aLabel selector: aSelector
   "Private - Adds a menu choice to a menu."
   ^self
      addMenuEntryTo: aParent
      label: aLabel
      selector: aSelector
      clientData: nil

Method addMenuEntryTo:label:selector:clientData:

addMenuEntryTo: aParent label: aLabel selector: aSelector clientData: clientData
   "Private - Creates a push button with name aLabel, parent aParent, 
    callback aSelector, and nil as the client data for the callback. 
    Manages the resulting widget."
   | aButton |
   aButton := CwPushButton
      createManagedWidget: aLabel
      parent: aParent
      argBlock: nil.
   aButton
      addCallback: XmNactivateCallback
      receiver: self
      selector: aSelector
      clientData: clientData;
      labelString: aLabel.
   ^aButton

Method createEditMenuForTextWidget:

createEditMenuForTextWidget: aTextWidget
   "Private - Creates an Edit menu."
   | aMenu |
   aMenu := (self addMenuTo: menuBar label: 'Edit') subMenuId.
   self addMenuEntryTo: aMenu
      label: 'Copy'
      selector: #copySelection:clientData:callData:
      clientData: aTextWidget.
   self addMenuEntryTo: aMenu
      label: 'Cut'
      selector: #cutSelection:clientData:callData:
      clientData: aTextWidget.
   self addMenuEntryTo: aMenu
      label: 'Paste'
      selector: #pasteSelection:clientData:callData:
      clientData: aTextWidget.
   ^aMenu

Method createFileMenu

createFileMenu
   "Private - Creates a File menu. Answers the pulldown menu."
   | fileMenu |
   fileMenu := (self addPulldownMenu: 'File') subMenuId.
   (self
      addMenuEntryTo: fileMenu
      label: 'New Workspace'
      selector: #newWorkspace:clientData:callData:)
         accelerator: (CwAccelerator mask: ControlMask keysym: XKn);
         acceleratorText: 'Ctrl+N'.
   (self
      addMenuEntryTo: fileMenu
      label: 'Open...'
      selector: #open:clientData:callData:)
         accelerator: (CwAccelerator mask: ControlMask keysym: XKo);
         acceleratorText: 'Ctrl+O'.
   (fileMenu
      createSeparator: '-' argBlock: nil)
      manageChild.
   (self
      addMenuEntryTo: fileMenu
      label: 'Save' selector: #accept:clientData:callData:)
         accelerator: (CwAccelerator mask: ControlMask keysym: XKs);
         acceleratorText: 'Ctrl+S'.
   self addMenuEntryTo: fileMenu label: 'Save As...'
      selector: #saveAs:clientData:callData:.
   (self
      addMenuEntryTo: fileMenu
      label: 'Undo'
      selector: #undo:clientData:callData:)
         accelerator: (CwAccelerator mask: ControlMask keysym: XKr);
         acceleratorText: 'Ctrl+R'.
   (fileMenu
      createSeparator: '-' argBlock: nil)
      manageChild.
   (self
      addMenuEntryTo: fileMenu
      label: 'Exit'
      selector: #windowClose:clientData:callData:)
         accelerator: (CwAccelerator mask: ControlMask keysym: XKq);
         acceleratorText: 'Ctrl+Q'.
   ^fileMenu

Method createPopupMenu

createPopupMenu
   "Private - Calls methods which define choices in the popup menu."
   | clientData |
   popup := self text
      createPopupMenu: 'popup'
      argBlock: nil.
   clientData := Array with: self text with: [self].
   self createPopupUndo.
   self createPopupCopy.
   self createPopupCut.
   self createPopupPaste.
   self createPopupSave.

Method addPopupMenu

addPopupMenu
   "Private - Creates a popup menu."
   self text
      addEventHandler: ButtonMenuMask
      receiver: self
      selector: #popup:clientData:callData:
      clientData: self popup.

Method createPopupCopy

createPopupCopy
   "Private - Creates a Copy menu choice."
   | button |
   button := popup createPushButton: 'Copy' argBlock: nil.
   button
      addCallback: XmNactivateCallback
      receiver: self
      selector: #copySelection:clientData:callData:
      clientData: self text;
   manageChild.

Method createPopupCut

createPopupCut
   "Private - Creates a Cut menu choice."
   | button |
   button := popup createPushButton: 'Cut' argBlock: nil.
   button
      addCallback: XmNactivateCallback
      receiver: self
      selector: #cutSelection:clientData:callData:
      clientData: self text;
   manageChild.

Method createPopupPaste

createPopupPaste
   "Private - Creates a Paste menu choice."
   | button |
   button := popup createPushButton: 'Paste' argBlock: nil.
   button
      addCallback: XmNactivateCallback
      receiver: self
      selector: #pasteSelection:clientData:callData:
      clientData: self text;
   manageChild.
 
   (popup
      createSeparator: '-' argBlock: nil)
      manageChild.

Method createPopupSave

createPopupSave
   "Private - Creates a Save menu choice."
   | button |
   button := popup createPushButton: 'Save' argBlock: nil.
   button
      addCallback: XmNactivateCallback
      receiver: self
      selector: #accept:clientData:callData:
      clientData: self text;
   manageChild.

Method createPopupUndo

createPopupUndo
   "Private - Creates an Undo menu choice."
   | button |
   button := popup	createPushButton: 'Undo' argBlock: nil.
   button
      addCallback: XmNactivateCallback
      receiver: self
      selector: #undo:clientData:callData:
      clientData: self text;
   manageChild.
 
   (popup 
      createSeparator: '-' argBlock: nil)
   manageChild.

Method realizeWindow

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

Private methods for category Event Handlers

Method accept:clientData:callData:

accept: w clientData: clientData callData: callData
  "Private - Calls methods that save the text."
  fileName isNil
    ifTrue: [self saveAs: w clientData: clientData callData: callData]
    ifFalse: [
      self
        writeFileName: fileName;
        removeValueChangedCallback;
        addValueChangedCallback].

Method addValueChangedCallback

addValueChangedCallback
  "Private - Adds the valueChangedCallback and clears the modified flag."
  self text
    addCallback: XmNvalueChangedCallback
    receiver: self
    selector: #valueChanged:clientData:callData:
    clientData: nil.
  modified := false.

Method copySelection:clientData:callData:

copySelection: aButton clientData: aTextWidget callData: callData
   "Private - Marks selected text for copying."
   ^aTextWidget copySelection

Method cutSelection:clientData:callData:

cutSelection: aButton clientData: aTextWidget callData: callData
   "Private - Marks selected text for cut operation."
   ^aTextWidget cutSelection

Method newWorkspace:clientData:callData:

newWorkspace: w clientData: ignore1 callData: ignore2
  "Private - Opens a second instance of the text editor."
  self class new open.

Method open:clientData:callData:

open: w clientData: ignored1 callData: ignored2
  "Private - Processes the open callback from the file menu."
  | name |
  (name :=
    (CwFileSelectionPrompter for: self shell)
      title: 'Open File';
      prompt) isNil
    ifTrue: [^self].
  self removeValueChangedCallback.
  self readFileName: name.
  self addValueChangedCallback.
  self updateTitle.

Method pasteSelection:clientData:callData:

pasteSelection: aButton clientData: aTextWidget callData: callData
   "Private - Pastes text in the clipboard."
   ^aTextWidget paste

Method popup:clientData:callData:

popup: label clientData: aMenu callData: event
  "Private - Pops up a menu under the cursor."
  event button = 3 ifFalse: [^self].
  aMenu
    menuPosition: event;
    manageChild

Method removeValueChangedCallback

removeValueChangedCallback
  "Private - Removes the valueChangedCallback."
  self text
    removeCallback: XmNvalueChangedCallback
    receiver: self
    selector: #valueChanged:clientData:callData:
    clientData: nil.

Method saveAs:clientData:callData:

saveAs: w clientData: clientData callData: callData
  "Private - Processes the saveAs callback from the file menu."
  | name |
  (name :=
    (CwFileSelectionPrompter for: self shell)
      title: 'Save As';
      prompt) isNil
         ifTrue: [^self].
  self writeFileName: name.
  self
    removeValueChangedCallback;
    addValueChangedCallback.
    self updateTitle.

Method undo:clientData:callData:

undo: widget clientData: clientData callData: callData
  "Private - Processes the undo callback from the file menu. Re-reads the
   contents of the last opened or saved file into the workspace."
  self removeValueChangedCallback.
  fileName isNil
    ifTrue: [self text setString: '']
    ifFalse: [
      self readFileName: fileName].
  self addValueChangedCallback.

Method updateTitle

updateTitle
  "Private - Updates the window title."
  (fileName isNil or: [fileName = ''])
     ifTrue: [^self shell title: self class printString].
  self shell title: fileName

Method valueChanged:clientData:callData:

valueChanged: w clientData: ignore1 callData: ignore2
  "Private - Processes the valueChangedCallback from the text widget.
   Sets the modified flag to true and removes the callback."
  modified := true.
  self removeValueChangedCallback.

Method windowClose:clientData:callData:

windowClose: w clientData: clientData callData: callData
   "Private - Process the exit callback from the file menu. If the text
    has changed since the last save, prompt for the Save As dialog."
   self modified 
      ifTrue: [
         ((CwMessagePrompter for: self shell)
            iconType: XmICONQUESTION;
            buttonType: XmYESNO;
            messageString: 'Text has been modified - discard changes?';
            prompt) = true
               ifFalse: [self saveAs: w clientData: clientData callData: callData].
   ].
   self shell unmapWidget

Private methods for category File Operations

Method readFileName:

readFileName: name
  "Private - Reads the contents of the specified file into the workspace."
  | size file string result |
  file := CfsFileDescriptor open: name oflag: ORDONLY.
  file isCfsError
     ifTrue: [
       ^(CwMessagePrompter for: self shell)
         iconType: XmICONERROR;
         messageString: file printString;
         prompt
      ].
  (size := file size) >= self text maxLength
     ifTrue: [
        file close.
        ^(CwMessagePrompter for: self shell)
           iconType: XmICONERROR;
           messageString: 'File size (',size printString,') is greater
than Text widget maxLength (',
           self text maxLength printString,')' ;
           prompt
        ].
 
  self showFontCursor: XCWatch in: self shell window while: [
    string := String new: file size.
    result := file read: string startingAt: 1 nbyte: file size.
    ].
  result isCfsError
     ifTrue: [
        file close.
        ^(CwMessagePrompter for: self shell)
           iconType: XmICONERROR;
           messageString: result printString;
           prompt
        ].
 
  self showFontCursor: XCWatch in: self shell window while: [
     self text setString: string.
  ].
  fileName := name.
  file close.

Method showCursor:in:while:

showCursor: cursor in: aCgWindow while: aBlock
   "Private - shows cursor."
   | result |
   aCgWindow defineCursor: cursor.
   result := aBlock value.
   aCgWindow undefineCursor.
   ^result

Method showFontCursor:in:while:

showFontCursor: anInteger in: aCgWindow while: aBlock
   "Private - Shows cursor."
   | cursor |
   cursor := self display createFontCursor: anInteger.
   self showCursor: cursor in: aCgWindow while: aBlock.
   cursor freeCursor

Method writeFileName:

writeFileName: name
  "Private - Writes the contents of the workspace to the specified file."
  | file string result |
  file := CfsFileDescriptor open: name oflag: OCREAT | OTRUNC | OWRONLY.
  file isCfsError
     ifTrue: [
        ^(CwMessagePrompter for: self shell)
          iconType: XmICONERROR;
          messageString: file printString;
          prompt
        ].
  self showFontCursor: XCWatch in: self shell window while: [
     string := self text getString.
     result := file write: string startingAt: 1 nbyte: string size.
     ].
  result isCfsError
     ifTrue: [
        file close.
        ^(CwMessagePrompter for: self shell)
           iconType: XmICONERROR;
           messageString: result printString;
           prompt
        ].
  fileName := name.
  file close.

Now that you have all of the methods implemented for TextEditor, try opening an instance of the class using DevelopChooser or by evaluating:

TextEditor new open

The finished window resembles the following:
Text Editor


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