added:
authorClaus Gittinger <cg@exept.de>
Thu, 22 Oct 2009 23:21:17 +0200
changeset 2676 17095b9cdf97
parent 2675 7bd7413e3cb3
child 2677 e2c24a1be97f
added: #doStartMakeAll #doStartMakeExe #doStartMakeExeOnly #runBuildProcess: changed: #canEnterContentsSelection #page7_buildSpec #updateListOfStartupClassesInProject
Tools__ProjectBuilderAssistantApplication.st
--- a/Tools__ProjectBuilderAssistantApplication.st	Thu Oct 22 23:17:23 2009 +0200
+++ b/Tools__ProjectBuilderAssistantApplication.st	Thu Oct 22 23:21:17 2009 +0200
@@ -831,28 +831,65 @@
       )
 !
 
-)
-                 (ActionButtonSpec
-                    label: 'Stop Make'
-                    name: 'Button4'
-                    visibilityChannel: stopMakeButtonVisible
-                    translateLabel: true
-                    model: doStopMake
-                    extent: (Point 107 22)
+page8_deploySpec
+    "This resource specification was automatically generated
+     by the UIPainter of ST/X."
+
+    "Do not manually edit this!! If it is corrupted,
+     the UIPainter may not be able to read the specification."
+
+    "
+     UIPainter new openOnClass:Tools::ProjectBuilderAssistantApplication andSelector:#page8_deploySpec
+     Tools::ProjectBuilderAssistantApplication new openInterface:#page8_deploySpec
+    "
+
+    <resource: #canvas>
+
+    ^ 
+     #(FullSpec
+        name: #'page8_deploySpec'
+        window: 
+       (WindowSpec
+          label: 'Project Selection'
+          name: 'Project Selection'
+          min: (Point 0 0)
+          bounds: (Rectangle 0 0 521 472)
+        )
+        component: 
+       (SpecCollection
+          collection: (
+           (FramedBoxSpec
+              label: 'Files for Deployment'
+              name: 'FramedBox3'
+              layout: (LayoutFrame 0 0.0 5 0 4 1.0 0 1)
+              labelPosition: topLeft
+              translateLabel: true
+              component: 
+             (SpecCollection
+                collection: (
+                 (SubCanvasSpec
+                    name: 'SubCanvas1'
+                    layout: (LayoutFrame 0 0 0 0 0 1 -30 1)
+                    hasHorizontalScrollBar: false
+                    hasVerticalScrollBar: false
+                    clientHolder: fileBrowserInstance
+                    createNewApplication: true
+                    createNewBuilder: true
                   )
-                 )
-               
-              )
-            )
-           )
-         
-        )
-      )
-! !
-
-!ProjectBuilderAssistantApplication methodsFor:'actions'!
-
-: true
+                 (HorizontalPanelViewSpec
+                    name: 'HorizontalPanel1'
+                    layout: (LayoutFrame 0 0 -30 1 0 1 0 1)
+                    horizontalLayout: center
+                    verticalLayout: center
+                    horizontalSpace: 3
+                    verticalSpace: 3
+                    component: 
+                   (SpecCollection
+                      collection: (
+                       (ActionButtonSpec
+                          label: 'Open Windows Explorer'
+                          name: 'Button1'
+                          translateLabel: true
                           resizeForLabel: true
                           model: doOpenExplorer
                           extent: (Point 172 22)
@@ -869,26 +906,28 @@
          
         )
       )
+! !
+
+!ProjectBuilderAssistantApplication methodsFor:'actions'!
+
+buildDirectoryChanged
+    self updateButtonEnableState.
 !
 
-model: doOpenExplorer
-                          extent: (Point 172 22)
-                        )
-                       )
-                     
-                    )
-                  )
-                 )
-               
-              )
-            )
-           )
-         
-        )
-      )
-!
+createNewApplication
+    <resource: #uiCallback>
+
+    |newAppName newAppClass|
 
