home *** CD-ROM | disk | FTP | other *** search
/ BURKS 2 / BURKS_AUG97.ISO / BURKS / LANGUAGE / SMALTALK / TEXTBOOK / AP21.ST (.txt) < prev    next >
Text File  |  1997-04-22  |  16KB  |  683 lines

  1.  
  2. 'Smalltalk Textbook Appendix 21'!
  3.  
  4.  
  5.  
  6.  
  7.  
  8. View subclass: #EngiCalculatorView
  9.     instanceVariableNames: ''
  10.     classVariableNames: ''
  11.     poolDictionaries: ''
  12.     category: 'Engi-Calculator'!
  13. EngiCalculatorView comment:
  14. '
  15.  
  16. Engi 0.06 (19 March 1994)
  17. Copyright (C) 1994 by Atsushi Aoki
  18.  
  19. '!
  20.  
  21.  
  22. !EngiCalculatorView methodsFor: 'controller accessing'!
  23.  
  24. defaultControllerClass
  25.     ^EngiCalculatorController! !
  26.  
  27. !EngiCalculatorView methodsFor: 'displaying'!
  28.  
  29. displayOn: aGraphicsContext 
  30.     self model buttonImage displayOn: aGraphicsContext! !
  31.  
  32. !EngiCalculatorView methodsFor: 'updating'!
  33.  
  34. update: parameter 
  35.     ^self! !
  36. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  37.  
  38. EngiCalculatorView class
  39.     instanceVariableNames: ''!
  40.  
  41.  
  42. !EngiCalculatorView class methodsFor: 'instance creation'!
  43.  
  44. openOn: calculatorModel 
  45.     | calculatorView borderedWrapper compositePart layoutFrame calculatorDisplay edgeDecorator openRectangle topWindow |
  46.     calculatorView := self model: calculatorModel.
  47.     borderedWrapper := BorderedWrapper
  48.                 on: calculatorView
  49.                 in: (0 @ 0 corner: 1 @ 1)
  50.                 border: (Border width: 0).
  51.     compositePart := CompositePart new.
  52.     layoutFrame := LayoutFrame
  53.                 leftFraction: 0
  54.                 offset: 0
  55.                 rightFraction: 1
  56.                 offset: 0
  57.                 topFraction: 0
  58.                 offset: 30
  59.                 bottomFraction: 1
  60.                 offset: 0.
  61.     compositePart add: borderedWrapper in: layoutFrame.
  62.     calculatorDisplay := EngiCalculatorDisplay model: calculatorModel.
  63.     edgeDecorator := LookPreferences edgeDecorator on: calculatorDisplay.
  64.     edgeDecorator noMenuBar.
  65.     edgeDecorator noVerticalScrollBar.
  66.     edgeDecorator noHorizontalScrollBar.
  67.     layoutFrame := LayoutFrame
  68.                 leftFraction: 0
  69.                 offset: 0
  70.                 rightFraction: 1
  71.                 offset: 0
  72.                 topFraction: 0
  73.                 offset: 0
  74.                 bottomFraction: 0
  75.                 offset: 30.
  76.     compositePart add: edgeDecorator in: layoutFrame.
  77.     openRectangle := Point zero extent: calculatorModel buttonImage extent + (0 @ 30).
  78.     openRectangle := openRectangle expandedBy: 1.
  79.     topWindow := ScheduledWindow
  80.                 model: nil
  81.                 label: 'Calculator'
  82.                 minimumSize: openRectangle extent.
  83.     topWindow maximumSize: openRectangle extent.
  84.     topWindow component: compositePart.
  85.     topWindow open! !
  86.  
  87.  
  88.  
  89.  
  90.  
  91. View subclass: #EngiCalculatorDisplay
  92.     instanceVariableNames: ''
  93.     classVariableNames: ''
  94.     poolDictionaries: ''
  95.     category: 'Engi-Calculator'!
  96. EngiCalculatorDisplay comment:
  97. '
  98.  
  99. Engi 0.06 (19 March 1994)
  100. Copyright (C) 1994 by Atsushi Aoki
  101.  
  102. '!
  103.  
  104.  
  105. !EngiCalculatorDisplay methodsFor: 'displaying'!
  106.  
  107. displayOn: aGraphicsContext 
  108.     | string |
  109.     self model contents size = 0
  110.         ifTrue: [string := self model topString]
  111.         ifFalse: [string := self model contents].
  112.     self displayOn: aGraphicsContext value: string!
  113.  
  114. displayOn: aGraphicsContext value: aString 
  115.     | bounds para1 box1 para2 box2 |
  116.     bounds := self bounds.
  117.     aString isEmpty
  118.         ifTrue: [para1 := '0' asComposedText]
  119.         ifFalse: [para1 := aString asComposedText].
  120.     box1 := para1 bounds.
  121.     box1 := box1 align: box1 rightCenter with: bounds rightCenter.
  122.     box1 := box1 translatedBy: -10 @ 0.
  123.     self model memory = 0
  124.         ifTrue: [para2 := ' ' asComposedText]
  125.         ifFalse: [para2 := 'M' asComposedText].
  126.     box2 := para2 bounds.
  127.     box2 := box2 align: box2 leftCenter with: bounds leftCenter.
  128.     box2 := box2 translatedBy: 10 @ 0.
  129.     (box1 intersects: box2)
  130.         ifTrue: [^self model error].
  131.     para1 displayOn: aGraphicsContext at: box1 origin.
  132.     para2 displayOn: aGraphicsContext at: box2 origin! !
  133.  
  134. !EngiCalculatorDisplay methodsFor: 'updating'!
  135.  
  136. update: parameter 
  137.     parameter = #value
  138.         ifTrue: 
  139.             [self clearInside.
  140.             ^self displayOn: self graphicsContext].
  141.     ((parameter isKindOf: Association)
  142.         and: [parameter key = #value])
  143.         ifTrue: 
  144.             [self clearInside.
  145.             ^self displayOn: self graphicsContext value: parameter value]! !
  146.  
  147.  
  148.  
  149.  
  150.  
  151. ControllerWithMenu subclass: #EngiCalculatorController
  152.     instanceVariableNames: ''
  153.     classVariableNames: ''
  154.     poolDictionaries: ''
  155.     category: 'Engi-Calculator'!
  156. EngiCalculatorController comment:
  157. '
  158.  
  159. Engi 0.06 (19 March 1994)
  160. Copyright (C) 1994 by Atsushi Aoki
  161.  
  162. '!
  163.  
  164.  
  165. !EngiCalculatorController methodsFor: 'control defaults'!
  166.  
  167. redButtonActivity
  168.     | aPoint aRect rect gc |
  169.     aPoint := self sensor cursorPoint.
  170.     aPoint := self model whichButton: aPoint.
  171.     aPoint isNil ifTrue: [^nil].
  172.     aRect := self model buttonMapAt: aPoint.
  173.     gc := self view graphicsContext.
  174.     rect := aRect insetBy: (0 @ 0 corner: 1 @ 1).
  175.     gc paint: (ColorValue brightness: 0.75).
  176.     gc displayLineFrom: rect bottomLeft to: rect bottomRight.
  177.     gc displayLineFrom: rect topRight to: rect bottomRight.
  178.     gc paint: (ColorValue brightness: 0.25).
  179.     gc displayLineFrom: rect topLeft to: rect topRight.
  180.     gc displayLineFrom: rect topLeft to: rect bottomLeft.
  181.     [self sensor redButtonPressed and: [aRect containsPoint: self sensor cursorPoint]] whileTrue.
  182.     self view invalidateRectangle: aRect repairNow: true.
  183.     self model buttonAction: aPoint! !
  184.  
  185.  
  186.  
  187.  
  188.  
  189. Model subclass: #EngiCalculatorModel
  190.     instanceVariableNames: 'stack stream operator memory '
  191.     classVariableNames: 'ButtonImage ButtonMap ButtonTable '
  192.     poolDictionaries: ''
  193.     category: 'Engi-Calculator'!
  194. EngiCalculatorModel comment:
  195. '
  196.  
  197. Engi 0.06 (19 March 1994)
  198. Copyright (C) 1994 by Atsushi Aoki
  199.  
  200. '!
  201.  
  202.  
  203. !EngiCalculatorModel methodsFor: 'initialize-release'!
  204.  
  205. initialize
  206.     self resetCalculator.
  207.     self memoryClear.
  208.     ^self! !
  209.  
  210. !EngiCalculatorModel methodsFor: 'accessing'!
  211.  
  212. buttonImage
  213.     ^ButtonImage!
  214.  
  215. contents
  216.     ^stream contents!
  217.  
  218. contents: aString 
  219.     stream := ReadStream on: aString! !
  220.  
  221. !EngiCalculatorModel methodsFor: 'testing'!
  222.  
  223. isClearButton: aPoint 
  224.     | kind |
  225.     kind := self buttonTableAt: aPoint.
  226.     ^kind = 'AC' or: [kind = 'C']!
  227.  
  228. isMemoryButton: aPoint 
  229.     | kind |
  230.     kind := self buttonTableAt: aPoint.
  231.     ^kind = 'MC' or: [kind = 'MR' or: [kind = 'M+' or: [kind = 'M-']]]!
  232.  
  233. isNumberButton: aPoint 
  234.     | kind |
  235.     kind := self buttonTableAt: aPoint.
  236.     ^kind isKindOf: Number!
  237.  
  238. isOperatorButton: aPoint 
  239.     | kind |
  240.     kind := self buttonTableAt: aPoint.
  241.     ^kind isKindOf: Symbol!
  242.  
  243. isSpecialButton: aPoint 
  244.     | kind |
  245.     kind := self buttonTableAt: aPoint.
  246.     ^kind = '.'!
  247.  
  248. isUnaryButton: aPoint 
  249.     | kind |
  250.     kind := self buttonTableAt: aPoint.
  251.     ^kind = 'r' or: [kind = '+-' or: [kind = '=']]! !
  252.  
  253. !EngiCalculatorModel methodsFor: 'evaluating'!
  254.  
  255. evaluate
  256.     | a b |
  257.     b := self pop.
  258.     stack isEmpty
  259.         ifTrue: 
  260.             [self push: b.
  261.             ^true].
  262.     a := self pop.
  263.     self operator isNil
  264.         ifTrue: 
  265.             [self push: b.
  266.             ^true].
  267.     self operator = #add
  268.         ifTrue: 
  269.             [self push: a + b.
  270.             ^true].
  271.     self operator = #sub
  272.         ifTrue: 
  273.             [self push: a - b.
  274.             ^true].
  275.     self operator = #mlt
  276.         ifTrue: 
  277.             [self push: a * b.
  278.             ^true].
  279.     self operator = #div
  280.         ifTrue: 
  281.             [b abs = 0 ifTrue: [^false].
  282.             self push: a / b.
  283.             ^true].
  284.     ^false! !
  285.  
  286. !EngiCalculatorModel methodsFor: 'button accessing'!
  287.  
  288. buttonMapAt: aPoint 
  289.     | point |
  290.     ButtonMap
  291.         do: 
  292.             [:assoc | 
  293.             point := assoc value.
  294.             point = aPoint ifTrue: [^assoc key]].
  295.     ^nil!
  296.  
  297. buttonTableAt: aPoint 
  298.     | point |
  299.     ButtonTable
  300.         do: 
  301.             [:assoc | 
  302.             point := assoc key key.
  303.             point = aPoint ifTrue: [^assoc key value]].
  304.     ^nil!
  305.  
  306. whichButton: aPoint 
  307.     | area |
  308.     ButtonMap
  309.         do: 
  310.             [:assoc | 
  311.             area := assoc key.
  312.             (area containsPoint: aPoint)
  313.                 ifTrue: [^assoc value]].
  314.     ^nil! !
  315.  
  316. !EngiCalculatorModel methodsFor: 'stack accessing'!
  317.  
  318. pop
  319.     stack isEmpty ifTrue: [^0].
  320.     ^stack removeLast!
  321.  
  322. push
  323.     self push: (Number readFrom: stream)!
  324.  
  325. push: aNumber 
  326.     stack addLast: aNumber!
  327.  
  328. stack
  329.     ^stack!
  330.  
  331. top
  332.     | top |
  333.     top := self pop.
  334.     self push: top.
  335.     ^top!
  336.  
  337. topString
  338.     | top |
  339.     top := self top.
  340.     (top isKindOf: Fraction)
  341.         ifTrue: [^top asFloat printString].
  342.     ^top printString! !
  343.  
  344. !EngiCalculatorModel methodsFor: 'operator accessing'!
  345.  
  346. operator
  347.     ^operator!
  348.  
  349. operator: aSymbol 
  350.     operator := aSymbol! !
  351.  
  352. !EngiCalculatorModel methodsFor: 'memory accessing'!
  353.  
  354. memory
  355.     ^memory!
  356.  
  357. memory: aNumber 
  358.     memory := aNumber!
  359.  
  360. memoryClear
  361.     memory := 0! !
  362.  
  363. !EngiCalculatorModel methodsFor: 'button actions'!
  364.  
  365. buttonAction: aPoint 
  366.     (self isNumberButton: aPoint)
  367.         ifTrue: [^self numberAction: aPoint].
  368.     (self isOperatorButton: aPoint)
  369.         ifTrue: [^self operatorAction: aPoint].
  370.     (self isUnaryButton: aPoint)
  371.         ifTrue: [^self unaryAction: aPoint].
  372.     (self isClearButton: aPoint)
  373.         ifTrue: [^self clearAction: aPoint].
  374.     (self isSpecialButton: aPoint)
  375.         ifTrue: [^self specialAction: aPoint].
  376.     (self isMemoryButton: a