SmalltalkCodeGeneratorTool.st
changeset 9706 382fbd22e5b6
child 9720 1ea182385871
equal deleted inserted replaced
9705:3c29845b149d 9706:382fbd22e5b6
       
     1 "
       
     2  COPYRIGHT (c) 2002 by eXept Software AG
       
     3               All Rights Reserved
       
     4 
       
     5  This software is furnished under a license and may be used
       
     6  only in accordance with the terms of that license and with the
       
     7  inclusion of the above copyright notice.   This software may not
       
     8  be provided or otherwise made available to, or used by, any
       
     9  other person.  No title to or ownership of the software is
       
    10  hereby transferred.
       
    11 "
       
    12 "{ Package: 'stx:libtool' }"
       
    13 
       
    14 CodeGeneratorTool subclass:#SmalltalkCodeGeneratorTool
       
    15 	instanceVariableNames:''
       
    16 	classVariableNames:''
       
    17 	poolDictionaries:''
       
    18 	category:'Interface-Browsers'
       
    19 !
       
    20 
       
    21 !SmalltalkCodeGeneratorTool class methodsFor:'documentation'!
       
    22 
       
    23 copyright
       
    24 "
       
    25  COPYRIGHT (c) 2002 by eXept Software AG
       
    26               All Rights Reserved
       
    27 
       
    28  This software is furnished under a license and may be used
       
    29  only in accordance with the terms of that license and with the
       
    30  inclusion of the above copyright notice.   This software may not
       
    31  be provided or otherwise made available to, or used by, any
       
    32  other person.  No title to or ownership of the software is
       
    33  hereby transferred.
       
    34 "
       
    35 !
       
    36 
       
    37 documentation
       
    38 "
       
    39     This utility class contains various code generation facilites;
       
    40     these were extracted from the old and newBrowser.
       
    41     There is probably more to come...
       
    42 
       
    43     [author:]
       
    44         Claus Gittiner
       
    45 "
       
    46 ! !
       
    47 
       
    48 !SmalltalkCodeGeneratorTool class methodsFor:'code generation'!
       
    49 
       
    50 initialMenuSpecMethodSourceForApplications
       
    51     "return code for a menuSpec with typical stuff in it"
       
    52 
       
    53     ^
       
    54 'mainMenu
       
    55     "This resource specification was automatically generated by the CodeGeneratorTool."
       
    56 
       
    57     "Do not manually edit this!! If it is corrupted,
       
    58      the MenuEditor may not be able to read the specification."
       
    59 
       
    60     "
       
    61      MenuEditor new openOnClass:%1 andSelector:#mainMenu
       
    62     "
       
    63 
       
    64     <resource: #menu>
       
    65 
       
    66     ^ ',(self initialMenuSpecForApplications decodeAsLiteralArray literalArrayEncoding storeString),'
       
    67 '.
       
    68 !
       
    69 
       
    70 initialPageMenuSpecMethodSourceForWebApplications
       
    71     "return code for a menuSpec with typical stuff in it"
       
    72 
       
    73     ^
       
    74 'mainMenu
       
    75     "This resource specification was automatically generated by the CodeGeneratorTool."
       
    76 
       
    77     "Do not manually edit this!! If it is corrupted,
       
    78      the MenuEditor may not be able to read the specification."
       
    79 
       
    80     "
       
    81      MenuEditor new openOnClass:%1 andSelector:#mainMenu
       
    82     "
       
    83 
       
    84     <resource: #menu>
       
    85 
       
    86     ^ ',(self initialPageMenuSpecForWebApplications decodeAsLiteralArray literalArrayEncoding storeString),'
       
    87 '.
       
    88 
       
    89     "
       
    90      self initialPageMenuSpecMethodSourceForWebApplications
       
    91     "
       
    92 !
       
    93 
       
    94 initialPageSpecMethodSourceForWebApplications
       
    95     "return an empty pageSpec"
       
    96 
       
    97     ^
       
    98 'pageSpec
       
    99     "This resource specification was automatically generated by the CodeGeneratorTool."
       
   100 
       
   101     "Do not manually edit this!! If it is corrupted,
       
   102      the UIPainter may not be able to read the specification."
       
   103 
       
   104     "
       
   105      UIPainter new openOnClass:%1 andSelector:#pageSpec
       
   106     "
       
   107 
       
   108     <resource: #canvas>
       
   109 
       
   110     ^ ',(self initialPageSpecForWebApplications decodeAsLiteralArray literalArrayEncoding storeString),'
       
   111 '.
       
   112 !
       
   113 
       
   114 initialToolbarMenuSpecMethodSource
       
   115     "return a menuSpec with typical stuff in it"
       
   116 
       
   117     ^
       
   118 'toolbarMenu
       
   119     "This resource specification was automatically generated by the CodeGeneratorTool."
       
   120 
       
   121     "Do not manually edit this!! If it is corrupted,
       
   122      the MenuEditor may not be able to read the specification."
       
   123 
       
   124     "
       
   125      MenuEditor new openOnClass:%1 andSelector:#toolbarMenu
       
   126     "
       
   127 
       
   128     <resource: #menu>
       
   129 
       
   130     ^ ',(self initialToolbarMenuSpec decodeAsLiteralArray literalArrayEncoding storeString),'
       
   131 '.
       
   132 
       
   133     "
       
   134      self initialToolbarMenuSpecMethodSource
       
   135     "
       
   136 !
       
   137 
       
   138 initialWindowSpecMethodSourceForApplications
       
   139     "return an empty windowSpec with an initial menubar in it"
       
   140 
       
   141     ^
       
   142 'windowSpec
       
   143     "This resource specification was automatically generated by the CodeGeneratorTool."
       
   144 
       
   145     "Do not manually edit this!! If it is corrupted,
       
   146      the UIPainter may not be able to read the specification."
       
   147 
       
   148     "
       
   149      UIPainter new openOnClass:%1 andSelector:#windowSpec
       
   150     "
       
   151 
       
   152     <resource: #canvas>
       
   153 
       
   154     ^ ',
       
   155         self initialWindowSpecForApplications2 decodeAsLiteralArray prettyPrintString           
       
   156 .
       
   157 
       
   158     "
       
   159      self initialWindowSpecMethodSourceForApplications
       
   160     "
       
   161 !
       
   162 
       
   163 initialWindowSpecMethodSourceForDialogs
       
   164     "return an empty windowSpec for dialogs"
       
   165 
       
   166     ^
       
   167 'windowSpec
       
   168     "This resource specification was automatically generated by the CodeGeneratorTool."
       
   169 
       
   170     "Do not manually edit this!! If it is corrupted,
       
   171      the UIPainter may not be able to read the specification."
       
   172 
       
   173     "
       
   174      UIPainter new openOnClass:%1 andSelector:#windowSpec
       
   175     "
       
   176 
       
   177     <resource: #canvas>
       
   178 
       
   179     ^ ',
       
   180         self initialWindowSpecForDialogs decodeAsLiteralArray prettyPrintString           
       
   181 ! !
       
   182 
       
   183 !SmalltalkCodeGeneratorTool class methodsFor:'code generation-menus'!
       
   184 
       
   185 createActionMethodFor:aSelector in:aClass category:aCategory redefine:redefine
       
   186     |alreadyInSuperclass method code|
       
   187 
       
   188     (aClass includesSelector:aSelector) ifTrue:[
       
   189         ^ nil
       
   190     ].
       
   191 
       
   192     alreadyInSuperclass := aClass superclass canUnderstand:aSelector.
       
   193     (alreadyInSuperclass and:[redefine not]) ifTrue:[
       
   194         ^ nil
       
   195     ].
       
   196 
       
   197     method := self methodNameTemplateFor:aSelector.
       
   198 
       
   199     code := '%1
       
   200     "automatically generated by UIEditor ..."
       
   201 
       
   202     "*** the code below performs no action"
       
   203     "*** (except for some feedback on the Transcript)"
       
   204     "*** Please change as required and accept in the browser."
       
   205     "*** (and replace this comment by something more useful ;-)"
       
   206 
       
   207     "action to be added ..."
       
   208 
       
   209     Transcript showCR:self class name, '': action for #%2 ...''.
       
   210 ' bindWith:method with:aSelector.
       
   211 
       
   212     alreadyInSuperclass ifTrue:[
       
   213         code := code, (('\    super %1\' bindWith:method) withCRs).
       
   214     ].
       
   215     self compile:code forClass:aClass inCategory:(aCategory ? 'actions').
       
   216     ^ code
       
   217 !
       
   218 
       
   219 createAspectMethodFor:aSelector in:aClass category:aCategory redefine:redefine
       
   220     |alreadyInSuperclass method code text|
       
   221 
       
   222     (aClass includesSelector:aSelector) ifTrue:[
       
   223         ^ nil
       
   224     ].
       
   225 
       
   226     alreadyInSuperclass := aClass superclass canUnderstand:aSelector.
       
   227     (alreadyInSuperclass and:[redefine not]) ifTrue:[
       
   228         ^ nil
       
   229     ].
       
   230 
       
   231     method := self methodNameTemplateFor:aSelector.
       
   232 
       
   233     code := '%1
       
   234     "automatically generated by UIEditor ..."
       
   235 
       
   236     "*** the code below creates a default model when invoked"
       
   237     "*** (which may not be the one you wanted)"
       
   238     "*** Please change as required and accept in the browser."
       
   239     "*** (and replace this comment by something more useful ;-)"
       
   240 
       
   241     "aspect to be added ..."
       
   242 
       
   243     Transcript showCR:self class name, '': aspect for #%2 ...''.
       
   244 
       
   245 ' bindWith:method with:aSelector.
       
   246 
       
   247     alreadyInSuperclass ifTrue:[
       
   248         text := '    ^ super %1\' bindWith:method.
       
   249     ] ifFalse:[
       
   250         text := '    ^ builder valueAspectFor:#''%1'' initialValue:true\' bindWith:aSelector.
       
   251     ].
       
   252     code := code, (text withCRs).
       
   253     self compile:code forClass:aClass inCategory:(aCategory ? 'actions').
       
   254     ^ code
       
   255 ! !
       
   256 
       
   257 !SmalltalkCodeGeneratorTool class methodsFor:'private'!
       
   258 
       
   259 methodNameTemplateFor:aSelector
       
   260     |numArgs method|
       
   261 
       
   262     numArgs := aSelector numArgs.
       
   263     numArgs == 1 ifTrue:[
       
   264         method := aSelector, 'anArgument'.
       
   265     ] ifFalse:[
       
   266         numArgs == 0 ifTrue:[
       
   267             method := aSelector
       
   268         ] ifFalse:[
       
   269             method := ''.
       
   270             aSelector keywords keysAndValuesDo:[:i :key|
       
   271                 method := method, key, 'arg', i printString, ' '.
       
   272             ].
       
   273         ]
       
   274     ].
       
   275     ^ method
       
   276 ! !
       
   277 
       
   278 !SmalltalkCodeGeneratorTool methodsFor:'code generation'!
       
   279 
       
   280 createClassInitializeMethodIn:aClass
       
   281     "create a #initialize method on the class side (I'm tired of typing)"
       
   282 
       
   283     |nonMetaClass metaClass className code initializer bindings|
       
   284 
       
   285     nonMetaClass := aClass theNonMetaclass.
       
   286     metaClass := aClass theMetaclass.
       
   287     className := nonMetaClass name.
       
   288 
       
   289     self startCollectChanges.
       
   290 
       
   291     (metaClass includesSelector:#'initialize') ifFalse:[
       
   292 'initialize
       
   293     "Invoked at system start or when the class is dynamically loaded."
       
   294 
       
   295     "/ please change as required (and remove this comment)
       
   296 '.
       
   297         bindings := Dictionary new.
       
   298         bindings at:'INIT_CLASSINSTVARS' put:(
       
   299             String streamContents:[:s |
       
   300                 metaClass instVarNames do:[:eachClassInstVar |
       
   301                     initializer := 'nil'. "/ need more intelligence here (try to guess class from messages sent to it) ...
       
   302                     s nextPutLine:('    "/ %1 := %2.' bindWith:eachClassInstVar with:initializer).
       
   303                 ]
       
   304             ]).
       
   305 
       
   306         bindings at:'INIT_CLASSVARS' put:(
       
   307             String streamContents:[:s |
       
   308                 nonMetaClass classVarNames do:[:eachClassVar |
       
   309                     initializer := 'nil'. "/ need more intelligence here (try to guess class from messages sent to it) ...
       
   310                     s nextPutLine:('    "/ %1 := %2.' bindWith:eachClassVar with:initializer).
       
   311                 ]
       
   312             ]).
       
   313 
       
   314         code := (self codeFor_classInitialize) expandPlaceholdersWith:bindings.
       
   315 
       
   316         self 
       
   317             compile:code
       
   318             forClass:metaClass 
       
   319             inCategory:'initialization'.
       
   320     ].
       
   321 
       
   322     self executeCollectedChangesNamed:('Add Class Initializer to ' , className).
       
   323 !
       
   324 
       
   325 createClassTypeTestMethodsIn:aClass forClasses:subClasses
       
   326     "create a #isXXX test methods (I'm tired of typing)"
       
   327 
       
   328     | code|
       
   329 
       
   330     self startCollectChanges.
       
   331 
       
   332     subClasses do:[:eachSubClass |
       
   333         |nm selector|
       
   334 
       
   335         nm := eachSubClass nameWithoutPrefix.
       
   336         selector := 'is' , nm.
       
   337         (aClass includesSelector:selector) ifFalse:[
       
   338             code := (selector , '\    ^ false') withCRs.
       
   339             self 
       
   340                 compile:code
       
   341                 forClass:aClass 
       
   342                 inCategory:'testing'.
       
   343         ].
       
   344         (eachSubClass includesSelector:selector) ifFalse:[
       
   345             code := (selector , '\    ^ true') withCRs.
       
   346             self 
       
   347                 compile:code
       
   348                 forClass:eachSubClass 
       
   349                 inCategory:'testing'.
       
   350         ].
       
   351     ].
       
   352 
       
   353     self executeCollectedChangesNamed:'Add ClassType Tests'
       
   354 !
       
   355 
       
   356 createEnumTypeCodeFor:aClass
       
   357     |nonMetaClass metaClass className enumValues code initCode runValue maxValue|
       
   358 
       
   359     self startCollectChanges.
       
   360 
       
   361     nonMetaClass := aClass theNonMetaclass.
       
   362     metaClass := aClass theMetaclass.
       
   363     className := nonMetaClass name.
       
   364 
       
   365     enumValues := nonMetaClass classVarNames.
       
   366     enumValues do:[:eachVariableName |
       
   367         self 
       
   368             createAccessMethodsFor:(Array with:eachVariableName)
       
   369             in:metaClass  
       
   370             withChange:false
       
   371             asValueHolder:false
       
   372             readersOnly:true    
       
   373             writersOnly:false
       
   374     ].
       
   375 
       
   376     maxValue := enumValues 
       
   377                     inject:0 
       
   378                     into:[:maxSoFar :eachVariableName | 
       
   379                             |oldVal val| 
       
   380                             oldVal := nonMetaClass classVarAt:eachVariableName.
       
   381                             oldVal notNil ifTrue:[ val := oldVal numericValue ].
       
   382                             (val ? maxSoFar) max:maxSoFar
       
   383                          ].
       
   384 
       
   385     initCode := WriteStream on: String new.
       
   386     initCode nextPutLine:'initialize'.
       
   387     runValue := maxValue + 1.
       
   388     enumValues keysAndValuesDo:[:idx :eachVariableName |
       
   389         |oldValue thisValue|
       
   390 
       
   391         oldValue := nonMetaClass classVarAt:eachVariableName.
       
   392         oldValue notNil ifTrue:[
       
   393             thisValue := oldValue numericValue.
       
   394         ] ifFalse:[
       
   395             thisValue := runValue.
       
   396             runValue := runValue + 1.
       
   397         ].
       
   398         initCode 
       
   399             nextPutAll:'    ';
       
   400             nextPutAll:eachVariableName;
       
   401             nextPutAll:' := self basicNew'.
       
   402         (aClass canUnderstand:#'setNumericValue:') ifTrue:[
       
   403             initCode nextPutAll:' setNumericValue: ',thisValue printString.
       
   404         ].
       
   405         (aClass canUnderstand:#'setCssClassString:') ifTrue:[
       
   406             initCode nextPutAll:('; setCssClassString: ''' , nonMetaClass nameWithoutPrefix asLowercaseFirst , eachVariableName , '''').
       
   407         ].
       
   408         (aClass canUnderstand:#'setName:') ifTrue:[
       
   409             initCode nextPutAll:('; setName: ''' , eachVariableName asLowercaseFirst , '''').
       
   410         ].
       
   411         initCode nextPutLine:'.'.
       
   412     ].
       
   413     initCode cr.
       
   414     initCode nextPutLine:'    "'.
       
   415     initCode nextPutLine:'     ',className, ' initialize'.
       
   416     initCode nextPutLine:'    "'.
       
   417 
       
   418     self
       
   419         compile:(initCode contents)
       
   420         forClass:metaClass 
       
   421         inCategory:'class initialization'.
       
   422 
       
   423 
       
   424     code := 'allStateNames\    ^ #( ' ,
       
   425                 ((enumValues collect:[:each | '#''',each asLowercaseFirst,'''']) asStringWith:' ') , ')',
       
   426                 '\\    "\' ,
       
   427                 '     ',className, ' allStateNames\' ,
       
   428                 '    "\'.
       
   429     self
       
   430         compile:code withCRs
       
   431         forClass:metaClass 
       
   432         inCategory:'queries'.
       
   433 
       
   434     self executeCollectedChangesNamed:('Generate EnumType Code for ' , className).
       
   435 
       
   436     aClass initialize.
       
   437 
       
   438     "Modified: / 1.2.1998 / 16:10:03 / cg"
       
   439 !
       
   440 
       
   441 createExamplesMethodForViewClass:aClass
       
   442     "create an examples method"
       
   443 
       
   444     |nonMetaClass metaClass className code|
       
   445 
       
   446     nonMetaClass := aClass theNonMetaclass.
       
   447     metaClass := aClass theMetaclass.
       
   448     className := nonMetaClass name.
       
   449 
       
   450     self startCollectChanges.
       
   451 
       
   452     (metaClass includesSelector:#examples) ifFalse:[
       
   453         code := 
       
   454 'examples
       
   455 "
       
   456  Notice that everything between [exBegin] and [exEnd] is extracted by the html-doc generator
       
   457  to create nicely formatted and clickable executable examples in the generated html-doc.
       
   458  (see the browsers class-documentation menu items for more)
       
   459 
       
   460  trying the widget as standAlone view:
       
   461                                                         [exBegin]
       
   462     %1 new open
       
   463                                                         [exEnd]
       
   464 
       
   465  embedded in another view:
       
   466                                                         [exBegin]
       
   467     |top v|
       
   468 
       
   469     top := StandardSystemView new.
       
   470     top extent:300@300.
       
   471     v := %1 new.
       
   472     v origin:10@10 corner:150@150.
       
   473     top add:v.
       
   474     top open
       
   475                                                         [exEnd]
       
   476 "
       
   477 ' bindWith:className.    
       
   478 
       
   479         self 
       
   480             compile:code
       
   481             forClass:metaClass 
       
   482             inCategory:'documentation'.
       
   483     ].
       
   484 
       
   485     self executeCollectedChangesNamed:('Add Example to ' , className).
       
   486 !
       
   487 
       
   488 createInitializationMethodIn:aClass
       
   489     "create a #initialize methods (I'm tired of typing)"
       
   490 
       
   491     |nonMetaClass metaClass className code initializer m|
       
   492 
       
   493     nonMetaClass := aClass theNonMetaclass.
       
   494     metaClass := aClass theMetaclass.
       
   495     className := nonMetaClass name.
       
   496 
       
   497     self startCollectChanges.
       
   498 
       
   499     (nonMetaClass includesSelector:#'initialize') ifFalse:[
       
   500         code :=
       
   501 'initialize
       
   502     "Invoked when a new instance is created."
       
   503 
       
   504     "/ please change as required (and remove this comment)
       
   505 '.
       
   506 
       
   507         nonMetaClass instVarNames do:[:eachInstVar |
       
   508             initializer := 'nil'. "/ need more intelligence here (try to guess class from messages sent to it) ...
       
   509             code := code , ('    "/ ' , eachInstVar , ' := ' , initializer , '.' , Character cr).
       
   510         ].
       
   511 
       
   512         m := nonMetaClass responseTo:#initialize.
       
   513         (m notNil and:[m messagesSent size == 0]) ifTrue:[
       
   514             "/ inherits an empty initialize.
       
   515 
       
   516             code := code , '
       
   517     "/ super initialize.   -- commented since inherited method does nothing
       
   518 '.
       
   519         ] ifFalse:[
       
   520             code := code , '
       
   521     super initialize.
       
   522 '.
       
   523         ].
       
   524 
       
   525         self 
       
   526             compile:code
       
   527             forClass:nonMetaClass 
       
   528             inCategory:'initialization'.
       
   529     ].
       
   530 
       
   531     self executeCollectedChangesNamed:('Add Initialized Instance Creation to ' , className).
       
   532 !
       
   533 
       
   534 createInitializedInstanceCreationMethodsIn:aClass
       
   535     "create a #new and #initialize methods (I'm tired of typing)"
       
   536 
       
   537     |nonMetaClass metaClass className code m|
       
   538 
       
   539     nonMetaClass := aClass theNonMetaclass.
       
   540     metaClass := aClass theMetaclass.
       
   541     className := nonMetaClass name.
       
   542 
       
   543     self startCollectChanges.
       
   544 
       
   545     self createInitializationMethodIn:aClass.
       
   546 
       
   547     (metaClass includesSelector:#'new') ifFalse:[
       
   548         m := metaClass responseTo:#new.
       
   549         (m isNil 
       
   550         or:[ (m sends:#initialize) not 
       
   551         or:[ 
       
   552             (Dialog 
       
   553                 confirmWithCancel:'The inherited #new method already seems to invoke #initialize. Redefine ?'
       
   554                 onCancel:[^ self]) ]]) ifTrue:[
       
   555             code :=
       
   556 'new
       
   557     "return an initialized instance"
       
   558 
       
   559     ^ self basicNew initialize.
       
   560 '.
       
   561             self 
       
   562                 compile:code
       
   563                 forClass:metaClass 
       
   564                 inCategory:'instance creation'.
       
   565         ].
       
   566     ].
       
   567 
       
   568     self executeCollectedChangesNamed:('Add Initialized Instance Creation to ' , className).
       
   569 
       
   570     "Created: / 11.10.2001 / 22:18:55 / cg"
       
   571 !
       
   572 
       
   573 createParametrizedInstanceCreationMethodsNamed:selector in:aClass
       
   574     "create a #selector instance creation method (I'm tired of typing)"
       
   575 
       
   576     |nonMetaClass metaClass className code initializer m dfn|
       
   577 
       
   578     dfn := Method methodDefinitionTemplateForSelector:selector.
       
   579 
       
   580     nonMetaClass := aClass theNonMetaclass.
       
   581     metaClass := aClass theMetaclass.
       
   582     className := nonMetaClass name.
       
   583 
       
   584     self startCollectChanges.
       
   585 
       
   586     (nonMetaClass includesSelector:selector asSymbol) ifFalse:[
       
   587         code :=
       
   588 'initialize',dfn asUppercaseFirst,'
       
   589     "Invoked when a new instance is created for arg."
       
   590 
       
   591     "/ please change as required (and remove these comments)
       
   592     "/ do something with arg here (instVar-foo := arg)
       
   593 '.
       
   594         nonMetaClass instVarNames do:[:eachInstVar |
       
   595             initializer := 'nil'. "/ need more intelligence here (try to guess class from messages sent to it) ...
       
   596             code := code , ('    "/ ' , eachInstVar , ' := ' , initializer , '.' , Character cr).
       
   597         ].
       
   598 
       
   599         m := nonMetaClass responseTo:#initialize.
       
   600         (m notNil and:[ m messagesSent size == 0 ]) ifTrue:[
       
   601             "/ inherits an empty initialize.
       
   602 
       
   603             code := code , '
       
   604     "/ super initialize.   -- commented since inherited method does nothing
       
   605 '.
       
   606         ] ifFalse:[
       
   607             code := code , '
       
   608     super initialize.  
       
   609 '.
       
   610         ].
       
   611 
       
   612         self 
       
   613             compile:code
       
   614             forClass:nonMetaClass 
       
   615             inCategory:'initialization'.
       
   616     ].
       
   617 
       
   618     (metaClass includesSelector:selector) ifFalse:[
       
   619         m := metaClass responseTo:selector.
       
   620         (m isNil 
       
   621         or:[ (Dialog confirmWithCancel:'The ',selector,'- method is already inherited. Redefine ?' onCancel:[^ self]) ])
       
   622         ifTrue:[
       
   623             code :=
       
   624 dfn,'
       
   625     "Create & return a new instance for arg."
       
   626 
       
   627     ^ self basicNew initialize',dfn asUppercaseFirst,'
       
   628 '.
       
   629             self 
       
   630                 compile:code
       
   631                 forClass:metaClass 
       
   632                 inCategory:'instance creation'.
       
   633         ].
       
   634     ].
       
   635 
       
   636     self executeCollectedChangesNamed:('Add Parametrized Instance Creation to ' , className).
       
   637 !
       
   638 
       
   639 createPoolInitializationCodeFor:aClass
       
   640     |nonMetaClass metaClass className poolVars code initCode runValue maxValue|
       
   641 
       
   642     self startCollectChanges.
       
   643 
       
   644     nonMetaClass := aClass theNonMetaclass.
       
   645     metaClass := aClass theMetaclass.
       
   646     className := nonMetaClass name.
       
   647 
       
   648     poolVars := nonMetaClass classVarNames.
       
   649 
       
   650     initCode := WriteStream on: String new.
       
   651     initCode nextPutLine:'initialize'.
       
   652 
       
   653     poolVars do:[:eachVariableName |
       
   654         |oldValue thisValue|
       
   655 
       
   656         oldValue := nonMetaClass classVarAt:eachVariableName.
       
   657         oldValue notNil ifTrue:[
       
   658             thisValue := oldValue.
       
   659         ] ifFalse:[
       
   660             thisValue := nil.
       
   661         ].
       
   662         initCode 
       
   663             nextPutAll:'    ';
       
   664             nextPutAll:eachVariableName;
       
   665             nextPutAll:' := ';
       
   666             nextPutAll:thisValue storeString;
       
   667             nextPutLine:'.'.
       
   668     ].
       
   669     initCode cr.
       
   670     initCode nextPutLine:'    "'.
       
   671     initCode nextPutLine:'     ',className, ' initialize'.
       
   672     initCode nextPutLine:'    "'.
       
   673 
       
   674     self
       
   675         compile:(initCode contents)
       
   676         forClass:metaClass 
       
   677         inCategory:'class initialization'.
       
   678 
       
   679     self executeCollectedChangesNamed:('Generate Pool Initialization Code for ' , className).
       
   680 
       
   681     aClass initialize.
       
   682 
       
   683     "Created: / 25-10-2006 / 09:28:40 / cg"
       
   684 !
       
   685 
       
   686 createRedefinedInstanceCreationMethodsIn:aClass
       
   687     "create a redefined #new methods"
       
   688 
       
   689     |nonMetaClass metaClass className code|
       
   690 
       
   691     nonMetaClass := aClass theNonMetaclass.
       
   692     metaClass := aClass theMetaclass.
       
   693     className := nonMetaClass name.
       
   694 
       
   695     self startCollectChanges.
       
   696 
       
   697     (metaClass includesSelector:#'new') ifFalse:[
       
   698         code :=
       
   699 'new
       
   700     ^ super new.
       
   701 '.
       
   702         self 
       
   703             compile:code
       
   704             forClass:metaClass 
       
   705             inCategory:'redefined instance creation'.
       
   706     ].
       
   707     (metaClass includesSelector:#'new:') ifFalse:[
       
   708         code :=
       
   709 'new:n
       
   710     ^ super new:n.
       
   711 '.
       
   712         self 
       
   713             compile:code
       
   714             forClass:metaClass 
       
   715             inCategory:'redefined instance creation'.
       
   716     ].
       
   717 
       
   718     self executeCollectedChangesNamed:('Redefined Instance Creation to ' , className).
       
   719 !
       
   720 
       
   721 createStandardPrintOnMethodIn:aClass
       
   722     "create a #printOn: method (I'm tired of typing)"
       
   723 
       
   724     |code nonMetaClass|
       
   725 
       
   726     nonMetaClass := aClass theNonMetaclass.
       
   727 
       
   728     self startCollectChanges.
       
   729 
       
   730     (nonMetaClass includesSelector:#'printOn:') ifFalse:[
       
   731         code :=
       
   732 'printOn:aStream
       
   733     "append a printed representation if the receiver to the argument, aStream"
       
   734 
       
   735     super printOn:aStream.
       
   736 '.
       
   737         nonMetaClass instVarNames do:[:eachInstVarName |
       
   738             code := code , '    '.
       
   739             code := code , 'aStream nextPutAll:'''.
       
   740             code := code , eachInstVarName.
       
   741             code := code , ': ''.' , Character cr.
       
   742             code := code , '    '.
       
   743             code := code , eachInstVarName.
       
   744             code := code , ' printOn:aStream.' , Character cr.
       
   745         
       
   746         ].
       
   747 
       
   748         self 
       
   749             compile:code
       
   750             forClass:nonMetaClass 
       
   751             inCategory:'printing & storing'.
       
   752     ].
       
   753 
       
   754 
       
   755     self executeCollectedChangesNamed:('Add #printOn: to ' , nonMetaClass name).
       
   756 
       
   757     "Created: / 11.10.2001 / 22:18:55 / cg"
       
   758 !
       
   759 
       
   760 createStartupCodeFor:aClass forStartOf:anApplicationClassOrNil
       
   761     "create startup code (main)"
       
   762 
       
   763     |nonMetaClass metaClass className source 
       
   764      hasAplicationClass anApplicationClassNameOrStartupClassName|
       
   765 
       
   766     self startCollectChanges.
       
   767 
       
   768     hasAplicationClass := anApplicationClassOrNil notNil.
       
   769     nonMetaClass := aClass theNonMetaclass.
       
   770     metaClass := aClass theMetaclass.
       
   771     className := nonMetaClass name.
       
   772 
       
   773     (metaClass includesSelector:#main:) ifFalse:[
       
   774 
       
   775         source := String streamContents:[:stream |
       
   776             stream nextPutAll: 
       
   777 'main:argv
       
   778     self verboseInfo:''starting %1''.
       
   779 
       
   780 '.
       
   781             hasAplicationClass ifTrue: [
       
   782                 stream nextPutAll: 
       
   783 '    Smalltalk openDisplay.
       
   784     Display notNil ifTrue:[
       
   785         Display exitOnLastClose:true.
       
   786     ].
       
   787     %1 open.
       
   788 '.
       
   789             ].
       
   790         ].
       
   791 
       
   792         anApplicationClassNameOrStartupClassName := hasAplicationClass 
       
   793             ifTrue: [anApplicationClassOrNil name]
       
   794             ifFalse: [className.].
       
   795         self
       
   796             compile:(source bindWith:anApplicationClassNameOrStartupClassName)
       
   797             forClass:metaClass 
       
   798             inCategory:'startup'.
       
   799     ].
       
   800     self executeCollectedChangesNamed:('Add Startup Code to ' , className).
       
   801 !
       
   802 
       
   803 createTestCaseSampleCodeFor:aClass
       
   804     "create an (almost) empty testCase class"
       
   805 
       
   806     |nonMetaClass metaClass|
       
   807 
       
   808     nonMetaClass := aClass theNonMetaclass.
       
   809     metaClass := aClass theMetaclass.
       
   810     "/ className := nonMetaClass name.
       
   811 
       
   812     ( nonMetaClass includesSelector:#test1 ) ifFalse:[
       
   813         self
       
   814             compile:
       
   815 'test1
       
   816     "This is a demonstration testCase - it is meant to be removed eventually.
       
   817      This testCase will PASS.
       
   818      Double click on the TestCase class or open a TestRunner to see me checking...
       
   819      - please add more methods like this..."
       
   820 
       
   821     |o|
       
   822 
       
   823     o := Array new:2.
       
   824     self assert: ( o size == 2 ).
       
   825     self should: [ o at:0 ] raise:Error.
       
   826     self shouldnt: [ o at:1 ] raise:Error.
       
   827 
       
   828     "
       
   829      self run:#test1
       
   830      self new test1
       
   831     "
       
   832 '
       
   833             forClass:nonMetaClass 
       
   834             inCategory:'tests'.
       
   835     ].
       
   836 
       
   837     ( nonMetaClass includesSelector:#test2 ) ifFalse:[
       
   838         self
       
   839             compile:
       
   840 'test2
       
   841     "This is a demonstration testCase - it is meant to be removed eventually..
       
   842      This testCase WILL FAIL.
       
   843      Double click on the TestCase class or open a TestRunner to see me checking...
       
   844      - please add more methods like this..."
       
   845 
       
   846     |o|
       
   847 
       
   848     o := Array new:2.
       
   849     self assert: ( o size == 3 ).
       
   850 
       
   851     "
       
   852      self run:#test2
       
   853      self new test2
       
   854     "
       
   855 '
       
   856             forClass:nonMetaClass 
       
   857             inCategory:'tests'.
       
   858     ].
       
   859 
       
   860     ( nonMetaClass includesSelector:#test3 ) ifFalse:[
       
   861         self
       
   862             compile:
       
   863 'test3
       
   864     "This is a demonstration testCase - it is meant to be removed eventually..
       
   865      This testCase WILL generate an ERROR.
       
   866      Double click on the TestCase class or open a TestRunner to see me checking...
       
   867      - please add more methods like this..."
       
   868 
       
   869     |o|
       
   870 
       
   871     o := Array new:2.
       
   872     self assert: ( o foo ).
       
   873 
       
   874     "
       
   875      self run:#test3
       
   876      self new test3
       
   877     "
       
   878 '
       
   879             forClass:nonMetaClass 
       
   880             inCategory:'tests'.
       
   881     ].
       
   882 
       
   883     ( nonMetaClass includesSelector:#setUp ) ifFalse:[
       
   884         self
       
   885             compile:
       
   886 'setUp
       
   887     "common setup - invoked before testing."
       
   888 
       
   889     super setUp
       
   890 '
       
   891             forClass:nonMetaClass 
       
   892             inCategory:'initialize / release'.
       
   893     ].
       
   894 
       
   895     ( nonMetaClass includesSelector:#tearDown ) ifFalse:[
       
   896         self
       
   897             compile:
       
   898 'tearDown
       
   899     "common cleanup - invoked after testing."
       
   900 
       
   901     super tearDown
       
   902 '
       
   903             forClass:nonMetaClass 
       
   904             inCategory:'initialize / release'.
       
   905     ]
       
   906 !
       
   907 
       
   908 createVisitorMethodsIn:visitedClass andVisitorClass:visitorClass
       
   909     "create acceptVisitor: in visitedClass and acceptXXX in visitorClass. (I'm tired of typing)"
       
   910 
       
   911     |sel|
       
   912 
       
   913     self assert:( visitedClass isMeta not ).
       
   914     self assert:( visitorClass isMeta not ).
       
   915 
       
   916     self startCollectChanges.
       
   917 
       
   918     sel := ('visit' , visitedClass nameWithoutPrefix , ':').
       
   919     self createAcceptVisitorMethod:sel in:visitedClass.
       
   920 
       
   921     (visitorClass includesSelector:sel) ifFalse:[
       
   922         self 
       
   923             compile:
       
   924 (('%1anObject 
       
   925     "dispatched back from the visited %2-object (visitor pattern)"
       
   926 
       
   927     "fall back to general object-case - please change as required"
       
   928 
       
   929     ^ self visitObject:anObject
       
   930 ') bindWith:sel with:visitedClass nameWithoutPrefix asLowercaseFirst)
       
   931             forClass:visitorClass 
       
   932             inCategory:'visiting'.
       
   933     ].
       
   934 
       
   935     (visitorClass includesSelector:#'visitObject:') ifFalse:[
       
   936         self 
       
   937             compile:
       
   938 ('visitObject:anObject 
       
   939     "dispatched back from the visited objects (visitor pattern)"
       
   940 
       
   941     "general fallBack - please change as required"
       
   942 
       
   943     self halt:''not yet implemented''
       
   944 ')
       
   945             forClass:visitorClass 
       
   946             inCategory:'visiting'.
       
   947     ].
       
   948 
       
   949     (visitorClass includesSelector:#'visit:') ifFalse:[
       
   950         self 
       
   951             compile:
       
   952 ('visit:anObject 
       
   953     "visit anObject (visitor pattern).
       
   954      The object should call back one of my visitXXXX methods."
       
   955 
       
   956     ^ anObject acceptVisitor:self
       
   957 ')
       
   958             forClass:visitorClass 
       
   959             inCategory:'visiting'.
       
   960     ].
       
   961 
       
   962     self executeCollectedChangesNamed:('Add Visitor Pattern').
       
   963 !
       
   964 
       
   965 createWebApplicationCodeFor:aClass
       
   966     "create an empty webApplication framework"
       
   967 
       
   968     |nonMetaClass metaClass className txt|
       
   969 
       
   970     self startCollectChanges.
       
   971 
       
   972     nonMetaClass := aClass theNonMetaclass.
       
   973     metaClass := aClass theMetaclass.
       
   974     className := nonMetaClass name.
       
   975 
       
   976     (metaClass includesSelector:#pageSpec) ifFalse:[
       
   977         txt := self class initialPageSpecMethodSourceForWebApplications.
       
   978         self
       
   979             compile:(txt bindWith:className)
       
   980             forClass:metaClass 
       
   981             inCategory:'page specs'.
       
   982     ].
       
   983 
       
   984     self executeCollectedChangesNamed:('Add WebApplication Code for ' , className).
       
   985 
       
   986     "Modified: / 1.2.1998 / 16:10:03 / cg"
       
   987 !
       
   988 
       
   989 createWebServiceCodeFor:aClass
       
   990     "create an empty webService framework"
       
   991 
       
   992     |nonMetaClass metaClass className txt|
       
   993 
       
   994     self startCollectChanges.
       
   995 
       
   996     nonMetaClass := aClass theNonMetaclass.
       
   997     metaClass := aClass theMetaclass.
       
   998     className := nonMetaClass name.
       
   999 
       
  1000     (nonMetaClass includesSelector:#process:) ifFalse:[
       
  1001         txt :=
       
  1002 'process:aRequest
       
  1003     "This is the web services main processing method.
       
  1004      It will be invoked for every incoming webBrowser-request.
       
  1005      The argument, aRequest contains the parameters (url, fields, parameters etc.)."
       
  1006 
       
  1007     |response|
       
  1008 
       
  1009     response := aRequest response.
       
  1010     response nextPutLine:''<HTML>''.
       
  1011     response nextPutLine:''  <HEAD>''.
       
  1012     response nextPutLine:''  <TITLE>Hello</TITLE>''.
       
  1013     response nextPutLine:''  </HEAD>''.
       
  1014     response nextPutLine:''  <BODY>''.
       
  1015     response nextPutLine:''    <H1>Hello World !!</H1>''.
       
  1016     response nextPutLine:''  </BODY>''.
       
  1017     response nextPutLine:''</HTML>''.
       
  1018 '.
       
  1019         self
       
  1020             compile:txt
       
  1021             forClass:nonMetaClass 
       
  1022             inCategory:'response generation'.
       
  1023     ].
       
  1024 
       
  1025     (metaClass includesSelector:#linkName) ifFalse:[
       
  1026         txt :=
       
  1027 'linkName
       
  1028     "return the default linkName path (with slash)."
       
  1029 
       
  1030     ^ ''/NewService''
       
  1031 '.
       
  1032         self
       
  1033             compile:txt
       
  1034             forClass:metaClass 
       
  1035             inCategory:'defaults'.
       
  1036     ].
       
  1037 
       
  1038     (metaClass includesSelector:#settingsApplicationClass) ifFalse:[
       
  1039         txt :=
       
  1040 'settingsApplicationClass
       
  1041     "a SettingsApplication class - or nil (used in the settings dialog if non-nil)."
       
  1042 
       
  1043     ^ nil
       
  1044 '.
       
  1045         self
       
  1046             compile:txt
       
  1047             forClass:metaClass 
       
  1048             inCategory:'defaults'.
       
  1049     ].
       
  1050 
       
  1051 
       
  1052     self executeCollectedChangesNamed:('Add WebService Code for ' , className).
       
  1053 
       
  1054     "Modified: / 1.2.1998 / 16:10:03 / cg"
       
  1055 !
       
  1056 
       
  1057 createWidgetCodeFor:aClass
       
  1058     "create usually required widget code (redraw, model update, event handling)"
       
  1059 
       
  1060     |nonMetaClass metaClass className compileTemplateAction|
       
  1061 
       
  1062     self startCollectChanges.
       
  1063 
       
  1064     nonMetaClass := aClass theNonMetaclass.
       
  1065     metaClass := aClass theMetaclass.
       
  1066     className := nonMetaClass name.
       
  1067 
       
  1068     compileTemplateAction := 
       
  1069         [:selector :templateSelector :category |
       
  1070             (nonMetaClass includesSelector:selector) ifFalse:[
       
  1071                 |txt|
       
  1072 
       
  1073                 txt := self perform:templateSelector.
       
  1074                 self
       
  1075                     compile:txt
       
  1076                     forClass:nonMetaClass 
       
  1077                     inCategory:category.
       
  1078             ]
       
  1079         ].
       
  1080 
       
  1081     #(
       
  1082         #'initialize'               #code_forWidget_initialize  'initialization & release'
       
  1083         #'update:with:from:'        #code_forWidget_update      'change & update'
       
  1084         #'redrawX:y:width:height:'  #code_forWidget_redraw      'drawing'
       
  1085         #'buttonPress:x:y:'         #code_forWidget_buttonPress 'event handling'
       
  1086         #'keyPress:x:y:'            #code_forWidget_keyPress    'event handling'
       
  1087         #'sizeChanged:'             #code_forWidget_sizeChanged 'event handling'
       
  1088     ) inGroupsOf:3 do:compileTemplateAction.
       
  1089 
       
  1090     self executeCollectedChangesNamed:('Add Widget Code for ' , className).
       
  1091 ! !
       
  1092 
       
  1093 !SmalltalkCodeGeneratorTool methodsFor:'code generation-basic'!
       
  1094 
       
  1095 createAccessMethodsFor:aCollectionOfVarNames in:aClass withChange:withChange asValueHolder:asValueHolder readersOnly:readersOnly writersOnly:writersOnly lazyInitialization:lazyInitialization
       
  1096     "workhorse for creating access methods for instvars."
       
  1097 
       
  1098     |classesClassVars generateCommentsForSetters generateCommentsForGetters|
       
  1099 
       
  1100     self startCollectChanges.
       
  1101 
       
  1102     generateCommentsForSetters := userPreferences generateCommentsForSetters.
       
  1103     generateCommentsForGetters := userPreferences generateCommentsForGetters.
       
  1104 
       
  1105     classesClassVars := aClass theNonMetaclass allClassVarNames.
       
  1106 
       
  1107     aCollectionOfVarNames do:[:name |
       
  1108         |source varType methodName defaultMethodName argName|
       
  1109 
       
  1110         varType := (classesClassVars includes:name) 
       
  1111                         ifTrue:['static'] 
       
  1112                         ifFalse:[
       
  1113                             (aClass isMeta ifTrue:['classInstVar'] ifFalse:['instance'])].
       
  1114 
       
  1115         methodName := name.
       
  1116         name isUppercaseFirst ifTrue:[
       
  1117             methodName := methodName asLowercaseFirst. 
       
  1118         ].
       
  1119         argName := 'something'.
       
  1120 
       
  1121         "/ the GETTER
       
  1122         writersOnly ifFalse:[
       
  1123             lazyInitialization ifTrue:[
       
  1124                 defaultMethodName := 'default' , name asUppercaseFirst.
       
  1125             ].
       
  1126 
       
  1127             "check, if method is not already present"
       
  1128             (aClass includesSelector:(methodName asSymbol)) ifFalse:[
       
  1129                 asValueHolder ifTrue:[
       
  1130                     source := methodName , '\'.
       
  1131                     generateComments ifTrue:[
       
  1132                         source := source , '    "return/create the ''%2'' value holder (automatically generated)"\\'. 
       
  1133                     ].
       
  1134                     source := source , '    %2 isNil ifTrue:[\'.
       
  1135                     lazyInitialization ifTrue:[
       
  1136                         source := source
       
  1137                                    , '        %2 := self class %3 asValue.\'.
       
  1138                     ] ifFalse:[
       
  1139                         source := source
       
  1140                                    , '        %2 := ValueHolder new.\'.
       
  1141                     ].
       
  1142 
       
  1143                     withChange ifTrue:[
       
  1144                     source := source
       
  1145                                , '        %2 addDependent:self.\'.
       
  1146                     ].
       
  1147                     source := source
       
  1148                                , '    ].\'
       
  1149                                , '    ^ %2'.
       
  1150                 ] ifFalse:[
       
  1151                     source := methodName , '\'.
       
  1152                     lazyInitialization ifTrue:[
       
  1153                         generateCommentsForGetters ifTrue:[
       
  1154                             source := source , '    "return the %1 instance variable ''%2'' with lazy instance creation (automatically generated)"\\'. 
       
  1155                         ].
       
  1156                         source := source
       
  1157                                     , '    %2 isNil ifTrue:[\'
       
  1158                                     , '        %2 := self class %3.\'
       
  1159                                     , '    ].\'
       
  1160                                     , '    ^ %2'.
       
  1161                     ] ifFalse:[
       
  1162                         generateCommentsForGetters ifTrue:[
       
  1163                             source := source , '    "return the %1 instance variable ''%2'' (automatically generated)"\\'. 
       
  1164                         ].
       
  1165                         source := source
       
  1166                                     , '    ^ %2'.
       
  1167                     ].
       
  1168                 ].
       
  1169                 source := (source bindWith:varType with:name with:defaultMethodName) withCRs.
       
  1170                 self compile:source forClass:aClass inCategory:(asValueHolder ifTrue:['aspects'] ifFalse:['accessing']).
       
  1171             ] ifTrue:[
       
  1172                 Transcript showCR:'method ''', methodName , ''' already present'
       
  1173             ].
       
  1174 
       
  1175             "/ default for lazy on class side
       
  1176             lazyInitialization ifTrue:[
       
  1177                 (aClass theMetaclass includesSelector:(defaultMethodName asSymbol)) ifFalse:[
       
  1178                     source := defaultMethodName , '\'.
       
  1179                     generateComments ifTrue:[
       
  1180                         source := source , '    "default value for the ''%2'' instance variable (automatically generated)"\\'. 
       
  1181                     ].
       
  1182                     source := source    
       
  1183                                , '    self shouldImplement.\'
       
  1184                                , '    ^ nil.'.
       
  1185                     source := (source bindWith:varType with:name) withCRs.
       
  1186                     self compile:source forClass:aClass theMetaclass inCategory:'defaults'.
       
  1187                 ].
       
  1188             ].
       
  1189         ].
       
  1190 
       
  1191         "/ the SETTER
       
  1192         readersOnly ifFalse:[
       
  1193             (aClass includesSelector:((methodName , ':') asSymbol)) ifFalse:[
       
  1194                 ((methodName size > 2) and:[ (methodName startsWith:'is') and:[ (methodName at:3) isUppercase ]])
       
  1195                 ifTrue:[
       
  1196                     argName := 'aBoolean'
       
  1197                 ].
       
  1198                 asValueHolder ifTrue:[
       
  1199                     source := methodName , ':%3\'.  "/ argName
       
  1200                     generateComments ifTrue:[
       
  1201                         source := source , '    "set the ''%2'' value holder' , ' (automatically generated)"\\'.
       
  1202                     ].
       
  1203                     withChange ifTrue:[
       
  1204                         source := source
       
  1205                                   , '    |oldValue newValue|\\'
       
  1206                                   , '    %2 notNil ifTrue:[\'
       
  1207                                   , '        oldValue := %2 value.\'
       
  1208                                   , '        %2 removeDependent:self.\'
       
  1209                                   , '    ].\'
       
  1210                                   , '    %2 := %3.\'        "/ argName
       
  1211                                   , '    %2 notNil ifTrue:[\'
       
  1212                                   , '        %2 addDependent:self.\'
       
  1213                                   , '    ].\'
       
  1214                                   , '    newValue := %2 value.\'
       
  1215                                   , '    oldValue ~~ newValue ifTrue:[\'
       
  1216                                   , '        self update:#value with:newValue from:%2.\'
       
  1217                                   , '    ].\'
       
  1218                     ] ifFalse:[
       
  1219                         source := source 
       
  1220                                   , '    %2 := %3.'.  "/ argName
       
  1221                     ].
       
  1222                 ] ifFalse:[
       
  1223                     source := methodName , ':%3\'.    "/ argName
       
  1224                     withChange ifTrue:[
       
  1225                         generateComments ifTrue:[
       
  1226                             source := source , '    "set the value of the %1 variable ''%2'''.
       
  1227                             source := source , ' and send a change notification (automatically generated)"\\'.
       
  1228                         ].
       
  1229                         source := source
       
  1230                                   , '    (%2 ~~ %3) ifTrue:[\'
       
  1231                                   , '        %2 := %3.\'           "/ argName
       
  1232                                   , '        self changed:#%2.\'
       
  1233                                   , '     ].\'.
       
  1234                     ] ifFalse:[
       
  1235                         generateCommentsForSetters ifTrue:[
       
  1236                             source := source , '    "set the value of the %1 variable ''%2'''.
       
  1237                             source := source , ' (automatically generated)"\\'.
       
  1238                         ].
       
  1239                         source := source
       
  1240                                   , '    %2 := %3.'.          "/ argName
       
  1241                     ].
       
  1242                 ].
       
  1243                 source := (source bindWith:varType with:name with:argName) withCRs.
       
  1244                 self 
       
  1245                     compile:source 
       
  1246                     forClass:aClass 
       
  1247                     inCategory:(asValueHolder ifTrue:['aspects'] ifFalse:['accessing']).
       
  1248             ] ifTrue:[
       
  1249                 Transcript showCR:'method ''', methodName , ':'' already present'
       
  1250             ].
       
  1251         ].
       
  1252     ].
       
  1253 
       
  1254     self executeCollectedChangesNamed:('Add Accessors').
       
  1255 !
       
  1256 
       
  1257 createCollectionAccessMethodsFor:aCollectionOfVarNames in:aClass withChange:withChange
       
  1258     |classesClassVars|
       
  1259 
       
  1260     self startCollectChanges.
       
  1261 
       
  1262     classesClassVars := aClass theNonMetaclass allClassVarNames.
       
  1263 
       
  1264     aCollectionOfVarNames do:[:name |
       
  1265         |source varType methodNameBase methodName defaultMethodName|
       
  1266 
       
  1267         varType := (classesClassVars includes:name) 
       
  1268                         ifTrue:['static'] 
       
  1269                         ifFalse:[
       
  1270                             (aClass isMeta ifTrue:['classInstVar'] ifFalse:['instance'])].
       
  1271 
       
  1272         methodNameBase := name asUppercaseFirst.
       
  1273         (methodNameBase endsWith:'s') ifTrue:[
       
  1274             methodNameBase := methodNameBase copyWithoutLast:1.
       
  1275         ].
       
  1276         methodName := 'add' , methodNameBase, ':'. 
       
  1277 
       
  1278         "check, if method is not already present"
       
  1279         (aClass includesSelector:(methodName asSymbol)) ifFalse:[
       
  1280             source := methodName , 'a%1\'.
       
  1281             generateComments ifTrue:[
       
  1282                 source := source , '    "add a ',methodNameBase,'"\\'. 
       
  1283             ].
       
  1284             source := source , '    %2 isNil ifTrue:[\'.
       
  1285                 source := source
       
  1286                            , '        %2 := OrderedCollection new.\'.
       
  1287             source := source
       
  1288                        , '    ].\'
       
  1289                        , '    %2 add: a%1'.
       
  1290             source := (source bindWith:methodNameBase with:name) withCRs.
       
  1291             self compile:source forClass:aClass inCategory:'accessing'.
       
  1292         ] ifTrue:[
       
  1293             Transcript showCR:'method ''', methodName , ''' already present'
       
  1294         ].
       
  1295 
       
  1296         methodName := 'remove' , methodNameBase, ':'. 
       
  1297 
       
  1298         "check, if method is not already present"
       
  1299         (aClass includesSelector:(methodName asSymbol)) ifFalse:[
       
  1300             source := methodName , 'a%1\'.
       
  1301             generateComments ifTrue:[
       
  1302                 source := source , '    "remove a ',methodNameBase,'"\\'. 
       
  1303             ].
       
  1304             source := source
       
  1305                        , '    %2 remove: a%1'.
       
  1306             source := (source bindWith:methodNameBase with:name) withCRs.
       
  1307             self compile:source forClass:aClass inCategory:'accessing'.
       
  1308         ] ifTrue:[
       
  1309             Transcript showCR:'method ''', methodName , ''' already present'
       
  1310         ].
       
  1311     ].
       
  1312 
       
  1313     self
       
  1314         createAccessMethodsFor:aCollectionOfVarNames 
       
  1315         in:aClass 
       
  1316         withChange:withChange 
       
  1317         asValueHolder:false
       
  1318         readersOnly:true
       
  1319         writersOnly:false
       
  1320         lazyInitialization:false.
       
  1321 
       
  1322     self executeCollectedChangesNamed:('Add Collection Access').
       
  1323 
       
  1324     "Created: / 04-02-2007 / 15:52:31 / cg"
       
  1325 !
       
  1326 
       
  1327 createValueHoldersFor:aCollectionOfVarNames in:aClass lazyInitialization:lazyInitialization
       
  1328     "workhorse for creating access methods for instvars."
       
  1329 
       
  1330     |nonMetaClass metaClass classesClassVars generateCommentsForSetters generateCommentsForGetters|
       
  1331 
       
  1332     nonMetaClass := aClass theNonMetaclass.
       
  1333     metaClass := aClass theMetaclass.
       
  1334 
       
  1335     self startCollectChanges.
       
  1336 
       
  1337     generateCommentsForSetters := userPreferences generateCommentsForSetters.
       
  1338     generateCommentsForGetters := userPreferences generateCommentsForGetters.
       
  1339 
       
  1340     classesClassVars := nonMetaClass allClassVarNames.
       
  1341 
       
  1342     aCollectionOfVarNames do:[:name |
       
  1343         |source varType methodName holderMethodName defaultMethodName|
       
  1344 
       
  1345         holderMethodName := name.
       
  1346         name isUppercaseFirst ifTrue:[
       
  1347             holderMethodName := holderMethodName asLowercaseFirst. 
       
  1348         ].
       
  1349         (holderMethodName endsWith:'Holder') ifTrue:[
       
  1350             methodName := holderMethodName copyWithoutLast:6.
       
  1351         ] ifFalse:[
       
  1352             methodName := holderMethodName.
       
  1353             holderMethodName := methodName , 'Holder'.
       
  1354         ].
       
  1355 
       
  1356         methodName notNil ifTrue:[
       
  1357             (metaClass includesSelector:(methodName asSymbol)) ifFalse:[
       
  1358                 source := '%1\'.
       
  1359                 generateComments ifTrue:[
       
  1360                     source := source , '    "return the value in ''%2''"\\'. 
       
  1361                 ].
       
  1362                 source := source , '    ^ self %2 value'.
       
  1363                 source := (source bindWith:methodName with:holderMethodName) withCRs.
       
  1364                 self compile:source forClass:nonMetaClass inCategory:('accessing').
       
  1365             ] ifTrue:[
       
  1366                 Transcript showCR:'method ''', methodName , ''' already present'
       
  1367             ].
       
  1368 
       
  1369             (metaClass includesSelector:((methodName , ':') asSymbol)) ifFalse:[
       
  1370                 source := '%1: newValue\'.
       
  1371                 generateComments ifTrue:[
       
  1372                     source := source , '    "set the value in ''%2''"\\'. 
       
  1373                 ].
       
  1374                 source := source , '    self %2 value: newValue'.
       
  1375                 source := (source bindWith:methodName with:holderMethodName) withCRs.
       
  1376                 self compile:source forClass:nonMetaClass inCategory:('accessing').
       
  1377             ] ifTrue:[
       
  1378                 Transcript showCR:'method ''', methodName , ':'' already present'
       
  1379             ].
       
  1380         ].
       
  1381         (metaClass includesSelector:(holderMethodName asSymbol)) ifFalse:[
       
  1382             source := '%1\'.
       
  1383             generateComments ifTrue:[
       
  1384                 source := source , '    "return/create the valueHolder ''%1''"\\'. 
       
  1385             ].
       
  1386             source := source , '    %1 isNil ifTrue:[\'.
       
  1387             source := source , '        %1 := ValueHolder with:nil "defaultValue here".\'.
       
  1388             source := source , '    ].\'.
       
  1389             source := source , '    ^ %1\'.
       
  1390             source := (source bindWith:holderMethodName) withCRs.
       
  1391             self compile:source forClass:nonMetaClass inCategory:('accessing').
       
  1392         ] ifTrue:[
       
  1393             Transcript showCR:'method ''', methodName , ''' already present'
       
  1394         ].
       
  1395     ].
       
  1396 
       
  1397     self executeCollectedChangesNamed:('Add ValueHolder').
       
  1398 ! !
       
  1399 
       
  1400 !SmalltalkCodeGeneratorTool methodsFor:'code generation-individual methods'!
       
  1401 
       
  1402 createAcceptVisitorMethod:selector in:aClass
       
  1403     "create an acceptVisitor: method
       
  1404      (I'm tired of typing)"
       
  1405 
       
  1406     self assert:( aClass isMeta not ).
       
  1407 
       
  1408     (aClass includesSelector:#'acceptVisitor:') ifFalse:[
       
  1409         self 
       
  1410             compile:
       
  1411 (('acceptVisitor:aVisitor 
       
  1412     "Double dispatch back to the visitor, passing my type encoded in
       
  1413      the selector (visitor pattern)"
       
  1414 
       
  1415     "stub code automatically generated - please change if required"
       
  1416 
       
  1417     ^ aVisitor %1self
       
  1418 ') bindWith:selector)
       
  1419             forClass:aClass 
       
  1420             inCategory:'visiting'.
       
  1421     ]
       
  1422 !
       
  1423 
       
  1424 createAcceptVisitorMethodIn:aClass
       
  1425     "create an acceptVisitor: method
       
  1426      (I'm tired of typing)"
       
  1427 
       
  1428     self
       
  1429         createAcceptVisitorMethod:('visit' , aClass nameWithoutPrefix , ':') asSymbol
       
  1430         in:aClass
       
  1431 !
       
  1432 
       
  1433 createCopyrightMethodFor:copyRightText for:aClass
       
  1434     "add copyright method containing text,
       
  1435      but only if not already present."
       
  1436 
       
  1437     |txt|
       
  1438 
       
  1439     (aClass includesSelector:#copyright) ifFalse:[
       
  1440         copyRightText notNil ifTrue:[
       
  1441             txt := copyRightText bindWith:(Date today year).
       
  1442             self compile:
       
  1443 'copyright
       
  1444 "
       
  1445 ' , txt , '
       
  1446 "
       
  1447 '             forClass:aClass 
       
  1448               inCategory:'documentation'.
       
  1449         ]
       
  1450     ].
       
  1451 !
       
  1452 
       
  1453 createDocumentationMethodFor:aClass
       
  1454     "add documentation method containing doc template
       
  1455      but only if not already present."
       
  1456 
       
  1457     |metaClass nonMetaClass userName loginName hostName emailAddress code existingComment|
       
  1458 
       
  1459     metaClass := aClass theMetaclass.
       
  1460     nonMetaClass := aClass theNonMetaclass.
       
  1461 
       
  1462     (metaClass includesSelector:#documentation) ifFalse:[
       
  1463         existingComment := nonMetaClass comment.
       
  1464         existingComment isEmptyOrNil ifTrue:[
       
  1465             (nonMetaClass isSubclassOf:HTTPService) ifTrue:[
       
  1466                 existingComment := '    [start Server with:]
       
  1467         HTTPServer startServerOnPort:8080
       
  1468 
       
  1469     [start with:]
       
  1470         (self new)
       
  1471             registerServiceOn:(HTTPServer runningServerOnPort:8080)'.
       
  1472             ].
       
  1473         ].
       
  1474 
       
  1475         userName := OperatingSystem getFullUserName.
       
  1476         loginName := OperatingSystem getLoginName.
       
  1477         hostName := OperatingSystem getHostName.
       
  1478         emailAddress := loginName , '@' , hostName.
       
  1479 
       
  1480         "/ ugly; should ask the class for that    
       
  1481         metaClass isJavaScriptMetaclass ifTrue:[
       
  1482             code :=
       
  1483 'function documentation() {
       
  1484 /*
       
  1485 ' , (existingComment ? '    documentation to be added.') , '
       
  1486 
       
  1487     [author:]
       
  1488         ' , userName 
       
  1489           , ' (' , emailAddress , ')' , '
       
  1490 
       
  1491     [instance variables:]
       
  1492 
       
  1493     [class variables:]
       
  1494 
       
  1495     [see also:]
       
  1496 
       
  1497 */
       
  1498 }
       
  1499 '
       
  1500         ] ifFalse:[
       
  1501             code:= 
       
  1502 'documentation
       
  1503 "
       
  1504 ' , (existingComment ? '    documentation to be added.') , '
       
  1505 
       
  1506     [author:]
       
  1507         ' , userName 
       
  1508           , ' (' , emailAddress , ')' , '
       
  1509 
       
  1510     [instance variables:]
       
  1511 
       
  1512     [class variables:]
       
  1513 
       
  1514     [see also:]
       
  1515 
       
  1516 "
       
  1517 '
       
  1518         ].
       
  1519 
       
  1520         self 
       
  1521             compile:code
       
  1522             forClass:metaClass 
       
  1523             inCategory:'documentation'.
       
  1524     ].
       
  1525 
       
  1526     "Modified: / 24-11-2006 / 15:54:27 / cg"
       
  1527 !
       
  1528 
       
  1529 createExamplesMethodFor:aClass
       
  1530     "add examples method containing examples template
       
  1531      but only if not already present."
       
  1532 
       
  1533     |nonMetaclass fragment|
       
  1534 
       
  1535     nonMetaclass := aClass theNonMetaclass.
       
  1536 
       
  1537     (nonMetaclass isSubclassOf:View) ifTrue:[
       
  1538         self createExamplesMethodForViewClass:aClass.
       
  1539         ^ self
       
  1540     ].
       
  1541 
       
  1542     (nonMetaclass isSubclassOf:ApplicationModel) ifFalse:[
       
  1543         ^ self
       
  1544     ].
       
  1545 
       
  1546     (aClass includesSelector:#examples) ifFalse:[
       
  1547         (nonMetaclass isSubclassOf:ApplicationModel) ifTrue:[
       
  1548             fragment := '  Starting the application:
       
  1549                                                                 [exBegin]
       
  1550     ' , nonMetaclass name , ' open
       
  1551 
       
  1552                                                                 [exEnd]
       
  1553 '
       
  1554         ] ifFalse:[
       
  1555             fragment := ''
       
  1556         ].
       
  1557 
       
  1558         self 
       
  1559             compile:
       
  1560 'examples
       
  1561 "
       
  1562 ' , fragment , '
       
  1563   more examples to be added:
       
  1564                                                                 [exBegin]
       
  1565     ... add code fragment for 
       
  1566     ... executable example here ...
       
  1567                                                                 [exEnd]
       
  1568 "
       
  1569 '                   
       
  1570             forClass:aClass 
       
  1571             inCategory:'documentation'.
       
  1572     ].
       
  1573 !
       
  1574 
       
  1575 createImageSpecMethodFor:anImage comment:comment in:aClass selector:sel
       
  1576     |imageStoreStream mthd imageKey category|
       
  1577 
       
  1578     anImage storeOn: (imageStoreStream := WriteStream on: '').
       
  1579 
       
  1580     "/ if that method already exists, do not overwrite the category
       
  1581     category := 'image specs'.
       
  1582     (mthd := aClass compiledMethodAt:sel) notNil ifTrue:[
       
  1583         category := mthd category.
       
  1584     ].
       
  1585 
       
  1586     imageKey :=  (aClass name, ' ', sel) asSymbol.
       
  1587     Icon constantNamed: imageKey put:nil.
       
  1588     aClass
       
  1589         compile: ((sel,
       
  1590             '\', comment,
       
  1591             '\\' , 
       
  1592             '    "\',
       
  1593             '     self ' , sel , ' inspect\',
       
  1594             '     ImageEditor openOnClass:self andSelector:#', sel, '\',
       
  1595             '     Icon flushCachedIcons', 
       
  1596             '\    "',
       
  1597             '\\',
       
  1598             '    <resource: #image>',
       
  1599             '\\',
       
  1600             '    ^Icon\') withCRs, 
       
  1601             '        constantNamed:''', imageKey, '''\' withCRs,
       
  1602             '        ifAbsentPut:[', imageStoreStream contents, ']')
       
  1603        classified: category.
       
  1604 !
       
  1605 
       
  1606 createInitialHistoryMethodFor:aClass
       
  1607     "add history method containing created-entry
       
  1608      but only if not already present."
       
  1609 
       
  1610     |code|
       
  1611 
       
  1612     (aClass includesSelector:#history) ifFalse:[ 
       
  1613         HistoryManager notNil ifTrue:[
       
  1614             code := HistoryManager codeForInitialHistoryMethodIn:aClass.
       
  1615             self
       
  1616                 compile:code
       
  1617                 forClass:aClass 
       
  1618                 inCategory:'documentation'.
       
  1619         ].
       
  1620     ].
       
  1621 !
       
  1622 
       
  1623 createInstanceCreationMethodWithSetupFor:selector category:category in:aMetaClass
       
  1624     "add an inst-creation method"
       
  1625 
       
  1626     |template instMthd argNames|
       
  1627 
       
  1628     (aMetaClass includesSelector:selector) ifFalse:[
       
  1629         instMthd := aMetaClass theNonMetaclass compiledMethodAt:selector.
       
  1630         (instMthd notNil     
       
  1631         and:[  (argNames := instMthd methodArgNames) notEmptyOrNil ])
       
  1632         ifTrue:[
       
  1633             template := Parser methodSpecificationForSelector:selector argNames:argNames.
       
  1634         ] ifFalse:[
       
  1635             template := Parser methodSpecificationForSelector:selector.
       
  1636         ].
       
  1637 
       
  1638         self 
       
  1639             compile:
       
  1640 template , '
       
  1641     ^ self new ' , template , '
       
  1642 '                   
       
  1643             forClass:aMetaClass 
       
  1644             inCategory:category.
       
  1645     ].
       
  1646 !
       
  1647 
       
  1648 createMultiSetterMethodFor:aCollectionOfVarNames in:aClass
       
  1649     "create a multi-setter method for instvars."
       
  1650 
       
  1651     |source|
       
  1652 
       
  1653     source := ''.
       
  1654     aCollectionOfVarNames do:[:eachVar |
       
  1655         source := source , (eachVar , ':' , eachVar , 'Arg ').
       
  1656     ].
       
  1657     source := source , Character cr.
       
  1658     (userPreferences generateCommentsForSetters) ifTrue:[
       
  1659         source := source , ('    "set instance variables"' , Character cr , Character cr).
       
  1660     ].
       
  1661     aCollectionOfVarNames do:[:eachVar |
       
  1662         source := source , ('    ' , eachVar , ' := ' , eachVar , 'Arg.' , Character cr).
       
  1663     ].
       
  1664     self compile:source forClass:aClass inCategory:'accessing'.
       
  1665 !
       
  1666 
       
  1667 createSubclassResponsibilityMethodFor:aSelector category:cat in:aClass
       
  1668     "add a subclassResponsibility method;
       
  1669      but only if not already present."
       
  1670 
       
  1671     (aClass includesSelector:aSelector) ifFalse:[
       
  1672 
       
  1673         self compile:
       
  1674 (Method methodDefinitionTemplateForSelector:aSelector) ,
       
  1675 '
       
  1676     "raise an error: must be redefined in concrete subclass(es)"
       
  1677 
       
  1678     ^ self subclassResponsibility
       
  1679 ' 
       
  1680               forClass:aClass 
       
  1681               inCategory:cat.
       
  1682     ].
       
  1683 !
       
  1684 
       
  1685 createUpdateMethodIn:aClass
       
  1686     "create an update:with:from:-method
       
  1687      (I'm tired of typing)"
       
  1688 
       
  1689     |code|
       
  1690 
       
  1691     (aClass includesSelector:#'update:with:from:') ifFalse:[
       
  1692         generateComments ifFalse:[
       
  1693             code :=
       
  1694 'update:something with:aParameter from:changedObject
       
  1695     super update:something with:aParameter from:changedObject
       
  1696 '
       
  1697         ] ifTrue:[
       
  1698             code :=
       
  1699 'update:something with:aParameter from:changedObject
       
  1700     "Invoked when an object that I depend upon sends a change notification."
       
  1701 
       
  1702     "stub code automatically generated - please change as required"
       
  1703 
       
  1704     "/ changedObject == someOfMyValueHolders ifTrue:[
       
  1705     "/     self doSomethingApropriate.
       
  1706     "/     ^ self.
       
  1707     "/ ].
       
  1708     super update:something with:aParameter from:changedObject
       
  1709 '
       
  1710         ].
       
  1711 
       
  1712         self 
       
  1713             compile:code
       
  1714             forClass:aClass 
       
  1715             inCategory:'change & update'.
       
  1716     ]
       
  1717 !
       
  1718 
       
  1719 createVersionMethodFor:aClass
       
  1720     <resource: #obsolete>
       
  1721     "add version method containing RCS template
       
  1722      but only if not already present and its not a private class."
       
  1723 
       
  1724     |code|
       
  1725 
       
  1726     self obsoleteMethodWarning.
       
  1727 
       
  1728     aClass isPrivate ifFalse:[
       
  1729         (aClass includesSelector:#version) ifFalse:[
       
  1730             "/ ugly; should ask the class for that    
       
  1731             aClass isJavaScriptClass ifTrue:[
       
  1732                 code:= ('function version() {\    return ("$' , 'Header$");\}') withCRs
       
  1733             ] ifFalse:[
       
  1734                 code:= ('version\    ^ ''$' , 'Header$''') withCRs
       
  1735             ].
       
  1736             self 
       
  1737                 compile:code
       
  1738                 forClass:aClass 
       
  1739                 inCategory:'documentation'.
       
  1740         ]
       
  1741     ].
       
  1742 ! !
       
  1743 
       
  1744 !SmalltalkCodeGeneratorTool methodsFor:'code templates'!
       
  1745 
       
  1746 codeFor_classInitialize
       
  1747     generateComments ifFalse:[
       
  1748         ^
       
  1749 'initialize
       
  1750 %(INIT_CLASSINSTVARS)
       
  1751 %(INIT_CLASSVARS)
       
  1752 '.
       
  1753     ].
       
  1754 
       
  1755     ^
       
  1756 'initialize
       
  1757     "Invoked at system start or when the class is dynamically loaded."
       
  1758 
       
  1759     "/ please change as required (and remove this comment)
       
  1760 %(INIT_CLASSINSTVARS)
       
  1761 %(INIT_CLASSVARS)
       
  1762 '.
       
  1763 !
       
  1764 
       
  1765 codeFor_closeAccept
       
  1766     generateComments ifFalse:[
       
  1767         ^
       
  1768 'closeAccept
       
  1769     ^ super closeAccept
       
  1770 '.
       
  1771     ].
       
  1772 
       
  1773     ^
       
  1774 'closeAccept
       
  1775     "This is a hook method generated by the Browser/CodeGeneratorTool.
       
  1776      It will be invoked when your dialog-window is closed with OK."
       
  1777 
       
  1778     "/ add any actions as required here ...
       
  1779     Transcript showCR:''dialog accepted''.
       
  1780 
       
  1781     "/ do not remove the one below (otherwise, the dialog will not close itself)...
       
  1782     ^ super closeAccept
       
  1783 '.
       
  1784 
       
  1785     "Created: / 27-10-2006 / 10:03:31 / cg"
       
  1786 !
       
  1787 
       
  1788 codeFor_closeDownViews
       
  1789     generateComments ifFalse:[
       
  1790         ^
       
  1791 'closeDownViews
       
  1792     ^ super closeDownViews
       
  1793 '.
       
  1794     ].
       
  1795 
       
  1796     ^
       
  1797 'closeDownViews
       
  1798     "This is a hook method generated by the Browser/CodeGeneratorTool.
       
  1799      It will be invoked when your app/dialog-window is really closed.
       
  1800      See also #closeDownViews, which is invoked before and may suppress the close
       
  1801      or ask the user for confirmation."
       
  1802 
       
  1803     "/ change the code below as required ...
       
  1804     "/ This should cleanup any leftover resources
       
  1805     "/ (for example, temporary files)
       
  1806     "/ super closeRequest will initiate the closeDown
       
  1807 
       
  1808     "/ add your code here
       
  1809 
       
  1810     "/ do not remove the one below ...
       
  1811     ^ super closeDownViews
       
  1812 '.
       
  1813 
       
  1814     "Created: / 27-10-2006 / 10:01:32 / cg"
       
  1815 !
       
  1816 
       
  1817 codeFor_closeRequest
       
  1818     generateComments ifFalse:[
       
  1819         ^
       
  1820 'closeRequest
       
  1821     self hasUnsavedChanges ifTrue:[
       
  1822         (self confirm:(resources string:''Close without saving ?'')) ifFalse:[
       
  1823             ^ self
       
  1824         ]
       
  1825     ].
       
  1826     ^ super closeRequest
       
  1827 '.
       
  1828     ].
       
  1829 
       
  1830     ^
       
  1831 'closeRequest
       
  1832     "This is a hook method generated by the Browser/CodeGeneratorTool.
       
  1833      It will be invoked when your app/dialog-window is about to be
       
  1834      closed (this method has a chance to suppress the close).
       
  1835      See also #closeDownViews, which is invoked when the close is really done."
       
  1836 
       
  1837     "/ change the code below as required ...
       
  1838     "/ Closing can be suppressed, by simply returning.
       
  1839     "/ The ''super closeRequest'' at the end will initiate the real closeDown
       
  1840 
       
  1841     self hasUnsavedChanges ifTrue:[
       
  1842         (self confirm:(resources string:''Close without saving ?'')) ifFalse:[
       
  1843             ^ self
       
  1844         ]
       
  1845     ].
       
  1846 
       
  1847     ^ super closeRequest
       
  1848 '.
       
  1849 
       
  1850     "Created: / 27-10-2006 / 10:01:06 / cg"
       
  1851 !
       
  1852 
       
  1853 codeFor_emptyMenuActionCodeFor:selector menuItem:item
       
  1854     generateComments ifFalse:[
       
  1855         ^
       
  1856 selector,'
       
  1857     self warn:''no action for ''''',item,''''' defined.''.
       
  1858 '.
       
  1859     ].
       
  1860 
       
  1861     ^
       
  1862 selector,'
       
  1863     "This method was generated by the Browser/CodeGeneratorTool.
       
  1864      It will be invoked when the menu-item ''',item,''' is selected."
       
  1865 
       
  1866     "/ change below and add any actions as required here ...
       
  1867     self warn:''no action for ''''',item,''''' defined.''.
       
  1868 '.
       
  1869 
       
  1870     "Created: / 27-10-2006 / 10:16:43 / cg"
       
  1871 !
       
  1872 
       
  1873 codeFor_hasUnsavedChanges
       
  1874     generateComments ifFalse:[
       
  1875         ^
       
  1876 'hasUnsavedChanges
       
  1877     ^ false.
       
  1878 '.
       
  1879     ].
       
  1880 
       
  1881     ^
       
  1882 'hasUnsavedChanges
       
  1883     "Return true, if any unsaved changes are present 
       
  1884      (i.e. the contents needs to be saved or else will be lost)"
       
  1885 
       
  1886     "/ add real code as required (or remove the halt and always return false)...
       
  1887     "/ self halt:''check this code''.
       
  1888     ^ false.
       
  1889 '.
       
  1890 
       
  1891     "Created: / 27-10-2006 / 10:00:36 / cg"
       
  1892 !
       
  1893 
       
  1894 codeFor_menuSaveAs
       
  1895     ^
       
  1896 'menuSaveAs
       
  1897     "This method was generated by the Browser/CodeGeneratorTool.
       
  1898      It will be invoked when the menu-item ''saveAs'' is selected."
       
  1899 
       
  1900     "/ change below as required... (see examples in Dialog class for more options)
       
  1901     Dialog
       
  1902         requestSaveFileName:(resources string:''Save'') 
       
  1903         default:''foo.txt'' 
       
  1904         fromDirectory:nil 
       
  1905         action:[:fileName | self doSaveAs:fileName] 
       
  1906         appendAction:nil.
       
  1907 '.
       
  1908 
       
  1909     "Created: / 27-10-2006 / 10:01:57 / cg"
       
  1910 !
       
  1911 
       
  1912 codeFor_openAboutThisApplication
       
  1913     ^
       
  1914 'openAboutThisApplication
       
  1915     "This method was generated by the Browser/CodeGeneratorTool.
       
  1916      It will be invoked when the menu-item ''help-about'' is selected."
       
  1917 
       
  1918     "/ could open a customized aboutBox here ...
       
  1919     super openAboutThisApplication
       
  1920 '.
       
  1921 
       
  1922     "Created: / 27-10-2006 / 10:03:13 / cg"
       
  1923 !
       
  1924 
       
  1925 codeFor_openDocumentation
       
  1926     ^
       
  1927 'openDocumentation
       
  1928     "This method was generated by the Browser/CodeGeneratorTool.
       
  1929      It will be invoked when the menu-item ''help-documentation'' is selected."
       
  1930 
       
  1931     "/ change below as required ...
       
  1932 
       
  1933     "/ to open an HTML viewer on some document (under ''doc/online/<language>/'' ):
       
  1934     self openDocumentationFile:''TOP.html''.
       
  1935 
       
  1936     "/ add application-specific help files under the ''doc/online/<language>/help/appName''
       
  1937     "/ directory, and open a viewer with:
       
  1938     "/ self openDocumentationFile:''help/<MyApplication>/TOP.html''.
       
  1939 '.
       
  1940 
       
  1941     "Created: / 27-10-2006 / 10:02:55 / cg"
       
  1942 !
       
  1943 
       
  1944 codeFor_postBuildWith
       
  1945     generateComments ifFalse:[
       
  1946         ^
       
  1947 'postBuildWith:aBuilder
       
  1948     ^ super postBuildWith:aBuilder
       
  1949 '.
       
  1950     ].
       
  1951 
       
  1952     ^
       
  1953 'postBuildWith:aBuilder
       
  1954     "This is a hook method generated by the Browser/CodeGeneratorTool.
       
  1955      It will be invoked during the initialization of your app/dialog,
       
  1956      after all of the visual components have been built, 
       
  1957      but BEFORE the top window is made visible.
       
  1958      Add any app-specific actions here (reading files, setting up values etc.)
       
  1959      See also #postOpenWith:, which is invoked after opening."
       
  1960 
       
  1961     "/ add any code here ...
       
  1962 
       
  1963     ^ super postBuildWith:aBuilder
       
  1964 '.
       
  1965 
       
  1966     "Created: / 27-10-2006 / 09:59:33 / cg"
       
  1967 !
       
  1968 
       
  1969 codeFor_postOpenWith
       
  1970     generateComments ifFalse:[
       
  1971         ^
       
  1972 'postOpenWith:aBuilder
       
  1973     ^ super postOpenWith:aBuilder
       
  1974 '.
       
  1975     ].
       
  1976 
       
  1977     ^
       
  1978 'postOpenWith:aBuilder
       
  1979     "This is a hook method generated by the Browser/CodeGeneratorTool.
       
  1980      It will be invoked right after the applications window has been opened.
       
  1981      Add any app-specific actions here (starting background processes etc.).
       
  1982      See also #postBuildWith:, which is invoked before opening."
       
  1983 
       
  1984     "/ add any code here ...
       
  1985 
       
  1986     ^ super postOpenWith:aBuilder
       
  1987 '.
       
  1988 
       
  1989     "Created: / 27-10-2006 / 09:59:56 / cg"
       
  1990 !
       
  1991 
       
  1992 code_forWidget_buttonPress
       
  1993     generateComments ifFalse:[
       
  1994         ^
       
  1995 'buttonPress:button x:x y:y
       
  1996     Transcript show:''button: ''; showCR:button.
       
  1997     super buttonPress:button x:x y:y
       
  1998 '
       
  1999     ].
       
  2000 
       
  2001     ^
       
  2002 'buttonPress:button x:x y:y
       
  2003     "called when a mouse-button is pressed. button is the button-nr (1 for left-button).
       
  2004      x/y are the mouse position at the time of the click.
       
  2005      There are also corresponding buttonRelease and buttonMotion methods which could be
       
  2006      redefined...."
       
  2007 
       
  2008     Transcript show:''button: ''; showCR:button.
       
  2009     "/ super-code handles middleButtonMenu, if it was assigned (with middleButtonmenu:)
       
  2010     super buttonPress:button x:x y:y
       
  2011 '
       
  2012 !
       
  2013 
       
  2014 code_forWidget_initialize
       
  2015     ^
       
  2016 'initialize
       
  2017     super initialize "/ to initialize inherited state
       
  2018 
       
  2019     "/ add code to initialize private variables,
       
  2020     "/ and sub-components as required.
       
  2021 '
       
  2022 !
       
  2023 
       
  2024 code_forWidget_keyPress
       
  2025     generateComments ifFalse:[
       
  2026         ^
       
  2027 'keyPress:key x:x y:y
       
  2028 "/    key == #Copy ifTrue:[
       
  2029 "/    ].
       
  2030 "/    key == #Cut ifTrue:[
       
  2031 "/    ].
       
  2032     Transcript show:''key: ''; showCR:key.
       
  2033     super keyPress:key x:x y:y
       
  2034 '
       
  2035     ].
       
  2036     ^
       
  2037 'keyPress:key x:x y:y
       
  2038     "called when a keyboard-key was pressed. key is either a character (for ordinary keys)
       
  2039      or a symbol, such as #Copy, #Cut or #Paste.
       
  2040      x/y are the mouse position at the time of the key-press.
       
  2041      There is also a corresponding keyRelease method which could be redefined...."
       
  2042 
       
  2043     Transcript show:''key: ''; showCR:key.
       
  2044     super keyPress:key x:x y:y
       
  2045 '
       
  2046 !
       
  2047 
       
  2048 code_forWidget_redraw
       
  2049     |sel comment code|
       
  2050 
       
  2051     sel := 'redrawX:x y:y width:w height:h'.
       
  2052     generateComments ifFalse:[
       
  2053         comment := ''.
       
  2054     ] ifTrue:[
       
  2055         comment := '
       
  2056     "called to redraw a part of the widgets area. x/y define the origin, w/h the size of
       
  2057      that area. The clipping region has already been set by the caller, so even if the code
       
  2058      below draws outside the redraw-area, it will not affect what is on the screen. 
       
  2059      Therefore, the example below can fill the rectangle in the redraw area, but still draw
       
  2060      the cross in the outside regions."
       
  2061 
       
  2062 '.
       
  2063     ].
       
  2064 
       
  2065     code := '
       
  2066     self paint:Color red.
       
  2067     self fillRectangleX:x y:y width:w height:h.
       
  2068 
       
  2069     self paint:Color yellow.
       
  2070     self displayLineFrom:0@0 to:(width@height).
       
  2071     self displayLineFrom:width@0 to:(0@height).
       
  2072 '.
       
  2073 
       
  2074     ^ sel,comment,code
       
  2075 !
       
  2076 
       
  2077 code_forWidget_sizeChanged
       
  2078     generateComments ifFalse:[
       
  2079         ^
       
  2080 'sizeChanged:how
       
  2081     self invalidate.
       
  2082     super sizeChanged:how.
       
  2083 '
       
  2084     ].
       
  2085 
       
  2086     ^
       
  2087 'sizeChanged:how
       
  2088     "Invoked whenever the size of the view changes. 
       
  2089      Here, we force a full redraw, which might not be needed all the time"
       
  2090 
       
  2091     self invalidate.
       
  2092     super sizeChanged:how.
       
  2093 '
       
  2094 !
       
  2095 
       
  2096 code_forWidget_update
       
  2097     generateComments ifFalse:[
       
  2098         ^
       
  2099 'update:something with:aParameter from:changedObject
       
  2100     changedObject == model ifTrue:[
       
  2101         self invalidate.
       
  2102         ^ self
       
  2103     ].
       
  2104     super update:something with:aParameter from:changedObject
       
  2105 '
       
  2106     ].
       
  2107 
       
  2108     ^
       
  2109 'update:something with:aParameter from:changedObject
       
  2110     "Invoked when an object that I depend upon sends a change notification."
       
  2111 
       
  2112     "stub code automatically generated - please change as required"
       
  2113 
       
  2114     changedObject == model ifTrue:[
       
  2115         self invalidate.
       
  2116         ^ self
       
  2117     ].
       
  2118     super update:something with:aParameter from:changedObject
       
  2119 '
       
  2120 ! !
       
  2121 
       
  2122 !SmalltalkCodeGeneratorTool methodsFor:'private'!
       
  2123 
       
  2124 codeFor_shouldImplementFor:selector inClass:aClass
       
  2125     "used in the 'generate required protocol' to generate a shouldImplement-sending
       
  2126      method for each subclassClassresponsibility method above aClass."
       
  2127 
       
  2128     |mthd comment implClass methodBodyStream searcher errorMessageString|
       
  2129 
       
  2130     (aClass notNil
       
  2131     and:[ aClass superclass notNil ]) ifTrue:[
       
  2132         implClass := aClass superclass whichClassImplements:selector.
       
  2133     ].
       
  2134     implClass isNil ifTrue:[
       
  2135         ^ ((Method methodDefinitionTemplateForSelector:selector),'\    ^ self shouldImplement\') withCRs
       
  2136     ].
       
  2137 
       
  2138     mthd := implClass compiledMethodAt:selector.
       
  2139 
       
  2140     methodBodyStream := '' writeStream.
       
  2141     methodBodyStream 
       
  2142         nextPutAll:mthd methodDefinitionTemplate; cr;
       
  2143         nextPutAll:'    "'.
       
  2144 
       
  2145     "/ include the comment of the subclassResponsibility-sending method
       
  2146 
       
  2147     comment := mthd methodComment.
       
  2148     comment isEmptyOrNil ifTrue:[
       
  2149         methodBodyStream 
       
  2150             nextPutAll:('superclass <1s> says that I am responsible to implement this method'  
       
  2151                         expandMacrosWith:implClass name)
       
  2152     ] ifFalse:[
       
  2153         comment 
       
  2154             asStringCollection do:[:eachLine|
       
  2155                 methodBodyStream nextPutAll:eachLine.
       
  2156             ] separatedBy:[
       
  2157                 methodBodyStream cr; nextPutAll:'     '.
       
  2158             ].
       
  2159     ].
       
  2160     methodBodyStream 
       
  2161         nextPut:$"; cr; cr.
       
  2162 
       
  2163     "/ include the argument of the subclassResponsibility:-sending method
       
  2164     self canUseRefactoringSupport ifTrue:[
       
  2165         (mthd sends:#subclassResponsibility:) ifTrue:[
       
  2166             searcher := ParseTreeSearcher new.
       
  2167             searcher
       
  2168                     matches: 'self subclassResponsibility: `''.*'''
       
  2169                     do:[:node :answer | 
       
  2170                         errorMessageString := node arguments first value.
       
  2171                         true.
       
  2172                     ].
       
  2173             searcher executeTree: (mthd parseTree) initialAnswer: false.
       
  2174         ].
       
  2175     ].
       
  2176     errorMessageString notEmptyOrNil ifTrue:[
       
  2177         methodBodyStream 
       
  2178             nextPutAll:'    ^ self shouldImplement:'; 
       
  2179             nextPutLine:(errorMessageString storeString)
       
  2180     ] ifFalse:[
       
  2181         methodBodyStream 
       
  2182             nextPutLine:'    ^ self shouldImplement'.
       
  2183     ].
       
  2184 
       
  2185     ^ methodBodyStream contents
       
  2186 ! !
       
  2187 
       
  2188 !SmalltalkCodeGeneratorTool class methodsFor:'documentation'!
       
  2189 
       
  2190 version_CVS
       
  2191     ^ '$Header: /cvs/stx/stx/libtool/SmalltalkCodeGeneratorTool.st,v 1.1 2011-01-28 09:24:12 cg Exp $'
       
  2192 ! !