-:[
+    newAppName := self newApplicationsName value.
+    newAppName isEmptyOrNil ifTrue:[
+        Dialog warn:'Please enter the name of the Application-Class first.'.
+        ^ self
+    ].
+
+    self withWaitCursorDo:[
+        Class packageQuerySignal answer:(selectedProjectDefinition package)
+        do:[
             newAppClass := ApplicationModel
                             subclass:newAppName asSymbol
                             instanceVariableNames:''
@@ -901,7 +940,39 @@
     ].
 !
 
-"/ see if it has an AppModel class
+createNewProject
+    <resource: #uiCallback>
+
+    |newProjectID projectDefinitionType projectDefinitionClass projectClasses|
+
+    newProjectID := self newProjectsName value.
+    newProjectID isEmptyOrNil ifTrue:[
+        Dialog warn:'Please enter a packageID first.'.
+        ^ self
+    ].
+    newProjectID asPackageId isModuleId ifTrue:[
+        Dialog warn:'Please enter a corrent packageID (module:directory).'.
+        ^ self
+    ].
+
+    projectDefinitionType := ProjectDefinition perform:(self projectTypeHolder value).
+
+
+    projectDefinitionClass := ProjectDefinition
+                                definitionClassForPackage:newProjectID
+                                projectType: projectDefinitionType
+                                createIfAbsent:true.
+
+    projectDefinitionClass compileDescriptionMethods.
+    self updateListOfMatchingProjects.
+
+    self selectedProjectIndexHolder value:( self listOfMatchingProjects value indexOf:projectDefinitionClass).
+
+    projectClasses := projectDefinitionClass allClassNames 
+                            collect:[:nm |Smalltalk classNamed:nm].
+
+"/    projectDefinitionClass isGUIApplication ifTrue:[
+"/        "/ see if it has an AppModel class
 "/        (projectClasses contains:[:cls | cls isVisualStartable]) ifFalse:[
 "/            (Dialog confirm:'Create an Application Class ?') ifTrue:[
 "/                self halt.
@@ -916,7 +987,21 @@
 "/    ].
 !
 
-aloneStartup
+createNewStartupClass
+    <resource: #uiCallback>
+
+    |newClassName newStartupClass|
+
+    newClassName := self newStartupClassName value.
+    newClassName isEmptyOrNil ifTrue:[
+        Dialog warn:'Please enter the name of the Startup-Class first.'.
+        ^ self
+    ].
+
+    self withWaitCursorDo:[
+        Class packageQuerySignal answer:(selectedProjectDefinition package)
+        do:[
+            newStartupClass := StandaloneStartup
                             subclass:newClassName asSymbol
                             instanceVariableNames:''
                             classVariableNames:''
@@ -928,22 +1013,15 @@
     ].
 !
 
-classVariableNames:''
-                            poolDictionaries:''
-                            category:'Applications'.
-            CodeGeneratorTool createStartupCodeFor:newStartupClass forStartOf:selectedApplication.
-        ].
-        self updateListOfStartupClassesInProject
-    ].
-!
-
-#uiCallback>
+doAddClassToProject
+    <resource: #uiCallback>
 
     Transcript showCR:self class name, ': action for doAddClassToProject ...'.
     self halt.
 !
 
-<resource: #uiCallback>
+doBrowseApplication
+    <resource: #uiCallback>
 
     |appClass|
 
@@ -954,23 +1032,56 @@
     ].
 !
 
-].
+doBrowseProject
+    <resource: #uiCallback>
+
+    UserPreferences systemBrowserClass openOnPackage:selectedProjectDefinition package.
 !
 
-emBrowserClass 
+doBrowseProjectDefinitionClass
+    <resource: #uiCallback>
+
+    |defClass|
+
+    self hasProjectSelected ifTrue:[
+        defClass := self selectedProjectDefinition.
+        UserPreferences systemBrowserClass 
             openInClass:defClass class selector:#classNamesAndAttributes.
     ].
 !
 
-ibutes.
+doBrowseStartupClass
+    <resource: #uiCallback>
+
+    |startupClass|
+
+    self hasStartupClassSelected ifTrue:[
+        startupClass := self listOfStartupClassesInProject value at:(self selectedStartupClassIndexHolder value).
+        UserPreferences systemBrowserClass 
+            openInClass:startupClass class selector:#main:.
     ].
 !
 
-UserPreferences systemBrowserClass 
-            openInClass:startupClass class selector:#main:.
+doGenerateProjectContentsDefinition
+    self generatePackageContentsMethods
+!
+
+doLaunchApplication
+    <resource: #uiCallback>
+
+    |appClass|
+
+    self hasApplicationSelected ifTrue:[
+        appClass := self listOfApplicationsInProject value at:(self selectedApplicationIndexHolder value).
+        appClass open.
     ].
 !
 
+doOpenExplorer
+    OperatingSystem
+        openApplicationForDocument:(projectBuilder packageBuildDirectory) operation:#explore.
+!
+
 doStartMakeAll
     <resource: #uiCallback>
 
@@ -1021,24 +1132,27 @@
     makeProcess resume.
 !
 
-[
-                [
-                    self runBuildProcess:'all'
-                ] ensure:[
-                    self stopMakeButtonVisible value:false.
-                    self startMakeButtonEnabled value:true.
-                    makeProcess := nil.
-                    self updateButtonEnableState.
-                ].
-            ] newProcess.
+doStopMake
+    <resource: #uiCallback>
+
+    |p|
 
-    makeProcess priority:4.
-    makeProcess priorityRange:(4 to:8).
-    makeProcess resume.
+    (p := makeProcess) notNil ifTrue:[
+        makeProcess := nil.
+        p terminate.
+        p waitUntilTerminated.
+
+        makeOutputWindow endEntry.
+        makeOutputWindow cr.
+        makeOutputWindow nextPutLine:('Make Cancelled' colorizeAllWith:Color white on:Color red).
+        makeOutputWindow endEntry.
+    ].
 !
 
-makeProcess priorityRange:(4 to:8).
-    makeProcess resume.
+projectTypeChanged
+    <resource: #uiCallback>
+
+    self updateListOfMatchingProjects
 !
 
 runBuildProcess:what
@@ -1075,56 +1189,20 @@
     ].
 !
 
