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

  1.  
  2. 'Smalltalk Textbook Appendix 17'!
  3.  
  4.  
  5.  
  6.  
  7.  
  8. EngiDisplayModel subclass: #EngiFreehandModel
  9.     instanceVariableNames: 'polylines changed element trace '
  10.     classVariableNames: 'FileMenu FreehandMenu '
  11.     poolDictionaries: ''
  12.     category: 'Engi-Figure'!
  13. EngiFreehandModel comment:
  14. '
  15.  
  16. Engi 0.05 (3 March 1994)
  17. Copyright (C) 1994 by Atsushi Aoki
  18.  
  19. '!
  20.  
  21.  
  22. !EngiFreehandModel methodsFor: 'initialize-release'!
  23.  
  24. initialize
  25.     self value: OrderedCollection new.
  26.     self fresh.
  27.     self windowLabel: 'Freehand'.
  28.     changed := false.
  29.     trace := false! !
  30.  
  31. !EngiFreehandModel methodsFor: 'accessing'!
  32.  
  33. element
  34.     ^element!
  35.  
  36. element: freehandElement 
  37.     element := freehandElement.
  38.     element notNil ifTrue: [self polylines: freehandElement polylines].
  39.     changed := false!
  40.  
  41. polylines
  42.     ^polylines!
  43.  
  44. polylines: collectionOfPolylines 
  45.     polylines := collectionOfPolylines asOrderedCollection.
  46.     self flushBounds.
  47.     changed := true!
  48.  
  49. trace
  50.     ^trace = true!
  51.  
  52. trace: aBoolean 
  53.     trace := aBoolean = true! !
  54.  
  55. !EngiFreehandModel methodsFor: 'bounds accessing'!
  56.  
  57. computeBounds
  58.     | bounds |
  59.     bounds := nil.
  60.     self element isNil
  61.         ifTrue: [(self polylines isNil or: [self polylines isEmpty])
  62.                 ifTrue: [bounds := Point zero extent: Point zero]
  63.                 ifFalse: [self polylines do: [:polyline | polyline do: [:point | bounds isNil
  64.                                 ifTrue: [bounds := point extent: Point zero]
  65.                                 ifFalse: [bounds := bounds merge: (point extent: Point zero)]]]]]
  66.         ifFalse: [bounds := self element bounds].
  67.     bounds := bounds expandedBy: self expandedRectangle.
  68.     bounds := bounds merge: (Point zero corner: Point zero).
  69.     displayOrigin := Point zero - bounds origin.
  70.     ^Point zero extent: bounds extent!
  71.  
  72. expandedRectangle
  73.     | expandWidth |
  74.     (self polylines isNil or: [self polylines isEmpty])
  75.         ifTrue: [^Point zero corner: Point zero].
  76.     expandWidth := self defaultLineWidth + 1 // 2.
  77.     ^expandWidth @ expandWidth corner: expandWidth @ expandWidth! !
  78.  
  79. !EngiFreehandModel methodsFor: 'displaying'!
  80.  
  81. displayAxesOn: graphicsContext at: aPoint!
  82.  
  83. displayValueOn: graphicsContext at: aPoint 
  84.     displayOrigin isNil ifTrue: [self bounds].
  85.     self element isNil
  86.         ifTrue: 
  87.             [graphicsContext capStyle: GraphicsContext capRound.
  88.             graphicsContext joinStyle: GraphicsContext joinRound.
  89.             graphicsContext lineWidth: self defaultLineWidth.
  90.             self polylines do: [:each | graphicsContext displayPolyline: each at: aPoint + displayOrigin]]
  91.         ifFalse: [self element displayOn: graphicsContext at: aPoint]! !
  92.  
  93. !EngiFreehandModel methodsFor: 'viewing'!
  94.  
  95. open
  96.     | displayView edgeDecorator topView freshButton analyzeButton registerButton recognizeButton |
  97.     displayView := self defaultViewClass model: self.
  98.     edgeDecorator := LookPreferences edgeDecorator on: displayView.
  99.     edgeDecorator noMenuBar.
  100.     edgeDecorator useVerticalScrollBar.
  101.     edgeDecorator useHorizontalScrollBar.
  102.     freshButton := Button trigger model: ((PluggableAdaptor on: self)
  103.                     getBlock: [:m | false]
  104.                     putBlock: [:m :v | m fresh: displayView controller]
  105.                     updateBlock: [:m :a :p | false]).
  106.     freshButton label: 'fresh'.
  107.     analyzeButton := Button trigger model: ((PluggableAdaptor on: self)
  108.                     getBlock: [:m | false]
  109.                     putBlock: [:m :v | m analyze: displayView controller]
  110.                     updateBlock: [:m :a :p | false]).
  111.     analyzeButton label: 'analyze'.
  112.     registerButton := Button trigger model: ((PluggableAdaptor on: self)
  113.                     getBlock: [:m | false]
  114.                     putBlock: [:m :v | m register: displayView controller]
  115.                     updateBlock: [:m :a :p | false]).
  116.     registerButton label: 'register'.
  117.     recognizeButton := Button trigger model: ((PluggableAdaptor on: self)
  118.                     getBlock: [:m | false]
  119.                     putBlock: [:m :v | m recognize: displayView controller]
  120.                     updateBlock: [:m :a :p | false]).
  121.     recognizeButton label: 'recognize'.
  122.     topView := EngiTopView
  123.                 model: nil
  124.                 label: self windowLabel
  125.                 minimumSize: 300 @ 320.
  126.     topView add: freshButton in: (topView frameFraction: (0 @ 0 corner: 0.25 @ 0)
  127.             offset: (0 @ 0 corner: 0 @ 20)).
  128.     topView add: analyzeButton in: (topView frameFraction: (0.25 @ 0 corner: 0.5 @ 0)
  129.             offset: (0 @ 0 corner: 0 @ 20)).
  130.     topView add: registerButton in: (topView frameFraction: (0.5 @ 0 corner: 0.75 @ 0)
  131.             offset: (0 @ 0 corner: 0 @ 20)).
  132.     topView add: recognizeButton in: (topView frameFraction: (0.75 @ 0 corner: 1 @ 0)
  133.             offset: (0 @ 0 corner: 0 @ 20)).
  134.     topView add: edgeDecorator in: (topView frameFraction: (0 @ 0 corner: 1 @ 1)
  135.             offset: (0 @ 20 corner: 0 @ 0)).
  136.     topView open! !
  137.  
  138. !EngiFreehandModel methodsFor: 'controlling'!
  139.  
  140. redButtonActivity: aController 
  141.     | aSensor graphicsContext pointCollection previousPoint currentPoint |
  142.     aSensor := aController sensor.
  143.     graphicsContext := aController view graphicsContext.
  144.     graphicsContext capStyle: GraphicsContext capRound.
  145.     graphicsContext joinStyle: GraphicsContext joinRound.
  146.     graphicsContext lineWidth: self defaultLineWidth.
  147.     pointCollection := OrderedCollection new.
  148.     currentPoint := previousPoint := aSensor cursorPoint.
  149.     pointCollection add: currentPoint.
  150.     [aSensor redButtonPressed]
  151.         whileTrue: 
  152.             [aController poll.
  153.             currentPoint := aSensor cursorPoint.
  154.             currentPoint = previousPoint
  155.                 ifFalse: 
  156.                     [graphicsContext displayLineFrom: previousPoint to: currentPoint.
  157.                     pointCollection add: currentPoint.
  158.                     previousPoint := currentPoint]].
  159.     pointCollection size > 1
  160.         ifTrue: 
  161.             [self polylines isNil ifTrue: [self fresh].
  162.             self polylines add: pointCollection asArray.
  163.             changed := true]!
  164.  
  165. yellowButtonActivity: aController 
  166.     | aMenu aSymbol |
  167.     aMenu := self yellowButtonMenu.
  168.     aMenu isNil ifTrue: [^nil].
  169.     aSymbol := aMenu startUp.
  170.     aSymbol = 0
  171.         ifFalse: 
  172.             [aSymbol numArgs = 0 ifTrue: [self perform: aSymbol].
  173.             aSymbol numArgs = 1 ifTrue: [self perform: aSymbol with: aController]]! !
  174.  
  175. !EngiFreehandModel methodsFor: 'menu messages'!
  176.  
  177. analyze: aController 
  178.     | freehandElement |
  179.     self polylines isEmpty ifTrue: [^nil].
  180.     changed = true
  181.         ifTrue: 
  182.             [freehandElement := EngiFreehandElement new.
  183.             freehandElement polylines: self polylines.
  184.             self element: freehandElement.
  185.             self changed: #value].
  186.     changed := false!
  187.  
  188. debug: aController 
  189.     | bool |
  190.     bool := self confirm: 'Do you want to trace?' default: self trace.
  191.     self trace: bool!
  192.  
  193. fileMenu
  194.     "EngiFreehandModel flushMenus."
  195.  
  196.     FileMenu isNil
  197.         ifTrue: 
  198.             [| collection |
  199.             collection := OrderedCollection new.
  200.             collection add: 'new' -> #new:.
  201.             collection add: 'open' -> #open:.
  202.             collection add: nil.
  203.             collection add: 'save' -> #save:.
  204.             FileMenu := EngiMenuMaker fromCollection: collection].
  205.     ^FileMenu!
  206.  
  207. fresh: aController 
  208.     self fresh.
  209.     self changed: #value!
  210.  
  211. new: aController 
  212.     self class new open!
  213.  
  214. open: aController 
  215.     | fileName fileStream binaryObjectStorage readBlockClosure className freehandModel |
  216.     fileName := self request: 'file name?' default: String new.
  217.     (fileName isNil or: [fileName isEmpty])
  218.         ifTrue: [^nil].
  219.     (self class errorSignal
  220.         handle: 
  221.             [:exception | 
  222.             Transcript cr; show: 'file not found'.
  223.             exception returnWith: nil]
  224.         do: [fileStream := fileName asFilename readStream]) isNil ifTrue: [^nil].
  225.     (self class errorSignal
  226.         handle: 
  227.             [:exception | 
  228.             Transcript cr; show: 'can not read boss'.
  229.             exception returnWith: nil]
  230.         do: [binaryObjectStorage := BinaryObjectStorage onOldNoScan: fileStream]) isNil ifTrue: [^nil].
  231.     readBlockClosure := 
  232.             [className := binaryObjectStorage next.
  233.             className = self class name ifTrue: [freehandModel := binaryObjectStorage next]].
  234.     Cursor read showWhile: [[readBlockClosure value]
  235.             valueNowOrOnUnwindDo: [binaryObjectStorage close]].
  236.     className = self class name ifFalse: [^nil].
  237.     freehandModel open.
  238.     ^freehandModel!
  239.  
  240. recognize: aController 
  241.     | result index |
  242.     self polylines isEmpty ifTrue: [^nil].
  243.     self analyze: aController.
  244.     result := self recognize0: self element with: self value.
  245.     result isEmpty
  246.         ifTrue: 
  247.             [(PopUpMenu labelArray: #('can not recognize' )) startUp.
  248.             ^nil].
  249.     index := (PopUpMenu labelArray: (result collect: [:item | item value])) startUp.
  250.     index > 0 ifTrue: [(result at: index) open]!
  251.  
  252. register: aController 
  253.     | figure shape opaque answer message |
  254.     self polylines isEmpty ifTrue: [^nil].
  255.     self analyze: aController.
  256.     figure := self element image.
  257.     shape := figure copy.
  258.     shape palette: CoveragePalette monoMaskPalette.
  259.     opaq