home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BURKS 2
/
BURKS_AUG97.ISO
/
BURKS
/
LANGUAGE
/
SMALTALK
/
TEXTBOOK
/
AP21.ST
(
.txt
)
< prev
next >
Wrap
Text File
|
1997-04-22
|
16KB
|
683 lines
'Smalltalk Textbook Appendix 21'!
View subclass: #EngiCalculatorView
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Engi-Calculator'!
EngiCalculatorView comment:
'
Engi 0.06 (19 March 1994)
Copyright (C) 1994 by Atsushi Aoki
'!
!EngiCalculatorView methodsFor: 'controller accessing'!
defaultControllerClass
^EngiCalculatorController! !
!EngiCalculatorView methodsFor: 'displaying'!
displayOn: aGraphicsContext
self model buttonImage displayOn: aGraphicsContext! !
!EngiCalculatorView methodsFor: 'updating'!
update: parameter
^self! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
EngiCalculatorView class
instanceVariableNames: ''!
!EngiCalculatorView class methodsFor: 'instance creation'!
openOn: calculatorModel
| calculatorView borderedWrapper compositePart layoutFrame calculatorDisplay edgeDecorator openRectangle topWindow |
calculatorView := self model: calculatorModel.
borderedWrapper := BorderedWrapper
on: calculatorView
in: (0 @ 0 corner: 1 @ 1)
border: (Border width: 0).
compositePart := CompositePart new.
layoutFrame := LayoutFrame
leftFraction: 0
offset: 0
rightFraction: 1
offset: 0
topFraction: 0
offset: 30
bottomFraction: 1
offset: 0.
compositePart add: borderedWrapper in: layoutFrame.
calculatorDisplay := EngiCalculatorDisplay model: calculatorModel.
edgeDecorator := LookPreferences edgeDecorator on: calculatorDisplay.
edgeDecorator noMenuBar.
edgeDecorator noVerticalScrollBar.
edgeDecorator noHorizontalScrollBar.
layoutFrame := LayoutFrame
leftFraction: 0
offset: 0
rightFraction: 1
offset: 0
topFraction: 0
offset: 0
bottomFraction: 0
offset: 30.
compositePart add: edgeDecorator in: layoutFrame.
openRectangle := Point zero extent: calculatorModel buttonImage extent + (0 @ 30).
openRectangle := openRectangle expandedBy: 1.
topWindow := ScheduledWindow
model: nil
label: 'Calculator'
minimumSize: openRectangle extent.
topWindow maximumSize: openRectangle extent.
topWindow component: compositePart.
topWindow open! !
View subclass: #EngiCalculatorDisplay
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Engi-Calculator'!
EngiCalculatorDisplay comment:
'
Engi 0.06 (19 March 1994)
Copyright (C) 1994 by Atsushi Aoki
'!
!EngiCalculatorDisplay methodsFor: 'displaying'!
displayOn: aGraphicsContext
| string |
self model contents size = 0
ifTrue: [string := self model topString]
ifFalse: [string := self model contents].
self displayOn: aGraphicsContext value: string!
displayOn: aGraphicsContext value: aString
| bounds para1 box1 para2 box2 |
bounds := self bounds.
aString isEmpty
ifTrue: [para1 := '0' asComposedText]
ifFalse: [para1 := aString asComposedText].
box1 := para1 bounds.
box1 := box1 align: box1 rightCenter with: bounds rightCenter.
box1 := box1 translatedBy: -10 @ 0.
self model memory = 0
ifTrue: [para2 := ' ' asComposedText]
ifFalse: [para2 := 'M' asComposedText].
box2 := para2 bounds.
box2 := box2 align: box2 leftCenter with: bounds leftCenter.
box2 := box2 translatedBy: 10 @ 0.
(box1 intersects: box2)
ifTrue: [^self model error].
para1 displayOn: aGraphicsContext at: box1 origin.
para2 displayOn: aGraphicsContext at: box2 origin! !
!EngiCalculatorDisplay methodsFor: 'updating'!
update: parameter
parameter = #value
ifTrue:
[self clearInside.
^self displayOn: self graphicsContext].
((parameter isKindOf: Association)
and: [parameter key = #value])
ifTrue:
[self clearInside.
^self displayOn: self graphicsContext value: parameter value]! !
ControllerWithMenu subclass: #EngiCalculatorController
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Engi-Calculator'!
EngiCalculatorController comment:
'
Engi 0.06 (19 March 1994)
Copyright (C) 1994 by Atsushi Aoki
'!
!EngiCalculatorController methodsFor: 'control defaults'!
redButtonActivity
| aPoint aRect rect gc |
aPoint := self sensor cursorPoint.
aPoint := self model whichButton: aPoint.
aPoint isNil ifTrue: [^nil].
aRect := self model buttonMapAt: aPoint.
gc := self view graphicsContext.
rect := aRect insetBy: (0 @ 0 corner: 1 @ 1).
gc paint: (ColorValue brightness: 0.75).
gc displayLineFrom: rect bottomLeft to: rect bottomRight.
gc displayLineFrom: rect topRight to: rect bottomRight.
gc paint: (ColorValue brightness: 0.25).
gc displayLineFrom: rect topLeft to: rect topRight.
gc displayLineFrom: rect topLeft to: rect bottomLeft.
[self sensor redButtonPressed and: [aRect containsPoint: self sensor cursorPoint]] whileTrue.
self view invalidateRectangle: aRect repairNow: true.
self model buttonAction: aPoint! !
Model subclass: #EngiCalculatorModel
instanceVariableNames: 'stack stream operator memory '
classVariableNames: 'ButtonImage ButtonMap ButtonTable '
poolDictionaries: ''
category: 'Engi-Calculator'!
EngiCalculatorModel comment:
'
Engi 0.06 (19 March 1994)
Copyright (C) 1994 by Atsushi Aoki
'!
!EngiCalculatorModel methodsFor: 'initialize-release'!
initialize
self resetCalculator.
self memoryClear.
^self! !
!EngiCalculatorModel methodsFor: 'accessing'!
buttonImage
^ButtonImage!
contents
^stream contents!
contents: aString
stream := ReadStream on: aString! !
!EngiCalculatorModel methodsFor: 'testing'!
isClearButton: aPoint
| kind |
kind := self buttonTableAt: aPoint.
^kind = 'AC' or: [kind = 'C']!
isMemoryButton: aPoint
| kind |
kind := self buttonTableAt: aPoint.
^kind = 'MC' or: [kind = 'MR' or: [kind = 'M+' or: [kind = 'M-']]]!
isNumberButton: aPoint
| kind |
kind := self buttonTableAt: aPoint.
^kind isKindOf: Number!
isOperatorButton: aPoint
| kind |
kind := self buttonTableAt: aPoint.
^kind isKindOf: Symbol!
isSpecialButton: aPoint
| kind |
kind := self buttonTableAt: aPoint.
^kind = '.'!
isUnaryButton: aPoint
| kind |
kind := self buttonTableAt: aPoint.
^kind = 'r' or: [kind = '+-' or: [kind = '=']]! !
!EngiCalculatorModel methodsFor: 'evaluating'!
evaluate
| a b |
b := self pop.
stack isEmpty
ifTrue:
[self push: b.
^true].
a := self pop.
self operator isNil
ifTrue:
[self push: b.
^true].
self operator = #add
ifTrue:
[self push: a + b.
^true].
self operator = #sub
ifTrue:
[self push: a - b.
^true].
self operator = #mlt
ifTrue:
[self push: a * b.
^true].
self operator = #div
ifTrue:
[b abs = 0 ifTrue: [^false].
self push: a / b.
^true].
^false! !
!EngiCalculatorModel methodsFor: 'button accessing'!
buttonMapAt: aPoint
| point |
ButtonMap
do:
[:assoc |
point := assoc value.
point = aPoint ifTrue: [^assoc key]].
^nil!
buttonTableAt: aPoint
| point |
ButtonTable
do:
[:assoc |
point := assoc key key.
point = aPoint ifTrue: [^assoc key value]].
^nil!
whichButton: aPoint
| area |
ButtonMap
do:
[:assoc |
area := assoc key.
(area containsPoint: aPoint)
ifTrue: [^assoc value]].
^nil! !
!EngiCalculatorModel methodsFor: 'stack accessing'!
pop
stack isEmpty ifTrue: [^0].
^stack removeLast!
push
self push: (Number readFrom: stream)!
push: aNumber
stack addLast: aNumber!
stack
^stack!
top
| top |
top := self pop.
self push: top.
^top!
topString
| top |
top := self top.
(top isKindOf: Fraction)
ifTrue: [^top asFloat printString].
^top printString! !
!EngiCalculatorModel methodsFor: 'operator accessing'!
operator
^operator!
operator: aSymbol
operator := aSymbol! !
!EngiCalculatorModel methodsFor: 'memory accessing'!
memory
^memory!
memory: aNumber
memory := aNumber!
memoryClear
memory := 0! !
!EngiCalculatorModel methodsFor: 'button actions'!
buttonAction: aPoint
(self isNumberButton: aPoint)
ifTrue: [^self numberAction: aPoint].
(self isOperatorButton: aPoint)
ifTrue: [^self operatorAction: aPoint].
(self isUnaryButton: aPoint)
ifTrue: [^self unaryAction: aPoint].
(self isClearButton: aPoint)
ifTrue: [^self clearAction: aPoint].
(self isSpecialButton: aPoint)
ifTrue: [^self specialAction: aPoint].
(self isMemoryButton: a