-(p := makeProcess) notNil ifTrue:[
-        makeProcess := nil.
-        p terminate.
-        p waitUntilTerminated.
-
-        makeOutputWindow endEntry.
-        makeOutputWindow cr.
-        makeOutputWindow nextPutLine:('Make Cancelled' colorizeAllWith:Color white on:Color red).
-        makeOutputWindow endEntry.
-    ].
-!
-
-akeOutputWindow nextPutLine:(ex messageText colorizeAllWith:Color white on:Color blue).
-            makeOutputWindow endEntry.
-        ].
-        ex proceed.
-    ] do:[
-        projectBuilder := ProjectBuilder new.
-        projectBuilder package:(selectedProjectDefinition package).
-        what = 'exe' ifTrue:[
-            projectBuilder makeExeOnly:true
-        ] ifFalse:[
-            projectBuilder makeExeOnly:false
-        ].
+selectedApplicationChanged
+    |idx|
 
-        Error handle:[:ex |
-            makeOutputWindow endEntry.
-            makeOutputWindow cr.
-            makeOutputWindow nextPutLine:(ex messageText colorizeAllWith:Color white on:Color red).
-            makeOutputWindow endEntry.
-        ] do:[
-            projectBuilder buildWithColorizedOutputTo:makeOutputWindow.
-        ].
+    ((idx := self selectedApplicationIndexHolder value) isNil
+    or:[idx == 0]) ifTrue:[
+        selectedApplication := nil.
+    ] ifFalse:[
+        selectedApplication := self listOfApplicationsInProject value at:idx.
     ].
-!
+    self hasApplicationSelectedHolder value:(selectedApplication notNil).
 
-Error handle:[:ex |
-            makeOutputWindow endEntry.
-            makeOutputWindow cr.
-            makeOutputWindow nextPutLine:(ex messageText colorizeAllWith:Color white on:Color red).
-            makeOutputWindow endEntry.
-        ] do:[
-            projectBuilder buildWithColorizedOutputTo:makeOutputWindow.
-        ].
-    ].
-! !
-
-!ProjectBuilderAssistantApplication methodsFor:'aspects'!
-
-CodeGeneratorTool
+"/    selectedApplication notNil ifTrue:[
+"/        "/ generate startupClass code
+"/        CodeGeneratorTool
 "/            compile:(selectedProjectDefinition startupClassName_codeFor:(selectedApplication name))
 "/            forClass:selectedProjectDefinition theMetaclass
 "/            inCategory:'description - startup'.
@@ -1133,11 +1211,24 @@
     self updateButtonEnableState.
 !
 
-onsInProject.
+selectedProjectChanged
+    self selectedProjectIndexHolder value isNil ifTrue:[
+        selectedProjectDefinition := nil.
+    ] ifFalse:[
+        selectedProjectDefinition := self listOfMatchingProjects value at:(self selectedProjectIndexHolder value).
+    ].
+    self hasProjectSelectedHolder value:(selectedProjectDefinition notNil).
+
+    self updateComment.
+    self updateListOfApplicationsInProject.
     self updateButtonEnableState.
 !
 
-StartupClassesInProject value at:(self selectedStartupClassIndexHolder value).
+selectedStartupClassChanged
+    self selectedStartupClassIndexHolder value isNil ifTrue:[
+        selectedStartupClass := nil.
+    ] ifFalse:[
+        selectedStartupClass := self listOfStartupClassesInProject value at:(self selectedStartupClassIndexHolder value).
     ].
     self hasStartupClassSelectedHolder value:(selectedStartupClass notNil).
 
@@ -1149,24 +1240,12 @@
             inCategory:'description - startup'.
     ].
     self updateButtonEnableState.
-!
+! !
 
-"/ generate startupClass code
-        CodeGeneratorTool
-            compile:(selectedProjectDefinition startupClassName_codeFor:(selectedStartupClass name))
-            forClass:selectedProjectDefinition theMetaclass
-            inCategory:'description - startup'.
-    ].
-    self updateButtonEnableState.
-!
+!ProjectBuilderAssistantApplication methodsFor:'aspects'!
 
-ojectDefinition theMetaclass
-            inCategory:'description - startup'.
-    ].
-    self updateButtonEnableState.
-!
-
-<resource: #uiAspect>
+buildDirectoryHolder
+    <resource: #uiAspect>
 
     |buildDirectory|
 
@@ -1187,74 +1266,94 @@
     ^ buildDirectoryHolder.
 !
 
-s::ProjectBuilder previousBuildDirectory.
-        buildDirectory isNil ifTrue:[
-            buildDirectory := UserPreferences current buildDirectory.
-            buildDirectory isNil ifTrue:[
-                buildDirectory := Filename tempDirectory construct:'stx_build'.
-            ].
-        ].
-        buildDirectoryHolder value: buildDirectory.
-    ].
-    ^ buildDirectoryHolder.
-!
+fileBrowserInstance
+    |targetDirectory browser|
 
-].
-        ].
-        buildDirectoryHolder value: buildDirectory.
-    ].
-    ^ buildDirectoryHolder.
-!
+    targetDirectory := projectBuilder packageBuildDirectory.
 
-rowser := FileBrowserV2 new.
+    browser := FileBrowserV2 new.
     browser onDirectory:targetDirectory.
     browser filter:'*.exe'.
     ^ browser.
 !
 
