'From etoys4.0 of 5 November 2008 [latest update: #2321] on 28 September 2009 at 3:54:02 pm'! "Change Set: reduceBlockUsage-sw Date: 28 September 2009 Author: Scott Wallace Cease using blocks in the actionBlock mechanism in the EToyProjectDetailsMorph and related classes. This turned out to involve a surprising number of methods. Some of the code affected is not reachable in the current image so may not have been deeply tested; the EToyProjectRenamerMorph is never instantiated these days (presumably it once was,) and the EToyProjectQueryMorph is only referenced by a method which itself is never called. But I converted all the code that relies on the actionBlock being a block anyway, since possibly there are packages (e.g. superswiki implementations) which may need them in their de-blockified form."! !EToyProjectRenamerMorph commentStamp: 'sw 9/25/2009 15:21' prior: 0! Nowadays, anyway, EToyProjectRenamerMorph only occurs as an abstract superclass for EToyProjectQueryMorph and EToyProjectDetailsMorph.! !EToyProjectRenamerMorph methodsFor: 'ok button pressed' stamp: 'sw 9/25/2009 16:11'! doOK "The user hit the ok button in the renamer dialog box; carry out the rename." | aName | self validateTheProjectName ifFalse: [^self]. aName := (namedFields at: 'projectname') contents string withBlanksTrimmed. self delete. actionBlock isMessageSend ifTrue: [actionBlock arguments: (Array with: aName). actionBlock value] ifFalse: [actionBlock value: aName]! ! !EToyProjectDetailsMorph methodsFor: 'utilities' stamp: 'sw 9/28/2009 15:13'! doOK "User hit the ok button in the project-info dialog. Store the updated project-info back in the project. Call the message-send residing in the receiver's actionBlock to carry out any subsequent desired task. Note that this method sets the 'arguments' of the message-send in the actionBlock" | args actionSelector | self validateTheProjectName ifFalse: [^false]. projectDetails := self copyOutDetails. theProject acceptProjectDetails: projectDetails. "Make sure project & world feel the changes" actionBlock isMessageSend "new way -- hopefully all cases" ifTrue: "please excuse this ugly, non-modular code..." [actionSelector := actionBlock selector. args := (actionSelector = #handUserSorterMorphForProjectNamed:) ifTrue: [{theProject name}] ifFalse: [actionSelector numArgs = 0 ifTrue: [nil] ifFalse: [Array with: projectDetails]]. actionBlock arguments: args. actionBlock value] ifFalse: "Old way, with actionBlock actually a block of one argument. This should no longer occur." [actionBlock value: projectDetails]. self delete! ! !EToyProjectDetailsMorph class methodsFor: 'instance creation' stamp: 'sw 9/28/2009 15:42'! getFullInfoFor: aProject ifValid: aMessageSend expandedFormat: expandedFormat "Obtain project info for the project by putting up a dialog-box showing current values for the various project-info variables and allowing the user to change the data." | detailsMorph | detailsMorph := self basicNew. detailsMorph expandedFormat: expandedFormat; project: aProject actionBlock: aMessageSend; initialize; becomeModal; beSticky; openCenteredInWorld! ! !EToyProjectQueryMorph methodsFor: 'ok button hit' stamp: 'sw 9/25/2009 15:38'! doOK "User hit the ok button in the project-query dialog." | details | details := self copyOutDetails. actionBlock isMessageSend "new way -- hopefully all cases" ifTrue: [actionBlock arguments: {details. actionBlock arguments second}. actionBlock value] ifFalse: "Old way, with actionBlock actually a block of one argument. This should no longer occur." [actionBlock value: details]. self delete! ! !EToyProjectQueryMorph methodsFor: 'query' stamp: 'sw 9/25/2009 15:36'! carryOutQuery: details onProjectServer: aProjectServer "The user submitted a query; the parameter holds the details dictionary. Carry out the query." | criteria clean | criteria := OrderedCollection new. details keysAndValuesDo: [ :k :v | (clean _ v withBlanksTrimmed convertToEncoding: SuperSwikiServer defaultEncodingName) isEmpty ifFalse: [criteria add: k,': *',clean,'*']]. aProjectServer queryProjectsAndShow: criteria! ! !EToyProjectQueryMorph class methodsFor: 'instance creation' stamp: 'sw 9/25/2009 15:36'! onServer: aProjectServer "EToyProjectQueryMorph onServer: SuperSwikiServer testOnlySuperSwiki" | detailsMorph messageToSendIfValid | detailsMorph := self basicNew. messageToSendIfValid := MessageSend receiver: detailsMorph selector: #carryOutQuery:onProjectServer: arguments: {nil. aProjectServer}. detailsMorph project: nil actionBlock: messageToSendIfValid; "*** actionBlock: [ :x | criteria _ OrderedCollection new. x keysAndValuesDo: [ :k :v | (clean _ v withBlanksTrimmed convertToEncoding: SuperSwikiServer defaultEncodingName) isEmpty ifFalse: [criteria add: k,': *',clean,'*']]. aProjectServer queryProjectsAndShow: criteria]; ****" initialize; becomeModal; openCenteredInWorld! ! !InternalThreadNavigationMorph methodsFor: 'navigation' stamp: 'sw 9/25/2009 16:19'! insertNewProject "Insert a new project in the thread." | newProj messageToSendIfValid | [newProj _ Project newMorphicOn: nil.] on: ProjectViewOpenNotification do: [ :ex | ex resume: false]. messageToSendIfValid := MessageSend receiver: self selector: #insertNewProjectActionFor: arguments: {newProj}. EToyProjectDetailsMorph getFullInfoFor: newProj ifValid: messageToSendIfValid expandedFormat: false! ! !Project methodsFor: 'menu messages' stamp: 'sw 9/28/2009 01:48'! acceptDetailsAndStoreProjectWithForget: details "The user having hit the ok button in the dialog, send the details back to the project, store the project on the server, " self acceptProjectDetails: details. self isCurrentProject ifTrue: ["exit, then do the command" (world hasProperty: #forgetURL) ifTrue: [self forgetExistingURL] ifFalse: [urlList isEmptyOrNil ifTrue: [urlList _ parentProject urlList]]. self armsLengthCommand: #storeOnServerAssumingNameValid withDescription: 'Publishing' translated] ifFalse: [self storeOnServerWithProgressInfo]! ! !Project methodsFor: 'menu messages' stamp: 'sw 9/28/2009 00:44'! acceptDetailsAndStoreProject: details "The user having hit the ok button in the dialog, send the details back to the project, store the project on the server, " self acceptProjectDetails: details. self isCurrentProject ifTrue: ["exit, then do the command" self armsLengthCommand: #storeOnServerAssumingNameValid withDescription: 'Publishing' translated] ifFalse: [self storeOnServerWithProgressInfo]! ! !Project methodsFor: 'menu messages' stamp: 'sw 9/28/2009 15:48'! acceptProjectDetails: details "Store project details back into a property of the world, and if a name is provided, make sure the name is properly installed in the project." world setProperty: #ProjectDetails toValue: details. details at: 'projectname' ifPresent: [ :newName | self renameTo: newName]! ! !Project methodsFor: 'menu messages' stamp: 'sw 9/28/2009 02:43'! validateProjectNameIfOK: aMessageSend "Validate the project name, possibly putting up the project-info dialog, and if all is well, evaluate the message-send provided." | details | details _ world valueOfProperty: #ProjectDetails. details ifNotNil: ["ensure project info matches real project name" details at: 'projectname' put: self name]. self doWeWantToRename ifFalse: [^aMessageSend value]. EToyProjectDetailsMorph getFullInfoFor: self ifValid: aMessageSend expandedFormat: false! ! !Project methodsFor: 'file in/out' stamp: 'sw 9/28/2009 00:45'! storeOnServer "Save to disk as an Export Segment. Then put that file on the server I came from, as a new version. Version is literal piece of file name. Mime encoded and http encoded." | aMessageSend | world setProperty: #optimumExtentFromAuthor toValue: world extent. aMessageSend := MessageSend receiver: self selector: #acceptDetailsAndStoreProject:. self validateProjectNameIfOK: aMessageSend! ! !Project methodsFor: 'file in/out' stamp: 'sw 9/28/2009 01:49'! storeOnServerShowProgressOn: aMorphOrNil forgetURL: forget "Save to disk as an Export Segment. Then put that file on the server I came from, as a new version. Version is literal piece of file name. Mime encoded and http encoded." | aMessageSend | world setProperty: #optimumExtentFromAuthor toValue: world extent. world setProperty: #forgetURL toValue: forget. aMessageSend := MessageSend receiver: self selector: #acceptDetailsAndStoreProjectWithForget:. self validateProjectNameIfOK: aMessageSend! ! !ProjectNavigationMorph methodsFor: 'the actions' stamp: 'sw 9/28/2009 15:51'! editProjectInfo "Put up the project-info dialog, and if the user accept his edits in that dialog, save the changed info back to the project." | aMessageSend | aMessageSend := MessageSend receiver: ActiveWorld selector: #yourself argument: nil. "The handling in doOK already installs the project-info changes into the project, so there is no extra processing needed via the actionBlock mechanism in this case, so we supply a no-op message send instead." EToyProjectDetailsMorph getFullInfoFor: (self world ifNil: [^self]) project ifValid: aMessageSend expandedFormat: true! ! !ProjectSorterMorph methodsFor: 'menu commands' stamp: 'sw 9/28/2009 02:45'! handUserSorterMorphForProjectNamed: aName "Hand the user a sorter token representing the project of the given name." (self sorterMorphForProjectNamed: aName) openInHand! ! !ProjectSorterMorph methodsFor: 'menu commands' stamp: 'sw 9/28/2009 02:45'! insertNewProject: evt "Insert a new project into the image, and hand the user a sorter token representing that project." | newProj msgSend | [newProj _ Project newMorphicOn: nil.] on: ProjectViewOpenNotification do: [ :ex | ex resume: false]. msgSend := MessageSend receiver: self selector: #handUserSorterMorphForProjectNamed: arguments: {newProj name}. EToyProjectDetailsMorph getFullInfoFor: newProj ifValid: msgSend expandedFormat: false! ! EToyProjectDetailsMorph class removeSelector: #test1:!