'From Squeak2.9alpha of 12 June 2000 [latest update: #2799] on 4 October 2000 at 11:04:53 am'! "Change Set: CipherTweak Date: 19 September 2000 Author: Ted Kaehler, Dan Ingalls Generates CipherPanels from random method comments. Execute CipherPanel tedsHack in morphic or MVC. This update makes the 'Squeak quote' feature available as a menu and button command. Also warns before discarding changes. "! !CipherPanel methodsFor: 'initialization' stamp: 'di 10/4/2000 10:59'! encodedQuote: aString "World addMorph: CipherPanel new" | morph prev | (letterMorphs == nil or: [self isClean]) ifFalse: [(self confirm: 'Are you sure you want to discard all typing?') ifFalse: [^ self]]. haveTypedHere _ false. quote _ aString asUppercase. prev _ nil. originalMorphs _ quote asArray collectWithIndex: [:c :i | WordGameLetterMorph new plain indexInQuote: i id1: nil; setLetter: (quote at: i)]. letterMorphs _ OrderedCollection new. decodingMorphs _ quote asArray collectWithIndex: [:c :i | (quote at: i) isLetter ifTrue: [morph _ WordGameLetterMorph new underlined indexInQuote: i id1: nil. morph on: #mouseDown send: #mouseDownEvent:letterMorph: to: self. morph on: #keyStroke send: #keyStrokeEvent:letterMorph: to: self. letterMorphs addLast: morph. morph predecessor: prev. prev ifNotNil: [prev successor: morph]. prev _ morph] ifFalse: [WordGameLetterMorph new plain indexInQuote: i id1: nil; setLetter: (quote at: i)]]. self color: originalMorphs first color. self extent: 500@500 ! ! !CipherPanel methodsFor: 'menu' stamp: 'di 10/4/2000 10:55'! addMenuItemsTo: aMenu hand: aHandMorph aMenu add: 'show cipher help' target: self action: #showHelpWindow. aMenu add: 'show cipher hints' target: self action: #showHintsWindow. aMenu add: 'clear cipher typing' target: self action: #clearTyping. aMenu add: 'enter a new cipher' target: self action: #enterANewCipher. aMenu add: 'quote from Squeak' target: self action: #squeakCipher. ! ! !CipherPanel methodsFor: 'menu' stamp: 'di 10/4/2000 10:54'! buttonRow | row aButton | row _ AlignmentMorph newRow color: self color; hResizing: #shrinkWrap; vResizing: #shrinkWrap. aButton _ SimpleButtonMorph new target: self. aButton color: Color transparent; borderWidth: 1; borderColor: Color black. #('show help' 'show hints' 'clear typing' 'enter a new cipher' 'quote from Squeak') with: #(showHelpWindow showHintsWindow clearTyping enterANewCipher squeakCipher) do: [:label :selector | aButton _ aButton fullCopy. aButton actionSelector: selector. aButton label: label. row addMorphBack: aButton. row addTransparentSpacerOfSize: (3 @ 0)]. ^ row ! ! !CipherPanel methodsFor: 'menu' stamp: 'di 10/4/2000 11:00'! enterANewCipher self clearTyping; encodedQuote: (FillInTheBlank request: 'Type a cipher text to work on here below...')! ! !CipherPanel methodsFor: 'menu' stamp: 'di 10/4/2000 10:48'! squeakCipher self encodedQuote: (CipherPanel encode: (CipherPanel randomComment))! ! !CipherPanel methodsFor: 'initialization' stamp: 'di 2/14/2001 13:50'! extent: newExtent "Lay out with word wrap, alternating bewteen decoded and encoded lines." "Currently not tolerant of narrow (less than a word) margins" | w h relLoc topLeft thisWord i m corner row firstWord | self removeAllMorphs. w _ originalMorphs first width - 1. h _ originalMorphs first height * 2 + 10. topLeft _ self position + self borderWidth + (0@10). thisWord _ OrderedCollection new. i _ 1. firstWord _ true. relLoc _ 0@0. corner _ topLeft. [i <= originalMorphs size] whileTrue: [m _ originalMorphs at: i. thisWord addLast: ((decodingMorphs at: i) position: topLeft + relLoc). thisWord addLast: (m position: topLeft + relLoc + (0@m height)). (m letter = Character space or: [i = originalMorphs size]) ifTrue: [self addAllMorphs: thisWord. corner _ corner max: thisWord last bounds bottomRight. thisWord reset. firstWord _ false]. relLoc _ relLoc + (w@0). (relLoc x + w) > newExtent x ifTrue: [firstWord ifTrue: ["No spaces -- force a line break" thisWord removeLast; removeLast. self addAllMorphs: thisWord. corner _ corner max: thisWord last bounds bottomRight] ifFalse: [i _ i - (thisWord size//2) + 1]. thisWord reset. firstWord _ true. relLoc _ 0@(relLoc y + h)] ifFalse: [i _ i + 1]]. row _ self buttonRow. row fullBounds. self addMorph: row. super extent: (corner - topLeft) + (self borderWidth * 2) + (0@row height+10). row align: row bounds bottomCenter with: self bounds bottomCenter - (0@2).! ! !CipherPanel class methodsFor: 'as yet unclassified' stamp: 'di 10/4/2000 10:42'! encode: aString "CipherPanel encode: 'Now is the time for all good men to come to the aid of their country.'" | dict repeat | dict _ Dictionary new. repeat _ true. [repeat] whileTrue: [repeat _ false. ($A to: $Z) with: ($A to: $Z) shuffled do: [:a :b | a = b ifTrue: [repeat _ true]. dict at: a put: b]]. ^ aString asUppercase collect: [:a | dict at: a ifAbsent: [a]]! ! !CipherPanel class methodsFor: 'as yet unclassified' stamp: 'di 10/4/2000 10:43'! randomComment "CipherPanel randomComment" "Generate cryptic puzzles from method comments in the system" | c s | s _ 'none'. [s = 'none'] whileTrue: [s _ ((c _ Smalltalk allClasses atRandom) selectors collect: [:sel | (c firstCommentAt: sel) asString]) detect: [:str | str size between: 100 and: 200] ifNone: ['none']]. ^ s! ! !CipherPanel class methodsFor: 'as yet unclassified' stamp: 'di 10/4/2000 10:45'! tedsHack "Generate cryptic puzzles from method comments in the system" (self newFromQuote: (self encode: (self randomComment))) openInWorld "CipherPanel tedsHack"! ! WordGameLetterMorph allInstancesDo: [:each | each letter ifNotNil: [each setLetter: (Character value: each letter asInteger)]]! CipherPanel class removeSelector: #quoteToScramble:! CipherPanel class removeSelector: #tedsGreatIdea! CipherPanel removeSelector: #quoteToScramble:!