'From Squeak2.7 of 5 January 2000 [latest update: #1762] on 9 September 2000 at 11:37:29 pm'! AlignmentMorph subclass: #HexAlignmentMorph instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! Morph subclass: #HexAnnotation instanceVariableNames: 'hex ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Annotation'! Object subclass: #HexChi instanceVariableNames: 'momentum amplitude velocity localTime propogationCount ' classVariableNames: 'ColorWheel ' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexChi class instanceVariableNames: ''! HexAnnotation subclass: #HexConnection instanceVariableNames: 'other state entropy ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Connection'! HexConnection class instanceVariableNames: ''! Object subclass: #HexConnectionState instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Connection'! HexConnection subclass: #HexDoppelgangerConnection instanceVariableNames: 'pairLabel ' classVariableNames: 'LabelPool LabelPoolPointer ' poolDictionaries: '' category: 'Morphic-7Hex-Annotation'! HexConnectionState subclass: #HexDynamicConnectionState instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Connection'! HexDynamicConnectionState subclass: #HexConditionalConnectionState instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Connection'! HexAnnotation subclass: #HexEmitterAnnotation instanceVariableNames: 'period ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Annotation'! FMSound subclass: #HexFMSound instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Media'! HexEmitterAnnotation subclass: #HexFiniteEmitterAnnotation instanceVariableNames: 'count currentCount counterLabel ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Annotation'! AlignmentMorph subclass: #HexGrid instanceVariableNames: 'angle scale xfactor yfactor columns rows verticesCache radius translation lookupTable displayP ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexDynamicConnectionState subclass: #HexIndexedConnectionState instanceVariableNames: 'index stateList ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Connection'! Object subclass: #HexLookPolicy instanceVariableNames: 'color drawStyle shadowColor shadowOffset windowColor ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexAnnotation subclass: #HexMirrorAnnotation instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Annotation'! HexAnnotation subclass: #HexMutatorAnnotation instanceVariableNames: 'polarity aspect ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Annotation'! HexMutatorAnnotation subclass: #HexMutatorSetAnnotation instanceVariableNames: 'load ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Annotation'! HexAlignmentMorph subclass: #HexPalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexPalette subclass: #HexExtrasPalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexPalette subclass: #HexFMSoundPalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexFMSoundPalette subclass: #HexBassPalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexFMSoundPalette subclass: #HexBrassPalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexFMSoundPalette subclass: #HexFlutePalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexPalette subclass: #HexMulePalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexMulePalette subclass: #HexAnnotationPalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexMulePalette subclass: #HexConnectionStatePalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexPalette subclass: #HexMultiPalette instanceVariableNames: '' classVariableNames: 'Scale ' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexAnnotation subclass: #HexSinkAnnotation instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Annotation'! Object subclass: #HexSoundWrapper instanceVariableNames: 'duration magnitude pitch dependentMorphs pitchName instrumentName ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexSoundWrapper subclass: #HexFMSoundWrapper instanceVariableNames: 'fmSound rawDuration ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexConnectionState subclass: #HexStaticConnectionState instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Connection'! HexStaticConnectionState subclass: #HexClosedConnectionState instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Connection'! HexStaticConnectionState subclass: #HexOpenConnectionState instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Connection'! HexConditionalConnectionState subclass: #HexThreshholdConnectionState instanceVariableNames: 'threshhold polarity aspect ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Connection'! HexOpenConnectionState subclass: #HexTieConnectionState instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Connection'! HexFMSoundPalette subclass: #HexTongPalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexFMSoundPalette subclass: #HexWhoomfPalette instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Application'! HexAlignmentMorph subclass: #HexWorld instanceVariableNames: 'gridSpace entropy entropySlider velocity velocitySlider doppelsP playingP ' classVariableNames: 'LookPolicy ' poolDictionaries: '' category: 'Morphic-7Hex-Application'! PolygonMorph subclass: #HexagonMorph instanceVariableNames: 'connections annotations coordinates centerCache paletteVersion sound chi ' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexagonMorph subclass: #HexAnnotationMule instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexAnnotationMule subclass: #HexClearAnnotationMule instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexagonMorph subclass: #HexConnectionStateMule instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexConnectionStateMule subclass: #HexClearConnectionStateMule instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexagonMorph subclass: #HexGridGhost instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexagonMorph subclass: #HexRestMorph instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexClearConnectionStateMule subclass: #HexTieConnectionStateMule instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-7Hex-Widgets'! HexagonMorph class instanceVariableNames: ''! !FMSound class methodsFor: 'instruments' stamp: 'jm 1/14/1999 12:00'! oboe2 "FMSound oboe2 play" "(FMSound majorScaleOn: FMSound oboe2) play" | snd p | snd _ FMSound new modulation: 1 ratio: 1. p _ OrderedCollection new. p add: 0@0; add: 20@1.0; add: 100@1.0; add: 120@0.0. snd addEnvelope: (VolumeEnvelope points: p loopStart: 2 loopEnd: 3). snd addEnvelope: (RandomEnvelope for: #pitch:). ^ snd setPitch: 440.0 dur: 1.0 loudness: 0.5 ! ! !HexAlignmentMorph reorganize! ('accessing' foreColor label) ('initialization' addCloseButton addLabel getLabelWithText: initialize makeCloseButton) ('private' buildButtonWithTarget:label:selector: buildButtonWithTarget:label:selector:arguments: buildSwitchWithTarget:label:selector:setSwitchTest:) ('visual properties' lookPolicy) ! !HexAlignmentMorph methodsFor: 'accessing' stamp: 'ADT 9/8/2000 14:49'! foreColor ^Color white! ! !HexAlignmentMorph methodsFor: 'accessing' stamp: 'ADT 9/8/2000 14:49'! label "Answer a string identifying what is on this palette." ^'7hex'! ! !HexAlignmentMorph methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:44'! addCloseButton "Add some temporary, ugly controls" self addMorph: self makeCloseButton. ^self ! ! !HexAlignmentMorph methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:48'! addLabel self addMorph: (self getLabelWithText: self label). ! ! !HexAlignmentMorph methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:44'! getLabelWithText: someText | label | label _ TextMorph new contents: someText. label color: self foreColor. ^label ! ! !HexAlignmentMorph methodsFor: 'initialization' stamp: 'ADT 9/9/2000 21:48'! initialize super initialize. color _ self lookPolicy windowColor. orientation _ #vertical. centering _ #center. vResizing _ #spaceFill. hResizing _ #spaceFill. inset _ 2! ! !HexAlignmentMorph methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:44'! makeCloseButton ^self buildButtonWithTarget: self label: 'close' selector: #delete! ! !HexAlignmentMorph methodsFor: 'private' stamp: 'ADT 9/8/2000 14:46'! buildButtonWithTarget: aTarget label: aLabel selector: aSelector "wrap a button in an alignmentMorph to provide some space around the button" | a aButton | aButton _ SimpleButtonMorph new. aButton target: aTarget; label: aLabel; actionSelector: aSelector; borderColor: #raised; borderWidth: 2; color: Color gray. a _ AlignmentMorph newColumn centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 1. a addMorph: aButton. ^ a ! ! !HexAlignmentMorph methodsFor: 'private' stamp: 'ADT 9/8/2000 14:44'! buildButtonWithTarget: aTarget label: aLabel selector: aSelector arguments: anArray "wrap a button or switch in an alignmentMorph to provide some space around the button" | a aButton | aButton _ SimpleButtonMorph new. aButton target: aTarget; label: aLabel; actionSelector: aSelector; arguments: anArray; borderColor: #raised; borderWidth: 2; color: Color gray. a _ AlignmentMorph newColumn centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 1. a addMorph: aButton. ^ a ! ! !HexAlignmentMorph methodsFor: 'private' stamp: 'ADT 9/8/2000 14:47'! buildSwitchWithTarget: aTarget label: aLabel selector: aSelector setSwitchTest: aTest "wrap a switch in an alignmentMorph to provide some space around the button" | a aSwitch | aSwitch _ SimpleSwitchMorph new. aSwitch offColor: Color darkGray; onColor: Color lightGray; borderWidth: 2; label: aLabel; actionSelector: aSelector; target: aTarget; setSwitchState: aTest. a _ AlignmentMorph newColumn centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 1. a addMorph: aSwitch. ^ a ! ! !HexAlignmentMorph methodsFor: 'visual properties' stamp: 'ADT 9/9/2000 21:47'! lookPolicy "For now, kludge it and all look to HexWorld to hold a master." ^HexWorld lookPolicy! ! !HexAnnotation commentStamp: 'ADT 8/25/2000 02:50' prior: 0! I am an abstract class collecting subs who collectively modify the behavior of the hex who holds me. Connections are a special privelaged subclass which are defined according to the facet they inhabit, and the fact that they must connect the holding hex to another. Annotations adhering to the node typically change the property of the hex in relation to the chi that passes through it. Annotations are given an opportunity to affect each Chi that activates their hex. They are sent preactivateWithChi: before the node activate, and postActivateWithChi: after it has played. Annotations can do anything they want to the Chi, and are expected to return it, or nil, as they choose. Hence each annotation must handle the case where it passed nil, because an earlier annotation already removed the Chi...! !HexAnnotation reorganize! ('accessing' addSelfToHex: hex hex: removeSelfFromHex:) ('drawing' drawOn:in:) ('hierarchy operations' hexGrid hexWorld world) ('model - chi' postactivateWithChi: preactivateWithChi:) ('private' delete) ('reset' reset) ('testing' isDoppelganger oppositesP) ('visual properties' annotationColor lookPolicy) ! !HexAnnotation methodsFor: 'accessing' stamp: 'ADT 9/8/2000 15:54'! addSelfToHex: aHex "aHex is comissioning us. Make the hex our own, subs can do any other settup they would like." self hex: aHex. ^self! ! !HexAnnotation methodsFor: 'accessing' stamp: 'ADT 8/5/2000 16:53'! hex ^hex! ! !HexAnnotation methodsFor: 'accessing' stamp: 'ADT 8/5/2000 16:54'! hex: aHex hex _ aHex. ^self! ! !HexAnnotation methodsFor: 'accessing' stamp: 'ADT 8/21/2000 21:15'! removeSelfFromHex: aHex "aHex is decomissioning us. Remove the bond, so we can be cleaned up. Note that aHex might not be our hex, if we are a (shallow) copy." self hex == aHex ifTrue: [self hex: nil]. ^self! ! !HexAnnotation methodsFor: 'drawing' stamp: 'ADT 8/5/2000 16:55'! drawOn: aCanvas in: aHex "Draw myself within aHex." ^self ! ! !HexAnnotation methodsFor: 'hierarchy operations' stamp: 'ADT 9/8/2000 15:18'! hexGrid ^self hex == nil ifFalse: [self hex hexGrid] ifTrue: [nil]! ! !HexAnnotation methodsFor: 'hierarchy operations' stamp: 'ADT 9/8/2000 15:18'! hexWorld ^self hex == nil ifFalse: [self hex hexWorld] ifTrue: [nil]! ! !HexAnnotation methodsFor: 'hierarchy operations' stamp: 'ADT 8/9/2000 00:33'! world ^self hex == nil ifFalse: [self hex world] ifTrue: [nil]! ! !HexAnnotation methodsFor: 'model - chi' stamp: 'ADT 8/17/2000 01:26'! postactivateWithChi: aChi "Affect aChi if I like, according to what I am." ^aChi! ! !HexAnnotation methodsFor: 'model - chi' stamp: 'ADT 8/17/2000 01:26'! preactivateWithChi: aChi "Affect aChi if I like, according to what I am." ^aChi! ! !HexAnnotation methodsFor: 'private' stamp: 'ADT 8/6/2000 03:04'! delete self hex removeAnnotation: self! ! !HexAnnotation methodsFor: 'reset' stamp: 'ADT 9/9/2000 02:44'! reset ^self! ! !HexAnnotation methodsFor: 'testing' stamp: 'ADT 9/8/2000 17:16'! isDoppelganger ^false! ! !HexAnnotation methodsFor: 'testing' stamp: 'ADT 8/17/2000 01:31'! oppositesP ^false! ! !HexAnnotation methodsFor: 'visual properties' stamp: 'ADT 8/21/2000 21:47'! annotationColor self hex == nil ifTrue: [^Color white]. ^self hex annotationColor! ! !HexAnnotation methodsFor: 'visual properties' stamp: 'ADT 9/9/2000 21:49'! lookPolicy "For now, kludge it and all look to HexWorld to hold a master." ^HexWorld lookPolicy! ! !HexAnnotation class methodsFor: 'menus' stamp: 'ADT 8/21/2000 21:08'! addRowsToPalette: aPalette "Palette requested set of current Annotations. Better to list here than there..." aPalette addMule: (HexClearAnnotationMule default) label: 'clear existing'. aPalette add: (HexSinkAnnotation new) label: 'sink'. aPalette add: (HexMirrorAnnotation new) label: 'mirror'. aPalette addLabelText: 'misc'. HexEmitterAnnotation addRowsToPalette: aPalette. HexMutatorAnnotation addRowsToPalette: aPalette. ! ! !HexAnnotation class methodsFor: 'menus' stamp: 'ADT 8/15/2000 21:29'! getIndividualMenuWithEvent: evt hex: aHex annotation: anAnnotation "Annotation dependent submenu. Requested by HexagonMorph generally...." | sub | sub _ MenuMorph new defaultTarget: anAnnotation. sub add: 'delete' action: #delete. anAnnotation oppositesP ifTrue: [sub add: 'opposite' action: #opposite]. ^ sub! ! !HexAnnotation class methodsFor: 'menus' stamp: 'ADT 8/17/2000 01:38'! getMenuWithEvent: evt hex: aHex "Facet dependent submenu. Requested by HexagonMorph generally...." | sub subsub | sub _ MenuMorph new defaultTarget: aHex. sub title: 'Annotations'. aHex annotations do: [ :a | subsub _ a class getIndividualMenuWithEvent: evt hex: aHex annotation: a. sub add: a name subMenu: subsub]. aHex annotations size > 0 ifTrue: [sub addLine]. subsub _ HexMutatorAnnotation getMenuWithEvent: evt hex: aHex. sub add: 'mutator...' subMenu: subsub. subsub _ HexEmitterAnnotation getMenuWithEvent: evt hex: aHex. sub add: 'emitter...' subMenu: subsub. sub addLine. sub add: 'mirror' selector: #newAnnotation: argument: (HexMirrorAnnotation new). sub add: 'sink' selector: #newAnnotation: argument: (HexSinkAnnotation new). ^ sub! ! !HexChi reorganize! ('accessing' amplitude amplitude: localTime localTime: momentumDirection momentumDirection: propogationCount propogationCount: velocity velocity:) ('copying' propogationCopyWithDirection:) ('defaults' defaultAmplitude defaultVelocity maximumAmplitude maximumVelocity minimumAmplitude minimumVelocity propogationCountRollover resetTime) ('drawing' drawOn:in:) ('model - connections' dontPassDirection opposingDirectionOf:) ('mutation' OLDdecrementTime decreaseAmplitude decreaseVelocity decrementTimeInWorld: defaultMutationFactor increaseAmplitude increaseVelocity mutateAspect:with:andMaybe:) ('visual properties' glowColor) ! !HexChi methodsFor: 'accessing' stamp: 'ADT 8/6/2000 21:12'! amplitude "Varies between 0 and 1" (amplitude == nil) ifTrue: [self amplitude: self defaultAmplitude]. ^amplitude! ! !HexChi methodsFor: 'accessing' stamp: 'ADT 8/21/2000 20:38'! amplitude: aFloat "Varies between 0 and 1" aFloat isNumber ifTrue: [amplitude _ aFloat]. aFloat == #default ifTrue: [amplitude _ self defaultAmplitude]. aFloat == #min ifTrue: [amplitude _ self minimumAmplitude]. aFloat == #max ifTrue: [amplitude _ self maximumAmplitude]. ^self! ! !HexChi methodsFor: 'accessing' stamp: 'ADT 7/13/2000 14:43'! localTime (localTime == nil) ifTrue: [self localTime: 0]. ^localTime! ! !HexChi methodsFor: 'accessing' stamp: 'ADT 7/13/2000 14:43'! localTime: anInteger localTime _ anInteger. ^self! ! !HexChi methodsFor: 'accessing' stamp: 'ADT 7/13/2000 14:02'! momentumDirection "Answer my momentum direction in terms of facets, not actual angle. Facets are numbered 1 - 6, starting with 0-60 degree facet (lower right)" momentum == nil ifTrue: [self momentumDirection: 0]. ^momentum! ! !HexChi methodsFor: 'accessing' stamp: 'ADT 7/13/2000 13:57'! momentumDirection: anInteger "Direction in terms of facets, not actual angle. Facets are numbered 1 - 6, starting with 0-60 degree facet (lower right)" momentum _ anInteger. ^self! ! !HexChi methodsFor: 'accessing' stamp: 'ADT 8/16/2000 02:52'! propogationCount (propogationCount == nil) ifTrue: [self propogationCount: 1]. ^propogationCount! ! !HexChi methodsFor: 'accessing' stamp: 'ADT 8/16/2000 02:53'! propogationCount: anInteger propogationCount _ (anInteger \\ self propogationCountRollover) max: 1. ^self! ! !HexChi methodsFor: 'accessing' stamp: 'ADT 8/6/2000 21:13'! velocity "Varies between 0 and 1. Should be crossed with world property." (velocity == nil) ifTrue: [self velocity: self defaultVelocity]. ^velocity! ! !HexChi methodsFor: 'accessing' stamp: 'ADT 8/21/2000 20:39'! velocity: aFloat "Varies between 0 and 1" aFloat isNumber ifTrue: [velocity _ aFloat]. aFloat == #default ifTrue: [velocity _ self defaultVelocity]. aFloat == #min ifTrue: [velocity _ self minimumVelocity]. aFloat == #max ifTrue: [velocity _ self maximumVelocity]. ^self! ! !HexChi methodsFor: 'copying' stamp: 'ADT 8/16/2000 02:43'! propogationCopyWithDirection: aDirection "Return a copy of me for for propogation -- that is, a copy with unique instances of key properties." | n | n _ self class new. n resetTime. n momentumDirection: aDirection. n amplitude: self amplitude copy. n velocity: self velocity copy. n propogationCount: (self propogationCount + 1). ^n ! ! !HexChi methodsFor: 'defaults' stamp: 'ADT 8/6/2000 21:12'! defaultAmplitude "Varies between 0 and 1" ^1! ! !HexChi methodsFor: 'defaults' stamp: 'ADT 8/6/2000 21:12'! defaultVelocity "Varies between 0 and 1" ^0.5! ! !HexChi methodsFor: 'defaults' stamp: 'ADT 8/21/2000 20:39'! maximumAmplitude "Varies between 0 and 1" ^1! ! !HexChi methodsFor: 'defaults' stamp: 'ADT 8/21/2000 20:39'! maximumVelocity "Varies between 0 and 1" ^1! ! !HexChi methodsFor: 'defaults' stamp: 'ADT 8/21/2000 20:40'! minimumAmplitude "Varies between 0 and 1" ^0.1! ! !HexChi methodsFor: 'defaults' stamp: 'ADT 8/21/2000 20:40'! minimumVelocity "Varies between 0 and 1" ^0.1! ! !HexChi methodsFor: 'defaults' stamp: 'ADT 8/16/2000 02:54'! propogationCountRollover ^100! ! !HexChi methodsFor: 'defaults' stamp: 'ADT 7/13/2000 14:45'! resetTime self localTime: (HexChi defaultTime). ^self! ! !HexChi methodsFor: 'drawing' stamp: 'ADT 8/16/2000 01:20'! drawOn: aCanvas in: aHex "Draw myself within aHex." aCanvas fillOval: (Rectangle center: aHex center extent: (aHex width * 0.5 * self amplitude)) color: self glowColor borderWidth: 0 borderColor: Color transparent! ! !HexChi methodsFor: 'model - connections' stamp: 'ADT 7/13/2000 14:41'! dontPassDirection ^self opposingDirectionOf: self momentumDirection! ! !HexChi methodsFor: 'model - connections' stamp: 'ADT 7/13/2000 14:02'! opposingDirectionOf: aDirection "Answer the direction opposite aDirection, given our arbitrary numbering of our facets." ^(aDirection = 0) ifTrue: [0] ifFalse: [(aDirection < 4) ifTrue: [aDirection + 3] ifFalse: [aDirection - 3]]! ! !HexChi methodsFor: 'mutation' stamp: 'ADT 8/8/2000 15:50'! OLDdecrementTime | nt | nt _ (self localTime - (self velocity)) max: 0. self localTime: nt. ^nt! ! !HexChi methodsFor: 'mutation' stamp: 'ADT 8/6/2000 02:48'! decreaseAmplitude | a | a _ self amplitude. a > 0 ifTrue: [self amplitude: a - (a * self defaultMutationFactor)]! ! !HexChi methodsFor: 'mutation' stamp: 'ADT 8/6/2000 02:48'! decreaseVelocity | a | a _ self velocity. a > 0 ifTrue: [self velocity: a - (a * self defaultMutationFactor)]! ! !HexChi methodsFor: 'mutation' stamp: 'ADT 8/8/2000 15:50'! decrementTimeInWorld: aHexWorld | nt | nt _ (self localTime - (self velocity * aHexWorld velocity)) max: 0. self localTime: nt. ^nt! ! !HexChi methodsFor: 'mutation' stamp: 'ADT 8/6/2000 02:48'! defaultMutationFactor ^0.3! ! !HexChi methodsFor: 'mutation' stamp: 'ADT 8/6/2000 02:47'! increaseAmplitude | a | a _ self amplitude. a < 1 ifTrue: [self amplitude: a + ((1 - a) * self defaultMutationFactor)]! ! !HexChi methodsFor: 'mutation' stamp: 'ADT 8/6/2000 02:47'! increaseVelocity | a | a _ self velocity. a < 1 ifTrue: [self velocity: a + ((1 - a) * self defaultMutationFactor)]! ! !HexChi methodsFor: 'mutation' stamp: 'ADT 8/21/2000 20:36'! mutateAspect: anAspect with: aSymbol andMaybe: anArgument anAspect == #amplitude ifTrue: [aSymbol == #increase ifTrue: [self increaseAmplitude]. aSymbol == #decrease ifTrue: [self decreaseAmplitude]. aSymbol == #set ifTrue: [self amplitude: anArgument]]. anAspect == #velocity ifTrue: [aSymbol == #increase ifTrue: [self increaseVelocity]. aSymbol == #decrease ifTrue: [self decreaseVelocity]. aSymbol == #set ifTrue: [self velocity: anArgument]]. ^self! ! !HexChi methodsFor: 'visual properties' stamp: 'ADT 8/16/2000 02:58'! glowColor ^(self class colorWheel at: self propogationCount) "muchLighter" "Color white"! ! !HexChi class reorganize! ('defaults' defaultTime) ('accessing' clearColorWheel colorWheel) ! !HexChi class methodsFor: 'defaults' stamp: 'ADT 8/8/2000 15:57'! defaultTime ^2! ! !HexChi class methodsFor: 'accessing' stamp: 'ADT 8/16/2000 02:58'! clearColorWheel "convenience function to reset it when we tweak" "HexChi clearColorWheel" ColorWheel _ nil! ! !HexChi class methodsFor: 'accessing' stamp: 'ADT 8/16/2000 02:57'! colorWheel ColorWheel == nil ifTrue: [ColorWheel _ Color yellow twiceLighter wheel: (self new propogationCountRollover)]. ^ColorWheel! ! !HexConnection commentStamp: 'ADT 8/6/2000 00:27' prior: 0! I reify the connection between two Atoms (Hexagons). Input and output are hexagons. Directionality is arbitrary, determined at the time of connection according to which is being added to which. ! !HexConnection reorganize! ('accessing' entropy entropy:) ('drawing' drawOn:in:at:) ('hierarchy operations' hexWorld) ('menus' getMenuWithEvent:facet:) ('model - chi' propogateChi:from:direction:) ('model - connection' connectedTo: oppositeSide other other: removeFrom:) ('reset' reset) ('state based' newState: state state: toggleState twidle) ! !HexConnection methodsFor: 'accessing' stamp: 'ADT 8/15/2000 21:00'! entropy "Answer a factor between 0 and 1, the degree to which the amplitude of chis should be diminished when passing through me. 1 indicates no decay; 0 indicates no propogation." ^self hexWorld entropy! ! !HexConnection methodsFor: 'accessing' stamp: 'ADT 7/25/2000 14:32'! entropy: aFloat "Set a factor between 0 and 1, the degree to which the amplitude of chis should be diminished when passing through me. 1 indicates no decay; 0 indicates no propogation. Eventually this factor should be a function of both the connection and inherited (eg from the world or hexagram) properties..." "This is crossed with world entropy..." entropy _ aFloat. ^self! ! !HexConnection methodsFor: 'drawing' stamp: 'ADT 7/21/2000 00:36'! drawOn: aCanvas in: aHex at: facetNumber "Delegate -- ask my state object to draw itself within aHex at position aFacet." self state drawOn: aCanvas in: aHex at: facetNumber. ^self ! ! !HexConnection methodsFor: 'hierarchy operations' stamp: 'ADT 8/8/2000 15:32'! hexWorld ^self hex hexWorld! ! !HexConnection methodsFor: 'menus' stamp: 'ADT 8/15/2000 16:01'! getMenuWithEvent: evt facet: facet "Facet dependent submenu. Requested by HexagonMorph generally...." | sub kludge subsub | sub _ MenuMorph new defaultTarget: self. sub title: 'Facet Properties'. self state oppositesP ifTrue: [sub add: 'opposite' selector: #toggleState argument: nil. kludge _ true]. self state twidlesP ifTrue: [sub add: 'twidle' selector: #twidle argument: nil. kludge _ true]. kludge == nil ifFalse: [sub addLine]. subsub _ HexStaticConnectionState getMenuWithEvent: evt facet: facet target: self. sub add: 'fixed...' subMenu: subsub. subsub _ HexIndexedConnectionState getMenuWithEvent: evt facet: facet target: self. sub add: 'indexed...' subMenu: subsub. subsub _ HexThreshholdConnectionState getMenuWithEvent: evt facet: facet target: self. sub add: 'conditional...' subMenu: subsub. (self hex isSameAs: self oppositeSide) ifTrue: [sub add: 'tie' target: self hex selector: #tieAt: argument: facet. (self oppositeSide hexConnectedToAt: facet) == nil ifFalse: [(self hex isSameAs: (self oppositeSide hexConnectedToAt: facet)) ifTrue: [sub add: 'tie along' target: self hex selector: #tieTo:at:cascade: argumentList: (Array with: self oppositeSide with: facet with: true)]]]. ^ sub! ! !HexConnection methodsFor: 'model - chi' stamp: 'ADT 7/26/2000 00:52'! propogateChi: aChi from: aHex direction: aDirection "aHex is passing us aChi to pass on to the hex on the other side. Defer to our state to propogate the chi, which allows for special handling based on our state." self state propogateChi: aChi from: aHex direction: aDirection for: self! ! !HexConnection methodsFor: 'model - connection' stamp: 'ADT 7/20/2000 18:16'! connectedTo: aHex "Answer whether my input or output is aHex or not. Useful for enumerating blocks." ^(self hex == aHex) or: [self oppositeSide == aHex]! ! !HexConnection methodsFor: 'model - connection' stamp: 'ADT 7/20/2000 18:15'! oppositeSide "Determine what's on the other end from aHex, and answer it. If aHex is neither my input nor my output, answer nil." ^self other hex! ! !HexConnection methodsFor: 'model - connection' stamp: 'ADT 7/20/2000 18:14'! other "The hex connection on the other side" ^other! ! !HexConnection methodsFor: 'model - connection' stamp: 'ADT 7/20/2000 18:14'! other: aHexConnection "The hex connection on the other side" other _ aHexConnection. ^self! ! !HexConnection methodsFor: 'model - connection' stamp: 'ADT 7/26/2000 01:29'! removeFrom: aHex "aHex is sponsoring removal of me. Request that the party on the other end remove the connection also." | otherSide | otherSide _ self oppositeSide. otherSide == nil ifFalse: [otherSide privateRemoveConnection: self other]. self state beingRemovedFrom: aHex. "notify in case it wants to take any action" ^self! ! !HexConnection methodsFor: 'reset' stamp: 'ADT 9/9/2000 02:45'! reset super reset. self state reset! ! !HexConnection methodsFor: 'state based' stamp: 'ADT 8/15/2000 15:51'! newState: aState "Assign myself a new connectionState" aState == nil ifFalse: [self state: aState. self hex changed] ! ! !HexConnection methodsFor: 'state based' stamp: 'ADT 7/21/2000 00:17'! state "Answer the HexConnectionState I hold, which maintains state for me. I hold a seperate object since there are a variety of kinds of connections -- toggling, fixed closed, fixed open, etc. My state is responsible for answering currentState with #open or #closed" state == nil ifTrue: [self state: HexOpenConnectionState new]. ^state! ! !HexConnection methodsFor: 'state based' stamp: 'ADT 7/21/2000 00:18'! state: aHexConnectionState "the connection state is responsible for answering current state with #open or #closed" state _ aHexConnectionState. ^self! ! !HexConnection methodsFor: 'state based' stamp: 'ADT 7/24/2000 17:01'! toggleState "Ask my state to return an alternative to itself. THe only obligation is that it return an instance of HExConnectionState; if the idea of 'opposite' is not well defined, it is free to return itself. Static open and closed connection states return instances of each other. Binary toggling states return instances of themselves with polarity reversed." self state: self state opposite. self hex changed. ^self ! ! !HexConnection methodsFor: 'state based' stamp: 'ADT 7/21/2000 02:10'! twidle "Ask my state to twidle (update or advance its internal state)." self state twidle. self hex changed ! ! !HexConnection class reorganize! ('instance creation' input:output:) ! !HexConnection class methodsFor: 'instance creation' stamp: 'ADT 7/20/2000 18:39'! input: anInput output: anOutput "Create a pair of matched connections that regard each other as 'other' in a symmetrical fashion. Caller is assumed to be anInput, and to take responsibility for passing the 'other' of its own side, to an output." | this that | this _ (self new) hex: anInput. that _ (self new) hex: anOutput. this other: that. that other: this. ^this! ! !HexConnectionState commentStamp: 'ADT 8/6/2000 00:27' prior: 0! I encapsulate type information for a HexConnection. HexConnections themselves are always a function of two hexes. I represent the nature of the connection between those hexes. One reason I am a seperate object is that this makes it easy to change that relationship -- one of my subclasses can simply be swapped for anotherl, without rebuilding the whole Connection.! !HexConnectionState reorganize! ('drawing' OLDsixPointsBetween:and: midpointBetween:and: points:between:and: sixPointsBetween:and:) ('model - chi' propogateChi:from:direction:for:) ('notification' beingRemovedFrom:) ('reset' reset) ('state based' twidle) ('subclass responsibilities' currentStateForChi: drawOn:in:at: opposite) ('testing' oppositesP twidlesP) ('visual properties' lookPolicy) ! !HexConnectionState methodsFor: 'drawing' stamp: 'ADT 8/5/2000 17:35'! OLDsixPointsBetween: start and: end "Interpolate 4 evenly spaced points between start and end, and return a collection containing them in order." | pts delta | pts _ Array new: 6. pts at: 1 put: start. pts at: 6 put: end. delta _ (end - start) / 6. pts at: 2 put: (start + delta). pts at: 3 put: (start + (2 * delta)). pts at: 4 put: (end - (2 * delta)). pts at: 5 put: (end - delta). ^pts! ! !HexConnectionState methodsFor: 'drawing' stamp: 'ADT 7/26/2000 01:01'! midpointBetween: start and: end "Answer the midpoint between start and end, and return a collection containing them in order." ^ (start + end) / 2! ! !HexConnectionState methodsFor: 'drawing' stamp: 'ADT 8/5/2000 19:46'! points: n between: start and: end "Interpolate (n -2) evenly spaced points between start and end, and return a collection containing them in order." | pts delta | pts _ Array new: n. pts at: 1 put: start. pts at: n put: end. delta _ (end - start) / (n - 1). 2 to: (n-1) do: [ :i | pts at: i put: ((pts at: (i - 1)) + delta)]. ^pts! ! !HexConnectionState methodsFor: 'drawing' stamp: 'ADT 8/5/2000 17:36'! sixPointsBetween: start and: end "Interpolate 4 evenly spaced points between start and end, and return a collection containing them in order." ^self points: 6 between: start and: end! ! !HexConnectionState methodsFor: 'model - chi' stamp: 'ADT 8/6/2000 21:07'! propogateChi: aChi from: aHex direction: aDirection for: aConnection "aHex is passing us aChi to pass on to the hex on the other side. Make a copy of aChi, and update its parameters however we choose. Note that we are free to not pass the chi, if the selected direction is not current open; change the Chi's parameters (decrement it according to entropy...), etc." (self currentStateForChi: aChi) == #open ifTrue: [| newAmp | newAmp _ aChi amplitude * aConnection entropy. (newAmp > 0.1) ifTrue: [| newChi | newChi _ aChi propogationCopyWithDirection: aDirection. newChi amplitude: newAmp. aConnection oppositeSide activateWithChi: newChi]]. self twidle.! ! !HexConnectionState methodsFor: 'notification' stamp: 'ADT 7/26/2000 01:28'! beingRemovedFrom: aHex "The connection to which we belong is being removed. We are being notified in case we wish to take any action. Some subclasses may need to do so..." ^self! ! !HexConnectionState methodsFor: 'reset' stamp: 'ADT 9/9/2000 02:46'! reset ^self! ! !HexConnectionState methodsFor: 'state based' stamp: 'ADT 7/21/2000 01:10'! twidle "Step to next position, if I'm activation-based." ^self! ! !HexConnectionState methodsFor: 'subclass responsibilities' stamp: 'ADT 8/6/2000 00:44'! currentStateForChi: aChi "Return #open or #closed." self subclassResponsibility! ! !HexConnectionState methodsFor: 'subclass responsibilities' stamp: 'ADT 7/21/2000 00:33'! drawOn: aCanvas in: aHex at: facetNumber "Draw myself on top of aHex at position number facetNumber. After all, I know my current state, etc.!!" self subclassResponsibility! ! !HexConnectionState methodsFor: 'subclass responsibilities' stamp: 'ADT 7/25/2000 14:27'! opposite "Return an instance of myself that is philosophically opposite myself. Fixed open instances return fixed closed instances and vice versa. Binary togglers return themselves with polarity reversed. If 'opposite' doesn't make sense, I can return myself." ^self! ! !HexConnectionState methodsFor: 'testing' stamp: 'ADT 8/5/2000 20:03'! oppositesP ^false! ! !HexConnectionState methodsFor: 'testing' stamp: 'ADT 8/5/2000 17:21'! twidlesP "Do I step between multiple states?" ^false! ! !HexConnectionState methodsFor: 'visual properties' stamp: 'ADT 9/9/2000 21:48'! lookPolicy "For now, kludge it and all look to HexWorld to hold a master." ^HexWorld lookPolicy! ! !HexConnectionState class methodsFor: 'menus' stamp: 'ADT 8/23/2000 03:37'! addRowsToPalette: aPalette "Palette requested set of current ConnectionStates. Better to list here than there..." aPalette addMule: (HexTieConnectionStateMule default) label: 'tie (if possible)'. aPalette addLabelText: 'misc'. HexThreshholdConnectionState addRowsToPalette: aPalette. HexIndexedConnectionState addRowsToPalette: aPalette. HexStaticConnectionState addRowsToPalette: aPalette. ! ! !HexDoppelgangerConnection reorganize! ('accessing' pairLabel pairLabel: privatePairLabel: updatePairLabelWithScale:) ('drawing' OLDdrawOn:in:at: drawOn:in:at:) ('model - chi' preactivateWithChi:) ('printing' printOn:) ('private' delete removeSelfFromHex:) ('testing' isDoppelganger) ! !HexDoppelgangerConnection methodsFor: 'accessing' stamp: 'ADT 9/8/2000 16:11'! pairLabel pairLabel == nil ifTrue: [self pairLabel: '*']. ^pairLabel! ! !HexDoppelgangerConnection methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:49'! pairLabel: aString pairLabel _ StringMorph contents: aString. pairLabel font: self lookPolicy defaultFont. pairLabel color: self annotationColor. ^self! ! !HexDoppelgangerConnection methodsFor: 'accessing' stamp: 'ADT 9/8/2000 16:24'! privatePairLabel: aStringMorph pairLabel _ aStringMorph. ^self! ! !HexDoppelgangerConnection methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:50'! updatePairLabelWithScale: aFloat | aSize | aSize _ (self lookPolicy defaultFontSize * aFloat) rounded. self pairLabel font: (self lookPolicy fontOfSize: aSize). ^self! ! !HexDoppelgangerConnection methodsFor: 'drawing' stamp: 'ADT 9/8/2000 16:35'! OLDdrawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position oriented towards aFacet." | r | r _ Rectangle encompassing: (aHex verticesInsetBy: 0.4). aCanvas drawPolygon: (Array with:(r topLeft) with: (r topRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (r topRight) with: (r bottomCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (r bottomCenter) with: (r topLeft) ) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor. self drawLabelOn: aCanvas in: aHex rect: r! ! !HexDoppelgangerConnection methodsFor: 'drawing' stamp: 'ADT 9/8/2000 17:21'! drawOn: aCanvas in: aHex at: aFacet "Draw my label within aHex" self pairLabel center: aHex center. aHex hexGrid == nil ifFalse: [self updatePairLabelWithScale: aHex hexGrid scale]. self pairLabel drawOn: aCanvas.! ! !HexDoppelgangerConnection methodsFor: 'model - chi' stamp: 'ADT 8/25/2000 03:14'! preactivateWithChi: aChi "Affect aChi if I like, according to what I am. We ask the chi itself to handle this..." ^self oppositeSide dontActivateWithChi: (aChi propogationCopyWithDirection: 0)! ! !HexDoppelgangerConnection methodsFor: 'printing' stamp: 'ADT 8/25/2000 03:26'! printOn: aStream aStream nextPutAll: 'Doppelganger (tie)' ! ! !HexDoppelgangerConnection methodsFor: 'private' stamp: 'ADT 8/25/2000 19:16'! delete self other hex privateRemoveAnnotation: self other. super delete! ! !HexDoppelgangerConnection methodsFor: 'private' stamp: 'ADT 8/25/2000 19:21'! removeSelfFromHex: aHex "aHex is decomissioning us. Remove the bond, so we can be cleaned up. Note that aHex might not be our hex, if we are a (shallow) copy." super removeSelfFromHex: aHex. self other hex privateRemoveAnnotation: self other! ! !HexDoppelgangerConnection methodsFor: 'testing' stamp: 'ADT 9/8/2000 17:16'! isDoppelganger ^true! ! !HexDoppelgangerConnection class reorganize! ('accessing' defaultLabelPool incrementLabelPoolPointer labelPool labelPool: labelPoolPointer labelPoolPointer: newLabel resetLabelPoolPointer) ('instance creation' input:output:) ! !HexDoppelgangerConnection class methodsFor: 'accessing' stamp: 'ADT 9/8/2000 16:10'! defaultLabelPool ^Character alphabet asOrderedCollection collect: [ :char | char asString]! ! !HexDoppelgangerConnection class methodsFor: 'accessing' stamp: 'ADT 9/8/2000 16:06'! incrementLabelPoolPointer self labelPoolPointer: self labelPoolPointer + 1. self labelPoolPointer > self labelPool size ifTrue: [self labelPoolPointer: 1]. ! ! !HexDoppelgangerConnection class methodsFor: 'accessing' stamp: 'ADT 9/8/2000 16:02'! labelPool LabelPool == nil ifTrue: [self labelPool: self defaultLabelPool]. ^LabelPool! ! !HexDoppelgangerConnection class methodsFor: 'accessing' stamp: 'ADT 9/8/2000 16:02'! labelPool: aCollection LabelPool _ aCollection. ^self! ! !HexDoppelgangerConnection class methodsFor: 'accessing' stamp: 'ADT 9/8/2000 17:09'! labelPoolPointer LabelPoolPointer == nil ifTrue: [self resetLabelPoolPointer]. "always incremented BEFORE we use it" ^LabelPoolPointer! ! !HexDoppelgangerConnection class methodsFor: 'accessing' stamp: 'ADT 9/8/2000 16:04'! labelPoolPointer: aNumber LabelPoolPointer _ aNumber. ^self! ! !HexDoppelgangerConnection class methodsFor: 'accessing' stamp: 'ADT 9/8/2000 16:07'! newLabel self incrementLabelPoolPointer. ^self labelPool at: self labelPoolPointer ! ! !HexDoppelgangerConnection class methodsFor: 'accessing' stamp: 'ADT 9/8/2000 17:08'! resetLabelPoolPointer self labelPoolPointer: 0. "always incremented BEFORE we use it" ^self! ! !HexDoppelgangerConnection class methodsFor: 'instance creation' stamp: 'ADT 9/8/2000 16:24'! input: anInput output: anOutput "Create a pair of matched connections that regard each other as 'other' in a symmetrical fashion. Caller is assumed to be anInput, and to take responsibility for passing the 'other' of its own side, to an output." | this that | this _ super input: anInput output: anOutput. that _ this other. this pairLabel: self newLabel. that privatePairLabel: this pairLabel copy. ^this! ! !HexDynamicConnectionState commentStamp: 'ADT 8/6/2000 00:25' prior: 0! I am a subclass of connection state whose state, open or closed, is not fixed. Typically this is because I have a conditional state, or I alternate in a fixed pattern between a variety of states.! !HexConditionalConnectionState commentStamp: 'ADT 8/6/2000 00:24' prior: 0! I am a subclass of dynamic connection state whose state, open or closed, is dependent on the results of a conditional test. Typically I evaluate the factor of my interest on a just in time basis.! !HexEmitterAnnotation reorganize! ('accessing' defaultPeriod hex: period period: removeSelfFromHex:) ('drawing' drawOn:in:at:) ('printing' printOn:) ('stepping and presenter' startStepping step stepTime) ('visual properties' annotationColor) ! !HexEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 8/9/2000 00:03'! defaultPeriod "Answer the default interval that determines how often I (autonomously) emit chi" ^10000! ! !HexEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 8/9/2000 00:34'! hex: aHex "When we learn our hex, start our clock. Kind of a kludge but should work OK." super hex: aHex. self startStepping. ^self! ! !HexEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 8/9/2000 00:02'! period "Answer the interval that determines how often I (autonomously) emit chi" period == nil ifTrue: [self period: self defaultPeriod]. ^period! ! !HexEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 8/9/2000 00:02'! period: aMagnitude "Set the interval that determines how often I (autonomously) emit chi" period _ aMagnitude. ^self! ! !HexEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 8/21/2000 21:16'! removeSelfFromHex: aHex "aHex is decomissioning us. Remove the bond, so we can be cleaned up... Note that I do my thing before calling super, since it can clear my hex property." self hex == aHex ifTrue: [self stopStepping]. ^super removeSelfFromHex: aHex.! ! !HexEmitterAnnotation methodsFor: 'drawing' stamp: 'ADT 9/9/2000 22:15'! drawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position oriented towards aFacet." | r lp | lp _ self lookPolicy. r _ Rectangle encompassing: (aHex verticesInsetBy: (1.2 * self period log reciprocal)). lp drawStyle == #shadow ifTrue: [| s | s _ r translateBy: lp shadowOffset. aCanvas drawPolygon: (Array with: (s topCenter) with: (s bottomCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: (s leftCenter) with: (s rightCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: (s topLeft) with: (s bottomRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: (s topRight) with: (s bottomLeft)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (r topCenter) with: (r bottomCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (r leftCenter) with: (r rightCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (r topLeft) with: (r bottomRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (r topRight) with: (r bottomLeft)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor! ! !HexEmitterAnnotation methodsFor: 'printing' stamp: 'ADT 8/15/2000 21:23'! printOn: aStream aStream nextPutAll: 'Emitter: '. aStream nextPutAll: 'period: '. aStream nextPutAll: (self period printString). ! ! !HexEmitterAnnotation methodsFor: 'stepping and presenter' stamp: 'ADT 8/9/2000 00:06'! startStepping "Start getting sent the 'step' message." | w | w _ self world. w ifNotNil: [ w startStepping: self].! ! !HexEmitterAnnotation methodsFor: 'stepping and presenter' stamp: 'ADT 9/8/2000 15:19'! step self hexWorld == nil ifFalse: [self hexWorld playingP ifTrue: [self hex activate]]! ! !HexEmitterAnnotation methodsFor: 'stepping and presenter' stamp: 'ADT 8/9/2000 00:07'! stepTime "Answer the desired time between steps in milliseconds." ^ self period! ! !HexEmitterAnnotation methodsFor: 'visual properties' stamp: 'ADT 8/21/2000 21:45'! annotationColor ^Color lightYellow! ! !HexEmitterAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/9/2000 00:32'! highFrequency ^self new period: 10000! ! !HexEmitterAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/9/2000 00:40'! lowFrequency ^self new period: 25000! ! !HexEmitterAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/9/2000 00:39'! mediumFrequency ^self new period: 15000! ! !HexEmitterAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/9/2000 00:32'! veryHighFrequency ^self new period: 5000! ! !HexEmitterAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/9/2000 00:40'! veryLowFrequency ^self new period: 45000! ! !HexEmitterAnnotation class methodsFor: 'menus' stamp: 'ADT 8/19/2000 04:30'! addRowsToPalette: aPalette aPalette add: (self veryLowFrequency) label: 'very low frequency'. aPalette add: (self lowFrequency) label: 'low frequency'. aPalette add: (self mediumFrequency) label: 'medium frequency'. aPalette add: (self highFrequency) label: 'high frequency'. aPalette add: (self veryHighFrequency) label: 'very high frequency'. aPalette addLabelText: 'emitters' ! ! !HexEmitterAnnotation class methodsFor: 'menus' stamp: 'ADT 8/15/2000 15:39'! getMenuWithEvent: evt hex: aHex "Facet dependent sub-submenu. Requested by HexAnnotation..." | sub | sub _ MenuMorph new defaultTarget: aHex. sub add: 'very high frequency' selector: #newAnnotation: argument: (self veryHighFrequency). sub add: 'high frequency' selector: #newAnnotation: argument: (self highFrequency). sub add: 'medium frequency' selector: #newAnnotation: argument: (self mediumFrequency). sub add: 'low frequency' selector: #newAnnotation: argument: (self lowFrequency). sub add: 'very low frequency' selector: #newAnnotation: argument: (self veryLowFrequency). ^ sub! ! !HexFMSound class methodsFor: 'instruments' stamp: 'ADT 8/21/2000 22:00'! tong "HexFMSound tong play" "(FMSound majorScaleOn: HexFMSound tong) play" | snd p | snd _ HexFMSound new modulation: 0 ratio: 1. p _ OrderedCollection new. p add: 0@1.0; add: 10@1.0; add: 20@0.8; add: 190@0.0. snd addEnvelope: (VolumeEnvelope points: p loopStart: 2 loopEnd: 3). ^ snd setPitch: 440.0 dur: 0.3 loudness: 0.5 ! ! !HexFMSound class methodsFor: 'instruments' stamp: 'ADT 8/16/2000 02:33'! whoomf "HexFMSound whoomf play" "(FMSound majorScaleOn: HexFMSound whoomf) play" | snd p | snd _ HexFMSound new modulation: 0 ratio: 1. p _ OrderedCollection new. p add: 0@0.0; add: 160@1.0; add: 180@1.0; add: 190@0.0. snd addEnvelope: (VolumeEnvelope points: p loopStart: 2 loopEnd: 3). ^ snd setPitch: 440.0 dur: 1.0 loudness: 0.5 ! ! !HexFiniteEmitterAnnotation reorganize! ('accessing' count count: counterLabel counterLabel: currentCount currentCount: decrementCount updateCounterLabelWithCount: updateCounterLabelWithScale:) ('drawing' drawOn:in:at:) ('reset' reset) ('stepping and presenter' step) ! !HexFiniteEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 9/9/2000 02:29'! count "Answer the number of times that I (autonomously) emit chi" count == nil ifTrue: [self count: 1]. ^count! ! !HexFiniteEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 9/9/2000 02:28'! count: aMagnitude "Set the number of times that I (autonomously) emit chi" count _ aMagnitude. ^self! ! !HexFiniteEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 9/9/2000 02:41'! counterLabel counterLabel == nil ifTrue: [self counterLabel: '*']. ^counterLabel! ! !HexFiniteEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:50'! counterLabel: aString counterLabel _ StringMorph contents: aString. counterLabel font: self lookPolicy defaultFont. counterLabel color: self annotationColor. ^self! ! !HexFiniteEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 9/9/2000 02:32'! currentCount "Answer the number of times that I will emit chi *this time around*, between count and 0." currentCount == nil ifTrue: [self reset]. ^currentCount! ! !HexFiniteEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 9/9/2000 02:42'! currentCount: anInteger "Answer the number of times that I will emit chi *this time around*, between count and 0." currentCount _ anInteger. self updateCounterLabelWithCount: anInteger. ^self! ! !HexFiniteEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 9/9/2000 02:33'! decrementCount "Answer the number of times that I will emit chi *this time around*, between count and 0." self currentCount = 0 ifFalse: [self currentCount: self currentCount - 1]! ! !HexFiniteEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 9/9/2000 02:42'! updateCounterLabelWithCount: anInteger self counterLabel contents: (anInteger asString). ^self! ! !HexFiniteEmitterAnnotation methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:50'! updateCounterLabelWithScale: aFloat | aSize | aSize _ (self lookPolicy defaultFontSize * aFloat) rounded. self counterLabel font: (self lookPolicy fontOfSize: aSize). ^self! ! !HexFiniteEmitterAnnotation methodsFor: 'drawing' stamp: 'ADT 9/9/2000 02:53'! drawOn: aCanvas in: aHex at: aFacet "Draw my label within aHex" super drawOn: aCanvas in: aHex at: aFacet. self counterLabel center: aHex center. aHex hexGrid == nil ifFalse: [self updateCounterLabelWithScale: aHex hexGrid scale]. self counterLabel drawOn: aCanvas.! ! !HexFiniteEmitterAnnotation methodsFor: 'reset' stamp: 'ADT 9/9/2000 02:43'! reset self currentCount: self count! ! !HexFiniteEmitterAnnotation methodsFor: 'stepping and presenter' stamp: 'ADT 9/9/2000 02:54'! step super step. self hexWorld == nil ifFalse: [self hexWorld playingP ifTrue: [self decrementCount]]! ! !HexGrid reorganize! ('accessing' angle angle: columns columns: displayP displayP: normal radius rotateClockwise rotateCounterclockwise rotateWithStart:end: rows rows: scale scale: translation translation: zoomIn zoomOut) ('coordinate operations' colorForCoordinates: gridSnapX:Y: logicalCoordinatesForPoint: physicalCoordinatesForX:Y:) ('default') ('drawing' ALTdrawHexAtPhysicalCoordinates:on: FILLEDdrawHexAtPhysicalCoordinates:on: OLDdrawHexAtPhysicalCoordinates:on: drawHexAtLogicalX:Y:on: drawHexAtPhysicalCoordinates:on: drawOn: hexIsVisibleAt: hexagonVerticesAtCoordinates:) ('dropping/grabbing' acceptDroppingMorph:event: rotateWithGhost:event: translateWithGhost:event: wantsDroppedMorph:event:) ('event handling' click: doubleClick: drag: handlesMouseDown: handlesMouseOver: mouseDown: mouseEnter: mouseLeave: mouseUp: yellowButtonActivity:) ('hexagon operations' clearCanvas hexAtCoordinates: hexagons placeHex:At: reset stopPlayback toggleGrid) ('hierarchy operations' hexWorld) ('initialization' initialize) ('layout' minHeightWhenEmpty minWidthWhenEmpty) ('notification' hexChanged) ('optimizations' recalculateHexCache) ('private' addMorphFront: addTestHexes neighborCoordinates privateAddMorph:atIndex: privateRemoveMorph: unscaledRadius unscaledRadius: xfactor xfactor: yfactor yfactor:) ('visual properties' defaultWidth gridWidth) ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! angle angle == nil ifTrue: [self angle: 0]. ^ angle! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! angle: anAngle angle _ anAngle. (angle < 0) ifTrue: [angle _ angle + 360]. (angle > 360) ifTrue: [angle _ angle - 360]. self xfactor: angle degreesToRadians cos. self yfactor: angle degreesToRadians sin. self hexChanged! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! columns columns == nil ifTrue: [self columns: 20]. ^ columns! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! columns: c columns _ c. ^self! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! displayP displayP == nil ifTrue: [self displayP: true]. ^displayP! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 9/8/2000 14:30'! displayP: aBool displayP _ aBool. self changed. ^self! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 8/23/2000 04:40'! normal "sent by button" self scale: 1. self translation: 0 @ 0. self angle: 0.! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! radius ^ self unscaledRadius * self scale! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 8/23/2000 04:39'! rotateClockwise self angle: (self angle + 30)! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 8/23/2000 04:39'! rotateCounterclockwise self angle: (self angle - 30)! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 8/24/2000 10:59'! rotateWithStart: start end: end "start and end are two points on the world within our bounds. Try to determine the rotation intended by the user, then translate us a bit that way." "For now, calculate angle between end and start points (as reckoned from my center). Rationalize the difference to our grid snap of 30. Note that I don't use rotateC... methods since each one triggers redraw." | endAngle startAngle delta | startAngle _ self center bearingToPoint: start. endAngle _ self center bearingToPoint: end. delta _ ((endAngle - startAngle) \\ 360) truncateTo: 30. self angle: (self angle + delta)! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! rows rows == nil ifTrue: [self rows: 20]. ^ rows! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! rows: r rows _ r. ^self! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! scale scale == nil ifTrue: [self scale: 1]. ^ scale! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! scale: aFloat scale _ aFloat. self hexChanged! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! translation "logical coordinates" translation == nil ifTrue: [self translation: (Point x: 0 y: 0)]. ^translation! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 7/25/2000 12:57'! translation: aPoint "logical coordinates" translation _ aPoint. self hexChanged. ^self! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 8/23/2000 04:34'! zoomIn self scale: ((self scale + 0.2) min: 3)! ! !HexGrid methodsFor: 'accessing' stamp: 'ADT 8/23/2000 04:34'! zoomOut self scale: ((self scale - 0.2) max: 0)! ! !HexGrid methodsFor: 'coordinate operations' stamp: 'ADT 7/25/2000 12:57'! colorForCoordinates: aPoint | temp x y | "Answer a color graded to the current position of aPoint within the encompassing view. Provides us with the ability to do a gradient wash across the grid." x _ aPoint x. y _ aPoint y. temp _ ((y - self bounds origin y) / self height) abs. temp _ temp + ((0.47 - temp) * ((x - self bounds origin x) / self width) abs). ^ Color r: 0 "(temp/1.7)" g: "temp" 0 b: temp! ! !HexGrid methodsFor: 'coordinate operations' stamp: 'ADT 7/25/2000 12:57'! gridSnapX: x Y: y "The offset tiling of a hexagonal grid (every other row offset by .5) means logical coordinates must be massaged to fit. If we just tile every .5 interval (or double the grid...), the effect is to populate twice as many hexes, half of them on 'illegal' coordinates. It turns out the rule is simple -- if one coordinate is an integer, the other must be too. This method returns the closest legal coordinate for an arbitrary pair of values, x and y." | correctedX correctedY | correctedX _ (x * 2) rounded. correctedY _ (y * 2) rounded. "Doubling allows us to test coordinate legality on the basis of parity..." (((correctedX even) and: [correctedY even]) or: [(correctedX odd) and: [correctedY odd]]) ifFalse: ["Coordinates are illegal. Figure out which dimension is closest and snap to it." ((((x * 2) abs - correctedX abs) abs) < (((y * 2) abs - correctedY abs) abs)) ifTrue: ["X is closer. Keep x, snap Y." (((y * 2) abs) > (correctedY abs)) ifTrue: [correctedY _ correctedY + (y sign)] ifFalse: [correctedY _ correctedY - (y sign)]] ifFalse: ["Y is closer. Keep y, snap X." (((x * 2) abs) > (correctedX abs)) ifTrue: [correctedX _ correctedX + (x sign)] ifFalse: [correctedX _ correctedX - (x sign)]]]. ^Point x: ((correctedX / 2) asFloat) y: ((correctedY / 2) asFloat)! ! !HexGrid methodsFor: 'coordinate operations' stamp: 'ADT 7/25/2000 12:57'! logicalCoordinatesForPoint: aPoint "Return the screen coordinates of logical coordinates X@Y, taking into account our current scale, offset, and angle. First, convert logical X and Y to geometrically true version." | x y r theta pX pY | "Correct for current translation" pX _ (aPoint x) - (self center x). pY _ (aPoint y) - (self center y). r _ ((pX raisedToInteger: 2) + (pY raisedToInteger: 2)) sqrt. "physical radius" (pX abs < 0.1) ifTrue: [pX _ 0.00000000001]. "prevent divide by zero" theta _ (pY / pX) arcTan radiansToDegrees. "Correct for quadrant" (pX < 0) ifTrue: [theta _ theta + 180]. "quadrant II or III" "Rotate to appropriate position." theta _ (theta - self angle) \\ 360. "Scale to current radius" r _ r / (self radius * 2.99). x _ (r * (theta degreesToRadians cos)). y _ (r * (theta degreesToRadians sin)) * 1.733. "Correct for assymmetry in hex tiling" ^((self gridSnapX: x Y: y) - self translation)! ! !HexGrid methodsFor: 'coordinate operations' stamp: 'ADT 7/25/2000 12:57'! physicalCoordinatesForX: logicalX Y: logicalY "Return the screen coordinates of logical coordinates X@Y, taking into account our current scale, translation, and angle. First, convert logical X and Y to geometrically true version." | x y r theta xindex yindex | yindex _ (logicalY + (self translation y)) * 0.5777. "Correct for assymetry in hexagonal tiling." xindex _ logicalX + self translation x. (xindex abs < 0.1) ifTrue: [xindex _ 0.00000000001]. r _ ((xindex raisedToInteger: 2) + (yindex raisedToInteger: 2)) sqrt. theta _ (yindex / xindex) arcTan radiansToDegrees. "Correct for quadrant" (xindex < 0) ifTrue: [theta _ theta + 180]. "quadrant II or III" "Rotate to appropriate position." theta _ (theta + self angle) \\ 360. "Scale to current radius" r _ r * self radius * 3. x _ (r * (theta degreesToRadians cos)). y _ (r * (theta degreesToRadians sin)). ^ (Point x: x y: y) + self center! ! !HexGrid methodsFor: 'drawing' stamp: 'ADT 8/9/2000 01:00'! ALTdrawHexAtPhysicalCoordinates: aPoint on: aCanvas (self hexIsVisibleAt: aPoint) ifFalse: [^self]. aCanvas clipBy: self innerBounds during: [:clippedCanvas | clippedCanvas drawPolygon: (self hexagonVerticesAtCoordinates: aPoint) fillStyle: Color transparent "(self colorForCoordinates: aPoint)" borderWidth: 2 borderColor: Color blue dansDarker "(Color black)"]! ! !HexGrid methodsFor: 'drawing' stamp: 'ADT 8/15/2000 21:06'! FILLEDdrawHexAtPhysicalCoordinates: aPoint on: aCanvas (self hexIsVisibleAt: aPoint) ifFalse: [^self]. aCanvas clipBy: self innerBounds during: [:clippedCanvas | clippedCanvas drawPolygon: (self hexagonVerticesAtCoordinates: aPoint) fillStyle: (self colorForCoordinates: aPoint) borderWidth: self gridWidth borderColor: Color black]! ! !HexGrid methodsFor: 'drawing' stamp: 'ADT 8/9/2000 00:58'! OLDdrawHexAtPhysicalCoordinates: aPoint on: aCanvas (self hexIsVisibleAt: aPoint) ifFalse: [^self]. aCanvas clipBy: self innerBounds during: [:clippedCanvas | clippedCanvas drawPolygon: (self hexagonVerticesAtCoordinates: aPoint) fillStyle: (self colorForCoordinates: aPoint) borderWidth: 2 borderColor: (Color black)]! ! !HexGrid methodsFor: 'drawing' stamp: 'ADT 7/25/2000 12:57'! drawHexAtLogicalX: xindex Y: yindex on: aCanvas ^ self drawHexAtPhysicalCoordinates: (self physicalCoordinatesForX: xindex Y: yindex) on: aCanvas! ! !HexGrid methodsFor: 'drawing' stamp: 'ADT 9/8/2000 15:08'! drawHexAtPhysicalCoordinates: aPoint on: aCanvas (self hexIsVisibleAt: aPoint) ifFalse: [^self]. aCanvas clipBy: self innerBounds during: [:clippedCanvas | clippedCanvas drawPolygon: (self hexagonVerticesAtCoordinates: aPoint) fillStyle: (self colorForCoordinates: aPoint) borderWidth: self gridWidth borderColor: Color black]! ! !HexGrid methodsFor: 'drawing' stamp: 'ADT 9/8/2000 18:12'! drawOn: aCanvas "Draw a hexfield, scaled and rotated to reflect our current properties." | fc | fc _ Color black. self displayP ifTrue: [fc _ Color transparent. columns * -1 to: columns do: [:xindex | rows * -1 to: rows do: [:yindex | self drawHexAtLogicalX: xindex Y: yindex on: aCanvas. self drawHexAtLogicalX: (xindex + 0.5) Y: (yindex + 0.5) on: aCanvas]]]. aCanvas frameAndFillRectangle: bounds fillColor: fc borderWidth: 2 borderColor: Color white.! ! !HexGrid methodsFor: 'drawing' stamp: 'ADT 7/25/2000 12:57'! hexIsVisibleAt: aPoint ^(self bounds expandBy: (Point x: self radius y: self radius)) containsPoint: aPoint! ! !HexGrid methodsFor: 'drawing' stamp: 'ADT 7/25/2000 12:57'! hexagonVerticesAtCoordinates: aPoint "Answer an Array defining the vertices of a hexagon at logical coordinates aPoint, given the current scale, angle, etc. Called not only by myself, but my component hexes who want to know their vertices given my current properties." ^ (verticesCache collect: [ :v | aPoint + v])! ! !HexGrid methodsFor: 'dropping/grabbing' stamp: 'ADT 8/19/2000 02:24'! acceptDroppingMorph: aMorph event: evt "This message is sent when a morph is dropped onto a morph that has agreed to accept the dropped morph by responding 'true' to the wantsDroppedMorph:Event: message. This default implementation just adds the given morph to the receiver." "Ask the morph to act back on us: To translate ourselves, we create a special instance of hex, a grid ghost. When we receieve that, we translate ourselves by the offeset between its center cache and the current cursor point. The ghost is not kept. Otherwise, hexes add themselves to me, and annoations add themselves to hexes they are dropped on." aMorph dropOnto: self withEvent: evt ! ! !HexGrid methodsFor: 'dropping/grabbing' stamp: 'ADT 8/24/2000 11:02'! rotateWithGhost: aGhost event: evt "To translate or rotate ourselves, we can create a special instance of hex, a grid ghost. When we receieve that, we translate or rotate ourselves by the offeset between its center cache and the current cursor point. The ghost is not kept. We accumulate translations to allow relative movement..." self rotateWithStart: aGhost centerCache end: evt cursorPoint ! ! !HexGrid methodsFor: 'dropping/grabbing' stamp: 'ADT 8/24/2000 11:03'! translateWithGhost: aGhost event: evt "To translate ourselves, we create a special instance of hex, a grid ghost. When we receieve that, we translate ourselves by the offeset between its center cache and the current cursor point. The ghost is not kept. We accumulate translations to allow relative movement..." | offset | offset _ self logicalCoordinatesForPoint: ((evt cursorPoint - (aGhost centerCache)) + self center). self translation: (self translation + offset) ! ! !HexGrid methodsFor: 'dropping/grabbing' stamp: 'ADT 7/25/2000 12:57'! wantsDroppedMorph: aMorph event: evt "Return true if the receiver wishes to accept the given morph, which is being dropped by a hand in response to the given event. The default implementation returns false. NOTE: the event is assumed to be in global (world) coordinates." ^ (aMorph isKindOf: HexagonMorph) ! ! !HexGrid methodsFor: 'event handling' stamp: 'ADT 8/23/2000 04:56'! click: evt "Clicking zooms me in. Shift-clicking zooms me out." evt yellowButtonPressed "First check for option (menu) click" ifTrue: [^ self yellowButtonActivity: evt]. evt shiftPressed ifTrue: [self zoomOut] ifFalse: [self zoomIn] ! ! !HexGrid methodsFor: 'event handling' stamp: 'ADT 7/25/2000 12:57'! doubleClick: evt "Shift double clicking toggles connections between open and closed. Simple double clicking activates me." evt shiftPressed ifFalse: [self stopPlayback] ! ! !HexGrid methodsFor: 'event handling' stamp: 'ADT 8/23/2000 04:50'! drag: evt "Implement logic to translate the world here." evt isMouseDown ifTrue: [| g | g _ HexGridGhost new. g centerCache: evt cursorPoint. evt hand attachMorph: g]! ! !HexGrid methodsFor: 'event handling' stamp: 'ADT 7/25/2000 12:57'! handlesMouseDown: evt ^ true! ! !HexGrid methodsFor: 'event handling' stamp: 'ADT 9/8/2000 18:20'! handlesMouseOver: evt ^ true! ! !HexGrid methodsFor: 'event handling' stamp: 'ADT 7/25/2000 12:57'! mouseDown: evt "Do nothing upon mouse-down except inform the hand to watch for a double-click; wait until an ensuing click:, doubleClick:, or drag: message gets dispatched" evt hand waitForClicksOrDrag: self event: evt! ! !HexGrid methodsFor: 'event handling' stamp: 'ADT 9/8/2000 18:24'! mouseEnter: evt ((self hexWorld == nil) not and: [self hexWorld playingP not]) ifTrue: [evt hand showTemporaryCursor: Cursor webLink]! ! !HexGrid methodsFor: 'event handling' stamp: 'ADT 9/8/2000 18:24'! mouseLeave: evt evt hand showTemporaryCursor: nil! ! !HexGrid methodsFor: 'event handling' stamp: 'ADT 7/29/2000 22:34'! mouseUp: evt "Handle a mouse up event. The default response is to let my eventHandler, if any, handle it." self eventHandler ifNotNil: [Cursor normal show]. ! ! !HexGrid methodsFor: 'event handling' stamp: 'ADT 8/23/2000 04:56'! yellowButtonActivity: evt self zoomOut! ! !HexGrid methodsFor: 'hexagon operations' stamp: 'ADT 8/5/2000 19:27'! clearCanvas self hexagons do: [ :h | h delete] ! ! !HexGrid methodsFor: 'hexagon operations' stamp: 'ADT 7/25/2000 12:57'! hexAtCoordinates: aPoint "Answer (the first) hex at aPoint, if any." "Bears thinking about, is it worth keeping a registry...?" ^self hexagons detect: [ :aHex | aHex coordinates = aPoint] ifNone: [nil]! ! !HexGrid methodsFor: 'hexagon operations' stamp: 'ADT 7/25/2000 12:57'! hexagons "Answer my submorphs who are proper HexagonMorphs. Could register them but this works for now." ^self submorphs select: [:sub | sub isKindOf: HexagonMorph].! ! !HexGrid methodsFor: 'hexagon operations' stamp: 'ADT 8/19/2000 02:31'! placeHex: aHex At: aPoint "Actually do the work of putting a hex at aPoint. Determine if there are hexes in adjacent coordinates. If so, connect to them with the default connection." | nearby | self addMorphFront: aHex. aHex coordinates: aPoint. nearby _ self neighborCoordinates collect: [ :anOffset | aPoint + anOffset]. self hexagons do: [ :aPotentialNeighbor | | direction | "index of nearby coordinates is direction *to* that neighbor..." direction _ nearby indexOf: (aPotentialNeighbor coordinates). (direction = 0) ifFalse: [aHex connectTo: aPotentialNeighbor at: direction]]. self hexChanged ! ! !HexGrid methodsFor: 'hexagon operations' stamp: 'ADT 9/9/2000 02:51'! reset self stopPlayback. self hexagons do: [ :h | h reset] ! ! !HexGrid methodsFor: 'hexagon operations' stamp: 'ADT 7/25/2000 12:57'! stopPlayback self hexagons do: [ :h | h killPlay] ! ! !HexGrid methodsFor: 'hexagon operations' stamp: 'ADT 9/8/2000 14:31'! toggleGrid "Toggle whether or not we are to display on and off." self displayP: (self displayP not). "self changed" "moved to displayP:" ! ! !HexGrid methodsFor: 'hierarchy operations' stamp: 'ADT 8/8/2000 15:27'! hexWorld ^self owner owner! ! !HexGrid methodsFor: 'initialization' stamp: 'ADT 8/23/2000 04:26'! initialize super initialize. self unscaledRadius: 15; rows: 10; columns: 10; angle: 0; scale: 1; translation: 0 @ 0; displayP: false. vResizing _ #rigid. hResizing _ #rigid. self height: 300. self width: 600! ! !HexGrid methodsFor: 'layout' stamp: 'ADT 8/21/2000 22:26'! minHeightWhenEmpty ^ 300 ! ! !HexGrid methodsFor: 'layout' stamp: 'ADT 8/21/2000 22:26'! minWidthWhenEmpty ^ 300 ! ! !HexGrid methodsFor: 'notification' stamp: 'ADT 7/25/2000 12:57'! hexChanged "Private implementation that in addtion to cascading to normal changed, also triggers update of our constituent hexes. Specifically used to force nodes to update when the grid is rotated, scaled or translated." self recalculateHexCache. self hexagons do: [:aHex | aHex updateWithGrid: self]. self changed.! ! !HexGrid methodsFor: 'optimizations' stamp: 'ADT 7/25/2000 12:57'! recalculateHexCache | radians points x y r | "Cache an Array defining the vertices of a hexagon at 0@0, to be added to coordinates of real hexes, given the current scale, angle, etc." points _ OrderedCollection new. 0 to: 360 by: 60 do: [:hexAngle | r _ self radius. radians _ (hexAngle + self angle) degreesToRadians. x _ (r * radians cos) rounded. y _ (r * radians sin) rounded. points add: x @ y]. verticesCache _ Array withAll: points! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! addMorphFront: aMorph | newSubmorphs | aMorph owner ifNotNil: [aMorph owner privateRemoveMorph: aMorph]. "aMorph layoutChanged." aMorph privateOwner: self. newSubmorphs _ submorphs species new: submorphs size + 1. newSubmorphs at: 1 put: aMorph. newSubmorphs replaceFrom: 2 to: newSubmorphs size with: submorphs startingAt: 1. submorphs _ newSubmorphs. "aMorph changed. self layoutChanged." ! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! addTestHexes self addMorph: (HexagonMorph coordinates: 0@0 color: (Color blue)). self addMorph: (HexagonMorph coordinates: 0.5@0.5 color: (Color green)). self addMorph: (HexagonMorph coordinates: 1@0 color: (Color yellow)). self addMorph: (HexagonMorph coordinates: 1.5@0.5 color: (Color orange)). self addMorph: (HexagonMorph coordinates: 2@0 color: (Color red)). self addMorph: (HexagonMorph coordinates: 2.5@0.5 color: (Color magenta)). self addMorph: (HexagonMorph coordinates: -0.5@0.5 color: (Color white)).! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! neighborCoordinates "Answer a table with offsets necessary to arrive at all of a given hex's neighbors. Neighbor in this case being defined as those sharing a side. Those sharing a side can be connected." lookupTable == nil ifTrue: [lookupTable _ Array new: 6. lookupTable at: 1 put: 0.5@0.5; at: 2 put: 0@1; at: 3 put: -0.5@0.5; at: 4 put: -0.5@-0.5; at: 5 put: 0@-1; at: 6 put: 0.5@-0.5]. ^lookupTable! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! privateAddMorph: aMorph atIndex: index ((index >= 1) and: [index <= (submorphs size + 1)]) ifFalse: [^ self error: 'index out of range']. aMorph owner ifNotNil: [aMorph owner privateRemoveMorph: aMorph]. "aMorph layoutChanged." aMorph privateOwner: self. submorphs _ submorphs copyReplaceFrom: index to: index-1 with: (Array with: aMorph). "self layoutChanged."! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! privateRemoveMorph: aMorph "Private!! Should only be used by methods that maintain the ower/submorph invariant." aMorph changed. submorphs _ submorphs copyWithout: aMorph. "self layoutChanged." ! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! unscaledRadius radius == nil ifTrue: [self radius: 20]. ^ radius! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! unscaledRadius: t1 radius _ t1! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! xfactor xfactor == nil ifTrue: [self xfactor: 1]. xfactor. ^ xfactor! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! xfactor: aFloat xfactor _ aFloat. ^ self! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! yfactor yfactor == nil ifTrue: [self yfactor: 0]. yfactor. ^ yfactor! ! !HexGrid methodsFor: 'private' stamp: 'ADT 7/25/2000 12:57'! yfactor: aFloat yfactor _ aFloat. ^ self! ! !HexGrid methodsFor: 'visual properties' stamp: 'ADT 8/9/2000 01:02'! defaultWidth ^2! ! !HexGrid methodsFor: 'visual properties' stamp: 'ADT 8/9/2000 01:03'! gridWidth ^(self defaultWidth * self scale) rounded max: 1! ! Smalltalk renameClassNamed: #HexCyclicalConnectionState as: #HexIndexedConnectionState! !HexIndexedConnectionState commentStamp: 'ADT 8/6/2000 00:31' prior: 0! I am a subclass of dynamic connection state which iterates over a fixed list of states. stateList is the list (arbitrary length) of states, which alternate between #open and #closed. Hypothetically I could also have a state such as #test, and hold onto a test which could be evaluated when that state is my current one. index is the pointer into that list. My index moves every time I am twiddled. It wraps around. I will get around to implementing a wrap-around flag. Currently I always do.! !HexIndexedConnectionState reorganize! ('accessing' currentStateForChi: opposite) ('accessing - index' incrementIndex index index:) ('drawing' activeColor drawOn:in:at: inactiveColor) ('reset' reset) ('state based' stateList stateList: twidle) ('testing' oppositesP twidlesP) ! !HexIndexedConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 00:44'! currentStateForChi: aChi "Answer the status of me, given the current index" ^self stateList at: self index! ! !HexIndexedConnectionState methodsFor: 'accessing' stamp: 'ADT 8/5/2000 17:32'! opposite "Return an instance of myself that is philosophically opposite myself. Fixed open instances return fixed closed instances and vice versa. Binary togglers return themselves with position reversed. If 'opposite' doesn't make sense, I can return myself." self stateList: self stateList reversed. ^self! ! !HexIndexedConnectionState methodsFor: 'accessing - index' stamp: 'ADT 8/5/2000 18:07'! incrementIndex | i | ((i _ self index + 1) > (self stateList size)) ifTrue: [i _ 1]. self index: i! ! !HexIndexedConnectionState methodsFor: 'accessing - index' stamp: 'ADT 8/5/2000 17:10'! index index == nil ifTrue: [self index: 1]. ^index! ! !HexIndexedConnectionState methodsFor: 'accessing - index' stamp: 'ADT 8/5/2000 18:06'! index: anInt index _ anInt. ^self! ! !HexIndexedConnectionState methodsFor: 'drawing' stamp: 'ADT 8/5/2000 19:20'! activeColor ^Color white! ! !HexIndexedConnectionState methodsFor: 'drawing' stamp: 'ADT 9/9/2000 22:33'! drawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position aFacet. Draw a half-line to indicates when I'm blocked. Draw a circle to indicates when I'm open." | end v pts numParts col dc aw ac lp | v _ aHex verticesInsetBy: 0.7. facetNumber = 6 ifTrue: [end _ 1] ifFalse: [end _ facetNumber + 1]. numParts _ self stateList size. pts _ self points: (numParts + 1) between: (v at: facetNumber) and: (v at: end). dc _ self activeColor. aw _ aHex annotationWidth. ac _ aHex annotationColor. lp _ self lookPolicy. 1 to: numParts do: [ :i | self index = i ifTrue: [col _ dc ] ifFalse: [col _ ac]. (self stateList at: i) == #closed ifTrue: [lp drawStyle == #shadow ifTrue: [aCanvas line: ((pts at: i) + lp shadowOffset) to: ((pts at: (i + 1))+ lp shadowOffset) width: aw color: lp shadowColor]. aCanvas line: (pts at: i) to: (pts at: (i + 1)) width: aw color: col] ifFalse: [lp drawStyle == #shadow ifTrue: [aCanvas fillOval: (Rectangle center: ((self midpointBetween: (pts at: i) and: (pts at: (i + 1))) + lp shadowOffset) extent: ((pts at: i) dist: (pts at: (i + 1)))) fillStyle: lp shadowColor borderWidth: 0 borderColor: Color transparent]. aCanvas fillOval: (Rectangle center: (self midpointBetween: (pts at: i) and: (pts at: (i + 1))) extent: ((pts at: i) dist: (pts at: (i + 1)))) fillStyle: col borderWidth: 0 borderColor: Color transparent]]! ! !HexIndexedConnectionState methodsFor: 'drawing' stamp: 'ADT 8/16/2000 02:09'! inactiveColor ^Color gray! ! !HexIndexedConnectionState methodsFor: 'reset' stamp: 'ADT 9/9/2000 02:46'! reset self index: 1.! ! !HexIndexedConnectionState methodsFor: 'state based' stamp: 'ADT 8/5/2000 17:27'! stateList "Answer an OrderedCollection, consisting of the states that I am when my index is n" stateList == nil ifTrue: [self stateList: (OrderedCollection with: #open)]. ^stateList! ! !HexIndexedConnectionState methodsFor: 'state based' stamp: 'ADT 8/5/2000 18:03'! stateList: anOrderedCollection "Set an OrderedCollection, consisting of the states that I am when my index is n" stateList _ anOrderedCollection. ^self! ! !HexIndexedConnectionState methodsFor: 'state based' stamp: 'ADT 8/5/2000 17:16'! twidle "Step to next position, if I'm activation-based." self incrementIndex. ^self! ! !HexIndexedConnectionState methodsFor: 'testing' stamp: 'ADT 8/5/2000 20:03'! oppositesP ^true! ! !HexIndexedConnectionState methodsFor: 'testing' stamp: 'ADT 8/5/2000 17:07'! twidlesP ^true! ! !HexIndexedConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/5/2000 18:12'! toggling "Answer an instance that is a two-state toggler." ^(self with: #open with: #closed)! ! !HexIndexedConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/5/2000 18:12'! with: s1 with: s2 "Answer an instance that is a two-state toggler." ^self new stateList: (OrderedCollection with: s1 with: s2)! ! !HexIndexedConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/5/2000 18:12'! with: s1 with: s2 with: s3 "Answer an instance that is a three-state toggler." ^self new stateList: (OrderedCollection with: s1 with: s2 with: s3)! ! !HexIndexedConnectionState class methodsFor: 'menus' stamp: 'ADT 8/23/2000 02:46'! LABELEDaddRowsToPalette: aPalette aPalette add: (self with: #closed with: #open with: #closed) label: '- o -'. aPalette add: (self with: #open with: #closed with: #closed) label: 'o - -'. aPalette add: (self with: #closed with: #closed with: #open) label: '- - o'. aPalette add: (self with: #open with: #closed with: #open) label: 'o - o'. aPalette add: (self with: #closed with: #open with: #open) label: '- o o'. aPalette add: (self with: #open with: #open with: #closed) label: 'o o -'. aPalette add: self toggling label: 'toggling'. aPalette addLabelText: 'indexed' ! ! !HexIndexedConnectionState class methodsFor: 'menus' stamp: 'ADT 8/23/2000 03:00'! addRowsToPalette: aPalette | stack | stack _ OrderedCollection new. stack add: (self with: #closed with: #open with: #closed); add: (self with: #open with: #closed with: #closed); add: (self with: #closed with: #closed with: #open); add: (self with: #open with: #closed with: #open); add: (self with: #closed with: #open with: #open); add: (self with: #open with: #open with: #closed); add: self toggling. aPalette addMules: stack. aPalette addLabelText: 'indexed' ! ! !HexIndexedConnectionState class methodsFor: 'menus' stamp: 'ADT 8/23/2000 01:40'! getMenuWithEvent: evt facet: facet target: target "Facet dependent sub-submenu. Requested by HexConnection...." | sub | sub _ MenuMorph new defaultTarget: target. sub add: 'toggling' selector: #newState: argument: (self toggling). sub add: 'o o -' selector: #newState: argument: (self with: #open with: #open with: #closed). sub add: '- o o' selector: #newState: argument: (self with: #closed with: #open with: #open). sub add: 'o - o' selector: #newState: argument: (self with: #open with: #closed with: #open). sub add: '- - o' selector: #newState: argument: (self with: #closed with: #closed with: #open). sub add: 'o - -' selector: #newState: argument: (self with: #open with: #closed with: #closed). sub add: '- o -' selector: #newState: argument: (self with: #closed with: #open with: #closed). ^ sub! ! Smalltalk renameClassNamed: #LookPolicy as: #HexLookPolicy! !HexLookPolicy reorganize! ('accessing' color color: drawStyle drawStyle: shadow: shadowColor shadowColor: shadowOffset shadowOffset: windowColor windowColor:) ('font properties' defaultFont defaultFontSize fontOfSize:) ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:32'! color color == nil ifTrue: [self color: Color blue]. ^ color! ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 7/12/2000 23:59'! color: aColor color _ aColor. ^self! ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:29'! drawStyle drawStyle == nil ifTrue: [self drawStyle: #shadow]. ^ drawStyle! ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:29'! drawStyle: aSymbol drawStyle _ aSymbol. ^self! ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 9/9/2000 23:32'! shadow: aBool "Interface for toggle buttons" aBool ifTrue: [self drawStyle: #shadow] ifFalse: [self drawStyle: #normal]! ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:32'! shadowColor shadowColor == nil ifTrue: [self shadowColor: Color gray]. ^ shadowColor! ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:30'! shadowColor: aColor shadowColor _ aColor. ^self! ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:32'! shadowOffset shadowOffset == nil ifTrue: [self shadowOffset: (Point x: 1 y: 1)]. ^shadowOffset! ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:32'! shadowOffset: aPoint shadowOffset _ aPoint. ^self! ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:42'! windowColor windowColor == nil ifTrue: [self windowColor: Color gray dansDarker]. ^ windowColor! ! !HexLookPolicy methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:42'! windowColor: aColor windowColor _ aColor. ^self! ! !HexLookPolicy methodsFor: 'font properties' stamp: 'ADT 9/9/2000 21:44'! defaultFont ^self fontOfSize: self defaultFontSize! ! !HexLookPolicy methodsFor: 'font properties' stamp: 'ADT 9/9/2000 21:44'! defaultFontSize ^36! ! !HexLookPolicy methodsFor: 'font properties' stamp: 'ADT 9/9/2000 21:44'! fontOfSize: anInteger ^StrikeFont familyName: #NewYork size: anInteger! ! !HexMirrorAnnotation reorganize! ('accessing' opposite privateOpposite) ('drawing' drawOn:in:at:) ('model - chi' postactivateWithChi:) ('printing' printOn:) ('testing' oppositesP) ('visual properties' annotationColor) ! !HexMirrorAnnotation methodsFor: 'accessing' stamp: 'ADT 8/17/2000 01:42'! opposite "Requires special action, should be cleaned up!!" self hex removeAnnotation: self. self hex newAnnotation: self privateOpposite! ! !HexMirrorAnnotation methodsFor: 'accessing' stamp: 'ADT 8/17/2000 01:40'! privateOpposite ^HexSinkAnnotation new! ! !HexMirrorAnnotation methodsFor: 'drawing' stamp: 'ADT 9/9/2000 22:17'! drawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position oriented towards aFacet." | r lp | lp _ self lookPolicy. r _ Rectangle encompassing: (aHex verticesInsetBy: 0.4). lp drawStyle == #shadow ifTrue: [| s | s _ r translateBy: lp shadowOffset. aCanvas drawPolygon: (Array with: (s bottomLeft) with: (s topLeft) with: (s bottomCenter) with: (s topRight) with: (s bottomRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (r bottomLeft) with: (r topLeft) with: (r bottomCenter) with: (r topRight) with: (r bottomRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor! ! !HexMirrorAnnotation methodsFor: 'model - chi' stamp: 'ADT 8/17/2000 01:24'! postactivateWithChi: aChi "Insure that aChi reflects back out the direction it entered, just as it will be propogated on in all *other* directions" aChi momentumDirection: 0. "so no direction is 'no go'!!" ^aChi! ! !HexMirrorAnnotation methodsFor: 'printing' stamp: 'ADT 8/15/2000 21:27'! printOn: aStream aStream nextPutAll: 'Mirror' ! ! !HexMirrorAnnotation methodsFor: 'testing' stamp: 'ADT 8/17/2000 01:31'! oppositesP ^true! ! !HexMirrorAnnotation methodsFor: 'visual properties' stamp: 'ADT 8/21/2000 21:48'! annotationColor ^Color lightBlue! ! !HexMutatorAnnotation commentStamp: 'ADT 8/8/2000 23:55' prior: 0! I am an annotation that transforms an aspect of the chi that passes through me. Operations I might perform are raise, lower, and set...! !HexMutatorAnnotation reorganize! ('accessing' aspect aspect: opposite polarity polarity:) ('drawing' drawAmplitudeOn:in:at: drawOn:in:at:) ('model - chi' preactivateWithChi:) ('printing' printOn:) ('testing' oppositesP) ('visual properties' annotationColor) ! !HexMutatorAnnotation methodsFor: 'accessing' stamp: 'ADT 8/6/2000 01:51'! aspect "Set the property that I test against the threshold" aspect == nil ifTrue: [self aspect: #amplitude]. ^aspect! ! !HexMutatorAnnotation methodsFor: 'accessing' stamp: 'ADT 8/6/2000 01:51'! aspect: aSymbol "Set the property that I test against the threshold" aspect _ aSymbol. ^self! ! !HexMutatorAnnotation methodsFor: 'accessing' stamp: 'ADT 8/8/2000 13:37'! opposite self polarity == #increase ifTrue: [self polarity: #decrease. self hex changed] ifFalse: [self polarity: #increase. self hex changed]. ^self! ! !HexMutatorAnnotation methodsFor: 'accessing' stamp: 'ADT 8/6/2000 02:05'! polarity "Answer whether I increase or decrease the aspect" polarity == nil ifTrue: [self polarity: #increase]. ^polarity! ! !HexMutatorAnnotation methodsFor: 'accessing' stamp: 'ADT 8/6/2000 02:05'! polarity: aSymbol "Set whether I increase or decrease the aspect" polarity _ aSymbol. ^self! ! !HexMutatorAnnotation methodsFor: 'drawing' stamp: 'ADT 9/9/2000 22:23'! drawAmplitudeOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position oriented towards aFacet." | r lp | r _ Rectangle encompassing: (aHex verticesInsetBy: 0.3). lp _ self lookPolicy. self polarity == #increase ifTrue: [lp drawStyle == #shadow ifTrue: [| s | s _ r translateBy: lp shadowOffset. aCanvas drawPolygon: (Array with: (s bottomLeft) with: (s bottomRight) with: (s topRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (r bottomLeft) with: (r bottomRight) with: (r topRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor] ifFalse: [lp drawStyle == #shadow ifTrue: [| s | s _ r translateBy: lp shadowOffset. aCanvas drawPolygon: (Array with: (s topLeft) with: (s bottomLeft) with: (s bottomRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (r topLeft) with: (r bottomLeft) with: (r bottomRight) ) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor] ! ! !HexMutatorAnnotation methodsFor: 'drawing' stamp: 'ADT 9/9/2000 22:31'! drawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position oriented towards aFacet." | r lp | self aspect == #amplitude ifTrue: [^self drawAmplitudeOn: aCanvas in: aHex at: facetNumber]. "aspect must be #velocity" lp _ self lookPolicy. r _ Rectangle encompassing: (aHex verticesInsetBy: 0.3). self polarity == #increase ifTrue: [lp drawStyle == #shadow ifTrue: [| s | s _ r translateBy: lp shadowOffset. aCanvas drawPolygon: (Array with: (s topCenter) with: (s bottomCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: (s leftCenter) with: (s rightCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (r topCenter) with: (r bottomCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (r leftCenter) with: (r rightCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor] ifFalse: [lp drawStyle == #shadow ifTrue: [| s | s _ r translateBy: lp shadowOffset. aCanvas drawPolygon: (Array with: (s leftCenter) with: (s rightCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (r leftCenter) with: (r rightCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor] ! ! !HexMutatorAnnotation methodsFor: 'model - chi' stamp: 'ADT 8/17/2000 01:27'! preactivateWithChi: aChi "Affect aChi if I like, according to what I am. We ask the chi itself to handle this..." ^aChi mutateAspect: self aspect with: self polarity andMaybe: nil! ! !HexMutatorAnnotation methodsFor: 'printing' stamp: 'ADT 8/8/2000 14:06'! printOn: aStream aStream nextPutAll: 'Mutator: '. aStream nextPutAll: (self polarity printString). aStream nextPutAll: ' '. aStream nextPutAll: (self aspect printString). ! ! !HexMutatorAnnotation methodsFor: 'testing' stamp: 'ADT 8/8/2000 13:37'! oppositesP ^true! ! !HexMutatorAnnotation methodsFor: 'visual properties' stamp: 'ADT 8/21/2000 21:48'! annotationColor self aspect == #amplitude ifTrue: [^Color lightGreen]. self aspect == #velocity ifTrue: [^Color lightRed]. ^super annotationColor! ! !HexMutatorAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/6/2000 02:39'! amplitudeDecrease ^self new polarity: #decrease; aspect: #amplitude! ! !HexMutatorAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/6/2000 02:39'! amplitudeIncrease ^self new polarity: #increase; aspect: #amplitude! ! !HexMutatorAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/6/2000 02:39'! velocityDecrease ^self new polarity: #decrease; aspect: #velocity! ! !HexMutatorAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/6/2000 02:39'! velocityIncrease ^self new polarity: #increase; aspect: #velocity! ! !HexMutatorAnnotation class methodsFor: 'menus' stamp: 'ADT 8/19/2000 04:51'! addRowsToPalette: aPalette "Needs to be modified so sub MutatorSetAnnotation handles its own menu!!" aPalette add: (HexMutatorSetAnnotation velocityMin) label: 'velocity minimum'. aPalette add: (self velocityDecrease) label: 'velocity decrease'. aPalette add: (HexMutatorSetAnnotation velocityReset) label: 'velocity reset'. aPalette add: (self velocityIncrease) label: 'velocity increase'. aPalette add: (HexMutatorSetAnnotation velocityMax) label: 'velocity maximum'. "aPalette addLine." aPalette add: (HexMutatorSetAnnotation amplitudeMin) label: 'amplitude minimum'. aPalette add: (self amplitudeDecrease) label: 'amplitude decrease'. aPalette add: (HexMutatorSetAnnotation amplitudeReset) label: 'amplitude reset'. aPalette add: (self amplitudeIncrease) label: 'amplitude increase'. aPalette add: (HexMutatorSetAnnotation amplitudeMax) label: 'amplitude maximum'. aPalette addLabelText: 'mutators' ! ! !HexMutatorAnnotation class methodsFor: 'menus' stamp: 'ADT 8/15/2000 21:17'! getMenuWithEvent: evt hex: aHex "Facet dependent sub-submenu. Requested by HexAnnotation..." "Needs to be modified so sub MutatorSetAnnotation handles its own menu!!" | sub | sub _ MenuMorph new defaultTarget: aHex. sub add: 'amplitude maximum' selector: #newAnnotation: argument: (HexMutatorSetAnnotation amplitudeMax). sub add: 'amplitude increase' selector: #newAnnotation: argument: (self amplitudeIncrease). sub add: 'amplitude reset' selector: #newAnnotation: argument: (HexMutatorSetAnnotation amplitudeReset). sub add: 'amplitude decrease' selector: #newAnnotation: argument: (self amplitudeDecrease). sub add: 'amplitude minimum' selector: #newAnnotation: argument: (HexMutatorSetAnnotation amplitudeMin). sub addLine. sub add: 'velocity maximum' selector: #newAnnotation: argument: (HexMutatorSetAnnotation velocityMax). sub add: 'velocity increase' selector: #newAnnotation: argument: (self velocityIncrease). sub add: 'velocity reset' selector: #newAnnotation: argument: (HexMutatorSetAnnotation velocityReset). sub add: 'velocity decrease' selector: #newAnnotation: argument: (self velocityDecrease). sub add: 'velocity minimum' selector: #newAnnotation: argument: (HexMutatorSetAnnotation velocityMin). ^ sub! ! !HexMutatorSetAnnotation commentStamp: 'ADT 8/8/2000 23:55' prior: 0! I am a subclass of mutator that sets an aspect of the chi that passes through me to the value I call load.! !HexMutatorSetAnnotation methodsFor: 'accessing' stamp: 'ADT 8/8/2000 13:36'! load "Answer the value that I set the aspect to, if any" ^load! ! !HexMutatorSetAnnotation methodsFor: 'accessing' stamp: 'ADT 8/9/2000 00:00'! load: aMagnitude "Set the value that I set the aspect to, if any" load _ aMagnitude. ^self! ! !HexMutatorSetAnnotation methodsFor: 'testing' stamp: 'ADT 8/8/2000 13:37'! oppositesP ^false! ! !HexMutatorSetAnnotation methodsFor: 'drawing' stamp: 'ADT 9/9/2000 22:28'! drawOn: aCanvas in: aHex at: facetNumber | r lp | r _ Rectangle encompassing: (aHex verticesInsetBy: 0.3). lp _ self lookPolicy. lp drawStyle == #shadow ifTrue: [| s | s _ r translateBy: lp shadowOffset. aCanvas drawPolygon: (Array with: (s topLeft) with: (s topRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: (s bottomLeft) with: (s bottomRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (r topLeft) with: (r topRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (r bottomLeft) with: (r bottomRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor. ((self load == #default) or: [self load isNumber]) ifFalse: [| rr ss | rr _ Rectangle encompassing: (aHex verticesInsetBy: 0.2). lp drawStyle == #shadow ifTrue: [ss _ rr translateBy: lp shadowOffset. aCanvas drawPolygon: (Array with: (ss leftCenter) with: (ss rightCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (rr leftCenter) with: (rr rightCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor. self load == #max ifTrue: [lp drawStyle == #shadow ifTrue: [aCanvas drawPolygon: (Array with: (ss topCenter) with: (ss bottomCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (rr topCenter) with: (rr bottomCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor]].! ! !HexMutatorSetAnnotation methodsFor: 'model - chi' stamp: 'ADT 8/17/2000 01:27'! preactivateWithChi: aChi "Affect aChi if I like, according to what I am. We ask the chi itself to handle this..." ^aChi mutateAspect: self aspect with: #set andMaybe: self load! ! !HexMutatorSetAnnotation methodsFor: 'printing' stamp: 'ADT 8/8/2000 14:07'! printOn: aStream aStream nextPutAll: 'Mutator: '. aStream nextPutAll: 'reset '. aStream nextPutAll: (self aspect printString). ! ! !HexMutatorSetAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/21/2000 20:32'! amplitudeMax ^self new aspect: #amplitude; load: #max! ! !HexMutatorSetAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/21/2000 20:31'! amplitudeMin ^self new aspect: #amplitude; load: #min! ! !HexMutatorSetAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/8/2000 13:41'! amplitudeReset ^self new aspect: #amplitude; load: #default! ! !HexMutatorSetAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/21/2000 20:31'! velocityMax ^self new aspect: #velocity; load: #max! ! !HexMutatorSetAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/21/2000 20:31'! velocityMin ^self new aspect: #velocity; load: #min! ! !HexMutatorSetAnnotation class methodsFor: 'instance creation' stamp: 'ADT 8/8/2000 13:41'! velocityReset ^self new aspect: #velocity; load: #default! ! !HexPalette reorganize! ('initialization' addCloseButton addRows initialize makeCloseButton makePaletteRows) ! !HexPalette methodsFor: 'initialization' stamp: 'ADT 8/19/2000 03:43'! addCloseButton "Add some temporary, ugly controls" self addMorph: self makeCloseButton. ^self ! ! !HexPalette methodsFor: 'initialization' stamp: 'ADT 8/16/2000 02:29'! addRows "Add some temporary, ugly palette rows" self makePaletteRows! ! !HexPalette methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:51'! initialize super initialize. self addRows. self addLabel! ! !HexPalette methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:40'! makeCloseButton ^self buildButtonWithTarget: self label: 'close' selector: #delete! ! !HexPalette methodsFor: 'initialization' stamp: 'ADT 8/16/2000 02:31'! makePaletteRows self subclassResponsibility! ! !HexExtrasPalette reorganize! ('palette properties' foreColor label) ('initialization' addRows) ! !HexExtrasPalette methodsFor: 'palette properties' stamp: 'ADT 8/19/2000 03:01'! foreColor ^Color gray! ! !HexExtrasPalette methodsFor: 'palette properties' stamp: 'ADT 8/16/2000 02:36'! label ^'Rest (silent)'! ! !HexExtrasPalette methodsFor: 'initialization' stamp: 'ADT 8/19/2000 04:41'! addRows | a h | a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 1. h _ HexRestMorph default. h bePaletteVersion. a addMorph: h. self addMorph: a! ! !HexFMSoundPalette reorganize! ('initialization' makePaletteRows rows) ('palette properties' foreColor instrumentBorderColor) ('scales' aeolian dorian harmonic ionian pentatonic twelvetone) ! !HexFMSoundPalette methodsFor: 'initialization' stamp: 'ADT 9/8/2000 18:15'! makePaletteRows | a h d s l i | i _ self instrument. d _ self dur. l _ self loudness. self rows do: [ :aRow | "row is assumed to be a collection of hex templates" a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 1. aRow do: [ :aHexTemplate | "hex template is assumed to be a collection (color, pitch name)" h _ HexagonMorph coordinates: 0@0 color: (aHexTemplate at: 1). s _ HexFMSoundWrapper new pitchName: (aHexTemplate at: 2); instrumentName: i printString; magnitude: l; duration: d. s sound: ((HexFMSound perform: i) setPitch: (AbstractSound pitchForName: (aHexTemplate at: 2)) dur: d loudness: l). h sound: s; bePaletteVersion; borderColor: self instrumentBorderColor. a addMorph: h]. self addMorph: a]. ! ! !HexFMSoundPalette methodsFor: 'initialization' stamp: 'ADT 8/17/2000 00:53'! rows ^self perform: (HexMultiPalette scale) ! ! !HexFMSoundPalette methodsFor: 'palette properties' stamp: 'ADT 8/19/2000 03:08'! foreColor ^self instrumentBorderColor! ! !HexFMSoundPalette methodsFor: 'palette properties' stamp: 'ADT 8/19/2000 03:02'! instrumentBorderColor "Essentially the same as foreColor, but renamed to reflect what we *do* with it in our case..." self subclassResponsibility! ! !HexFMSoundPalette methodsFor: 'scales' stamp: 'ADT 8/17/2000 00:54'! aeolian | theRows row | theRows _ OrderedCollection new. row _ OrderedCollection new. row add: (Array with: (Color blue twiceDarker) with: 'a2'). row add: (Array with: (Color cyan twiceDarker) with: 'b2'). row add: (Array with: (Color green twiceDarker) with: 'c3'). row add: (Array with: (Color yellow twiceDarker) with: 'd3'). row add: (Array with: (Color orange twiceDarker) with: 'e3'). row add: (Array with: (Color red twiceDarker) with: 'f3'). row add: (Array with: (Color magenta twiceDarker) with: 'g3'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue dansDarker) with: 'a3'). row add: (Array with: (Color cyan dansDarker) with: 'b3'). row add: (Array with: (Color green dansDarker) with: 'c4'). row add: (Array with: (Color yellow dansDarker) with: 'd4'). row add: (Array with: (Color orange dansDarker) with: 'e4'). row add: (Array with: (Color red dansDarker) with: 'f4'). row add: (Array with: (Color magenta dansDarker) with: 'g4'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue ) with: 'a4'). row add: (Array with: (Color cyan ) with: 'b4'). row add: (Array with: (Color green ) with: 'c5'). row add: (Array with: (Color yellow ) with: 'd5'). row add: (Array with: (Color orange ) with: 'e5'). row add: (Array with: (Color red ) with: 'f5'). row add: (Array with: (Color magenta ) with: 'g5'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue lighter) with: 'a5'). row add: (Array with: (Color cyan lighter) with: 'b5'). row add: (Array with: (Color green lighter) with: 'c6'). row add: (Array with: (Color yellow lighter) with: 'd6'). row add: (Array with: (Color orange lighter) with: 'e6'). row add: (Array with: (Color red lighter) with: 'f6'). row add: (Array with: (Color magenta lighter) with: 'g6'). theRows add: row. ^ theRows ! ! !HexFMSoundPalette methodsFor: 'scales' stamp: 'ADT 8/17/2000 02:14'! dorian | theRows row | theRows _ OrderedCollection new. row _ OrderedCollection new. row add: (Array with: (Color blue twiceDarker) with: 'a2'). row add: (Array with: (Color cyan twiceDarker) with: 'b2'). row add: (Array with: (Color green twiceDarker) with: 'c3'). row add: (Array with: (Color yellow twiceDarker) with: 'd3'). row add: (Array with: (Color orange twiceDarker) with: 'e3'). row add: (Array with: ((Color red twiceDarker) mixed: 0.5 with: (Color magenta twiceDarker)) with: 'f#3'). row add: (Array with: (Color magenta twiceDarker) with: 'g3'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue dansDarker) with: 'a3'). row add: (Array with: (Color cyan dansDarker) with: 'b3'). row add: (Array with: (Color green dansDarker) with: 'c4'). row add: (Array with: (Color yellow dansDarker) with: 'd4'). row add: (Array with: (Color orange dansDarker) with: 'e4'). row add: (Array with: ((Color red dansDarker) mixed: 0.5 with: (Color magenta dansDarker)) with: 'f#4'). row add: (Array with: (Color magenta dansDarker) with: 'g4'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue ) with: 'a4'). row add: (Array with: (Color cyan ) with: 'b4'). row add: (Array with: (Color green ) with: 'c5'). row add: (Array with: (Color yellow ) with: 'd5'). row add: (Array with: (Color orange ) with: 'e5'). row add: (Array with: ((Color red ) mixed: 0.5 with: (Color magenta )) with: 'f#5'). row add: (Array with: (Color magenta ) with: 'g5'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue lighter) with: 'a5'). row add: (Array with: (Color cyan lighter) with: 'b5'). row add: (Array with: (Color green lighter) with: 'c6'). row add: (Array with: (Color yellow lighter) with: 'd6'). row add: (Array with: (Color orange lighter) with: 'e6'). row add: (Array with: ((Color red lighter) mixed: 0.5 with: (Color magenta lighter)) with: 'f#6'). row add: (Array with: (Color magenta lighter) with: 'g6'). theRows add: row. ^ theRows ! ! !HexFMSoundPalette methodsFor: 'scales' stamp: 'ADT 8/17/2000 02:20'! harmonic | theRows row | theRows _ OrderedCollection new. row _ OrderedCollection new. row add: (Array with: (Color blue twiceDarker) with: 'a2'). row add: (Array with: (Color cyan twiceDarker) with: 'b2'). row add: (Array with: (Color green twiceDarker) with: 'c3'). row add: (Array with: (Color yellow twiceDarker) with: 'd3'). row add: (Array with: (Color orange twiceDarker) with: 'e3'). row add: (Array with: (Color red twiceDarker) with: 'f3'). row add: (Array with: ((Color magenta twiceDarker) mixed: 0.5 with: (Color blue twiceDarker)) with: 'g#3'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue dansDarker) with: 'a3'). row add: (Array with: (Color cyan dansDarker) with: 'b3'). row add: (Array with: (Color green dansDarker) with: 'c4'). row add: (Array with: (Color yellow dansDarker) with: 'd4'). row add: (Array with: (Color orange dansDarker) with: 'e4'). row add: (Array with: (Color red dansDarker) with: 'f4'). row add: (Array with: ((Color magenta dansDarker) mixed: 0.5 with: (Color blue dansDarker)) with: 'g#4'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue ) with: 'a4'). row add: (Array with: (Color cyan ) with: 'b4'). row add: (Array with: (Color green ) with: 'c5'). row add: (Array with: (Color yellow ) with: 'd5'). row add: (Array with: (Color orange ) with: 'e5'). row add: (Array with: (Color red ) with: 'f5'). row add: (Array with: ((Color magenta ) mixed: 0.5 with: (Color blue)) with: 'g#5'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue lighter) with: 'a5'). row add: (Array with: (Color cyan lighter) with: 'b5'). row add: (Array with: (Color green lighter) with: 'c6'). row add: (Array with: (Color yellow lighter) with: 'd6'). row add: (Array with: (Color orange lighter) with: 'e6'). row add: (Array with: (Color red lighter) with: 'f6'). row add: (Array with: ((Color magenta lighter) mixed: 0.5 with: (Color blue lighter)) with: 'g#6'). theRows add: row. ^ theRows ! ! !HexFMSoundPalette methodsFor: 'scales' stamp: 'ADT 8/17/2000 02:18'! ionian | theRows row | theRows _ OrderedCollection new. row _ OrderedCollection new. row add: (Array with: (Color blue twiceDarker) with: 'a2'). row add: (Array with: (Color cyan twiceDarker) with: 'b2'). row add: (Array with: ((Color green twiceDarker) mixed: 0.5 with: (Color yellow twiceDarker)) with: 'c#3'). row add: (Array with: (Color yellow twiceDarker) with: 'd3'). row add: (Array with: (Color orange twiceDarker) with: 'e3'). row add: (Array with: ((Color red twiceDarker) mixed: 0.5 with: (Color magenta twiceDarker)) with: 'f#3'). row add: (Array with: ((Color magenta twiceDarker) mixed: 0.5 with: (Color blue twiceDarker)) with: 'g#3'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue dansDarker) with: 'a3'). row add: (Array with: (Color cyan dansDarker) with: 'b3'). row add: (Array with: ((Color green dansDarker) mixed: 0.5 with: (Color yellow dansDarker)) with: 'c#4'). row add: (Array with: (Color yellow dansDarker) with: 'd4'). row add: (Array with: (Color orange dansDarker) with: 'e4'). row add: (Array with: ((Color red dansDarker) mixed: 0.5 with: (Color magenta dansDarker)) with: 'f#4'). row add: (Array with: ((Color magenta dansDarker) mixed: 0.5 with: (Color blue dansDarker)) with: 'g#4'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue ) with: 'a4'). row add: (Array with: (Color cyan ) with: 'b4'). row add: (Array with: ((Color green ) mixed: 0.5 with: (Color yellow )) with: 'c#5'). row add: (Array with: (Color yellow ) with: 'd5'). row add: (Array with: (Color orange ) with: 'e5'). row add: (Array with: ((Color red ) mixed: 0.5 with: (Color magenta )) with: 'f#5'). row add: (Array with: ((Color magenta ) mixed: 0.5 with: (Color blue )) with: 'g#5'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue lighter) with: 'a5'). row add: (Array with: (Color cyan lighter) with: 'b5'). row add: (Array with: ((Color green lighter) mixed: 0.5 with: (Color yellow lighter)) with: 'c#6'). row add: (Array with: (Color yellow lighter) with: 'd6'). row add: (Array with: (Color orange lighter) with: 'e6'). row add: (Array with: ((Color red lighter) mixed: 0.5 with: (Color magenta lighter)) with: 'f#6'). row add: (Array with: ((Color magenta lighter) mixed: 0.5 with: (Color blue lighter)) with: 'g#6'). theRows add: row. ^ theRows ! ! !HexFMSoundPalette methodsFor: 'scales' stamp: 'ADT 8/17/2000 00:53'! pentatonic | theRows row | theRows _ OrderedCollection new. row _ OrderedCollection new. row add: (Array with: (Color blue twiceDarker) with: 'a2'). row add: (Array with: (Color green twiceDarker) with: 'c3'). row add: (Array with: (Color yellow twiceDarker) with: 'd3'). row add: (Array with: (Color orange twiceDarker) with: 'e3'). row add: (Array with: (Color red twiceDarker) with: 'g3'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue dansDarker) with: 'a3'). row add: (Array with: (Color green dansDarker) with: 'c4'). row add: (Array with: (Color yellow dansDarker) with: 'd4'). row add: (Array with: (Color orange dansDarker) with: 'e4'). row add: (Array with: (Color red dansDarker) with: 'g4'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue ) with: 'a4'). row add: (Array with: (Color green ) with: 'c5'). row add: (Array with: (Color yellow ) with: 'd5'). row add: (Array with: (Color orange ) with: 'e5'). row add: (Array with: (Color red ) with: 'g5'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue lighter) with: 'a5'). row add: (Array with: (Color green lighter) with: 'c6'). row add: (Array with: (Color yellow lighter) with: 'd6'). row add: (Array with: (Color orange lighter) with: 'e6'). row add: (Array with: (Color red lighter) with: 'g6'). theRows add: row. ^ theRows ! ! !HexFMSoundPalette methodsFor: 'scales' stamp: 'ADT 8/17/2000 02:16'! twelvetone | theRows row | theRows _ OrderedCollection new. row _ OrderedCollection new. row add: (Array with: (Color blue twiceDarker) with: 'a2'). row add: (Array with: ((Color blue twiceDarker) mixed: 0.5 with: (Color cyan twiceDarker)) with: 'a#2'). row add: (Array with: (Color cyan twiceDarker) with: 'b2'). row add: (Array with: (Color green twiceDarker) with: 'c3'). row add: (Array with: ((Color green twiceDarker) mixed: 0.5 with: (Color yellow twiceDarker)) with: 'c#3'). row add: (Array with: (Color yellow twiceDarker) with: 'd3'). row add: (Array with: ((Color yellow twiceDarker) mixed: 0.5 with: (Color orange twiceDarker)) with: 'd#3'). row add: (Array with: (Color orange twiceDarker) with: 'e3'). row add: (Array with: (Color red twiceDarker) with: 'f3'). row add: (Array with: ((Color red twiceDarker) mixed: 0.5 with: (Color magenta twiceDarker)) with: 'f#3'). row add: (Array with: (Color magenta twiceDarker) with: 'g3'). row add: (Array with: ((Color magenta twiceDarker) mixed: 0.5 with: (Color blue twiceDarker)) with: 'g#3'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue dansDarker) with: 'a3'). row add: (Array with: ((Color blue dansDarker) mixed: 0.5 with: (Color cyan dansDarker)) with: 'a#3'). row add: (Array with: (Color cyan dansDarker) with: 'b3'). row add: (Array with: (Color green dansDarker) with: 'c4'). row add: (Array with: ((Color green dansDarker) mixed: 0.5 with: (Color yellow dansDarker)) with: 'c#4'). row add: (Array with: (Color yellow dansDarker) with: 'd4'). row add: (Array with: ((Color yellow dansDarker) mixed: 0.5 with: (Color orange dansDarker)) with: 'd#4'). row add: (Array with: (Color orange dansDarker) with: 'e4'). row add: (Array with: (Color red dansDarker) with: 'f4'). row add: (Array with: ((Color red dansDarker) mixed: 0.5 with: (Color magenta dansDarker)) with: 'f#4'). row add: (Array with: (Color magenta dansDarker) with: 'g4'). row add: (Array with: ((Color magenta dansDarker) mixed: 0.5 with: (Color blue dansDarker)) with: 'g#4'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue ) with: 'a4'). row add: (Array with: ((Color blue ) mixed: 0.5 with: (Color cyan )) with: 'a#4'). row add: (Array with: (Color cyan ) with: 'b4'). row add: (Array with: (Color green ) with: 'c5'). row add: (Array with: ((Color green ) mixed: 0.5 with: (Color yellow )) with: 'c#5'). row add: (Array with: (Color yellow ) with: 'd5'). row add: (Array with: ((Color yellow ) mixed: 0.5 with: (Color orange )) with: 'd#5'). row add: (Array with: (Color orange ) with: 'e5'). row add: (Array with: (Color red ) with: 'f5'). row add: (Array with: ((Color red ) mixed: 0.5 with: (Color magenta )) with: 'f#5'). row add: (Array with: (Color magenta ) with: 'g5'). row add: (Array with: ((Color magenta ) mixed: 0.5 with: (Color blue )) with: 'g#5'). theRows add: row. row _ OrderedCollection new. row add: (Array with: (Color blue lighter) with: 'a5'). row add: (Array with: ((Color blue lighter) mixed: 0.5 with: (Color cyan lighter)) with: 'a#5'). row add: (Array with: (Color cyan lighter) with: 'b5'). row add: (Array with: (Color green lighter) with: 'c6'). row add: (Array with: ((Color green lighter) mixed: 0.5 with: (Color yellow lighter)) with: 'c#6'). row add: (Array with: (Color yellow lighter) with: 'd6'). row add: (Array with: ((Color yellow lighter) mixed: 0.5 with: (Color orange lighter)) with: 'd#6'). row add: (Array with: (Color orange lighter) with: 'e6'). row add: (Array with: (Color red lighter) with: 'f6'). row add: (Array with: ((Color red lighter) mixed: 0.5 with: (Color magenta lighter)) with: 'f#6'). row add: (Array with: (Color magenta lighter) with: 'g6'). row add: (Array with: ((Color magenta lighter) mixed: 0.5 with: (Color blue lighter)) with: 'g#6'). theRows add: row. ^ theRows ! ! !HexBassPalette reorganize! ('default - sounds' dur loudness) ('palette properties' instrument instrumentBorderColor label) ! !HexBassPalette methodsFor: 'default - sounds' stamp: 'ADT 7/26/2000 01:45'! dur "Answer default duration to play each tone" ^0.25! ! !HexBassPalette methodsFor: 'default - sounds' stamp: 'ADT 8/17/2000 21:21'! loudness "Answer default volume to play each tone" ^0.4! ! !HexBassPalette methodsFor: 'palette properties' stamp: 'ADT 7/18/2000 00:59'! instrument ^#bass1! ! !HexBassPalette methodsFor: 'palette properties' stamp: 'ADT 9/8/2000 17:57'! instrumentBorderColor ^Color green "lightGreen"! ! !HexBassPalette methodsFor: 'palette properties' stamp: 'ADT 7/18/2000 00:59'! label ^'Bass'! ! !HexBrassPalette reorganize! ('default - sounds' dur loudness) ('palette properties' instrument instrumentBorderColor label) ! !HexBrassPalette methodsFor: 'default - sounds' stamp: 'ADT 7/26/2000 01:40'! dur "Answer default duration to play each tone" ^0.25! ! !HexBrassPalette methodsFor: 'default - sounds' stamp: 'ADT 8/17/2000 21:20'! loudness "Answer default volume to play each tone" ^0.45! ! !HexBrassPalette methodsFor: 'palette properties' stamp: 'ADT 7/18/2000 00:58'! instrument ^#mellowBrass! ! !HexBrassPalette methodsFor: 'palette properties' stamp: 'ADT 8/6/2000 02:55'! instrumentBorderColor ^Color lightBlue! ! !HexBrassPalette methodsFor: 'palette properties' stamp: 'ADT 7/17/2000 01:57'! label ^'Brass'! ! !HexFlutePalette reorganize! ('default - sounds' loudness) ('palette properties' instrument instrumentBorderColor label) ! !HexFlutePalette methodsFor: 'default - sounds' stamp: 'ADT 7/17/2000 23:57'! loudness "Answer default volume to play each tone" ^0.6! ! !HexFlutePalette methodsFor: 'palette properties' stamp: 'ADT 7/18/2000 00:56'! instrument ^#flute1! ! !HexFlutePalette methodsFor: 'palette properties' stamp: 'ADT 7/17/2000 02:24'! instrumentBorderColor ^Color white! ! !HexFlutePalette methodsFor: 'palette properties' stamp: 'ADT 7/17/2000 01:56'! label ^'Flute'! ! !HexMulePalette methodsFor: 'palette properties' stamp: 'ADT 8/23/2000 02:47'! foreColor ^Color white! ! !HexMulePalette methodsFor: 'initialization' stamp: 'ADT 8/23/2000 02:47'! addCloseButton "Add some temporary, ugly controls" self addMorph: self makeCloseButton. ^self ! ! !HexMulePalette methodsFor: 'initialization' stamp: 'ADT 8/23/2000 02:47'! addControls "Add some temporary, ugly controls" self addMorph: self makeControlPalette. ^self ! ! !HexMulePalette methodsFor: 'initialization' stamp: 'ADT 8/23/2000 02:48'! addRows "Add some temporary, ugly controls. Called by initialize when we are opening in the world." self addCloseButton. self addLine. self muleClass addRowsToPalette: self. ! ! !HexMulePalette methodsFor: 'initialization' stamp: 'ADT 8/23/2000 02:52'! muleClass "the class of the thing my palette members carry (e.g., annotation, connection...)" self subclassResponsibility! ! !HexMulePalette methodsFor: 'construction' stamp: 'ADT 8/23/2000 02:54'! add: cargo label: aLabel ^self addMule: (self makeMuleToCarry: cargo) label: aLabel ! ! !HexMulePalette methodsFor: 'construction' stamp: 'ADT 8/23/2000 02:47'! addLabelText: someText | a l | a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 2. l _ self getLabelWithText: someText. l color: Color lightBlue. a addMorph: l. self addMorph: a. ^self ! ! !HexMulePalette methodsFor: 'construction' stamp: 'ADT 8/23/2000 02:47'! addLine self addLabelText: ' '. ^self ! ! !HexMulePalette methodsFor: 'construction' stamp: 'ADT 8/23/2000 02:47'! addMule: aMule label: aLabel | a | a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 2. a addMorph: (self getLabelWithText: aLabel). a addMorph: aMule. self addMorph: a. ^ self ! ! !HexMulePalette methodsFor: 'construction' stamp: 'ADT 8/23/2000 03:00'! addMules: mules ^self addMules: mules label: nil ! ! !HexMulePalette methodsFor: 'construction' stamp: 'ADT 8/23/2000 03:02'! addMules: mules label: aLabel | a | a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 2. aLabel == nil ifFalse: [a addMorph: (self getLabelWithText: aLabel)]. mules do: [ :m | a addMorph: (self makeMuleToCarry: m)]. self addMorph: a. ^ self ! ! !HexMulePalette methodsFor: 'construction' stamp: 'ADT 8/23/2000 02:55'! makeMuleToCarry: anAnnotation self subclassResponsibility ! ! !HexAnnotationPalette methodsFor: 'palette properties' stamp: 'ADT 8/19/2000 03:04'! label ^'sevenhex annotation palette'! ! !HexAnnotationPalette methodsFor: 'initialization' stamp: 'ADT 8/23/2000 02:49'! muleClass ^HexAnnotation ! ! !HexAnnotationPalette methodsFor: 'construction' stamp: 'ADT 8/23/2000 02:53'! makeMuleToCarry: anAnnotation ^HexAnnotationMule annotation: anAnnotation ! ! !HexConnectionStatePalette methodsFor: 'palette properties' stamp: 'ADT 8/23/2000 03:14'! label ^'sevenhex connections palette'! ! !HexConnectionStatePalette methodsFor: 'initialization' stamp: 'ADT 8/23/2000 02:50'! muleClass ^HexConnectionState ! ! !HexConnectionStatePalette methodsFor: 'construction' stamp: 'ADT 8/23/2000 02:55'! makeMuleToCarry: aConnection ^HexConnectionStateMule connectionState: aConnection ! ! !HexMultiPalette reorganize! ('palette properties' foreColor label newScale:) ('initialization' addControls addRows makeAeolianButton makeControlPalette makeHarmonicButton makeIonianButton makePentatonicButton makeTwelvetoneButton) ! !HexMultiPalette methodsFor: 'palette properties' stamp: 'ADT 8/19/2000 03:06'! foreColor ^Color white! ! !HexMultiPalette methodsFor: 'palette properties' stamp: 'ADT 8/17/2000 00:58'! label ^'sevenhex ', self class scale asString, ' palette'! ! !HexMultiPalette methodsFor: 'palette properties' stamp: 'ADT 8/17/2000 01:04'! newScale: aSymbol "Update the class variable scale. Open a new instance of myself, which will display the new scale; then delete myself." self class scale: aSymbol. self class new openInWorld topLeft: (self topLeft). self delete! ! !HexMultiPalette methodsFor: 'initialization' stamp: 'ADT 8/16/2000 23:56'! addControls "Add some temporary, ugly controls" self addMorph: self makeControlPalette. ^self ! ! !HexMultiPalette methodsFor: 'initialization' stamp: 'ADT 8/21/2000 22:02'! addRows "Add some temporary, ugly controls. Called by initialize when we are opening in the world." self addCloseButton. self addMorph: HexExtrasPalette new. self addMorph: HexTongPalette new. self addMorph: HexWhoomfPalette new. self addMorph: HexBassPalette new. self addMorph: HexBrassPalette new. self addControls! ! !HexMultiPalette methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:43'! makeAeolianButton ^self buildButtonWithTarget: self label: 'aeol' selector: #newScale: arguments: (Array with: #aeolian)! ! !HexMultiPalette methodsFor: 'initialization' stamp: 'ADT 8/17/2000 02:22'! makeControlPalette | a | a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 2. a addMorph: self makeAeolianButton. a addMorph: self makeHarmonicButton. a addMorph: self makeIonianButton. a addMorph: self makePentatonicButton. a addMorph: self makeTwelvetoneButton. ^ a ! ! !HexMultiPalette methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:43'! makeHarmonicButton ^self buildButtonWithTarget: self label: 'harm' selector: #newScale: arguments: (Array with: #harmonic)! ! !HexMultiPalette methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:43'! makeIonianButton ^self buildButtonWithTarget: self label: 'io' selector: #newScale: arguments: (Array with: #ionian)! ! !HexMultiPalette methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:42'! makePentatonicButton ^self buildButtonWithTarget: self label: 'pent' selector: #newScale: arguments: (Array with: #pentatonic)! ! !HexMultiPalette methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:43'! makeTwelvetoneButton ^self buildButtonWithTarget: self label: 'full' selector: #newScale: arguments: (Array with: #twelvetone)! ! !HexMultiPalette class methodsFor: 'accessing' stamp: 'ADT 8/17/2000 00:45'! scale Scale == nil ifTrue: [self scale: #pentatonic]. ^Scale! ! !HexMultiPalette class methodsFor: 'accessing' stamp: 'ADT 8/17/2000 00:45'! scale: aSymbol Scale _ aSymbol. ^self! ! !HexSinkAnnotation reorganize! ('accessing' opposite privateOpposite) ('drawing' drawOn:in:at:) ('model - chi' postactivateWithChi:) ('printing' printOn:) ('testing' oppositesP) ('visual properties' annotationColor) ! !HexSinkAnnotation methodsFor: 'accessing' stamp: 'ADT 8/17/2000 01:42'! opposite "Requires special action, should be cleaned up!!" self hex removeAnnotation: self. self hex newAnnotation: self privateOpposite! ! !HexSinkAnnotation methodsFor: 'accessing' stamp: 'ADT 8/17/2000 01:40'! privateOpposite ^HexMirrorAnnotation new! ! !HexSinkAnnotation methodsFor: 'drawing' stamp: 'ADT 9/9/2000 22:30'! drawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position oriented towards aFacet." | r s lp | lp _ self lookPolicy. r _ Rectangle encompassing: (aHex verticesInsetBy: 0.4). s _ r insetBy: (r width / 4). lp drawStyle == #shadow ifTrue: [ | rr ss | rr _ r translateBy: lp shadowOffset. ss _ s translateBy: lp shadowOffset. aCanvas drawPolygon: (Array with:(rr topLeft) with: (rr topRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: (ss leftCenter) with: (ss rightCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: (rr bottomCenter - (1 @ 0)) with: (rr bottomCenter + (1 @ 0)) ) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with:(r topLeft) with: (r topRight)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (s leftCenter) with: (s rightCenter)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (r bottomCenter - (1 @ 0)) with: (r bottomCenter + (1 @ 0)) ) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor! ! !HexSinkAnnotation methodsFor: 'model - chi' stamp: 'ADT 8/17/2000 01:25'! postactivateWithChi: aChi "Insure that aChi is not propogated at all" ^nil! ! !HexSinkAnnotation methodsFor: 'printing' stamp: 'ADT 8/17/2000 01:33'! printOn: aStream aStream nextPutAll: 'Sink' ! ! !HexSinkAnnotation methodsFor: 'testing' stamp: 'ADT 8/17/2000 01:25'! oppositesP ^true! ! !HexSinkAnnotation methodsFor: 'visual properties' stamp: 'ADT 8/21/2000 21:48'! annotationColor ^Color lightBlue! ! Smalltalk renameClassNamed: #HexSound as: #HexSoundWrapper! !HexSoundWrapper reorganize! ('accessing' duration duration: instrument instrumentName instrumentName: magnitude magnitude: pitch pitch: pitchName pitchName:) ('dependents' addDependent:type: addDoppel: addTie: clearDependentMorphs clearTies dependentDoppels dependentMorphs dependentMorphs: dependentTies dependentsOfType: numberOfDoppels numberOfTies removeDependent: removeDoppel: removeTie:) ('playing' play) ('testing' isSameAs:) ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 8/17/2000 21:16'! duration "Answer my duration in a form my actual sound can use. Subclasses need to coordinate the form these properties take, and the way they are used in overriden methods." duration == nil ifTrue: [self duration: 1]. "this value means nothing unless sub overrides..." ^duration! ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 8/17/2000 21:15'! duration: aDuration "Set my duration in a form my actual sound can use. Subclasses that override for their own purposes should call super to insure I cache this value." duration _ aDuration. ^self! ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 8/17/2000 01:54'! instrument ^'unknown instrument'! ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 8/17/2000 02:04'! instrumentName instrumentName == nil ifTrue: [self instrumentName: 'unknown']. ^instrumentName! ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 8/17/2000 02:04'! instrumentName: aString instrumentName _ aString. ^self! ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 8/17/2000 21:15'! magnitude "Answer my magnitude in a form my actual sound can use. Subclasses need to coordinate the form these properties take, and the way they are used in overriden methods." magnitude == nil ifTrue: [self magnitude: 1]. ^magnitude! ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 8/17/2000 21:13'! magnitude: aFloat "Set my magnitude in a form my actual sound can use. Magnitude is maintained as a float between 0 and 1. Subclasses must use this privately to determine their own performance volume (whatever that means for their type...). Subclasses that override for their own purposes should call super to insure I cache this value." magnitude _ aFloat. ^self! ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 7/25/2000 13:06'! pitch "Answer my ptich in a form my actual sound can use. Subclasses need to coordinate the form these properties take, and the way they are used in overriden methods." self subclassResponsibility! ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 7/25/2000 13:08'! pitch: aPitch "Set my ptich in a form my actual sound can use. Subclasses need to coordinate the form these properties take, and the way they are used in overriden methods." self subclassResponsibility! ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 8/17/2000 02:01'! pitchName pitchName == nil ifTrue: [self pitchName: 'unknown']. ^pitchName! ! !HexSoundWrapper methodsFor: 'accessing' stamp: 'ADT 8/17/2000 02:01'! pitchName: aString pitchName _ aString. ^self! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:45'! addDependent: aHexagon type: aSymbol (self dependentMorphs includesKey: aHexagon) ifFalse: [self dependentMorphs at: aHexagon put: aSymbol]! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:47'! addDoppel: aHexagon self addDependent: aHexagon type: #doppel! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:47'! addTie: aHexagon self addDependent: aHexagon type: #tie! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/26/2000 01:37'! clearDependentMorphs "Reset our list of dependentMorphs" self dependentMorphs: Dictionary new. ^self! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 20:27'! clearTies "Remove any dependent morphs whose relationship to me is of type #tie." | cleaned | cleaned _ Dictionary new. self dependentMorphs associationsDo: [:assoc | (assoc value == #tie) ifTrue: [cleaned add: assoc]]. self dependentMorphs: cleaned. ^self ! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:48'! dependentDoppels "Answer thedependent morphs whose relationship to me is of type #doppel." ^self dependentsOfType: #doppel ! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:30'! dependentMorphs "Answer the dictionary of morphs who glow or are interested in me as their sound. Convoluted syntax because there are two obvious cases of this: two to one relations of 'twins' or doppelgangers; many to one relations of tied nodes. In both cases, numerous nodes are interested in the playback of a single sound. I keep track of the collection, so I can keep count of how long I am supposed to play -- a multiplier which is a function over dependentMorphs." dependentMorphs == nil ifTrue: [self dependentMorphs: Dictionary new]. ^dependentMorphs! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:31'! dependentMorphs: aDictionary "Set the dictionary of morphs who glow or are interested in me as their sound. Convoluted syntax because there are two obvious cases of this: two to one relations of 'twins' or doppelgangers; many to one relations of tied nodes. In both cases, numerous nodes are interested in the playback of a single sound. I keep track of the collection, so I can keep count of how long I am supposed to play -- a multiplier which is a function over dependentMorphs." dependentMorphs _ aDictionary. ^self! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:43'! dependentTies "Answer the dependent morphs whose relationship to me is of type #tie." ^self dependentsOfType: #tie ! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 20:56'! dependentsOfType: aSymbol "Answer the dependent morphs whose relationship to me is of type aSymbol. At time of writing most likely relations are: #tie multiple morphs which are tied to me, meaning I have a multiplied duration; #doppel mulitple morphs which glow simultaneously when I am active." | sheep | sheep _ Dictionary new. self dependentMorphs associationsDo: [:assoc | (assoc value == aSymbol) ifTrue: [sheep add: assoc]]. ^sheep ! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:48'! numberOfDoppels "Answer the number of dependent morphs whose relationship to me is of type #doppel." ^self dependentDoppels size ! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:43'! numberOfTies "Answer the number of dependent morphs whose relationship to me is of type #tie." ^self dependentTies size ! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:46'! removeDependent: aHexagon self dependentMorphs removeKey: aHexagon ifAbsent: [nil]! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:47'! removeDoppel: aHexagon self removeDependent: aHexagon! ! !HexSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/26/2000 01:39'! removeTie: aHexagon self removeDependent: aHexagon. aHexagon sound: self copy clearDependentMorphs. "if we're no longer tied, it needs its own sound back!!"! ! !HexSoundWrapper methodsFor: 'playing' stamp: 'ADT 7/25/2000 13:09'! play "Produce a sound. Depending on subclass, this could mean actually play a generated sound or sample; or schedule a MIDI event. When we have a scheduler, this will probably have to be enhanced with a notion of the time to schedule the play event for..." self subclassResponsibility! ! !HexSoundWrapper methodsFor: 'testing' stamp: 'ADT 8/6/2000 02:53'! isSameAs: aHexSound "kludge, used to answer equality between instances of myself. NOt interested in identify, but pitch and instrument!!" ^self pitch = aHexSound pitch! ! Smalltalk renameClassNamed: #HexFMSound as: #HexFMSoundWrapper! !HexFMSoundWrapper methodsFor: 'defaults' stamp: 'ADT 7/25/2000 13:14'! defaultDuration "Answer default duration to play each tone" ^0.35! ! !HexFMSoundWrapper methodsFor: 'defaults' stamp: 'ADT 7/25/2000 13:13'! defaultInstrument ^#flute1! ! !HexFMSoundWrapper methodsFor: 'defaults' stamp: 'ADT 7/25/2000 13:14'! defaultLoudness "Answer default volume to play each tone" ^0.75! ! !HexFMSoundWrapper methodsFor: 'playing' stamp: 'ADT 7/25/2000 13:15'! play "Produce a sound. Actually play a generated sound." self fmSound play! ! !HexFMSoundWrapper methodsFor: 'accessing' stamp: 'ADT 7/25/2000 13:12'! fmSound "Answer the (private) FMSound I am to play..." fmSound == nil ifTrue: [self fmSound: ((FMSound perform: self defaultInstrument) setPitch: (AbstractSound pitchForName: 'a2') dur: self defaultDuration loudness: self defaultLoudness)]. ^fmSound! ! !HexFMSoundWrapper methodsFor: 'accessing' stamp: 'ADT 7/25/2000 19:56'! fmSound: anFMSound "Set the (private) FMSound I am to play..." fmSound _ anFMSound. self rawDuration: (anFMSound duration). ^self! ! !HexFMSoundWrapper methodsFor: 'accessing' stamp: 'ADT 8/17/2000 21:14'! magnitude: aMagnitude "Actually regenerate/redial our FMSound to reflect the new magnitude." super magnitude: aMagnitude. self fmSound setPitch: self fmSound pitch dur: self fmSound duration loudness: aMagnitude! ! !HexFMSoundWrapper methodsFor: 'accessing' stamp: 'ADT 7/25/2000 14:13'! sound: anFMSound "Set the (private) FMSound I am to play..." ^self fmSound: anFMSound! ! !HexFMSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:51'! addTie: aHexagon "Our duration is based on the number of tied dependents we have. Every time we add or remove a dependent of type #tie, update our duration." super addTie: aHexagon. self recalculateDuration! ! !HexFMSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 20:28'! dependentMorphs: aDictionary "Set the dictionary of morphs who glow or are interested in me as their sound. Convoluted syntax because there are two obvious cases of this: two to one relations of 'twins' or doppelgangers; many to one relations of tied nodes. In both cases, numerous nodes are interested in the playback of a single sound. I keep track of the collection, so I can keep count of how long I am supposed to play -- a multiplier which is a function over dependentMorphs." super dependentMorphs: aDictionary. self recalculateDuration! ! !HexFMSoundWrapper methodsFor: 'dependents' stamp: 'ADT 7/25/2000 19:51'! removeTie: aHexagon "Our duration is based on the number of tied dependents we have. Every time we add or remove a dependent of type #tie, update our duration." super removeTie: aHexagon. self recalculateDuration! ! !HexFMSoundWrapper methodsFor: 'private' stamp: 'ADT 7/25/2000 19:53'! rawDuration "The raw duration of our sound is cached, since when we have ties or other annotations, our actual sound's (calculated) duration is affected." rawDuration == nil ifTrue: [self rawDuration: self defaultDuration]. ^rawDuration! ! !HexFMSoundWrapper methodsFor: 'private' stamp: 'ADT 7/25/2000 19:54'! rawDuration: aDuration "The raw duration of our sound is cached, since when we have ties or other annotations, our actual sound's (calculated) duration is affected." rawDuration _ aDuration! ! !HexFMSoundWrapper methodsFor: 'private' stamp: 'ADT 7/25/2000 19:56'! recalculateDuration "The raw duration of our sound is cached, since when we have ties or other annotations, our actual sound's (calculated) duration is affected." self fmSound duration: (self rawDuration * self numberOfTies). ! ! !HexFMSoundWrapper methodsFor: 'testing' stamp: 'ADT 8/9/2000 01:33'! isSameAs: aHexSound "kludge, used to answer equality between instances of myself. NOt interested in identify, but pitch and instrument!!" "total kludge since depends on aHexSound being an instance of HexFMSound" ^(self fmSound pitch = aHexSound fmSound pitch) and: [self fmSound multiplier = aHexSound fmSound multiplier]! ! Smalltalk renameClassNamed: #HexFixedConnectionState as: #HexStaticConnectionState! !HexStaticConnectionState commentStamp: 'ADT 8/6/2000 00:28' prior: 0! I am a subclass of HexConnectionState and am abstract superclass with two, fixed subs which represent open and closed connections. My connections never change, I am very passive.! !HexStaticConnectionState methodsFor: 'testing' stamp: 'ADT 8/5/2000 20:03'! oppositesP ^true! ! !HexStaticConnectionState methodsFor: 'testing' stamp: 'ADT 8/5/2000 17:05'! twidlesP ^false! ! !HexClosedConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 00:43'! currentStateForChi: aChi ^#closed! ! !HexClosedConnectionState methodsFor: 'accessing' stamp: 'ADT 7/21/2000 00:26'! opposite "Return an instance of myself that is philosophically opposite myself. Fixed open instances return fixed closed instances and vice versa. Binary togglers return themselves with polarity reversed. If 'opposite' doesn't make sense, I can return myself." ^HexOpenConnectionState new! ! !HexClosedConnectionState methodsFor: 'drawing' stamp: 'ADT 9/9/2000 21:49'! drawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position aFacet." | start end v lp | v _ aHex verticesInsetBy: 0.7. ((start _ facetNumber) = 6) ifTrue: [end _ 1] ifFalse: [end _ start + 1]. lp _ self lookPolicy. lp drawStyle == #shadow ifTrue: [aCanvas line: ((v at: start) + lp shadowOffset) to: ((v at: end) + lp shadowOffset) width: aHex annotationWidth color: lp shadowColor]. aCanvas line: (v at: start) to: (v at: end) width: aHex annotationWidth color: aHex annotationColor ! ! !HexOpenConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 00:44'! currentStateForChi: aChi ^#open! ! !HexOpenConnectionState methodsFor: 'accessing' stamp: 'ADT 7/21/2000 00:25'! opposite "Return an instance of myself that is philosophically opposite myself. Fixed open instances return fixed closed instances and vice versa. Binary togglers return themselves with polarity reversed. If 'opposite' doesn't make sense, I can return myself." ^HexClosedConnectionState new! ! !HexOpenConnectionState methodsFor: 'drawing' stamp: 'ADT 7/21/2000 00:32'! drawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position aFacet." ^self ! ! !HexStaticConnectionState class methodsFor: 'menus' stamp: 'ADT 8/23/2000 01:49'! addRowsToPalette: aPalette aPalette add: HexClosedConnectionState new label: 'closed'. aPalette addMule: HexClearConnectionStateMule default label: 'open'. aPalette addLabelText: 'fixed' ! ! !HexStaticConnectionState class methodsFor: 'menus' stamp: 'ADT 8/15/2000 15:41'! getMenuWithEvent: evt facet: facet target: target "Facet dependent sub-submenu. Requested by HexConnection...." | sub | sub _ MenuMorph new defaultTarget: target. sub add: 'open' selector: #newState: argument: (HexOpenConnectionState new). sub add: 'closed' selector: #newState: argument: (HexClosedConnectionState new). ^ sub! ! !HexThreshholdConnectionState commentStamp: 'ADT 8/6/2000 00:53' prior: 0! I am subclass of ConditionalConnectionState whose state depends on whether an aspect of the chi that is passing through me is beyond a certain threshold. Aspect is the quality of the chi that is passing through me that I am interested in. Currently this is limited to #velocity or #amplitude. The test I do varies according to my polarity. If polarity is #positive, I an open when the aspect exceeds or equals the threshold. If polarity is #negative, I am open when the aspect is less than the threshold. We might also want to implement #within and #without. Current implementation only attends to properties of the chi passing me. I might also be dependent on properties of the hex, etc.! !HexThreshholdConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 00:54'! aspect "Set the property that I test against the threshold" aspect == nil ifTrue: [self aspect: #amplitude]. ^aspect! ! !HexThreshholdConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 00:54'! aspect: aSymbol "Set the property that I test against the threshold" aspect _ aSymbol. ^self! ! !HexThreshholdConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 00:56'! currentStateForChi: aChi "Answer whether I am open or closed" ^self polarity == #positive ifTrue: [((aChi perform: self aspect) >= self threshhold) ifTrue: [#open] ifFalse: [#closed]] ifFalse: [((aChi perform: self aspect) < self threshhold) ifTrue: [#open] ifFalse: [#closed]]! ! !HexThreshholdConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 00:40'! opposite self polarity == #positive ifTrue: [self polarity: #negative] ifFalse: [self polarity: #positive]. ^self! ! !HexThreshholdConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 00:37'! polarity "Set whether I need to be over (positive) or under (negative) the threshold to be open" polarity == nil ifTrue: [self polarity: #positive]. ^polarity! ! !HexThreshholdConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 00:37'! polarity: aSymbol "Set whether I need to be over (positive) or under (negative) the threshold to be open" polarity _ aSymbol. ^self! ! !HexThreshholdConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 01:45'! threshhold "Answer the value that aspect must be over or under" threshhold == nil ifTrue: [self threshhold: 0]. ^threshhold! ! !HexThreshholdConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 01:44'! threshhold: aFloat "Set the value that aspect must be over or under" threshhold _ aFloat. ^self! ! !HexThreshholdConnectionState methodsFor: 'drawing' stamp: 'ADT 9/9/2000 22:07'! drawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position aFacet. First, draw the half-line that indicates what is blocked (based on current polarity). Then draw the circle that indicates the current toggle..." | end v w inPts outPts lp | v _ aHex verticesInsetBy: 0.6. w _ aHex verticesInsetBy: 0.8. facetNumber = 6 ifTrue: [end _ 1] ifFalse: [end _ facetNumber + 1]. outPts _ self points: 3 between: (w at: facetNumber) and: (w at: end). inPts _ self points:3 between: (v at: facetNumber) and: (v at: end). lp _ self lookPolicy. self polarity == #positive ifTrue: [lp drawStyle == #shadow ifTrue: [| o | o _ lp shadowOffset. aCanvas drawPolygon: (Array with: ((outPts at: 1) + o ) with: ((outPts at: 2) + o)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: ((outPts at: 2) + o) with: ((inPts at: 2) + o)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: ((inPts at: 2) + o ) with: ((inPts at: 3) + o)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (outPts at: 1) with: (outPts at: 2)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (outPts at: 2) with: (inPts at: 2)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (inPts at: 2) with: (inPts at: 3)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor] ifFalse: [lp drawStyle == #shadow ifTrue: [| o c | o _ lp shadowOffset. aCanvas drawPolygon: (Array with: ((inPts at: 1) + o ) with: ((inPts at: 2) + o)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: ((inPts at: 2) + o) with: ((outPts at: 2) + o)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: ((outPts at: 2) + o ) with: ((outPts at: 3) + o)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (inPts at: 1) with: (inPts at: 2)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (inPts at: 2) with: (outPts at: 2)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (outPts at: 2) with: (outPts at: 3)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: self annotationColor] ! ! !HexThreshholdConnectionState methodsFor: 'testing' stamp: 'ADT 8/6/2000 01:47'! oppositesP ^true! ! !HexThreshholdConnectionState methodsFor: 'visual properties' stamp: 'ADT 8/23/2000 03:09'! annotationColor self aspect == #amplitude ifTrue: [^Color lightGreen]. self aspect == #velocity ifTrue: [^Color lightRed]. ^super annotationColor! ! !HexThreshholdConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/6/2000 01:04'! amplitudeHighPass ^self new polarity: #positive; threshhold: 0.75; aspect: #amplitude! ! !HexThreshholdConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/6/2000 01:43'! amplitudeLowPass ^(self new) polarity: #negative; threshhold: 0.25; aspect: #amplitude! ! !HexThreshholdConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/8/2000 13:49'! amplitudeVeryHighPass ^self new polarity: #positive; threshhold: 0.85; aspect: #amplitude! ! !HexThreshholdConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/8/2000 13:49'! amplitudeVeryLowPass ^self new polarity: #negative; threshhold: 0.15; aspect: #amplitude! ! !HexThreshholdConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/6/2000 01:06'! velocityHighPass ^self new polarity: #positive; threshhold: 0.75; aspect: #velocity! ! !HexThreshholdConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/6/2000 01:06'! velocityLowPass ^self new polarity: #negative; threshhold: 0.25; aspect: #velocity! ! !HexThreshholdConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/8/2000 13:50'! velocityVeryHighPass ^self new polarity: #positive; threshhold: 0.85; aspect: #velocity! ! !HexThreshholdConnectionState class methodsFor: 'instance creation' stamp: 'ADT 8/8/2000 13:50'! velocityVeryLowPass ^self new polarity: #negative; threshhold: 0.15; aspect: #velocity! ! !HexThreshholdConnectionState class methodsFor: 'menus' stamp: 'ADT 8/23/2000 03:07'! addRowsToPalette: aPalette | stack | stack _ OrderedCollection new. stack add: (self velocityVeryLowPass); add: (self velocityLowPass); add: (self velocityHighPass); add: (self velocityVeryHighPass). aPalette addMules: stack. aPalette addLabelText: 'velocity dependent'. stack _ OrderedCollection new. stack add: (self amplitudeVeryLowPass); add: (self amplitudeLowPass); add: (self amplitudeHighPass); add: (self amplitudeVeryHighPass). aPalette addMules: stack. aPalette addLabelText: 'amplitude dependent' ! ! !HexThreshholdConnectionState class methodsFor: 'menus' stamp: 'ADT 8/15/2000 15:50'! getMenuWithEvent: evt facet: facet target: target "Facet dependent sub-submenu. Requested by HexConnection...." | sub | sub _ MenuMorph new defaultTarget: target. sub add: 'amplitude high pass' selector: #newState: argument: (self amplitudeHighPass). sub add: 'amplitude low pass' selector: #newState: argument: (self amplitudeLowPass). sub add: 'amplitude very high pass' selector: #newState: argument: (self amplitudeVeryHighPass). sub add: 'amplitude very low pass' selector: #newState: argument: (self amplitudeVeryLowPass). sub add: 'velocity high pass' selector: #newState: argument: (self velocityHighPass). sub add: 'velocity low pass' selector: #newState: argument: (self velocityLowPass). sub add: 'velocity very high pass' selector: #newState: argument: (self velocityVeryHighPass). sub add: 'velocity very low pass' selector: #newState: argument: (self velocityVeryLowPass). ^ sub! ! !HexTieConnectionState reorganize! ('accessing' currentStateForChi:) ('drawing' OLDdrawOn:in:at: RECENTdrawOn:in:at: drawOn:in:at:) ('model - chi' propogateChi:from:direction:for:) ('notification' beingRemovedFrom:) ('testing' oppositesP twidlesP) ! !HexTieConnectionState methodsFor: 'accessing' stamp: 'ADT 8/6/2000 00:43'! currentStateForChi: aChi "Return #open or #closed. We pass activation, though the tied other does not sound." ^#open! ! !HexTieConnectionState methodsFor: 'drawing' stamp: 'ADT 7/26/2000 00:57'! OLDdrawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position aFacet. First, draw the half-line that indicates what is blocked (based on current polarity). Then draw the circle that indicates the current toggle..." | end v pts | v _ aHex verticesInsetBy: 0.7. facetNumber = 6 ifTrue: [end _ 1] ifFalse: [end _ facetNumber + 1]. pts _ self sixPointsBetween: (v at: facetNumber) and: (v at: end). aCanvas fillOval: (Rectangle center: (pts at: 2) extent: ((pts at: 1) dist: (pts at: 3))) fillStyle: aHex annotationColor borderWidth: 0 borderColor: Color transparent. aCanvas fillOval: (Rectangle center: (pts at: 5) extent: ((pts at: 4) dist: (pts at: 6))) fillStyle: aHex annotationColor borderWidth: 0 borderColor: Color transparent ! ! !HexTieConnectionState methodsFor: 'drawing' stamp: 'ADT 7/29/2000 22:05'! RECENTdrawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position aFacet. First, draw the half-line that indicates what is blocked (based on current polarity). Then draw the circle that indicates the current toggle..." | end v c | v _ aHex verticesInsetBy: 0.7. facetNumber = 6 ifTrue: [end _ 1] ifFalse: [end _ facetNumber + 1]. c _ self midpointBetween: (v at: facetNumber) and: (v at: end). aCanvas fillOval: (Rectangle center: c extent: (((v at: facetNumber) dist: (v at: end)) / 3)) fillStyle: aHex annotationColor borderWidth: 0 borderColor: Color transparent. ! ! !HexTieConnectionState methodsFor: 'drawing' stamp: 'ADT 9/9/2000 22:12'! drawOn: aCanvas in: aHex at: facetNumber "Draw myself within aHex at position aFacet. Ties are indicated by parenthesis or straight lines connecting two hexes at a facet." | end v w inPts outPts lp | v _ aHex verticesInsetBy: 0.7. w _ aHex vertices. facetNumber = 6 ifTrue: [end _ 1] ifFalse: [end _ facetNumber + 1]. outPts _ self sixPointsBetween: (w at: facetNumber) and: (w at: end). inPts _ self sixPointsBetween: (v at: facetNumber) and: (v at: end). lp _ self lookPolicy. lp drawStyle == #shadow ifTrue: [| o | o _ lp shadowOffset. aCanvas drawPolygon: (Array with: ((outPts at: 1) + o) with: ((outPts at: 2) + o)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: ((outPts at: 2) + o) with: ((inPts at: 2) + o)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor. aCanvas drawPolygon: (Array with: ((inPts at: 5) + o) with: ((outPts at: 5) + o)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor; drawPolygon: (Array with: ((outPts at: 5) + o) with: ((outPts at: 6) + o)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: lp shadowColor]. aCanvas drawPolygon: (Array with: (outPts at: 1) with: (outPts at: 2)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: aHex annotationColor; drawPolygon: (Array with: (outPts at: 2) with: (inPts at: 2)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: aHex annotationColor. aCanvas drawPolygon: (Array with: (inPts at: 5) with: (outPts at: 5)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: aHex annotationColor; drawPolygon: (Array with: (outPts at: 5) with: (outPts at: 6)) fillStyle: Color transparent borderWidth: aHex annotationWidth borderColor: aHex annotationColor. ! ! !HexTieConnectionState methodsFor: 'model - chi' stamp: 'ADT 8/6/2000 21:05'! propogateChi: aChi from: aHex direction: aDirection for: aConnection "aHex is passing us aChi to pass on to the hex on the other side. Make a copy of aChi, and update its parameters however we choose. Note that we are free to not pass the chi, if the selected direction is not current open; change the Chi's parameters (decrement it according to entropy...), etc." "We are a tie to the next node. If we're tied, the original hex is responsible for playing a note of the tie duration. Hence we pass to the next node aChi without entropy, and using a seperate call which implies that the hex receiver is not to play, only glow," aConnection oppositeSide dontActivateWithChi: (aChi propogationCopyWithDirection: aDirection). ^self! ! !HexTieConnectionState methodsFor: 'notification' stamp: 'ADT 7/26/2000 01:31'! beingRemovedFrom: aHex "The connection to which we belong is being removed. We are being notified in case we wish to take any action. Make sure the hex's sound knows to remove us from its list of ties..." super beingRemovedFrom: aHex. aHex sound removeTie: aHex. ^self ! ! !HexTieConnectionState methodsFor: 'testing' stamp: 'ADT 8/9/2000 01:36'! oppositesP ^false! ! !HexTieConnectionState methodsFor: 'testing' stamp: 'ADT 8/9/2000 01:37'! twidlesP ^false! ! !HexTongPalette methodsFor: 'default - sounds' stamp: 'ADT 8/21/2000 22:01'! dur "Answer default duration to play each tone" ^0.25! ! !HexTongPalette methodsFor: 'default - sounds' stamp: 'ADT 8/21/2000 22:01'! loudness "Answer default volume to play each tone" ^0.4! ! !HexTongPalette methodsFor: 'palette properties' stamp: 'ADT 8/21/2000 22:01'! instrument ^#tong! ! !HexTongPalette methodsFor: 'palette properties' stamp: 'ADT 9/8/2000 17:58'! instrumentBorderColor ^Color white "lightRed"! ! !HexTongPalette methodsFor: 'palette properties' stamp: 'ADT 8/21/2000 22:01'! label ^'Tong'! ! !HexWhoomfPalette reorganize! ('default - sounds' dur loudness) ('palette properties' instrument instrumentBorderColor label) ! !HexWhoomfPalette methodsFor: 'default - sounds' stamp: 'ADT 8/16/2000 01:39'! dur "Answer default duration to play each tone" ^0.25! ! !HexWhoomfPalette methodsFor: 'default - sounds' stamp: 'ADT 8/17/2000 21:20'! loudness "Answer default volume to play each tone" ^0.35! ! !HexWhoomfPalette methodsFor: 'palette properties' stamp: 'ADT 8/16/2000 01:40'! instrument ^#whoomf! ! !HexWhoomfPalette methodsFor: 'palette properties' stamp: 'ADT 9/8/2000 17:59'! instrumentBorderColor ^Color blue twiceLighter! ! !HexWhoomfPalette methodsFor: 'palette properties' stamp: 'ADT 8/17/2000 02:29'! label ^'Whoomf'! ! !HexWorld reorganize! ('accessing' label publishEntropy: publishVelocity:) ('defaults - sounds' dur loudness) ('hierarchy operations' gridSpace) ('initialization' addApplicationControls addControls addHexGrid addMiscControls addWorldParameterControls initialize makeAnnotationPaletteButton makeClearButton makeCloseButton makeConnectionStatePaletteButton makeControlPalette makeDoppelsSwitch makeEntropySlider makeGridSwitch makeHexGrid makeNormalButton makePaletteButton makePlaySwitch makeResetButton makeRotationButtonClockwise makeRotationButtonCounterclockwise makeShadowSwitch makeStopButton makeVelocitySlider makeZoomButtonIn makeZoomButtonOut) ('model - world properties' defaultEntropy defaultVelocity doppelsP doppelsP: entropy entropy: establishDefaultWorldProperties playingP playingP: velocity velocity:) ('widget interface' clearCanvas normal reset rotateClockwise rotateCounterclockwise spawnAnnotationPalette spawnConnectionStatePalette spawnPalette stopPlayback toggleGrid zoomIn zoomOut) ! !HexWorld methodsFor: 'accessing' stamp: 'ADT 9/8/2000 18:07'! label ^'sevenhex prototype v0.0e0 (c) 2000 aaron thieme'! ! !HexWorld methodsFor: 'accessing' stamp: 'ADT 8/15/2000 20:54'! publishEntropy: aFloat "sends to slider" self entropy: aFloat. entropySlider == nil ifFalse: [entropySlider setValue: (1 - aFloat)]! ! !HexWorld methodsFor: 'accessing' stamp: 'ADT 8/8/2000 15:53'! publishVelocity: aFloat "sends to slider" self velocity: aFloat. velocitySlider == nil ifFalse: [velocitySlider setValue: aFloat]! ! !HexWorld methodsFor: 'defaults - sounds' stamp: 'ADT 7/25/2000 12:59'! dur "Answer default duration to play each tone" ^0.2 ! ! !HexWorld methodsFor: 'defaults - sounds' stamp: 'ADT 7/25/2000 12:59'! loudness "Answer default volume to play each tone" ^0.8! ! !HexWorld methodsFor: 'hierarchy operations' stamp: 'ADT 8/23/2000 04:16'! gridSpace gridSpace == nil ifTrue: [gridSpace _ HexGrid new]. ^ gridSpace! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 8/23/2000 02:15'! addApplicationControls "Add some temporary, ugly controls" | a | a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 2. a addMorph: self makeConnectionStatePaletteButton. a addMorph: self makeAnnotationPaletteButton. a addMorph: self makeCloseButton. a addMorph: self makePaletteButton. self addMorph: a. ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 7/25/2000 12:59'! addControls "Add some temporary, ugly controls" self addMorph: self makeControlPalette. ^self ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 7/25/2000 12:59'! addHexGrid "Add the grid" self addMorph: self makeHexGrid! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/9/2000 23:36'! addMiscControls "Add some temporary, ugly controls" | a | a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 2. a addMorph: self makeDoppelsSwitch. a addMorph: self makeResetButton. a addMorph: self makePlaySwitch. self addMorph: a. ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 8/8/2000 16:02'! addWorldParameterControls "Add some temporary, ugly controls" | label | self addMorph: self makeVelocitySlider. self addMorph: self makeEntropySlider. label _ TextMorph new contents: 'world properties'. label color: Color white. self addMorph: label. ^self ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/9/2000 21:50'! initialize super initialize. SoundPlayer stopReverb. "performance" color _ self lookPolicy windowColor. orientation _ #vertical. centering _ #center. self extent: 620 @ 460. vResizing _ #fixed. hResizing _ #fixed. inset _ 3. self addApplicationControls. self addMiscControls. self addWorldParameterControls. self addHexGrid. self addControls. self addLabel. self establishDefaultWorldProperties. self spawnPalette. "self spawnAnnotationPalette. self spawnConnectionStatePalette." HexDoppelgangerConnection resetLabelPoolPointer ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:38'! makeAnnotationPaletteButton ^self buildButtonWithTarget: self label: 'annotations' selector: #spawnAnnotationPalette! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:38'! makeClearButton ^self buildButtonWithTarget: self label: 'clear' selector: #clearCanvas! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:39'! makeCloseButton ^self buildButtonWithTarget: self label: 'close' selector: #delete! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:39'! makeConnectionStatePaletteButton ^self buildButtonWithTarget: self label: 'connections' selector: #spawnConnectionStatePalette! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/9/2000 23:36'! makeControlPalette | a | a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 2. a addMorph: self makeZoomButtonIn. a addMorph: self makeZoomButtonOut. a addMorph: self makeNormalButton. a addMorph: self makeStopButton. a addMorph: self makeGridSwitch. a addMorph: self makeShadowSwitch. a addMorph: self makeClearButton. "a addMorph: self makeEntropyButton." "not needed if we have the slider" a addMorph: self makeRotationButtonClockwise. a addMorph: self makeRotationButtonCounterclockwise. ^ a ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 15:03'! makeDoppelsSwitch | a aSwitch | aSwitch _ SimpleSwitchMorph new offColor: Color darkGray; onColor: Color lightGray; borderWidth: 2; label: 'Shift-Drag Makes Doppelgangers'; actionSelector: #doppelsP:; target: self; setSwitchState: self doppelsP. a _ AlignmentMorph newColumn centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 1. a addMorph: aSwitch. ^ a ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 8/8/2000 15:47'! makeEntropySlider | a s label | a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 2. s _ SimpleSliderMorph new color: color; extent: 200@2; target: self; actionSelector: #entropy:. label _ TextMorph new contents: ' entropy'. label color: Color white. a addMorph: label. entropySlider _ s. a addMorph: s. ^ a ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/9/2000 23:36'! makeGridSwitch | a aSwitch | aSwitch _ SimpleSwitchMorph new offColor: Color darkGray; onColor: Color lightGray; borderWidth: 2; label: 'grid'; actionSelector: #displayP:; target: self gridSpace; setSwitchState: self gridSpace displayP. a _ AlignmentMorph newColumn centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 1. a addMorph: aSwitch. ^ a ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 8/19/2000 04:18'! makeHexGrid | a | a _ AlignmentMorph new. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 2. a addMorph: self gridSpace. ^ a ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:39'! makeNormalButton ^self buildButtonWithTarget: self label: 'home' selector: #normal! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:39'! makePaletteButton ^self buildButtonWithTarget: self label: 'palette' selector: #spawnPalette! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 15:13'! makePlaySwitch | a aSwitch | aSwitch _ SimpleSwitchMorph new offColor: Color darkGray; onColor: Color lightGray; borderWidth: 2; label: 'Live'; actionSelector: #playingP:; target: self; setSwitchState: self playingP. a _ AlignmentMorph newColumn centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 1. a addMorph: aSwitch. ^ a ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/9/2000 02:50'! makeResetButton ^self buildButtonWithTarget: self label: 'reset' selector: #reset! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:40'! makeRotationButtonClockwise ^self buildButtonWithTarget: self label: '->' selector: #rotateClockwise! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:39'! makeRotationButtonCounterclockwise ^self buildButtonWithTarget: self label: '<-' selector: #rotateCounterclockwise! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/9/2000 23:33'! makeShadowSwitch | a aSwitch | aSwitch _ SimpleSwitchMorph new offColor: Color darkGray; onColor: Color lightGray; borderWidth: 2; label: 'shadow'; actionSelector: #shadow:; target: self lookPolicy; setSwitchState: (self lookPolicy drawStyle == #shadow). a _ AlignmentMorph newColumn centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 1. a addMorph: aSwitch. ^ a ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:40'! makeStopButton ^self buildButtonWithTarget: self label: 'stop' selector: #stopPlayback! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 8/8/2000 15:56'! makeVelocitySlider | a s label | a _ AlignmentMorph newRow. a centering: #center; hResizing: #shrinkWrap; vResizing: #shrinkWrap; color: Color transparent; inset: 2. s _ SimpleSliderMorph new color: color; extent: 200@2; target: self; actionSelector: #velocity:. label _ TextMorph new contents: ' velocity'. label color: Color white. a addMorph: label. velocitySlider _ s. a addMorph: s. ^ a ! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:40'! makeZoomButtonIn ^self buildButtonWithTarget: self label: '+' selector: #zoomIn! ! !HexWorld methodsFor: 'initialization' stamp: 'ADT 9/8/2000 14:40'! makeZoomButtonOut ^self buildButtonWithTarget: self label: '-' selector: #zoomOut! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 8/15/2000 20:55'! defaultEntropy ^0.02! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 8/8/2000 15:45'! defaultVelocity ^0.5! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 9/8/2000 14:59'! doppelsP "Temporary kludge. When set, shift-drag creates doppelgangers instead of simple copies." doppelsP == nil ifTrue: [self doppelsP: false]. ^doppelsP! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 9/8/2000 15:00'! doppelsP: aBool "Temporary kludge. When set, shift-dragging creates doppelgangers, not simple copies." doppelsP _ aBool.! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 8/8/2000 15:45'! entropy "sent by slider" entropy == nil ifTrue: [self entropy: self defaultEntropy]. ^entropy! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 8/15/2000 20:53'! entropy: aFloat "sent by slider" entropy _ 1 - aFloat.! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 9/8/2000 15:11'! establishDefaultWorldProperties "publish methods force sliders to update. Kludgey but works for now." self publishEntropy: self entropy. self publishVelocity: self velocity. self doppelsP: false. self playingP: true.! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 9/8/2000 15:17'! playingP "Answer whether we are playing or not. If not, no propogation, and emitters are on hold..." playingP == nil ifTrue: [self playingP: true]. ^playingP! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 9/8/2000 15:27'! playingP: aBool "Set whether we are playing or not. If not, no propogation, and emitters are on hold..." playingP _ aBool. aBool ifFalse: [self stopPlayback]. ^self! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 8/8/2000 15:44'! velocity velocity == nil ifTrue: [self velocity: self defaultVelocity]. ^velocity! ! !HexWorld methodsFor: 'model - world properties' stamp: 'ADT 8/8/2000 15:52'! velocity: aFloat "sent by slider" velocity _ aFloat.! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 8/5/2000 19:26'! clearCanvas "sent by button" self gridSpace clearCanvas! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 8/23/2000 04:41'! normal "sent by button" self gridSpace normal. self establishDefaultWorldProperties! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 9/9/2000 02:51'! reset "sent by button" self gridSpace reset.! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 8/23/2000 04:40'! rotateClockwise "sent by button" self gridSpace rotateClockwise! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 8/23/2000 04:40'! rotateCounterclockwise "sent by button" self gridSpace rotateCounterclockwise! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 8/19/2000 04:15'! spawnAnnotationPalette HexAnnotationPalette new openInWorld! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 8/23/2000 02:13'! spawnConnectionStatePalette HexConnectionStatePalette new openInWorld! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 8/17/2000 01:51'! spawnPalette HexMultiPalette new openInWorld! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 7/25/2000 12:59'! stopPlayback "sent by button" self gridSpace stopPlayback.! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 7/25/2000 12:59'! toggleGrid "sent by button" self gridSpace toggleGrid.! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 8/23/2000 04:35'! zoomIn "sent by button" self gridSpace zoomIn! ! !HexWorld methodsFor: 'widget interface' stamp: 'ADT 8/23/2000 04:35'! zoomOut "sent by button" self gridSpace zoomOut! ! !HexWorld class methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:35'! lookPolicy LookPolicy == nil ifTrue: [self lookPolicy: HexLookPolicy new]. ^LookPolicy! ! !HexWorld class methodsFor: 'accessing' stamp: 'ADT 9/9/2000 21:36'! lookPolicy: aPolicy LookPolicy _ aPolicy. ^self! ! !HexagonMorph reorganize! ('accessing' instrument pitch) ('copying' becomeLike: copy donateTo: doppelganger extension: privateBecomeLike:) ('drawing' drawAnnotationsOn: drawBorderOn: drawOn: drawOnHexGrid) ('editing' dragVertex:fromHandle:vertIndex:) ('event handling' doubleClick: doubleClickToggle: drag: dropOnto:withEvent: handlesMouseDown: handlesMouseOver: justDroppedInto:event: mouseDown: mouseEnter: prepareForDraggingWithEvent: removeFromContext yellowButtonActivity:) ('geometry' facetTargetedByEvent: merge: mergeDropThird:in:from: verticesInsetBy:) ('hierarchy operations' hexGrid hexWorld) ('initialization' initialize vertices:color:borderWidth:borderColor:) ('menu' addHandles) ('menus' getMenuWithEvent:) ('model - accessing' bePaletteVersion chi chi: coordinates coordinates: isPaletteVersionP notifyOwnerOfChange paletteVersion paletteVersion: updateWithGrid:) ('model - annotations' annotations annotations: clearAnnotations newAnnotation: removeAnnotation:) ('model - chi' activate activateConnectionsWithChi: activateStep activateWithChi: clearChi deactivate doneWithChi: dontActivateWithChi: glow glowWithChi: isActive killPlay privateActivateWithChi: privateDontActivateWithChi: unglow) ('model - connections' clearConnections connectTo:at: connectionAt: connectionTo: connections connections: hexConnectedToAt: opposingDirectionOf: removeConnections tieAt: tieTo:at: tieTo:at:cascade: toggleFacet: tryToTieAt:) ('model - sound' notifySoundOfTieTo: notifySoundOfUntieTo: simplePlay sound sound: soundPlayWithChi:) ('printing' printOn:) ('private' OLDlayoutChanged centerCache centerCache: computeVertices defaultVertices delete layoutChanged privateClearAnnotations privateConnectTo:at: privateRemoveAnnotation: privateRemoveConnection: updateHandles) ('reset' reset) ('stepping and presenter' startStepping step stepTime stopStepping) ('testing' isDoppelganger isMovable isSameAs: isTied myDouble) ('visual properties' annotationColor annotationWidth defaultColor defaultWidth lookPolicy) ! !HexagonMorph methodsFor: 'accessing' stamp: 'ADT 8/17/2000 02:04'! instrument ^self sound instrumentName! ! !HexagonMorph methodsFor: 'accessing' stamp: 'ADT 8/17/2000 02:02'! pitch ^self sound pitchName! ! !HexagonMorph methodsFor: 'copying' stamp: 'ADT 9/8/2000 17:35'! becomeLike: aHex "For one reason or another (for now, because it's been dropped on us!!) we should become 'like' aHex. For now, adopt aHex's sound and look policy as our own. It might in the future be better to give aHex our connections/annotations, and dispose of ourselves. THis has become a serious problem actually, since rests can't become me right now." self privateBecomeLike: aHex. self isDoppelganger ifTrue: [self myDouble privateBecomeLike: aHex]. aHex delete. self hexGrid hexChanged ! ! !HexagonMorph methodsFor: 'copying' stamp: 'ADT 9/9/2000 21:25'! copy "Return a copy free from encumbering connections to my own connections, etc." | n | n _ super copy. n clearChi. n clearConnections. n privateClearAnnotations. n paletteVersion: false. n centerCache: 0@0. n sound: (self sound veryDeepCopy). n extension: (self extension veryDeepCopy). ^n ! ! !HexagonMorph methodsFor: 'copying' stamp: 'ADT 8/19/2000 02:07'! donateTo: aHex "For one reason or another (for now, because I have been dropped on it!!) aHex should become 'like' self. For now, make aHex adopt aHex's sound and look policy as our own. Do this by in turn asking aHex to become like me. This lets aHex decline to do so." aHex becomeLike: self ! ! !HexagonMorph methodsFor: 'copying' stamp: 'ADT 8/25/2000 03:20'! doppelganger "Return a copy free from encumbering connections to my own connections, etc. -- which, however, is bridged to me via holding the same doppel connection annotation." | twin bridge | twin _ self copy. bridge _ HexDoppelgangerConnection input: self output: twin. self newAnnotation: bridge. twin newAnnotation: bridge other. ^twin ! ! !HexagonMorph methodsFor: 'copying' stamp: 'ADT 8/8/2000 14:59'! extension: anExtension extension _ anExtension ! ! !HexagonMorph methodsFor: 'copying' stamp: 'ADT 9/8/2000 17:34'! privateBecomeLike: aHex "For one reason or another (for now, because it's been dropped on us!!) we should become 'like' aHex. For now, adopt aHex's sound and look policy as our own. It might in the future be better to give aHex our connections/annotations, and dispose of ourselves. THis has become a serious problem actually, since rests can't become me right now." self sound: aHex sound. self borderColor: aHex borderColor. self color: aHex color. self fillStyle: aHex fillStyle! ! !HexagonMorph methodsFor: 'drawing' stamp: 'ADT 8/23/2000 02:12'! drawAnnotationsOn: aCanvas "Display annotations and connections of the receiver, a hex. Connections should really become submorphs?" "Draw the connections" self connections withIndexDo: [ :aConnection :facetNumber| (aConnection == nil) ifFalse: [aConnection drawOn: aCanvas in: self at: facetNumber]]. self annotations withIndexDo: [ :aConnection :facetNumber| (aConnection == nil) ifFalse: [aConnection drawOn: aCanvas in: self at: (facetNumber // 6)]]. ! ! !HexagonMorph methodsFor: 'drawing' stamp: 'ADT 9/9/2000 21:51'! drawBorderOn: aCanvas | lp | lp _ self lookPolicy. lp drawStyle == #shadow ifTrue: [2 to: (vertices size) do: [ :j | | i | i _ j - 1. (self connections at: i) == nil ifTrue: [aCanvas line: ((vertices at: i) + lp shadowOffset) to: ((vertices at: j) + lp shadowOffset) width: self annotationWidth color: lp shadowColor]]]. 2 to: (vertices size) do: [ :j | | i | i _ j - 1. (self connections at: i) == nil ifTrue: [ aCanvas line: (vertices at: i) to: (vertices at: j) width: self annotationWidth color: borderColor]]. ! ! !HexagonMorph methodsFor: 'drawing' stamp: 'ADT 9/8/2000 17:27'! drawOn: aCanvas "Display the receiver, a hexagon. Overridden as we have special properties." (self owner isHandMorph) ifTrue: [aCanvas drawPolygon: (self getVertices) fillStyle: (self fillStyle). self drawBorderOn: aCanvas. self drawAnnotationsOn: aCanvas] ifFalse: [(self valueOfProperty: #hidden ifAbsent: [false]) ifFalse: [aCanvas clipBy: (self owner innerBounds) during: [:clippedCanvas | clippedCanvas drawPolygon: (self getVertices) fillStyle: (self fillStyle). self drawBorderOn: clippedCanvas. self drawAnnotationsOn: clippedCanvas]]]! ! !HexagonMorph methodsFor: 'drawing' stamp: 'ADT 9/9/2000 20:44'! drawOnHexGrid "Useful as this method finds its own canvas" (self valueOfProperty: #hidden ifAbsent: [false]) ifFalse: [self world canvas clipBy: (self hexGrid innerBounds) during: [:clippedCanvas | clippedCanvas drawPolygon: (self "verticesInsetBy: 0.5 "getVertices) fillStyle: (self fillStyle). self drawBorderOn: clippedCanvas. self drawAnnotationsOn: clippedCanvas]]! ! !HexagonMorph methodsFor: 'editing' stamp: 'ADT 7/2/2000 23:14'! dragVertex: t1 fromHandle: t2 vertIndex: t3 ^ nil! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 8/8/2000 16:00'! doubleClick: evt "Shift double clicking toggles connections between open and closed. Simple double clicking activates me." self isPaletteVersionP ifTrue: [self simplePlay] ifFalse: [evt shiftPressed ifFalse: [self activate] ifTrue: [self doubleClickToggle: evt]] ! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 7/19/2000 00:40'! doubleClickToggle: evt "Determine where the double click occured. If we have a connection registered on the facet, change its type." self toggleFacet: (self facetTargetedByEvent: evt). ^self! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 9/9/2000 01:56'! drag: evt "Cache the offset between the cursorPoint and our center, to factor in for calculating new coords" ((evt isMouseDown and: [self isMovable]) and: [self isTied not]) ifTrue: [self isPaletteVersionP ifFalse: [evt shiftPressed ifTrue: [| n | ((self hexWorld doppelsP) and: [self isDoppelganger not]) ifTrue: [n _ self doppelganger] ifFalse: [n _ self copy]. evt hand attachMorph: n] ifFalse: [evt hand grabMorph: (self prepareForDraggingWithEvent: evt)]] ifTrue: [| n | n _ self copy. evt hand attachMorph: n]] ! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 8/19/2000 02:39'! dropOnto: aHexGrid withEvent: evt "HexGrid is asking me to handle being dropped onto itself. Deferred to me to allow different handling depending on whether I'm a Hex, an annotation carrying mule, etc." "In my case, ask the grid to place me on itself. If there's already a hex at the coordinates I would drop onto, donate myself instead." | there targetCoordinates | self simplePlay. targetCoordinates _ aHexGrid logicalCoordinatesForPoint: (evt cursorPoint - (self centerCache)). there _ aHexGrid hexAtCoordinates: targetCoordinates. there == nil ifTrue: [aHexGrid placeHex: self At: targetCoordinates] ifFalse: [self donateTo: there]! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 7/2/2000 19:30'! handlesMouseDown: evt ^ true! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 9/8/2000 15:24'! handlesMouseOver: evt "Do I want to receive mouseEnter: and mouseLeave: when the button is up and the hand is empty? The default response is false, except if you have added sensitivity to mouseEnter: or mouseLeave:, using the on:send:to: mechanism." self eventHandler ifNotNil: [^ self eventHandler handlesMouseOver: evt]. ^ true! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 8/19/2000 02:39'! justDroppedInto: aMorph event: anEvent (aMorph isKindOf: HexGrid) ifFalse: [self delete. "slideToTrash: anEvent"]! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 8/17/2000 21:27'! mouseDown: evt "Do nothing upon mouse-down except inform the hand to watch for a double-click; wait until an ensuing click:, doubleClick:, or drag: message gets dispatched" evt yellowButtonPressed "First check for option (menu) click" ifTrue: [^ self yellowButtonActivity: evt]. self isPaletteVersionP ifTrue: [self simplePlay]. evt hand waitForClicksOrDrag: self event: evt! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 9/8/2000 17:47'! mouseEnter: evt "If the world we're in is not playing, then play when the mouse enters me... this allows the user to trace out what their structure sounds like while it is paused..." self isPaletteVersionP ifFalse: [((self hexWorld == nil) not and: [self hexWorld playingP]) ifFalse: [self simplePlay]]! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 8/26/2000 00:59'! prepareForDraggingWithEvent: evt self removeFromContext. self centerCache: (self center - evt cursorPoint). ^self ! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 8/26/2000 00:58'! removeFromContext self removeConnections. self stopStepping. ^self ! ! !HexagonMorph methodsFor: 'event handling' stamp: 'ADT 7/19/2000 00:36'! yellowButtonActivity: evt | menu event | (menu _ self getMenuWithEvent: evt) ifNotNil: [event _ self primaryHand lastEvent. menu setInvokingView: self. menu popUpAt: event cursorPoint event: event]! ! !HexagonMorph methodsFor: 'geometry' stamp: 'ADT 8/8/2000 15:29'! facetTargetedByEvent: evt "Answer the evt cursor point was when evt occured -- find the nearest facet for now." | ang facet | ang _ ((evt cursorPoint - self center) theta radiansToDegrees + 30) - self hexGrid angle. ang _ (ang roundTo: 60) \\ 360. facet _ ang / 60. facet = 0 ifTrue: [facet _ 6]. ^facet! ! !HexagonMorph methodsFor: 'geometry' stamp: 'ADT 7/2/2000 17:14'! merge: aPolygon self shouldNotImplement! ! !HexagonMorph methodsFor: 'geometry' stamp: 'ADT 7/2/2000 17:14'! mergeDropThird: mv in: hv from: shared self shouldNotImplement! ! !HexagonMorph methodsFor: 'geometry' stamp: 'ADT 7/12/2000 18:26'! verticesInsetBy: aPercentage "Assumes we are drawn around (not offset from) our center. Adjust each vertice aPercentage closer or farther to the center." | c | c _ self center. ^self vertices collect: [ :aVert | ((aVert - c) * aPercentage) + c] ! ! !HexagonMorph methodsFor: 'hierarchy operations' stamp: 'ADT 9/8/2000 17:25'! hexGrid | o | o _ self owner. ^(o isKindOf: HexGrid) ifTrue: [o] ifFalse: [nil]! ! !HexagonMorph methodsFor: 'hierarchy operations' stamp: 'ADT 9/8/2000 17:26'! hexWorld ^self hexGrid == nil ifFalse: [self hexGrid hexWorld] ifTrue: [nil]! ! !HexagonMorph methodsFor: 'initialization' stamp: 'ADT 7/13/2000 01:23'! initialize super initialize. self borderColor: (Color white) "#raised". vertices _ self defaultVertices. self computeBounds. self stopStepping. ! ! !HexagonMorph methodsFor: 'initialization' stamp: 'ADT 7/2/2000 17:13'! vertices: mm color: ai borderWidth: gsiiss borderColor: bc self shouldNotImplement! ! !HexagonMorph methodsFor: 'menu' stamp: 'ADT 7/2/2000 17:15'! addHandles "We override super since, as a fixed poly, we don't want to ever had new vertices. So, no trianlges." | handle | self removeHandles. handles _ OrderedCollection new. vertices withIndexDo: [:vertPt :vertIndex | handle _ EllipseMorph newBounds: (Rectangle center: vertPt extent: 8@8) color: Color yellow. handle on: #mouseStillDown send: #dragVertex:fromHandle:vertIndex: to: self withValue: vertIndex. handle on: #mouseUp send: #dropVertex:fromHandle:vertIndex: to: self withValue: vertIndex. self addMorph: handle. handles addLast: handle]. self changed! ! !HexagonMorph methodsFor: 'menus' stamp: 'ADT 8/23/2000 03:46'! getMenuWithEvent: evt "Pull up a menu with context based on where the hexagon was (right) clicked on. Whichever facet was picked becomes the argument for any connection state toggling... NOTE: Ideally, this should switch menus based on evt shiftKeyState." | menu facet c sub | self isPaletteVersionP ifTrue: [^nil]. menu _ MenuMorph new defaultTarget: self. menu add: 'play me' action: #simplePlay. menu add: 'activate' action: #activate. menu title: self name. "'Hexagon'." menu add: 'delete' action: #delete. menu addLine. sub _ HexAnnotation getMenuWithEvent: evt hex: self. menu add: 'annotations...' subMenu: sub. facet _ self facetTargetedByEvent: evt. (c _ self connectionAt: facet) == nil ifFalse: [sub _ c getMenuWithEvent: evt facet: facet. menu addLine. menu add: 'facet...' subMenu: sub]. ^ menu! ! !HexagonMorph methodsFor: 'model - accessing' stamp: 'ADT 8/8/2000 14:31'! bePaletteVersion self paletteVersion: true.! ! !HexagonMorph methodsFor: 'model - accessing' stamp: 'ADT 7/13/2000 15:00'! chi "Set of activations I have now." chi == nil ifTrue: [self chi: OrderedCollection new]. ^ chi! ! !HexagonMorph methodsFor: 'model - accessing' stamp: 'ADT 7/13/2000 14:35'! chi: aCollection "Modifiers to my properties." chi _ aCollection. ^ self! ! !HexagonMorph methodsFor: 'model - accessing' stamp: 'ADT 7/2/2000 17:05'! coordinates "Logical coordinates, not screen coordinates" coordinates == nil ifTrue: [self coordinates: 0 @ 0]. ^ coordinates! ! !HexagonMorph methodsFor: 'model - accessing' stamp: 'ADT 7/2/2000 19:36'! coordinates: aPoint "Logical coordinates, not screen coordinates" coordinates _ aPoint. self notifyOwnerOfChange. ^self! ! !HexagonMorph methodsFor: 'model - accessing' stamp: 'ADT 8/8/2000 14:30'! isPaletteVersionP ^self paletteVersion! ! !HexagonMorph methodsFor: 'model - accessing' stamp: 'ADT 8/8/2000 15:29'! notifyOwnerOfChange owner == nil ifFalse: [self hexGrid hexChanged]. ^self! ! !HexagonMorph methodsFor: 'model - accessing' stamp: 'ADT 8/8/2000 14:31'! paletteVersion paletteVersion == nil ifTrue: [self paletteVersion: false]. ^paletteVersion! ! !HexagonMorph methodsFor: 'model - accessing' stamp: 'ADT 8/8/2000 14:30'! paletteVersion: aBool paletteVersion _ aBool. ^self! ! !HexagonMorph methodsFor: 'model - accessing' stamp: 'ADT 7/11/2000 01:01'! updateWithGrid: aHexgrid "Some event has changed a property of aHexGrid such as scale, translation or rotation. Update myself to fit into the new worldview." | myCoords c | myCoords _ self coordinates. c _ aHexgrid physicalCoordinatesForX: (myCoords x) Y: (myCoords y). self setVertices: (aHexgrid hexagonVerticesAtCoordinates: c). self setProperty: #hidden toValue: (aHexgrid hexIsVisibleAt: c) not. "self position: c" ! ! !HexagonMorph methodsFor: 'model - annotations' stamp: 'ADT 8/5/2000 16:51'! annotations "Answer a collection of my annotations." annotations == nil ifTrue: [self annotations: OrderedCollection new]. ^ annotations! ! !HexagonMorph methodsFor: 'model - annotations' stamp: 'ADT 8/5/2000 16:52'! annotations: aCollection annotations _ aCollection. ^ self! ! !HexagonMorph methodsFor: 'model - annotations' stamp: 'ADT 8/21/2000 21:29'! clearAnnotations "Used when copying to insure the copy does NOT have any (errant) connections. Unlike remove connections, I do not instruct the connections themselves to do anything. Detaching morphs need to use removeConnections which destroys the connections themselves." self annotations do: [ :a | self removeAnnotation: a]. self privateClearAnnotations. ^self! ! !HexagonMorph methodsFor: 'model - annotations' stamp: 'ADT 9/8/2000 15:54'! newAnnotation: anAnnotation "Assign myself a new annotation" anAnnotation == nil ifFalse: [anAnnotation addSelfToHex: self. self annotations add: anAnnotation. self changed] ! ! !HexagonMorph methodsFor: 'model - annotations' stamp: 'ADT 8/25/2000 19:13'! removeAnnotation: anAnnotation "If we have the annotation still in our annotations list, remove it." anAnnotation removeSelfFromHex: self. self privateRemoveAnnotation: anAnnotation. ^self! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 9/8/2000 15:15'! activate "Do a colorwash and eventually play a sound. This method is only called on the *original* hex that's activated. Others are activated through propogation with activatesWithChi:" | newChi | self clearChi. "just to be safe" self hexWorld playingP ifFalse: [^self simplePlay]. "If not playing, don't propogate, but do play..." newChi _ HexChi new. newChi resetTime. self activateWithChi: newChi. ^self! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 8/8/2000 14:32'! activateConnectionsWithChi: aChi "For all connections that are open, activate the next nodes." | nogo | (self isPaletteVersionP) ifTrue: [^self]. nogo _ aChi dontPassDirection. self connections withIndexDo: [ :c :i | (((i = nogo) not) and: [(c == nil) not]) ifTrue: [c propogateChi: aChi from: self direction: i]]! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 8/8/2000 15:50'! activateStep self chi do: [ :aChi | ((aChi decrementTimeInWorld: self hexWorld) = 0) ifTrue: [self doneWithChi: aChi]]. self chi isEmpty ifTrue: [self deactivate] ! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 8/17/2000 01:29'! activateWithChi: aChi "Do a colorwash and eventually play a sound." self annotations inject: aChi into: [ :c :a | c == nil ifFalse: [a preactivateWithChi: aChi]]. self privateActivateWithChi: aChi! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 7/13/2000 15:30'! clearChi self chi: OrderedCollection new. "just to be safe" ^self! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 9/9/2000 20:45'! deactivate self unglow. self stopStepping.! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 8/17/2000 01:23'! doneWithChi: aChi | result | result _ self annotations inject: aChi into: [ :c :a | c == nil ifFalse: [a postactivateWithChi: c]]. result == nil ifFalse: [self activateConnectionsWithChi: result]. self chi remove: aChi. ^self ! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 7/25/2000 14:26'! dontActivateWithChi: aChi "Do a colorwash and eventually DON'T play a sound." "Passthrough for tied, etc., activation..." self chi add: aChi. self glowWithChi: aChi. self startStepping. "self soundPlayWithChi: aChi"! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 8/8/2000 15:29'! glow (self valueOfProperty: #hidden ifAbsent: [false]) ifFalse: [self world canvas clipBy: (self hexGrid innerBounds) during: [:clippedCanvas | clippedCanvas frameAndFillRectangle: (Rectangle center: self center extent: (self width * 0.25)) fillColor: "self annotationColor" Color white borderWidth: 0 borderColor: Color transparent]]! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 8/16/2000 01:23'! glowWithChi: aChi (self valueOfProperty: #hidden ifAbsent: [false]) ifFalse: [self world canvas clipBy: (self hexGrid innerBounds) during: [:clippedCanvas | aChi drawOn: clippedCanvas in: self]]! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 7/13/2000 15:02'! isActive ^(self chi isEmpty not)! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 7/13/2000 15:30'! killPlay self clearChi. self deactivate. self changed.! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 8/17/2000 01:29'! privateActivateWithChi: aChi "Do a colorwash and eventually play a sound." aChi == nil ifTrue: [^self]. self chi add: aChi. self glowWithChi: aChi. self startStepping. self soundPlayWithChi: aChi! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 8/5/2000 16:48'! privateDontActivateWithChi: aChi "Do a colorwash and eventually DON'T play a sound." "Passthrough for tied, etc., activation..." self chi add: aChi. self glowWithChi: aChi. self startStepping. "self soundPlayWithChi: aChi"! ! !HexagonMorph methodsFor: 'model - chi' stamp: 'ADT 9/9/2000 20:44'! unglow self drawOnHexGrid! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/14/2000 16:25'! clearConnections "Used when copying to insure the copy does NOT have any (errant) connections. Unlike remove connections, I do not instruct the connections themselves to do anything. Detaching morphs need to use removeConnections which destroys the connections themselves." connections _ nil. ^self! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/20/2000 18:40'! connectTo: aHex at: aDirection | aConnection | aConnection _ HexConnection input: self output: aHex. aHex privateConnectTo: aConnection other at: (self opposingDirectionOf: aDirection). self privateConnectTo: aConnection at: aDirection. ^self! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/19/2000 00:41'! connectionAt: aFacet "If we have a connection on aFacet, answer it." ^self connections at: aFacet ! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/25/2000 20:49'! connectionTo: aHex "Answer the connection to aHex, if any..." ^self connections detect: [:c | (c == nil) not and: [ c oppositeSide == aHex]] ifNone: [nil] ! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/12/2000 17:49'! connections "Answer an array of my connections. Currently we only support explicit connections on our 6 faces, hence array size 6." connections == nil ifTrue: [self connections: (Array new: 6)]. ^ connections! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/12/2000 17:49'! connections: anArray connections _ anArray. ^ self! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/25/2000 20:42'! hexConnectedToAt: aDirection | x | x _ self connectionAt: aDirection. ^x == nil ifTrue: [nil] ifFalse: [x oppositeSide]! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/12/2000 18:02'! opposingDirectionOf: aDirection "Answer the direction opposite aDirection, given our arbitrary numbering of our facets." ^(aDirection < 4) ifTrue: [aDirection + 3] ifFalse: [aDirection - 3]! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/26/2000 01:29'! removeConnections "Iterate through my connections, removing them from my connections list. When they are removed, they need to be removed from the other side's list too." self connections do: [ :c | (c == nil) ifFalse: [c removeFrom: self]]. connections _ nil. ^self! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/25/2000 20:43'! tieAt: aDirection | aHex | aHex _ self hexConnectedToAt: aDirection. aHex == nil ifFalse: [self tieTo: aHex at: aDirection]! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 8/9/2000 01:17'! tieTo: aHex at: aDirection ^self tieTo: aHex at: aDirection cascade: false! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 8/15/2000 15:52'! tieTo: aHex at: aDirection cascade: cascade | aConnection | self connectTo: aHex at: aDirection. aConnection _ self connectionTo: aHex. aConnection newState: (HexTieConnectionState new). aConnection other newState: (HexTieConnectionState new). aHex sound: self sound. "gets its own copy back from HexSound-removeTie: if we break the tie" self sound addTie: self. self sound addTie: aHex. cascade == true ifTrue: [aHex tryToTieAt: aDirection]. ^self! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 7/20/2000 18:25'! toggleFacet: aFacet "If we have a connection on aFacet, inc its type. aFacet may not be occupied." | c | ((c _ self connectionAt: aFacet) == nil) ifFalse: [c toggleState] ! ! !HexagonMorph methodsFor: 'model - connections' stamp: 'ADT 8/9/2000 01:16'! tryToTieAt: aDirection | aHex | aHex _ self hexConnectedToAt: aDirection. aHex == nil ifFalse: [(aHex isSameAs: self) ifTrue: [self tieTo: aHex at: aDirection cascade: true]]! ! !HexagonMorph methodsFor: 'model - sound' stamp: 'ADT 7/25/2000 19:20'! notifySoundOfTieTo: aHexagon "Notify our hexSound that we are tieing to node aHexagon. Tihs lets our sounda adjust itself to compensate for the tie -- typically by multiplying its duration." self sound addTieTo: aHexagon. ^self! ! !HexagonMorph methodsFor: 'model - sound' stamp: 'ADT 7/25/2000 19:21'! notifySoundOfUntieTo: aHexagon "Notify our hexSound that we are untieing from node aHexagon. This lets our sound adjust itself to compensate for the loss of tie -- typically by reducing its duration." self sound removeTieTo: aHexagon. ^self! ! !HexagonMorph methodsFor: 'model - sound' stamp: 'ADT 8/8/2000 15:02'! simplePlay "Useful during painting to know what you're doing..." self sound play! ! !HexagonMorph methodsFor: 'model - sound' stamp: 'ADT 8/16/2000 01:16'! sound "Return the sound I play when activated" sound == nil ifTrue: [self sound: HexFMSoundWrapper new]. ^sound! ! !HexagonMorph methodsFor: 'model - sound' stamp: 'ADT 7/25/2000 13:17'! sound: aHexSound "Set the sound I play when activated. Note that we defer playing to the sound itself, which therefore must at minimum be a wrapper around a native Squeak (or Siren) sound." sound _ aHexSound. ^self! ! !HexagonMorph methodsFor: 'model - sound' stamp: 'ADT 8/17/2000 21:12'! soundPlayWithChi: aChi "Modulate the sound we play according to the current amplitude and/or other properties of aChi." | s | s _ self sound copy. s magnitude: aChi amplitude * s magnitude. s play! ! !HexagonMorph methodsFor: 'printing' stamp: 'ADT 8/17/2000 01:56'! printOn: aStream aStream nextPutAll: 'Hex ('. aStream nextPutAll: self instrument. aStream nextPutAll: ', '. aStream nextPutAll: self pitch. aStream nextPutAll: ')' ! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 7/2/2000 18:32'! OLDlayoutChanged "Note that something has changed about the size, shape, or location of the receiver or one of its submorphs, so that fullBounds must be recomputed." fullBounds _ nil. "self halt. owner ifNotNil: [owner layoutChanged]." submorphs size > 0 ifTrue: ["Let submorphs know about a change above" submorphs do: [:m | m ownerChanged]]. ! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 7/13/2000 16:51'! centerCache ^centerCache! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 7/13/2000 16:51'! centerCache: aPoint centerCache _ aPoint. ^self! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 7/2/2000 17:13'! computeVertices | verts | verts _ OrderedCollection new. 0 to: 300 by: 60 do: [ :angle | | x y v| x _ (angle + self rotationDegrees) degreesToRadians cos. y _ (angle + self rotationDegrees) degreesToRadians sin. v _ Point x: x y: y. v _ v * ((self width - self borderWidth) / 2). v _ v + self center. verts add: v]. verts add: (verts at: 1). ^Array withAll: verts! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 7/11/2000 00:32'! defaultVertices | verts radius offset | radius _ 10. offset _ 100@100. verts _ OrderedCollection new. 0 to: 300 by: 60 do: [ :angle | | x y v | x _ (angle + self rotationDegrees) degreesToRadians cos. y _ (angle + self rotationDegrees) degreesToRadians sin. v _ Point x: x y: y. v _ v * radius. v _ v + offset. verts add: v]. verts add: (verts at: 1). ^Array withAll: verts! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 8/26/2000 00:59'! delete self clearAnnotations. self removeFromContext. super delete! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 7/2/2000 18:34'! layoutChanged "Note that something has changed about the size, shape, or location of the receiver or one of its submorphs, so that fullBounds must be recomputed." fullBounds _ nil. "self halt. owner ifNotNil: [owner layoutChanged]." submorphs size > 0 ifTrue: ["Let submorphs know about a change above" submorphs do: [:m | m ownerChanged]]. ! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 8/21/2000 21:28'! privateClearAnnotations "Used when copying to insure the copy does NOT have any (errant) connections. Unlike remove connections, I do not instruct the connections themselves to do anything. Detaching morphs need to use removeConnections which destroys the connections themselves." annotations _ nil. ^self! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 7/12/2000 17:50'! privateConnectTo: aConnection at: aDirection self connections at: aDirection put: aConnection. ^self! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 8/25/2000 19:13'! privateRemoveAnnotation: anAnnotation "If we have the annotation still in our annotations list, remove it." self annotations remove: anAnnotation ifAbsent: [^self]. self changed! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 7/24/2000 17:06'! privateRemoveConnection: aConnection "If we have a connection to aConnection, remove it from our connections list. This private version assumes that the caller is also removing the connection from the other end's list...!! NOTE: at time of writing the caller is the HexConnection." | bye | ((bye _ self connections indexOf: aConnection) = 0) ifFalse: [self connections at: bye put: nil. self changed].! ! !HexagonMorph methodsFor: 'private' stamp: 'ADT 7/2/2000 17:14'! updateHandles "Needs to be further updated to allow only symmetrical growth." | oldVert | vertices withIndexDo: [:vertPt :vertIndex | oldVert _ handles at: vertIndex. oldVert position: vertPt - (oldVert extent//2)]! ! !HexagonMorph methodsFor: 'reset' stamp: 'ADT 9/9/2000 02:49'! reset "Reset annotations and connections" self connections do: [ :aConnection | (aConnection == nil) ifFalse: [aConnection reset]]. self annotations do: [ :anAnnotation | (anAnnotation == nil) ifFalse: [anAnnotation reset]]. ! ! !HexagonMorph methodsFor: 'stepping and presenter' stamp: 'ADT 7/13/2000 15:25'! startStepping "Start getting sent the 'step' message." | w | "self step. " "one to get started!!" w _ self world. w ifNotNil: [ w startStepping: self].! ! !HexagonMorph methodsFor: 'stepping and presenter' stamp: 'ADT 7/13/2000 01:18'! step "super step." self isActive ifTrue: [self activateStep].! ! !HexagonMorph methodsFor: 'stepping and presenter' stamp: 'ADT 8/6/2000 03:18'! stepTime "Answer the desired time between steps in milliseconds." ^ 25! ! !HexagonMorph methodsFor: 'stepping and presenter' stamp: 'ADT 7/13/2000 01:22'! stopStepping "Stop getting sent the 'step' message." | w | w _ self world. w ifNotNil: [ w stopStepping: self]. ! ! !HexagonMorph methodsFor: 'testing' stamp: 'ADT 9/8/2000 17:37'! isDoppelganger ^(self myDouble == nil) not! ! !HexagonMorph methodsFor: 'testing' stamp: 'ADT 8/9/2000 01:09'! isMovable "Answer whether I should be moved. At present, there is one known case when I shouldn't -- when I'm tied on two sides. In this case I'm in the middle of a tie and trouble will ensue if I'm moved." ^(self connections select: [ :c | (c == nil) not and: [c state isKindOf: HexTieConnectionState]]) size < 2! ! !HexagonMorph methodsFor: 'testing' stamp: 'ADT 8/9/2000 01:16'! isSameAs: aHex ^aHex == nil ifTrue: [false] ifFalse: [self sound isSameAs: aHex sound]! ! !HexagonMorph methodsFor: 'testing' stamp: 'ADT 9/9/2000 01:52'! isTied "Answer whether I am tied." ^(self connections select: [ :c | (c == nil) not and: [c state isKindOf: HexTieConnectionState]]) size > 0! ! !HexagonMorph methodsFor: 'testing' stamp: 'ADT 9/8/2000 17:37'! myDouble | i | i _ self annotations findFirst: [ :a | a isDoppelganger]. ^i = 0 ifTrue: [nil] ifFalse: [(self annotations at: i) oppositeSide]! ! !HexagonMorph methodsFor: 'visual properties' stamp: 'ADT 8/23/2000 02:18'! annotationColor ^self borderColor! ! !HexagonMorph methodsFor: 'visual properties' stamp: 'ADT 8/5/2000 20:00'! annotationWidth "Answer the width, scaled to the current zoom." ^(self owner isKindOf: HexGrid) ifTrue: [(self defaultWidth * self owner scale) rounded max: 1] ifFalse: [self defaultWidth]! ! !HexagonMorph methodsFor: 'visual properties' stamp: 'ADT 7/2/2000 17:07'! defaultColor ^ Color blue! ! !HexagonMorph methodsFor: 'visual properties' stamp: 'ADT 8/5/2000 19:52'! defaultWidth "Answer the width, scaled to the current zoom." ^2! ! !HexagonMorph methodsFor: 'visual properties' stamp: 'ADT 9/9/2000 21:51'! lookPolicy "For now, kludge it and all look to HexWorld to hold a master." ^HexWorld lookPolicy! ! !HexAnnotationMule commentStamp: 'ADT 8/19/2000 02:15' prior: 0! A subclass whose sole purpose at time of creation is to display and transport annotations from palettes onto existing HexagonMorphs. I act via donateTo:, which is called when I get dropped onto a grid location where a hex already exists.! !HexAnnotationMule reorganize! ('copying' copy donateTo:) ('drawing' drawOn:) ('event handling' dropOnto:withEvent:) ('model - chi' activate) ('model - sound' simplePlay) ('model - annotations' clearAnnotations) ! !HexAnnotationMule methodsFor: 'copying' stamp: 'ADT 8/19/2000 04:27'! copy "Kludgey overload to prevent super from erasing our annotations, which are after all our raison d'etre" | n kludge | kludge _ self annotations. n _ super copy. n annotations: kludge. ^n ! ! !HexAnnotationMule methodsFor: 'copying' stamp: 'ADT 8/19/2000 04:22'! donateTo: aHex "For one reason or another (for now, because I have been dropped on it!!) aHex should become 'like' self. For now, make aHex adopt my annoations." self annotations do: [ :a | | newAnn | newAnn _ a veryDeepCopy. newAnn hex: aHex. aHex newAnnotation: newAnn]. self delete. ! ! !HexAnnotationMule methodsFor: 'drawing' stamp: 'ADT 9/8/2000 17:29'! drawOn: aCanvas "Display the receiver, a hexagon. Overridden as we have special properties." (self owner isHandMorph) ifTrue: [self drawBorderOn: aCanvas. self drawAnnotationsOn: aCanvas] ifFalse: [(self valueOfProperty: #hidden ifAbsent: [false]) ifFalse: [aCanvas clipBy: (self owner innerBounds) during: [:clippedCanvas | self drawBorderOn: clippedCanvas. self drawAnnotationsOn: clippedCanvas]]]! ! !HexAnnotationMule methodsFor: 'event handling' stamp: 'ADT 8/21/2000 20:59'! dropOnto: aHexGrid withEvent: evt "HexGrid is asking me to handle being dropped onto itself. Deferred to me to allow different handling depending on whether I'm a Hex, an annotation carrying mule, etc." "In my case, check to see if there's a hex where I'm being dropped. If there is, donate my annotation(s) to it. If not, add a rest there, then add my properties to it." | there targetCoordinates | targetCoordinates _ aHexGrid logicalCoordinatesForPoint: (evt cursorPoint - (self centerCache)). there _ aHexGrid hexAtCoordinates: targetCoordinates. there == nil ifTrue: [there _ HexRestMorph default. aHexGrid placeHex: there At: targetCoordinates.]. self donateTo: there! ! !HexAnnotationMule methodsFor: 'model - chi' stamp: 'ADT 8/19/2000 02:54'! activate "Do nothing, I'm just a carrier. Useful since emitters (and probably others in the future) will be autonomously sending activate!!" ^self! ! !HexAnnotationMule methodsFor: 'model - sound' stamp: 'ADT 8/19/2000 02:55'! simplePlay "Override, I shouldn't do anything..." ^self! ! !HexAnnotationMule methodsFor: 'model - annotations' stamp: 'ADT 8/26/2000 00:56'! clearAnnotations "Used when copying to insure the copy does NOT have any (errant) connections. Unlike remove connections, I do not instruct the connections themselves to do anything. Detaching morphs need to use removeConnections which destroys the connections themselves." "Overloaded, as at time of writing, HexagonMorph delete calls me." ^self! ! !HexClearAnnotationMule commentStamp: 'ADT 8/23/2000 01:08' prior: 0! I am a subclass whose responsibility is to clear the existing annotations of the hex I am dropped onto, rather than add one.! !HexClearAnnotationMule reorganize! ('copying' donateTo:) ('drawing' drawAnnotationsOn:) ('private') ('event handling' dropOnto:withEvent:) ('visual properties' annotationColor) ! !HexClearAnnotationMule methodsFor: 'copying' stamp: 'ADT 8/21/2000 20:59'! donateTo: aHex "For one reason or another (for now, because I have been dropped on it!!) aHex should become 'like' self. For now, make aHex adopt my annoations. In my case, that means NONE" aHex clearAnnotations. self delete. ! ! !HexClearAnnotationMule methodsFor: 'drawing' stamp: 'ADT 8/21/2000 20:57'! drawAnnotationsOn: aCanvas "Display the receiver, a hexagon. Overridden as we have special properties." | r | r _ Rectangle encompassing: (self verticesInsetBy: 0.3). aCanvas drawPolygon: (Array with: (r topLeft) with: (r bottomRight)) fillStyle: Color transparent borderWidth: self annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (r bottomLeft) with: (r topRight)) fillStyle: Color transparent borderWidth: self annotationWidth borderColor: self annotationColor. ! ! !HexClearAnnotationMule methodsFor: 'event handling' stamp: 'ADT 8/21/2000 21:33'! dropOnto: aHexGrid withEvent: evt "HexGrid is asking me to handle being dropped onto itself. Deferred to me to allow different handling depending on whether I'm a Hex, an annotation carrying mule, etc." "In my case, check to see if there's a hex where I'm being dropped. If there is, donate my annotation(s) to it. If not, add a rest there, then add my properties to it." | there targetCoordinates | targetCoordinates _ aHexGrid logicalCoordinatesForPoint: (evt cursorPoint - (self centerCache)). there _ aHexGrid hexAtCoordinates: targetCoordinates. there == nil ifFalse: [self donateTo: there] ifTrue: [self delete]! ! !HexClearAnnotationMule methodsFor: 'visual properties' stamp: 'ADT 8/21/2000 21:32'! annotationColor ^Color red! ! !HexConnectionStateMule commentStamp: 'ADT 8/23/2000 01:09' prior: 0! I am a sub who carries connection states to be (perhaps) dropped onto connections between hexes at given facets, rather than annotations.! !HexConnectionStateMule reorganize! ('copying' copy donateTo:onFacet:) ('drawing' drawAnnotationsOn: drawOn:) ('event handling' dropOnto:withEvent:) ('private' OLDdefaultVertices defaultVertices) ('model - connections' removeConnections) ('model - sound' simplePlay) ! !HexConnectionStateMule methodsFor: 'copying' stamp: 'ADT 8/23/2000 02:09'! copy "Kludgey overload to prevent super from erasing our connection(s), which are after all our raison d'etre" | n kludge | kludge _ self connections. n _ super copy. n connections: kludge. ^n ! ! !HexConnectionStateMule methodsFor: 'copying' stamp: 'ADT 8/23/2000 02:10'! donateTo: aHex onFacet: aFacet "For one reason or another (for now, because I have been dropped on it!!) aHex should adopt my connection state on aFacet, if possible" | c | (c _ aHex connectionAt: aFacet) == nil ifFalse: [| s | (s _ self connections anyOne) == nil ifFalse: [c newState: s state veryDeepCopy]]. self delete. ! ! !HexConnectionStateMule methodsFor: 'drawing' stamp: 'ADT 8/23/2000 02:43'! drawAnnotationsOn: aCanvas "Display only the connections of the receiver, a hexagon. For now, just draw connections I'm carrying at facet 5 (the top one)." "Draw the connections" self connections withIndexDo: [ :aConnection :facetNumber| (aConnection == nil) ifFalse: [aConnection drawOn: aCanvas in: self at: 2]].! ! !HexConnectionStateMule methodsFor: 'drawing' stamp: 'ADT 9/8/2000 17:31'! drawOn: aCanvas "Display the receiver, a hexagon. Overridden as we have special properties." (self owner isHandMorph) ifTrue: ["self drawBorderOn: aCanvas." self drawAnnotationsOn: aCanvas] ifFalse: [(self valueOfProperty: #hidden ifAbsent: [false]) ifFalse: [aCanvas clipBy: (self owner innerBounds) during: [:clippedCanvas | "self drawBorderOn: clippedCanvas." self drawAnnotationsOn: clippedCanvas]]]! ! !HexConnectionStateMule methodsFor: 'event handling' stamp: 'ADT 8/23/2000 01:13'! dropOnto: aHexGrid withEvent: evt "HexGrid is asking me to handle being dropped onto itself. Deferred to me to allow different handling depending on whether I'm a Hex, an annotation carrying mule, etc." "In my case, check to see if there's a hex where I'm being dropped. If there is, donate my annotation(s) to it. If not, add a rest there, then add my properties to it." | there targetCoordinates | targetCoordinates _ aHexGrid logicalCoordinatesForPoint: (evt cursorPoint - (self centerCache)). there _ aHexGrid hexAtCoordinates: targetCoordinates. there == nil ifFalse: [self donateTo: there onFacet: (there facetTargetedByEvent: evt)] ifTrue: [self delete]! ! !HexConnectionStateMule methodsFor: 'private' stamp: 'ADT 8/23/2000 02:34'! OLDdefaultVertices | verts radius offset | radius _ 30. offset _ 100@100. verts _ OrderedCollection new. 0 to: 300 by: 60 do: [ :angle | | x y v | x _ (angle + self rotationDegrees) degreesToRadians cos. y _ (angle + self rotationDegrees) degreesToRadians sin. v _ Point x: x y: y. v _ v * radius. v _ v + offset. verts add: v]. verts add: (verts at: 1). ^Array withAll: verts! ! !HexConnectionStateMule methodsFor: 'private' stamp: 'ADT 8/23/2000 02:44'! defaultVertices ^Array with: 0@0 with: 35@0 with: 35@35 with: 0@35! ! !HexConnectionStateMule methodsFor: 'model - connections' stamp: 'ADT 9/8/2000 17:45'! removeConnections "Iterate through my connections, removing them from my connections list. When they are removed, they need to be removed from the other side's list too." connections _ nil. ^self! ! !HexConnectionStateMule methodsFor: 'model - sound' stamp: 'ADT 9/9/2000 01:40'! simplePlay "Override, I shouldn't do anything..." ^self! ! !HexClearConnectionStateMule reorganize! ('copying' donateTo:onFacet:) ('drawing' drawAnnotationsOn:) ('event handling' dropOnto:withEvent:) ('visual properties' annotationColor) ! !HexClearConnectionStateMule methodsFor: 'copying' stamp: 'ADT 8/23/2000 01:30'! donateTo: aHex onFacet: aFacet "For one reason or another (for now, because I have been dropped on it!!) aHex should adopt my connection state on aFacet, if possible" | c | (c _ aHex connectionAt: aFacet) == nil ifFalse: [c newState: HexOpenConnectionState new]. self delete. ! ! !HexClearConnectionStateMule methodsFor: 'drawing' stamp: 'ADT 8/23/2000 01:29'! drawAnnotationsOn: aCanvas "Display the receiver, a hexagon. Overridden as we have special properties." | r | r _ Rectangle encompassing: (self verticesInsetBy: 0.3). aCanvas drawPolygon: (Array with: (r topLeft) with: (r bottomRight)) fillStyle: Color transparent borderWidth: self annotationWidth borderColor: self annotationColor; drawPolygon: (Array with: (r bottomLeft) with: (r topRight)) fillStyle: Color transparent borderWidth: self annotationWidth borderColor: self annotationColor. ! ! !HexClearConnectionStateMule methodsFor: 'event handling' stamp: 'ADT 8/23/2000 01:29'! dropOnto: aHexGrid withEvent: evt "HexGrid is asking me to handle being dropped onto itself. Deferred to me to allow different handling depending on whether I'm a Hex, an annotation carrying mule, etc." "In my case, check to see if there's a hex where I'm being dropped. If there is, donate my annotation(s) to it. If not, add a rest there, then add my properties to it." | there targetCoordinates | targetCoordinates _ aHexGrid logicalCoordinatesForPoint: (evt cursorPoint - (self centerCache)). there _ aHexGrid hexAtCoordinates: targetCoordinates. there == nil ifFalse: [self donateTo: there onFacet: (there facetTargetedByEvent: evt)] ifTrue: [self delete]! ! !HexClearConnectionStateMule methodsFor: 'visual properties' stamp: 'ADT 8/23/2000 01:29'! annotationColor ^Color red! ! !HexGridGhost commentStamp: 'ADT 8/19/2000 02:14' prior: 0! A dummy subclass, used to allow a temporary, kludgey form of background-dragging. Gives the hand morph something to carry when I'm trying to drag-scroll the HexGrid.! !HexGridGhost reorganize! ('drawing' OLDdrawOn: drawOn:) ('event handling' dropOnto:withEvent: handlesMouseDown: handlesMouseOver:) ('model - chi' activate) ('visual properties' annotationColor) ('model - sound' simplePlay) ! !HexGridGhost methodsFor: 'drawing' stamp: 'ADT 8/23/2000 04:52'! OLDdrawOn: aCanvas (self owner isHandMorph) ifTrue: [self drawBorderOn: aCanvas]. ! ! !HexGridGhost methodsFor: 'drawing' stamp: 'ADT 8/23/2000 04:54'! drawOn: aCanvas (self owner isHandMorph) ifTrue: [aCanvas fillOval: (Rectangle encompassing: (self verticesInsetBy: 0.6)) fillStyle: Color transparent borderWidth: self annotationWidth borderColor: self annotationColor]. ! ! !HexGridGhost methodsFor: 'event handling' stamp: 'ADT 8/24/2000 11:04'! dropOnto: aHexGrid withEvent: evt "HexGrid is asking me to handle being dropped onto itself. Deferred to me to allow different handling depending on whether I'm a Hex, an annotation carrying mule, etc." "In my case, I am a dummy kludge object used to temporarily implement background grab-drag-scrolling." evt shiftPressed ifTrue: [aHexGrid translateWithGhost: self event: evt] ifFalse: [aHexGrid rotateWithGhost: self event: evt]! ! !HexGridGhost methodsFor: 'event handling' stamp: 'ADT 7/17/2000 23:50'! handlesMouseDown: evt ^ false! ! !HexGridGhost methodsFor: 'event handling' stamp: 'ADT 9/8/2000 15:28'! handlesMouseOver: evt ^ false! ! !HexGridGhost methodsFor: 'model - chi' stamp: 'ADT 8/19/2000 02:54'! activate "Do nothing, I'm just a carrier. Useful since emitters (and probably others in the future) will be autonomously sending activate!!" ^self! ! !HexGridGhost methodsFor: 'visual properties' stamp: 'ADT 8/23/2000 04:54'! annotationColor ^Color yellow! ! !HexGridGhost methodsFor: 'model - sound' stamp: 'ADT 8/19/2000 02:55'! simplePlay "Override, I shouldn't do anything..." ^self! ! !HexRestMorph reorganize! ('copying' becomeLike: donateTo:) ('model - sound' simplePlay soundPlayWithChi:) ('visual properties' annotationColor) ! !HexRestMorph methodsFor: 'copying' stamp: 'ADT 8/9/2000 01:42'! becomeLike: aHex "It might in the future be better to give aHex our connections/annotations, and dispose of ourselves. THis has become a serious problem actually, since rests can't become me right now." aHex delete ! ! !HexRestMorph methodsFor: 'copying' stamp: 'ADT 9/8/2000 17:40'! donateTo: aHex "For one reason or another (for now, because I have been dropped on it!!) aHex should become 'like' self. For now, make aHex adopt aHex's sound and look policy as our own. Do this by in turn asking aHex to become like me. This lets aHex decline to do so." self delete ! ! !HexRestMorph methodsFor: 'model - sound' stamp: 'ADT 8/9/2000 01:41'! simplePlay "Module the sound we play according to the current amplitude and/or other properties of aChi." "Do nothing. I'm a rest."! ! !HexRestMorph methodsFor: 'model - sound' stamp: 'ADT 7/18/2000 00:38'! soundPlayWithChi: aChi "Module the sound we play according to the current amplitude and/or other properties of aChi." "Do nothing. I'm a rest."! ! !HexRestMorph methodsFor: 'visual properties' stamp: 'ADT 7/18/2000 00:39'! annotationColor ^Color gray! ! !HexTieConnectionStateMule methodsFor: 'copying' stamp: 'ADT 8/23/2000 03:16'! donateTo: aHex onFacet: aFacet "For one reason or another (for now, because I have been dropped on it!!) aHex should adopt my connection state on aFacet, if possible" aHex tryToTieAt: aFacet. self delete. ! ! !HexTieConnectionStateMule methodsFor: 'drawing' stamp: 'ADT 8/23/2000 03:58'! TESTdrawAnnotationsOn: aCanvas "Display the receiver, a hexagon. Overridden as we have special properties." | r s aw ac | r _ Rectangle encompassing: (self verticesInsetBy: 0.3). s _ Rectangle encompassing: (self verticesInsetBy: 0.5). aw _ self annotationWidth. ac _ self annotationColor. aCanvas drawPolygon: (Array with: (r top @ s left) with: (s top @ r left)) fillStyle: Color transparent borderWidth: aw borderColor: ac; drawPolygon: (Array with: (s bottom @ r left) with: (r bottom @ s left)) fillStyle: Color transparent borderWidth: aw borderColor: ac; drawPolygon: (Array with: (r top @ s right) with: (s top @ r right)) fillStyle: Color transparent borderWidth: aw borderColor: ac; drawPolygon: (Array with: (s bottom @ r right) with: (r bottom @ s right)) fillStyle: Color transparent borderWidth: aw borderColor: ac. ! ! !HexTieConnectionStateMule methodsFor: 'drawing' stamp: 'ADT 8/23/2000 04:22'! drawAnnotationsOn: aCanvas "Display the receiver, a hexagon. Overridden as we have special properties." aCanvas fillOval: (Rectangle encompassing: (self verticesInsetBy: 0.6)) fillStyle: Color transparent borderWidth: self annotationWidth borderColor: self annotationColor.! ! !HexTieConnectionStateMule methodsFor: 'visual properties' stamp: 'ADT 8/23/2000 03:17'! annotationColor ^Color green! ! !HexagonMorph class methodsFor: 'instance creation' stamp: 'ADT 7/2/2000 18:37'! color: aColor ^(self new) privateColor: aColor! ! !HexagonMorph class methodsFor: 'instance creation' stamp: 'ADT 7/2/2000 18:37'! coordinates: aPoint color: aColor ^((self new) privateColor: aColor; coordinates: aPoint)! ! !HexagonMorph class methodsFor: 'instance creation'! shapeFromPen: t1 color: t2 borderWidth: t3 borderColor: t4 ^ nil! ! !HexagonMorph class methodsFor: 'instance creation'! vertices: t1 color: t2 borderWidth: t3 borderColor: t4 ^ nil! ! !HexAnnotationMule class methodsFor: 'instance creation' stamp: 'ADT 8/19/2000 04:13'! annotation: anAnnotation | n | n _ self coordinates: 0@0 color: Color black. n bePaletteVersion; borderColor: Color white; annotations: (OrderedCollection with: anAnnotation). ^n! ! !HexClearAnnotationMule class methodsFor: 'instance creation' stamp: 'ADT 8/21/2000 21:07'! default | n | n _ self coordinates: 0@0 color: Color black. n bePaletteVersion; borderColor: Color white; annotations: (OrderedCollection new). ^n! ! !HexConnectionStateMule class methodsFor: 'instance creation' stamp: 'ADT 8/23/2000 02:07'! connectionState: aConnectionState | kludge | kludge _ HexConnection new. kludge state: aConnectionState. ^self default privateConnectTo: kludge at: 1. "forgive me father, I know not what I do" ! ! !HexConnectionStateMule class methodsFor: 'instance creation' stamp: 'ADT 8/23/2000 02:37'! default | n | n _ self coordinates: 0@0 color: Color black. n bePaletteVersion; borderColor: Color white. ^n! ! !HexRestMorph class methodsFor: 'instance creation' stamp: 'ADT 8/19/2000 04:41'! default | n | n _ self coordinates: 0@0 color: Color gray twiceDarker. n borderColor: Color gray. ^n! ! !MenuItemMorph methodsFor: 'accessing' stamp: 'ADT 7/21/2000 15:20'! arguments arguments == nil ifTrue: [self arguments: Array new]. ^ arguments ! ! !MenuMorph methodsFor: 'construction' stamp: 'ADT 7/21/2000 15:01'! add: aString subMenu: aMenuMorph "Append the given submenu with the given label." | item | item _ MenuItemMorph new. item contents: aString; subMenu: aMenuMorph. self addMorphBack: item. ! ! HexAlignmentMorph removeSelector: #addRows! HexAlignmentMorph removeSelector: #makePaletteRows! HexAlignmentMorph class removeSelector: #hexWindowColor! HexAnnotation removeSelector: #getMenuWithEvent:hex:! HexAnnotation removeSelector: #getIndividualMenuWithEvent:hex:annotation:! HexChi removeSelector: #decrementTime! HexChi removeSelector: #incrementPropogationCount! HexConnection removeSelector: #outputState:! HexConnection removeSelector: #hex! HexConnection removeSelector: #newType:! HexConnection removeSelector: #output! HexConnection removeSelector: #input:! HexConnection removeSelector: #inputState! HexConnection removeSelector: #removeOriginatedBy:! HexConnection removeSelector: #inputIs:! HexConnection removeSelector: #oppositeFrom:! HexConnection removeSelector: #twiddleState! HexConnection removeSelector: #openFor:! HexConnection removeSelector: #toggleTypeWith:! HexConnection removeSelector: #type! HexConnection removeSelector: #outputState! HexConnection removeSelector: #inputState:! HexConnection removeSelector: #openP! HexConnection removeSelector: #output:! HexConnection removeSelector: #hex:! HexConnection removeSelector: #remove! HexConnection removeSelector: #stateFor:! HexConnection removeSelector: #toggleType! HexConnection removeSelector: #toggleStateFor:! HexConnection removeSelector: #type:! HexConnection removeSelector: #removeOrinatedBy:! HexConnection removeSelector: #input! HexConnection removeSelector: #outputIs:! HexConnection class removeSelector: #input:output:type:! HexConnectionState removeSelector: #beingRemove! HexConnectionState removeSelector: #currentState! HexConnectionState removeSelector: #beingRemoved! HexDoppelgangerConnection removeSelector: #drawLabelOn:in:rect:! HexDoppelgangerConnection class removeSelector: #defaultFontSize! HexDoppelgangerConnection class removeSelector: #defaultFont! HexDoppelgangerConnection class removeSelector: #fontOfSize:! HexDynamicConnectionState removeSelector: #incrementIndex! HexDynamicConnectionState removeSelector: #twidlesP! HexDynamicConnectionState removeSelector: #stateList! HexDynamicConnectionState removeSelector: #currentState! HexDynamicConnectionState removeSelector: #opposite! HexDynamicConnectionState removeSelector: #cycleLength! HexDynamicConnectionState removeSelector: #twidle! HexDynamicConnectionState removeSelector: #index! HexConditionalConnectionState removeSelector: #incrementIndex! HexConditionalConnectionState removeSelector: #twidlesP! HexConditionalConnectionState removeSelector: #stateList! HexConditionalConnectionState removeSelector: #currentState! HexConditionalConnectionState removeSelector: #opposite! HexConditionalConnectionState removeSelector: #cycleLength! HexConditionalConnectionState removeSelector: #twidle! HexConditionalConnectionState removeSelector: #index! HexDynamicConnectionState class removeSelector: #addRowsToPalette:! HexEmitterAnnotation removeSelector: #initialize! HexEmitterAnnotation removeSelector: #defaultperiod! HexEmitterAnnotation class removeSelector: #getIndividualMenuWithEvent:hex:annotation:! HexFiniteEmitterAnnotation removeSelector: #period! HexFiniteEmitterAnnotation removeSelector: #updatePairLabelWithScale:! HexGrid removeSelector: #lookPolicy:! HexGrid removeSelector: #defaultLookPolicy! HexGrid removeSelector: #OLDlogicalCoordinateLookup! HexGrid removeSelector: #OLDhexagonVerticesAtCoordinates:! HexGrid removeSelector: #hexFieldLookPolicy! HexGrid removeSelector: #OLDacceptDroppingMorph:event:! HexGrid removeSelector: #OLDlogicalTranslationFrom:to:! HexGrid removeSelector: #OLDdrawHexAtLogicalX:Y:lookPolicy:on:! HexGrid removeSelector: #entropyP:! HexGrid removeSelector: #OLDphysicalCoordinatesForX:Y:! HexGrid removeSelector: #privatePlaceHex:At:! HexGrid removeSelector: #OLDneighborCoordinateLookupAtAngle:! HexGrid removeSelector: #toggleEntropy! HexGrid removeSelector: #placeDroppedHex:withEvent:! HexGrid removeSelector: #lookPolicy! HexGrid removeSelector: #entropyP! HexIndexedConnectionState removeSelector: #increment! HexIndexedConnectionState removeSelector: #position:! HexIndexedConnectionState removeSelector: #OLDdrawOn:in:at:! HexIndexedConnectionState removeSelector: #togglePosition! HexIndexedConnectionState removeSelector: #currentState! HexIndexedConnectionState removeSelector: #position! HexIndexedConnectionState removeSelector: #cycleLength! HexIndexedConnectionState class removeSelector: #getMenuWithEvent:facet:! HexMirrorAnnotation removeSelector: #period:! HexMirrorAnnotation removeSelector: #period! HexMirrorAnnotation removeSelector: #defaultPeriod! HexMirrorAnnotation removeSelector: #step! HexMirrorAnnotation removeSelector: #startStepping! HexMirrorAnnotation removeSelector: #stepTime! HexMirrorAnnotation removeSelector: #hex:! HexMirrorAnnotation class removeSelector: #veryLowFrequency! HexMirrorAnnotation class removeSelector: #lowFrequency! HexMirrorAnnotation class removeSelector: #mediumFrequency! HexMirrorAnnotation class removeSelector: #getIndividualMenuWithEvent:hex:annotation:! HexMirrorAnnotation class removeSelector: #highFrequency! HexMirrorAnnotation class removeSelector: #veryHighFrequency! HexMirrorAnnotation class removeSelector: #getMenuWithEvent:hex:! HexMutatorAnnotation removeSelector: #currentStateForChi:! HexMutatorAnnotation removeSelector: #drawVelocityOn:in:at:! HexMutatorAnnotation removeSelector: #threshhold:! HexMutatorAnnotation removeSelector: #threshhold! HexMutatorAnnotation removeSelector: #load:! HexMutatorAnnotation removeSelector: #load! HexMutatorAnnotation class removeSelector: #amplitudeHighPass! HexMutatorAnnotation class removeSelector: #amplitudeVeryLowPass! HexMutatorAnnotation class removeSelector: #amplitudeReset! HexMutatorAnnotation class removeSelector: #fullPrintOn:! HexMutatorAnnotation class removeSelector: #getMenuWithEvent:facet:target:! HexMutatorAnnotation class removeSelector: #velocityReset! HexMutatorAnnotation class removeSelector: #printOn:! HexMutatorAnnotation class removeSelector: #amplitudeLowPass! HexMutatorAnnotation class removeSelector: #velocityVeryHighPass! HexMutatorAnnotation class removeSelector: #amplitudeVeryHighPass! HexMutatorAnnotation class removeSelector: #velocityVeryLowPass! HexMutatorAnnotation class removeSelector: #velocityLowPass! HexMutatorAnnotation class removeSelector: #velocityHighPass! HexPalette removeSelector: #makePaletteRow1! HexPalette removeSelector: #label! HexPalette removeSelector: #makePaletteRow0! HexPalette removeSelector: #instrumentBorderColor! HexPalette removeSelector: #buildButtonWithTarget:label:selector:arguments:! HexPalette removeSelector: #instrument! HexPalette removeSelector: #foreColor! HexPalette removeSelector: #getLabelWithText:! HexPalette removeSelector: #buildButton:target:label:selector:arguments:! HexPalette removeSelector: #makePaletteRow3! HexPalette removeSelector: #buildButton:target:label:selector:! HexPalette removeSelector: #addLabelText:! HexPalette removeSelector: #addLabel! HexPalette removeSelector: #loudness! HexPalette removeSelector: #dur! HexPalette removeSelector: #buildButtonWithTarget:label:selector:! HexPalette removeSelector: #makePaletteRow2! HexExtrasPalette removeSelector: #instrument! HexExtrasPalette removeSelector: #loudness! HexExtrasPalette removeSelector: #instrumentBorderColor! HexExtrasPalette removeSelector: #dur! HexExtrasPalette removeSelector: #makePaletteRow0! HexFMSoundPalette removeSelector: #initialize! HexFMSoundPalette removeSelector: #makePaletteRow1! HexFMSoundPalette removeSelector: #label! HexFMSoundPalette removeSelector: #makePaletteRow0! HexFMSoundPalette removeSelector: #pentatonicRows! HexFMSoundPalette removeSelector: #twelvetoneRows! HexFMSoundPalette removeSelector: #instrument! HexFMSoundPalette removeSelector: #aeolianRows! HexFMSoundPalette removeSelector: #makePaletteRow3! HexFMSoundPalette removeSelector: #addRows! HexFMSoundPalette removeSelector: #addLabel! HexFMSoundPalette removeSelector: #loudness! HexFMSoundPalette removeSelector: #dur! HexFMSoundPalette removeSelector: #makePaletteRow2! HexBrassPalette removeSelector: #initialize! HexBrassPalette removeSelector: #makePaletteRow1! HexBrassPalette removeSelector: #makePaletteRow3! HexBrassPalette removeSelector: #makePaletteRow0! HexBrassPalette removeSelector: #addRows! HexBrassPalette removeSelector: #addLabel! HexBrassPalette removeSelector: #makePaletteRow2! HexFlutePalette removeSelector: #initialize! HexFlutePalette removeSelector: #makePaletteRow1! HexFlutePalette removeSelector: #makePaletteRow3! HexFlutePalette removeSelector: #makePaletteRow0! HexFlutePalette removeSelector: #addRows! HexFlutePalette removeSelector: #addLabel! HexFlutePalette removeSelector: #dur! HexFlutePalette removeSelector: #makePaletteRow2! HexMulePalette removeSelector: #label! HexAnnotationPalette removeSelector: #addCloseButton! HexAnnotationPalette removeSelector: #instrumentBorderColor! HexAnnotationPalette removeSelector: #addMule:label:! HexAnnotationPalette removeSelector: #newScale:! HexAnnotationPalette removeSelector: #foreColor! HexAnnotationPalette removeSelector: #addLine! HexAnnotationPalette removeSelector: #add:label:! HexAnnotationPalette removeSelector: #makeAeolianButton! HexAnnotationPalette removeSelector: #makeIonianButton! HexAnnotationPalette removeSelector: #addRows! HexAnnotationPalette removeSelector: #addControls! HexAnnotationPalette removeSelector: #addLabelText:! HexAnnotationPalette removeSelector: #makeControlPalette! HexAnnotationPalette removeSelector: #loudness! HexAnnotationPalette removeSelector: #dur! HexAnnotationPalette removeSelector: #makePentatonicButton! HexAnnotationPalette removeSelector: #makeTwelvetoneButton! HexAnnotationPalette removeSelector: #makeCloseButton! HexAnnotationPalette removeSelector: #makeHarmonicButton! HexAnnotationPalette class removeSelector: #scale:! HexAnnotationPalette class removeSelector: #scale! HexConnectionStatePalette removeSelector: #add:label:! HexConnectionStatePalette removeSelector: #addCloseButton! HexConnectionStatePalette removeSelector: #addMule:label:! HexConnectionStatePalette removeSelector: #addRows! HexConnectionStatePalette removeSelector: #addControls! HexConnectionStatePalette removeSelector: #addLabelText:! HexConnectionStatePalette removeSelector: #foreColor! HexConnectionStatePalette removeSelector: #addLine! HexMultiPalette removeSelector: #initialize! HexMultiPalette removeSelector: #addCloseButton! HexMultiPalette removeSelector: #makePaletteRow0! HexMultiPalette removeSelector: #instrumentBorderColor! HexMultiPalette removeSelector: #pentatonic! HexMultiPalette removeSelector: #loudness! HexMultiPalette removeSelector: #dur! HexMultiPalette removeSelector: #makeCloseButton! HexMultiPalette class removeSelector: #pentatonic! HexSoundWrapper removeSelector: #numberOfDoppel! HexSoundWrapper removeSelector: #dependentMorphsdependentMorphs! HexSoundWrapper removeSelector: #copy! HexSoundWrapper removeSelector: #dependentDoppelgangers! HexSoundWrapper removeSelector: #numberOfDoppelgangers! HexFMSoundWrapper removeSelector: #magnitude! HexStaticConnectionState removeSelector: #drawOn:in:at:! HexStaticConnectionState removeSelector: #currentState! HexStaticConnectionState removeSelector: #opposite! HexClosedConnectionState removeSelector: #currentState! HexClosedConnectionState removeSelector: #currentStateWithChi:! HexClosedConnectionState removeSelector: #twidle! HexOpenConnectionState removeSelector: #currentState! HexOpenConnectionState removeSelector: #currentStateWithChi:! HexOpenConnectionState removeSelector: #twidle! HexStaticConnectionState class removeSelector: #getMenuWithEvent:facet:! HexThreshholdConnectionState removeSelector: #currentState! HexTieConnectionState removeSelector: #currentState! HexTieConnectionState removeSelector: #beingRemoved! HexTieConnectionState removeSelector: #propogateChi:from:direction:! HexWorld removeSelector: #lookPolicy! HexWorld removeSelector: #lookPolicy:! HexWorld removeSelector: #testEntropy:! HexWorld removeSelector: #buildSwitchWithTarget:label:selector:setSwitchTest:! HexWorld removeSelector: #buildButton:target:label:selector:! HexWorld removeSelector: #makeHexPalette! HexWorld removeSelector: #addPalette! HexWorld removeSelector: #makeWorldParameterPalette! HexWorld removeSelector: #addCloseButton! HexWorld removeSelector: #makeEntropyButton! HexWorld removeSelector: #toggleEntropy! HexWorld removeSelector: #addLabel! HexWorld removeSelector: #makeGridButton! HexWorld removeSelector: #buildButtonWithTarget:label:selector:! HexWorld class removeSelector: #defaultFontSize! HexWorld class removeSelector: #hexWindowColor! HexWorld class removeSelector: #defaultFont! HexWorld class removeSelector: #shadowColor! HexWorld class removeSelector: #shadowOffset! HexWorld class removeSelector: #createInWindow! HexWorld class removeSelector: #fontOfSize:! HexagonMorph removeSelector: #lookPolicy:! HexagonMorph removeSelector: #glowColor! HexagonMorph removeSelector: #getMenu:event:! HexagonMorph removeSelector: #activateConnections! HexagonMorph removeSelector: #privateRemoteConnection:! HexagonMorph removeSelector: #OLDdrag:! HexagonMorph removeSelector: #notPaletteVersion! HexagonMorph removeSelector: #localTime:! HexagonMorph removeSelector: #isGridGhost! HexagonMorph removeSelector: #OLDdrop:! HexagonMorph removeSelector: #allowSubmorphExtraction! HexagonMorph removeSelector: #OLDdrawAnnotationsOn:! HexagonMorph removeSelector: #connectTo:on:! HexagonMorph removeSelector: #drop:! HexagonMorph removeSelector: #privateColor:! HexagonMorph removeSelector: #addCustomMenuItems:hand:! HexagonMorph removeSelector: #OLDactivate! HexagonMorph removeSelector: #getFacetSubMenuWithEvent:facet:connection:! HexagonMorph removeSelector: #localTime! HexagonMorph removeSelector: #yellowButtonActivity:event:! HexagonMorph removeSelector: #OLDsoundPlay! HexagonMorph removeSelector: #connectTo:! HexagonMorph removeSelector: #color:! HexagonMorph removeSelector: #soundPlay! HexagonMorph removeSelector: #connectionsAdd:at:! HexagonMorph removeSelector: #OLDactivateStep! HexagonMorph removeSelector: #connectionsAdd:! HexagonMorph removeSelector: #getMenu:! HexagonMorph removeSelector: #OLDglow! HexAnnotationMule removeSelector: #isGridGhost! HexAnnotationMule removeSelector: #handlesMouseDown:! HexClearAnnotationMule removeSelector: #activate! HexClearAnnotationMule removeSelector: #simplePlay! HexClearAnnotationMule removeSelector: #drawOn:! HexClearAnnotationMule removeSelector: #copy! HexConnectionStateMule removeSelector: #donateTo:! HexConnectionStateMule removeSelector: #drawBorderOn:! HexConnectionStateMule removeSelector: #NOannotationColor! HexConnectionStateMule removeSelector: #annotationColor! HexGridGhost removeSelector: #isGridGhost! HexTieConnectionStateMule removeSelector: #dropOnto:withEvent:! HexClearAnnotationMule class removeSelector: #annotation:! HexClearAnnotationMule class removeSelector: #new! HexConnectionStateMule class removeSelector: #connection:! HexClearConnectionStateMule class removeSelector: #default! HexClearConnectionStateMule class removeSelector: #connection:! Smalltalk removeClassNamed: #HexAmplitudeHighPassConnectionState! Smalltalk removeClassNamed: #HexComposition! Smalltalk removeClassNamed: #Hexgrid! Smalltalk removeClassNamed: #HexCyclicalConnection! Smalltalk removeClassNamed: #Hexagram! Smalltalk removeClassNamed: #HexThresholdConnectionState! Smalltalk removeClassNamed: #Hexworld! Smalltalk removeClassNamed: #HexAtomPalette! Smalltalk removeClassNamed: #HexTogglingConnectionState!