-r isNil ifTrue:[
+hasApplicationSelectedHolder
+    <resource: #uiAspect>
+
+    hasApplicationSelectedHolder isNil ifTrue:[
         hasApplicationSelectedHolder := nil asValue.
     ].
     ^ hasApplicationSelectedHolder.
 !
 
-electedHolder isNil ifTrue:[
+hasProjectSelectedHolder
+    <resource: #uiAspect>
+
+    hasProjectSelectedHolder isNil ifTrue:[
         hasProjectSelectedHolder := nil asValue.
     ].
     ^ hasProjectSelectedHolder.
 !
 
-sStartupClassSelectedHolder isNil ifTrue:[
+hasStartupClassSelectedHolder
+    <resource: #uiAspect>
+
+    hasStartupClassSelectedHolder isNil ifTrue:[
         hasStartupClassSelectedHolder := nil asValue.
     ].
     ^ hasStartupClassSelectedHolder.
 !
 
-rApplicationClasses isNil ifTrue:[
+hideOtherApplicationClasses
+    <resource: #uiAspect>
+
+    hideOtherApplicationClasses isNil ifTrue:[
         hideOtherApplicationClasses := true asValue.
         hideOtherApplicationClasses onChangeSend:#updateListOfApplicationsInProject to:self.
     ].
     ^ hideOtherApplicationClasses.
 !
 
-oject to:self.
+hideOtherStartupClasses
+    <resource: #uiAspect>
+
+    hideOtherStartupClasses isNil ifTrue:[
+        hideOtherStartupClasses := true asValue.
+        hideOtherStartupClasses onChangeSend:#updateListOfStartupClassesInProject to:self.
     ].
-    ^ hideOtherApplicationClasses.
+    ^ hideOtherStartupClasses.
 !
 
-:[
+hideSTXProjects
+    <resource: #uiAspect>
+
+    hideSTXProjects isNil ifTrue:[
+        hideSTXProjects := true asValue.
+        hideSTXProjects onChangeSend:#updateListOfMatchingProjects to:self.
+    ].
+    ^ hideSTXProjects.
+!
+
+listOfApplicationsInProject
+    <resource: #uiAspect>
+
+    listOfApplicationsInProject isNil ifTrue:[
         listOfApplicationsInProject := ValueHolder new.
     ].
     ^ listOfApplicationsInProject.
 !
 
-listOfClassesInProject isNil ifTrue:[
+listOfClassesInProject
+    <resource: #uiAspect>
+
+    listOfClassesInProject isNil ifTrue:[
         listOfClassesInProject := ValueHolder new.
     ].
     ^ listOfClassesInProject.
 !
 
-#uiAspect>
+listOfMatchingProjects
+    <resource: #uiAspect>
 
     listOfMatchingProjects isNil ifTrue:[
         listOfMatchingProjects := ValueHolder new.
@@ -1262,7 +1361,17 @@
     ^ listOfMatchingProjects.
 !
 
-<resource: #uiAspect>
+listOfStartupClassesInProject
+    <resource: #uiAspect>
+
+    listOfStartupClassesInProject isNil ifTrue:[
+        listOfStartupClassesInProject := ValueHolder new.
+    ].
+    ^ listOfStartupClassesInProject.
+!
+
+makeOutputHolder
+    <resource: #uiAspect>
 
     makeOutputHolder isNil ifTrue:[
         makeOutputHolder := ValueHolder new.
@@ -1270,23 +1379,46 @@
     ^ makeOutputHolder.
 !
 
-below:
+newApplicationsName
+    <resource: #uiAspect>
+
+    "automatically generated by UIPainter ..."
+
+    "*** the code below creates a default model when invoked."
+    "*** (which may not be the one you wanted)"
+    "*** Please change as required and accept it in the browser."
+    "*** (and replace this comment by something more useful ;-)"
+
+    newApplicationsName isNil ifTrue:[
+        newApplicationsName := ValueHolder new.
+"/ if your app needs to be notified of changes, uncomment one of the lines below:
 "/       newApplicationsName addDependent:self.
 "/       newApplicationsName onChangeSend:#newApplicationsNameChanged to:self.
     ].
     ^ newApplicationsName.
 !
 
-wProjectsName isNil ifTrue:[
+newProjectsName
+    <resource: #uiAspect>
+
+    newProjectsName isNil ifTrue:[
         newProjectsName := nil asValue.
     ].
     ^ newProjectsName.
 !
 
-^ newProjectsName.
+newStartupClassName
+    <resource: #uiAspect>
+
+    newStartupClassName isNil ifTrue:[
+        newStartupClassName := ValueHolder new.
+    ].
+    ^ newStartupClassName.
 !
 
-ype
+projectType
+    self projectTypeHolder value == #libraryType ifTrue:[
+        ^ ProjectDefinition libraryType
     ].
     self projectTypeHolder value == #guiApplicationType ifTrue:[
         ^ ProjectDefinition guiApplicationType
@@ -1297,7 +1429,17 @@
     self error.
 !
 
-True:[
+projectType:aProjectTypeSymbol
+    |pType|
+
+    self assert:(ProjectDefinition projectTypes includes:aProjectTypeSymbol).
+    aProjectTypeSymbol == ProjectDefinition libraryType ifTrue:[
+        pType := #libraryType
+    ] ifFalse:[
+        aProjectTypeSymbol == ProjectDefinition guiApplicationType ifTrue:[
+            pType := #guiApplicationType
+        ] ifFalse:[
+            aProjectTypeSymbol == ProjectDefinition nonGuiApplicationType ifTrue:[
                 pType := #nonGuiApplicationType
             ] ifFalse:[
                 self error.
@@ -1307,26 +1449,34 @@
     self projectTypeHolder value:aProjectTypeSymbol
 !
 
-self error.
-            ].
-        ]
-    ].
-    self projectTypeHolder value:aProjectTypeSymbol
-!
+projectTypeHolder
+    <resource: #uiAspect>
 
-tionType.
+    projectTypeHolder isNil ifTrue:[
+        projectTypeHolder := RadioButtonGroup new.
+        projectTypeHolder value:#guiApplicationType.
     ].
     ^ projectTypeHolder.
 !
 
-selectedApplicationIndexHolder isNil ifTrue:[
+projectTypeIsNotLibrary
+    ^ self projectTypeHolder value ~~ #libraryType
+!
+
+selectedApplicationIndexHolder
+    <resource: #uiAspect>
+
+    selectedApplicationIndexHolder isNil ifTrue:[
         selectedApplicationIndexHolder := ValueHolder new.
         selectedApplicationIndexHolder onChangeSend:#selectedApplicationChanged to:self.
     ].
     ^ selectedApplicationIndexHolder.
 !
 
-tomatically generated by UIPainter ..."
+selectedApplicationsComment
+    <resource: #uiAspect>
+
+    "automatically generated by UIPainter ..."
 
     "*** the code below creates a default model when invoked."
     "*** (which may not be the one you wanted)"
@@ -1342,61 +1492,87 @@
     ^ selectedApplicationsComment.
 !
 
-d and accept it in the browser."
-    "*** (and replace this comment by something more useful ;-)"
+selectedProjectDefinition
+    <resource: #uiAspect>
 
-    selectedApplicationsComment isNil ifTrue:[
-        selectedApplicationsComment := '' asValue.
-"/ if your app needs to be notified of changes, uncomment one of the lines below:
-"/       selectedApplicationsComment addDependent:self.
-"/       selectedApplicationsComment onChangeSend:#selectedApplicationsCommentChanged to:self.
-    ].
-    ^ selectedApplicationsComment.
-! !
-
-!ProjectBuilderAssistantApplication methodsFor:'initialization & release'!
-
-the lines below:
-"/       selectedApplicationsComment addDependent:self.
-"/       selectedApplicationsComment onChangeSend:#selectedApplicationsCommentChanged to:self.
-    ].
-    ^ selectedApplicationsComment.
+    ^ selectedProjectDefinition.
 !
 
-self.
-"/       selectedApplicationsComment onChangeSend:#selectedApplicationsCommentChanged to:self.
-    ].
-    ^ selectedApplicationsComment.
-!
-
-ment.
-! !
-
-!ProjectBuilderAssistantApplication methodsFor:'menu actions'!
-
-<resource: #uiAspect>
+selectedProjectIndexHolder
+    <resource: #uiAspect>
 
     selectedProjectIndexHolder isNil ifTrue:[
         selectedProjectIndexHolder := ValueHolder new.
         selectedProjectIndexHolder onChangeSend:#selectedProjectChanged to:self.
     ].
     ^ selectedProjectIndexHolder.
+!
+
+selectedProjectsComment
+    <resource: #uiAspect>
+
+    selectedProjectsComment isNil ifTrue:[
+        selectedProjectsComment := '' asValue.
+    ].
+    ^ selectedProjectsComment.
+!
+
+selectedStartupClassIndexHolder
+    <resource: #uiAspect>
+
+    selectedStartupClassIndexHolder isNil ifTrue:[
+        selectedStartupClassIndexHolder := ValueHolder new.
+        selectedStartupClassIndexHolder onChangeSend:#selectedStartupClassChanged to:self.
+    ].
+    ^ selectedStartupClassIndexHolder.
+!
+
+startMakeButtonEnabled
+    <resource: #uiAspect>
+
+    startMakeButtonEnabled isNil ifTrue:[
+        startMakeButtonEnabled := true asValue.
+    ].
+    ^ startMakeButtonEnabled.
+!
+
+stopMakeButtonVisible
+    <resource: #uiAspect>
+
+    stopMakeButtonVisible isNil ifTrue:[
+        stopMakeButtonVisible := false asValue.
+    ].
+    ^ stopMakeButtonVisible.
+! !
+
+!ProjectBuilderAssistantApplication methodsFor:'initialization & release'!
+
+postBuildMakeOutputWindow:aView
+    makeOutputWindow := aView
+!
+
+postBuildWith:aBuilder
+    super postBuildWith:aBuilder.
+    self updateListOfMatchingProjects.
+
+    Smalltalk addDependent:self.
+!
+
+release
+    Smalltalk removeDependent:self.
+    super release
+! !
+
+!ProjectBuilderAssistantApplication methodsFor:'menu actions'!
+
+openDocumentation
+   self openHTMLDocument:'tools/misc/TOP.html#PACKAGER'.
 ! !
 
 !ProjectBuilderAssistantApplication methodsFor:'private'!
 
-ProjectIndexHolder onChangeSend:#selectedProjectChanged to:self.
-    ].
-    ^ selectedProjectIndexHolder.
-!
-
-akeButtonVisible.
-!
-
-ntApplication methodsFor:'private'
-!
-
-t indents minIndent maxLineLength|
+commentFromClass:aClass
+    |docMethod comment indents minIndent maxLineLength|
 
     docMethod := aClass class compiledMethodAt:#documentation.
     docMethod notNil ifTrue:[
@@ -1417,85 +1593,51 @@
     ^ comment
 !
 
-documentation.
-    docMethod notNil ifTrue:[
-        comment := docMethod comment.
-        comment := comment asStringCollection 
-                        collect:[:line | line withoutTrailingSeparators].
-        [comment notEmpty and:[comment first isBlank]] whileTrue:[ comment removeFirst ].
-        maxLineLength := (comment collect:[:line | line size]) max.
-        indents := comment collect:[:line | 
-                                        line isEmptyOrNil
-                                            ifTrue:[maxLineLength]
-                                            ifFalse:[ line findFirst:[:ch | ch isSeparator not]]].
-        (minIndent := indents min) > 1 ifTrue:[
-            comment := comment collect:[:line | line copyFrom:minIndent].
-        ].
-        comment := comment asString.
+generatePackageContentsMethods
+    <resource: #uiCallback>
+
+    Class packageQuerySignal answer:(selectedProjectDefinition package)
+    do:[
+        selectedProjectDefinition 
+            forEachContentsMethodsCodeToCompileDo:[:code :category |
+                    CodeGeneratorTool
+                        compile:code
+                        forClass:selectedProjectDefinition theMetaclass
+                        inCategory:category.
+                ]
+            ignoreOldDefinition:true
     ].
-    ^ comment
+    self updateListOfClassesInProject
 !
 
-comment := docMethod comment.
-        comment := comment asStringCollection 
-                        collect:[:line | line withoutTrailingSeparators].
-        [comment notEmpty and:[comment first isBlank]] whileTrue:[ comment removeFirst ].
-        maxLineLength := (comment collect:[:line | line size]) max.
-        indents := comment collect:[:line | 
-                                        line isEmptyOrNil
-                                            ifTrue:[maxLineLength]
-                                            ifFalse:[ line findFirst:[:ch | ch isSeparator not]]].
-        (minIndent := indents min) > 1 ifTrue:[
-            comment := comment collect:[:line | line copyFrom:minIndent].
-        ].
-        comment := comment asString.
-    ].
-    ^ comment
+hasApplicationSelected
+    ^ self selectedApplicationIndexHolder value notNil
+!
+
+hasBuildDirectorySpecified
+    ^ self buildDirectoryHolder value notEmptyOrNil
 !
 
-n 
-                        collect:[:line | line withoutTrailingSeparators].
-        [comment notEmpty and:[comment first isBlank]] whileTrue:[ comment removeFirst ].
-        maxLineLength := (comment collect:[:line | line size]) max.
-        indents := comment collect:[:line | 
-                                        line isEmptyOrNil
-                                            ifTrue:[maxLineLength]
-                                            ifFalse:[ line findFirst:[:ch | ch isSeparator not]]].
-        (minIndent := indents min) > 1 ifTrue:[
-            comment := comment collect:[:line | line copyFrom:minIndent].
-        ].
-        comment := comment asString.
-    ].
-    ^ comment
+hasProjectBuilder
+    ^ projectBuilder notNil
+!
+
+hasProjectSelected
+    ^ self selectedProjectIndexHolder value notNil
+!
+
+hasStartupClassSelected
+    ^ self selectedStartupClassIndexHolder value notNil
 ! !
 
 !ProjectBuilderAssistantApplication methodsFor:'queries'!
 
-ent removeFirst ].
-        maxLineLength := (comment collect:[:line | line size]) max.
-        indents := comment collect:[:line | 
-                                        line isEmptyOrNil
-                                            ifTrue:[maxLineLength]
-                                            ifFalse:[ line findFirst:[:ch | ch isSeparator not]]].
-        (minIndent := indents min) > 1 ifTrue:[
-            comment := comment collect:[:line | line copyFrom:minIndent].
-        ].
-        comment := comment asString.
-    ].
-    ^ comment
+canEnterApplicationSelection
+    ^ self hasProjectSelected
 !
 
-ne | line size]) max.
-        indents := comment collect:[:line | 
-                                        line isEmptyOrNil
-                                            ifTrue:[maxLineLength]
-                                            ifFalse:[ line findFirst:[:ch | ch isSeparator not]]].
-        (minIndent := indents min) > 1 ifTrue:[
-            comment := comment collect:[:line | line copyFrom:minIndent].
-        ].
-        comment := comment asString.
-    ].
-    ^ comment
+canEnterBuild
+    ^ self hasBuildDirectorySpecified
 !
 
 canEnterContentsSelection
@@ -1504,35 +1646,71 @@
     and:[ self hasStartupClassSelected ]]
 !
 
-ifFalse:[ line findFirst:[:ch | ch isSeparator not]]].
-        (minIndent := indents min) > 1 ifTrue:[
-            comment := comment collect:[:line | line copyFrom:minIndent].
-        ].
-        comment := comment asString.
-    ].
-    ^ comment
+canEnterDeploy
+    ^ self hasProjectBuilder
 !
 
-ndFirst:[:ch | ch isSeparator not]]].
-        (minIndent := indents min) > 1 ifTrue:[
-            comment := comment collect:[:line | line copyFrom:minIndent].
-        ].
-        comment := comment asString.
-    ].
-    ^ comment
+canEnterStartupClassSelection
+    ^ self hasProjectSelected "and:[ self hasApplicationSelected ]"
 ! !
 
 !ProjectBuilderAssistantApplication methodsFor:'specs'!
 
-].
-        comment := comment asString.
-    ].
-    ^ comment
-! !
+assistantSpec
+    ^ #(Array
+        ( AssistantPageSpec
+            pageTitle: 'Project Type Selection'
+            windowSpecSelector: page1_projectTypeSelectionSpec
+            enterCallbackSelector: updateListOfMatchingProjects
+            infoText: 'Choose the type of project you are about to build.'
+        )
+
+        (AssistantPageSpec
+            pageTitle: 'Project Selection'
+            windowSpecSelector: page2_projectSelectionSpec
+            enterCallbackSelector: updateListOfMatchingProjects
+            infoText: 'Choose an existing project or create a new one.
+                       These are subclasses of <I>ProjectDefinition</I> and define the
+                       type and contents of a project.'
+        )
 
-!ProjectBuilderAssistantApplication methodsFor:'update'!
+        (AssistantPageSpec
+            pageTitle: 'Application Selection'
+            windowSpecSelector: page3_applicationSelectionSpec
+            isEnabledQuerySelector: #projectTypeIsNotLibrary
+            canEnterQuerySelector: #canEnterApplicationSelection
+            enterCallbackSelector: updateListOfApplicationsInProject
+            infoText: 'Choose an existing application or create a new one.
+                       These are subclasses of <I>ApplicationModel</I> and define
+                       the GUI and control flow inside the application.
+                       Can also be left blank if the startup class does it all (stx build).'
+        )
 
-ecifyBuildDirectorySpec
+        (AssistantPageSpec
+            pageTitle: 'Startup Class Selection'
+            windowSpecSelector: page4_startupClassSelectionSpec
+            isEnabledQuerySelector: #projectTypeIsNotLibrary
+            canEnterQuerySelector: #canEnterStartupClassSelection
+            enterCallbackSelector: updateListOfStartupClassesInProject
+            infoText: 'Choose an existing startup-class or create a new one.
+                       These are subclasses of <I>StandaloneStartup</I> and 
+                       start the application. Command line arguments can be
+                       interpreted there.'
+        )
+
+        (AssistantPageSpec
+            pageTitle: 'Specify Contents'
+            windowSpecSelector: page5_specifyIncludedClasses
+            enterCallbackSelector: updateListOfClassesInProject
+            canEnterQuerySelector: #canEnterContentsSelection
+            infoText: 'Define which (other) classes are to be included.
+                       Press "<I>Scan</I>" to include all classes of the package;
+                       browse to edit the contents manually.'
+        )
+
+        (AssistantPageSpec
+            pageTitle: 'Specify Build Directory'
+            windowSpecSelector: page6_specifyBuildDirectorySpec
             infoText: 'Define where the build-process is to be performed.
                        All generated files are created below that directory.
                        After deployment, the build directory is no longer needed
@@ -1561,100 +1739,61 @@
                        (but you can keep it for a faster compile the next time).'
         )
     ) decodeAsLiteralArray.
+! !
+
+!ProjectBuilderAssistantApplication methodsFor:'update'!
+
+rememberMakeOutputsContents
+    makeOutputHolder value:(makeOutputWindow contents)
+!
+
+restoreMakeOutputsContents
+    makeOutputWindow contents:makeOutputHolder value
 !
 
-rformed.
-                       All generated files are created below that directory.
-                       After deployment, the build directory is no longer needed
-                       (but you can keep it for a faster compile the next time).'
-        )
-
-        (AssistantPageSpec
-            pageTitle: 'Build'
-            windowSpecSelector: page7_buildSpec
-            canEnterQuerySelector: #canEnterBuild
-            enterCallbackSelector: #restoreMakeOutputsContents
-            leaveCallbackSelector: #rememberMakeOutputsContents
-            infoText: 'Start the build-process. This will run make/bcc to compile
-                       all required classes and nsis to generate a self-installable
-                       executable. You must have the borland-cc and NullSoft NSIS
-                       packages installed for this to work.'
-        )
-
-        (AssistantPageSpec
-            pageTitle: 'Deploy'
-            windowSpecSelector: page8_deploySpec
-            canEnterQuerySelector: #canEnterDeploy
-            infoText: 'Find the installer to be deployed (or test-run the binary).
-                       You can open a WindowsExplorer there to copy the files for
-                       deployment. After that, the build directory is no longer needed
-                       (but you can keep it for a faster compile the next time).'
-        )
-    ) decodeAsLiteralArray.
+update:something with:anArgument from:changedObject
+    changedObject == Smalltalk ifTrue:[
+        (something == #newClass
+        or:[something == #classRemove
+        or:[something == #projectOrganization]]) ifTrue:[
+            self updateListOfMatchingProjects.
+            ^ self.
+        ].
+        ^ self.
+    ].
+    super update:something with:anArgument from:changedObject
 !
 
-After deployment, the build directory is no longer needed
-                       (but you can keep it for a faster compile the next time).'
-        )
+updateApplicationComment
+    |comment|
 
-        (AssistantPageSpec
-            pageTitle: 'Build'
-            windowSpecSelector: page7_buildSpec
-            canEnterQuerySelector: #canEnterBuild
-            enterCallbackSelector: #restoreMakeOutputsContents
-            leaveCallbackSelector: #rememberMakeOutputsContents
-            infoText: 'Start the build-process. This will run make/bcc to compile
-                       all required classes and nsis to generate a self-installable
-                       executable. You must have the borland-cc and NullSoft NSIS
-                       packages installed for this to work.'
-        )
-
-        (AssistantPageSpec
-            pageTitle: 'Deploy'
-            windowSpecSelector: page8_deploySpec
-            canEnterQuerySelector: #canEnterDeploy
-            infoText: 'Find the installer to be deployed (or test-run the binary).
-                       You can open a WindowsExplorer there to copy the files for
-                       deployment. After that, the build directory is no longer needed
-                       (but you can keep it for a faster compile the next time).'
-        )
-    ) decodeAsLiteralArray.
+    self selectedApplicationIndexHolder value notNil ifTrue:[
+        comment := self commentFromClass:selectedApplication.
+        comment isNil ifTrue:[
+            comment := 'Application has no comment' allItalic colorizeAllWith:Color lightGrey.
+        ].
+    ] ifFalse:[
+        comment := 'Please select an Application' allItalic colorizeAllWith:Color lightGrey.
+    ].
+    self selectedApplicationsComment value:comment.
 !
 
-ts
-            leaveCallbackSelector: #rememberMakeOutputsContents
-            infoText: 'Start the build-process. This will run make/bcc to compile
-                       all required classes and nsis to generate a self-installable
-                       executable. You must have the borland-cc and NullSoft NSIS
-                       packages installed for this to work.'
-        )
+updateComment
+    |comment|
 
-        (AssistantPageSpec
-            pageTitle: 'Deploy'
-            windowSpecSelector: page8_deploySpec
-            canEnterQuerySelector: #canEnterDeploy
-            infoText: 'Find the installer to be deployed (or test-run the binary).
-                       You can open a WindowsExplorer there to copy the files for
-                       deployment. After that, the build directory is no longer needed
-                       (but you can keep it for a faster compile the next time).'
-        )
-    ) decodeAsLiteralArray.
+    self selectedProjectIndexHolder value notNil ifTrue:[
+        comment := self commentFromClass:selectedProjectDefinition.
+        comment isNil ifTrue:[
+            comment := 'Project has no comment' allItalic colorizeAllWith:Color lightGrey.
+        ].
+    ] ifFalse:[
+        comment := 'Please select a Project' allItalic colorizeAllWith:Color lightGrey.
+    ].
+    self selectedProjectsComment value:comment.
 !
 
-: page8_deploySpec
-            canEnterQuerySelector: #canEnterDeploy
-            infoText: 'Find the installer to be deployed (or test-run the binary).
-                       You can open a WindowsExplorer there to copy the files for
-                       deployment. After that, the build directory is no longer needed
-                       (but you can keep it for a faster compile the next time).'
-        )
-    ) decodeAsLiteralArray.
-!
-
-tBuilderAssistantApplication methodsFor:'update'
-!
-
-lassIndex|
+updateListOfApplicationsInProject
+    |oldList applicationClasses package appClass appClassIndex|
 
     appClassIndex := nil.
 
@@ -1693,37 +1832,47 @@
     ].
 !
 
-s := #()
-    ] ifFalse:[
-        package := selectedProjectDefinition package.
+updateListOfClassesInProject
+    self listOfClassesInProject value:(selectedProjectDefinition classNames).
+!
 
-        applicationClasses := Smalltalk allClasses
-                                    select:[:cls |
-                                        ((cls isSubclassOf:ApplicationModel)
-                                        and:[ self hideOtherApplicationClasses value not
-                                              or:[ cls package = package ]])
-                                    ].
-        applicationClasses := applicationClasses asOrderedCollection.
-        applicationClasses sort:[:a :b | a name < b name].
+updateListOfMatchingProjects
+    |matching projectType idx|
+
+    projectType := self projectType.
+    matching := ProjectDefinition allSubclasses
+                    select:[:defClass |
+                        |match|
 
-"/        startUpClassName := [ selectedProjectDefinition startupClassName ] ifError:[ nil ].
-"/        startUpClassName notNil ifTrue:[
-"/            startUpClass := Smalltalk classNamed:startUpClassName.
-"/            startUpClass notNil ifTrue:[
-"/                appClassIndex := applicationClasses indexOf:startUpClass.
-"/                appClassIndex == 0 ifTrue:[ appClassIndex := nil ].
-"/            ].
-"/        ].
-    ].
+                        match := false.
+                        defClass isAbstract ifFalse:[
+                            (self hideSTXProjects value not
+                            or:[ defClass package asPackageId module ~= 'stx' ])
+                            ifTrue:[
+                                projectType == ProjectDefinition libraryType ifTrue:[
+                                    match := defClass isLibraryDefinition
+                                ] ifFalse:[
+                                    projectType == ProjectDefinition guiApplicationType ifTrue:[
+                                        match := defClass isGUIApplication
+                                    ] ifFalse:[
+                                        projectType == ProjectDefinition nonGuiApplicationType ifTrue:[
+                                            match := defClass isConsoleApplication
+                                        ] ifFalse:[
+                                            self error.
+                                        ].
+                                    ].
+                                ].
+                            ].
+                        ].
+                   ].
+    matching sort:[:a :b | a name < b name].
+    self listOfMatchingProjects value:matching.
 
-    oldList := self listOfApplicationsInProject value.
-    oldList = applicationClasses ifFalse:[
-        appClass := selectedApplication.
-        appClassIndex := applicationClasses indexOf:appClass.
-        appClassIndex == 0 ifTrue:[ appClassIndex := nil ].
-
-        self listOfApplicationsInProject value:applicationClasses.
-        self selectedApplicationIndexHolder value:appClassIndex.
+    idx := matching indexOf:selectedProjectDefinition.
+    idx == 0 ifTrue:[
+        self selectedProjectIndexHolder value:nil.
+    ] ifFalse:[
+        self selectedProjectIndexHolder value:idx.
     ].
 !