--- a/DataSetBuilder.st Thu May 07 14:42:54 1998 +0200
+++ b/DataSetBuilder.st Mon May 11 10:41:34 1998 +0200
@@ -14,9 +14,9 @@
-ToolApplicationModel subclass:#DataSetBuilder
- instanceVariableNames:'className superclassName hasChanged columnView columns
- selectedColumnIndex tabSelectionIndex aspects'
+ResourceSpecEditor subclass:#DataSetBuilder
+ instanceVariableNames:'rowClass rowSuperClass hasChanged columnView columns
+ selectedColumnIndex tabSelectionIndex'
classVariableNames:''
poolDictionaries:''
category:'Interface-UIPainter'
@@ -61,22 +61,36 @@
!DataSetBuilder class methodsFor:'instance creation'!
openOnClass:aClass andSelector:aSelector
- self information:'not yet implemented'
+
+ ^ self new openOnClass:aClass andSelector:aSelector
+! !
+
+!DataSetBuilder class methodsFor:'constants'!
- "Created: / 22.4.1998 / 10:21:03 / cg"
+resourceType
+ "get the type of resource of the method generated by the MenuEditor"
+
+ ^#dataset
+
+
! !
!DataSetBuilder class methodsFor:'help specs'!
helpSpec
- "return a dictionary filled with helpKey -> helptext associations.
- These are used by the activeHelp tool."
+ "This resource specification was automatically generated
+ by the UIHelpTool of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the UIHelpTool may not be able to read the specification."
"
- UIHelpTool openOnClass:DataSetBuilder
+ UIHelpTool openOnClass:DataSetBuilder
"
- ^ super helpSpec addPairsFrom:#(
+ <resource: #help>
+
+ ^super helpSpec addPairsFrom:#(
#addColumn
'Adds a new column.'
@@ -142,7 +156,7 @@
'Turns on/off displaying row separators.'
#selectionCellClickSelector
-'A selector called if cell was selected. '
+'A selector called if cell was selected.'
#selectionCellDoubleClickSelector
'A selector called if cell was double clicked.'
@@ -157,7 +171,7 @@
'A selector called if label cell was clicked.'
#selectionLabelSelectorArgument
-'An argument passed to label selection selector. '
+'An argument passed to label selection selector.'
#valuesChoiceSelector
'A selector returning a collection of choices for a cell having a ComboBox or a ComboList widget.'
@@ -1091,11 +1105,11 @@
#window:
#(#WindowSpec
#name: 'Data Set Builder'
- #layout: #(#LayoutFrame 662 0 70 0 1132 0 446 0)
+ #layout: #(#LayoutFrame 487 0 189 0 1031 0 690 0)
#label: 'Data Set Builder'
#min: #(#Point 10 10)
#max: #(#Point 1152 900)
- #bounds: #(#Rectangle 662 70 1133 447)
+ #bounds: #(#Rectangle 487 189 1032 691)
#menu: #menu
#usePreferredExtent: false
)
@@ -1103,75 +1117,107 @@
#(#SpecCollection
#collection:
#(
- #(#MenuPanelSpec
- #name: 'menuToolbarView'
- #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 32 0)
- #menu: #menuToolbar
- )
- #(#VariableHorizontalPanelSpec
- #name: 'VariablePanel'
- #layout: #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -26 1.0)
+ #(#ViewSpec
+ #name: 'Box1'
+ #layout: #(#LayoutFrame 0 0.0 100 0.0 0 1.0 0 1.0)
#component:
#(#SpecCollection
#collection:
#(
- #(#ViewSpec
- #name: 'labelsView'
+ #(#MenuPanelSpec
+ #name: 'menuToolbarView'
+ #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 32 0)
+ #menu: #menuToolbar
+ )
+ #(#VariableHorizontalPanelSpec
+ #name: 'VariablePanel'
+ #layout: #(#LayoutFrame 0 0.0 34 0.0 0 1.0 -26 1.0)
#component:
#(#SpecCollection
#collection:
#(
- #(#SequenceViewSpec
- #name: 'columnView'
- #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
- #model: #selectedColumnModel
- #menu: #menuEdit
- #hasHorizontalScrollBar: true
- #hasVerticalScrollBar: true
- #miniScrollerHorizontal: true
- #useIndex: true
- #sequenceList: #seqList
+ #(#ViewSpec
+ #name: 'labelsView'
+ #component:
+ #(#SpecCollection
+ #collection:
+ #(
+ #(#SequenceViewSpec
+ #name: 'labelAndColumns'
+ #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+ #model: #selectedColumnModel
+ #menu: #menuEdit
+ #hasHorizontalScrollBar: true
+ #hasVerticalScrollBar: true
+ #miniScrollerHorizontal: true
+ #useIndex: true
+ #sequenceList: #seqList
+ )
+ )
+ )
+ )
+ #(#ViewSpec
+ #name: 'specView'
+ #component:
+ #(#SpecCollection
+ #collection:
+ #(
+ #(#TabViewSpec
+ #name: 'tabView'
+ #layout: #(#LayoutFrame 1 0.0 0 0 0 1.0 35 0)
+ #model: #tabModel
+ #menu: #tabList
+ #useIndex: true
+ )
+ #(#SubCanvasSpec
+ #name: 'specCanvas'
+ #layout: #(#LayoutFrame 1 0.0 35 0.0 0 1.0 -30 1.0)
+ #specHolder: #specChannel
+ )
+ #(#UISubSpecification
+ #name: 'SubSpecification'
+ #layout: #(#LayoutFrame 2 0.0 -26 1 -2 1.0 -2 1.0)
+ #majorKey: #ToolApplicationModel
+ #minorKey: #windowSpecForCommit
+ )
+ )
+ )
+ #level: -1
)
)
)
+ #handles: #(#Any 0.346072 1.0)
)
- #(#ViewSpec
- #name: 'specView'
- #component:
- #(#SpecCollection
- #collection:
- #(
- #(#TabViewSpec
- #name: 'tabView'
- #layout: #(#LayoutFrame 1 0.0 0 0 0 1.0 35 0)
- #model: #tabModel
- #menu: #tabList
- #useIndex: true
- )
- #(#SubCanvasSpec
- #name: 'specCanvas'
- #layout: #(#LayoutFrame 1 0.0 35 0.0 0 1.0 -30 1.0)
- #specHolder: #specChannel
- )
- #(#UISubSpecification
- #name: 'SubSpecification'
- #layout: #(#LayoutFrame 2 0.0 -26 1 -2 1.0 -2 1.0)
- #majorKey: #ToolApplicationModel
- #minorKey: #windowSpecForCommit
- )
- )
- )
- #level: -1
+ #(#UISubSpecification
+ #name: 'infoBarSubSpec'
+ #layout: #(#LayoutFrame 0 0.0 -24 1 0 1.0 0 1.0)
+ #majorKey: #ToolApplicationModel
+ #minorKey: #windowSpecForInfoBar
)
)
)
- #handles: #(#Any 0.265905 1.0)
)
- #(#UISubSpecification
- #name: 'infoBarSubSpec'
- #layout: #(#LayoutFrame 0 0.0 -24 1 0 1.0 0 1.0)
- #majorKey: #ToolApplicationModel
- #minorKey: #windowSpecForInfoBar
+ #(#FramedBoxSpec
+ #name: 'ColumnFrame'
+ #layout: #(#LayoutFrame 0 0.0 5 0.0 0 1.0 100 0)
+ #component:
+ #(#SpecCollection
+ #collection:
+ #(
+ #(#DataSetSpec
+ #name: 'columnView'
+ #layout: #(#LayoutFrame 14 0.0 18 0.0 14 1.0 14 1.0)
+ #hasHorizontalScrollBar: true
+ #hasVerticalScrollBar: false
+ #miniScrollerHorizontal: true
+ #rowClassName: 'CodingExamples_GUI::GUIDemoDataSetView::Row'
+ #useIndex: false
+ #has3Dsepartors: true
+ )
+ )
+ )
+ #label: 'Table Columns'
+ #labelPosition: #topLeft
)
)
)
@@ -1181,10 +1227,11 @@
!DataSetBuilder class methodsFor:'menu specs'!
menu
- "this window spec was automatically generated by the ST/X MenuEditor"
+ "This resource specification was automatically generated
+ by the MenuEditor of ST/X."
- "do not manually edit this - the builder may not be able to
- handle the specification if its corrupted."
+ "Do not manually edit this!! If it is corrupted,
+ the MenuEditor may not be able to read the specification."
"
MenuEditor new openOnClass:DataSetBuilder andSelector:#menu
@@ -1199,75 +1246,160 @@
#(
#(#MenuItem
- #'label:' 'About'
- #'activeHelpKey:' #about
- #'labelImage:' #(#ResourceRetriever nil #menuIcon)
- #'submenuChannel:' #menuAbout
+ #label: 'About'
+ #accessCharacterPosition: 1
+ #labelImage: #(#ResourceRetriever nil #menuIcon)
+ #submenuChannel: #menuAbout
)
#(#MenuItem
- #'label:' 'File'
- #'activeHelpKey:' #file
- #'submenu:'
+ #label: 'File'
+ #activeHelpKey: #file
+ #submenu:
#(#Menu
#(
#(#MenuItem
- #'label:' 'Generate Code'
- #'value:' #doGenerateCode
+ #label: 'New'
+ #value: #doNew
+ #activeHelpKey: #fileNew
+ )
+ #(#MenuItem
+ #label: '-'
)
#(#MenuItem
- #'label:' '-'
+ #label: 'Load...'
+ #translateLabel: true
+ #value: #doLoad
+ #activeHelpKey: #fileLoad
)
#(#MenuItem
- #'label:' 'Define Class...'
- #'value:' #doDefineClass
- #'activeHelpKey:' #fileDefineClass
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Save'
+ #value: #doSave
+ #activeHelpKey: #fileSave
)
#(#MenuItem
- #'label:' 'Browse Class'
- #'value:' #doBrowseClass
- #'activeHelpKey:' #fileBrowseClass
+ #label: 'Save As...'
+ #value: #doSaveAs
+ #activeHelpKey: #fileSaveAs
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Pick Columns...'
+ #value: #doPickColumns
)
#(#MenuItem
- #'label:' '-'
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Browse Class'
+ #value: #doBrowseClass
+ #activeHelpKey: #fileBrowseClass
)
#(#MenuItem
- #'label:' 'Exit'
- #'value:' #closeRequest
- #'activeHelpKey:' #fileExit
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Exit'
+ #translateLabel: true
+ #value: #closeRequest
+ #activeHelpKey: #fileExit
)
) nil
nil
)
)
#(#MenuItem
- #'label:' 'Edit'
- #'activeHelpKey:' #edit
- #'submenuChannel:' #menuEdit
+ #label: 'Edit'
+ #activeHelpKey: #edit
+ #submenuChannel: #menuEdit
)
#(#MenuItem
- #'label:' 'Add'
- #'activeHelpKey:' #add
- #'submenu:'
+ #label: 'Add'
+ #submenu:
#(#Menu
#(
#(#MenuItem
- #'label:' 'Column'
- #'value:' #doCreateColumn
- #'activeHelpKey:' #addColumn
- #'enabled:' #columnIsNotEditing
- #'labelImage:' #(#ResourceRetriever nil #newColumnIcon 'Column')
+ #label: 'Column'
+ #value: #doCreateColumn
+ #activeHelpKey: #addColumn
+ #enabled: #columnIsNotEditing
+ #labelImage: #(#ResourceRetriever nil #newColumnIcon)
)
) nil
nil
)
)
#(#MenuItem
- #'label:' 'Help'
- #'startGroup:' #right
- #'activeHelpKey:' #help
- #'submenuChannel:' #menuHelp
+ #label: 'Generate'
+ #activeHelpKey: #file
+ #submenu:
+ #(#Menu
+
+ #(
+ #(#MenuItem
+ #label: 'Define Row Class...'
+ #value: #doDefineRowClass
+ #activeHelpKey: #fileDefineClass
+ )
+ #(#MenuItem
+ #label: 'Browse Row Class'
+ #value: #doBrowseRowClass
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Generate Code'
+ #value: #doGenerateCode
+ )
+ ) nil
+ nil
+ )
+ )
+ #(#MenuItem
+ #label: 'History'
+ #activeHelpKey: #history
+ #submenuChannel: #menuHistory
+ )
+ #(#MenuItem
+ #label: 'Help'
+ #startGroup: #right
+ #submenu:
+ #(#Menu
+
+ #(
+ #(#MenuItem
+ #label: 'Documentation'
+ #value: #openHTMLDocument:
+ #activeHelpKey: #helpTutorial
+ #argument: 'tools/uipainter/DataSetBuilder.html'
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Help Tool'
+ #value: #openHTMLDocument:
+ #activeHelpKey: #helpHelpTool
+ #argument: 'tools/uipainter/HelpTool.html'
+ )
+ #(#MenuItem
+ #label: '-'
+ )
+ #(#MenuItem
+ #label: 'Show Help Texts'
+ #activeHelpKey: #helpShowHelp
+ #indication: #showHelp:
+ )
+ ) nil
+ nil
+ )
)
) nil
nil
@@ -1405,51 +1537,50 @@
columns
"returns list of columns"
- ^columns
+ ^ columns
!
-columns:aListOfColumns fromView:aColumnView
+columns:aListOfColumns
"setup columns from a column view"
|list|
- columnView := aColumnView.
columns := OrderedCollection new.
list := self seqList.
hasChanged := false.
list removeAll.
- aListOfColumns size ~~ 0
- ifTrue:
- [
- aListOfColumns do:
- [:aColumn|
- columns add: aColumn copy.
- aColumn rendererType == #rowSelector
- ifFalse:[list add: aColumn label]
- ifTrue: [list add:'Row Selector']
+ aListOfColumns size ~~ 0 ifTrue:[
+ aListOfColumns do:[:aColumn||column|
+ (column := aColumn) isSequenceable ifTrue:[
+ column := DataSetColumnSpec new fromLiteralArrayEncoding:aColumn
+ ] ifFalse:[
+ column := aColumn copy
+ ].
+ columns add:column.
+ list add:(self labelFromColumn:column).
]
- ]
+ ].
+ self updateColumnView.
+
!
rowClassName
- ^(Smalltalk resolveName:className inClass:self class) notNil ifTrue:[className] ifFalse:[nil]
+ ^(Smalltalk resolveName:rowClass inClass:self class) notNil ifTrue:[rowClass] ifFalse:[nil]
!
rowClassName:aClassName
|cls|
- superclassName := nil.
+ rowSuperClass := nil.
- (className := aClassName) notNil
- ifTrue:
- [
- (cls := self resolveClassNamed) notNil
- ifTrue: [superclassName := cls superclass name asString]
- ifFalse:[superclassName := 'Object']
+ (rowClass := aClassName) notNil ifTrue:[
+ (cls := self resolveRowClassNamed) notNil
+ ifTrue: [rowSuperClass := cls superclass name asString]
+ ifFalse:[rowSuperClass := 'Object']
]
! !
@@ -1586,6 +1717,33 @@
^ holder
! !
+!DataSetBuilder methodsFor:'building'!
+
+buildFromClass:aClass andSelector:aSelector
+ |cls list|
+
+ list := nil.
+
+ (aClass notNil or:[self isStandAlone or:[self window shown]]) ifTrue:[
+
+ (aClass notNil and:[aSelector notNil]) ifTrue:[
+ cls := self resolveName:aClass.
+
+ (cls respondsTo:aSelector) ifTrue:[
+ list := cls perform:aSelector
+ ]
+ ]
+ ] ifFalse:[
+ list := columns
+ ].
+ self columns:list
+!
+
+buildFromResourceSpec:aResourceSpec
+
+ self columns:aResourceSpec
+! !
+
!DataSetBuilder methodsFor:'change & update'!
update:something with:aParameter from:someObject
@@ -1874,7 +2032,6 @@
selectedColumnIndex := 0.
tabSelectionIndex := 0.
columns := OrderedCollection new.
- aspects := IdentityDictionary new.
hasChanged := false.
#(
@@ -1935,16 +2092,20 @@
!
-resolveClassNamed
+labelFromColumn:aColumn
+ ^ aColumn rendererType == #rowSelector ifFalse:[aColumn label]
+ ifTrue:['Row Selector'].
+!
+
+resolveRowClassNamed
"returns current class or nil"
- ^Smalltalk resolveName:className inClass:self class.
+ ^Smalltalk resolveName:rowClass inClass:self class.
!
updateColumnView
"update column view from column descriptions"
-
columnView notNil ifTrue:[columnView columnDescriptors:columns]
!
@@ -2039,13 +2200,15 @@
postBuildWith:builder
+ columnView := self builder componentAt:#columnView.
+ columnView labelView enabled:false.
+
super postBuildWith:builder.
- (builder componentAt: #columnView)
+ (builder componentAt: #labelAndColumns)
selectConditionBlock: [:i|self checkMenuItemModified];
action: [:i|self cancel];
- selection: 1
-
+ selection: 1.
! !
@@ -2064,15 +2227,15 @@
type := (aspects at:#rendererType) value.
- type == #rowSelector
- ifTrue:
- [
+ type == #rowSelector ifTrue:[
#(label width minWidth editorType choices readSelector writeSelector printSelector
- formatString type size height canSelect selectSelector) do:[:aKey|(aspects at:aKey) value:nil]
+ formatString type size height canSelect selectSelector
+ ) do:[:aKey|
+ (aspects at:aKey) value:nil
+ ]
].
-
aspects keysAndValuesDo:[:aKey :aModel| column perform:(aKey , ':') asSymbol with: aModel value].
- self seqList at:selectedColumnIndex put: (aspects at:#label) value.
+ self seqList at:selectedColumnIndex put:(self labelFromColumn:column).
self updateColumnView.
self cancel
!
@@ -2085,12 +2248,12 @@
self columnIsNotEditing value: true.
!
-doBrowseClass
+doBrowseRowClass
"browse class of columns spec"
|cls|
- (cls := self resolveClassNamed) notNil
+ (cls := self resolveRowClassNamed) notNil
ifTrue: [SystemBrowser openInClass:cls]
ifFalse:[self information:'No class defined!!']
@@ -2121,7 +2284,8 @@
self seqList add:label afterIndex:selectedColumnIndex.
hasChanged := true.
self valueOfEnablingCommitButtons value ifFalse:[self selectedColumnModel value:selectedColumnIndex + 1].
- self cancel
+ self cancel.
+ self updateColumnView
!
@@ -2146,77 +2310,77 @@
]
!
-doDefineClass
+doDefineRowClass
"launch a dialog to define class and superclass"
|aspects cls oldClass oldSuper|
aspects := IdentityDictionary new.
- oldClass := className.
- oldSuper := superclassName.
+ oldClass := rowClass.
+ oldSuper := rowSuperClass.
[true]
whileTrue:
[
- className notNil
+ rowClass notNil
ifTrue:
[
- (cls := self resolveClassNamed) notNil
+ (cls := self resolveRowClassNamed) notNil
ifTrue:
[
- superclassName := cls superclass name asString
+ rowSuperClass := cls superclass name asString
].
- aspects at:#classNameChannel put:className asValue
+ aspects at:#classNameChannel put:rowClass asValue
]
ifFalse:
[
aspects at:#classNameChannel put:'DSVRow' asValue
].
- superclassName notNil
- ifTrue: [aspects at:#superclassNameChannel put:superclassName asValue]
+ rowSuperClass notNil
+ ifTrue: [aspects at:#superclassNameChannel put:rowSuperClass asValue]
ifFalse:[aspects at:#superclassNameChannel put:'Object' asValue].
(self openDialogInterface:#defineClassNameSpec withBindings:aspects)
ifFalse:
[
- className := oldClass.
- superclassName := oldSuper.
+ rowClass := oldClass.
+ rowSuperClass := oldSuper.
^self
].
- className := ((aspects at:#classNameChannel) value) withoutSeparators.
- superclassName := ((aspects at:#superclassNameChannel) value) withoutSeparators.
+ rowClass := ((aspects at:#classNameChannel) value) withoutSeparators.
+ rowSuperClass := ((aspects at:#superclassNameChannel) value) withoutSeparators.
- className size == 0
+ rowClass size == 0
ifTrue:
[
- className := nil.
+ rowClass := nil.
self information:'no valid className'
]
ifFalse:
[
- cls := self resolveClassNamed.
+ cls := self resolveRowClassNamed.
cls notNil ifTrue:[cls := cls superclass name asString].
- superclassName size == 0
+ rowSuperClass size == 0
ifTrue:
[
cls notNil ifTrue:[
- superclassName := cls
+ rowSuperClass := cls
] ifFalse:[
- superclassName := 'Object'
+ rowSuperClass := 'Object'
].
self information: 'set superclassName'
]
ifFalse:
[
- (cls isNil or:[superclassName = cls]) ifTrue:[hasChanged := true. ^self].
- self information:('A global named ' , className , ' exists,\' ,
- 'but is not a subclass of ' , superclassName, '.\\' ,
+ (cls isNil or:[rowSuperClass = cls]) ifTrue:[hasChanged := true. ^self].
+ self information:('A global named ' , rowClass , ' exists,\' ,
+ 'but is not a subclass of ' , rowSuperClass, '.\\' ,
'Check and try again if that is not what you want.') withCRs.
- superclassName := cls
+ rowSuperClass := cls
]
]
]
@@ -2227,17 +2391,17 @@
|cls superclass|
- className isNil ifTrue:[^self information:'No class defined!!'].
- cls := self resolveClassNamed.
+ rowClass isNil ifTrue:[^self information:'No class defined!!'].
+ cls := self resolveRowClassNamed.
cls isNil
ifTrue:
[
- superclass := Smalltalk resolveName:superclassName inClass:self class.
+ superclass := Smalltalk resolveName:rowSuperClass inClass:self class.
superclass isNil ifTrue:[^self information:'No superclass defined!!'].
- (self confirm:'create ' , className , ' ?') ifFalse:[^self].
- cls := superclass subclass:className asSymbol
+ (self confirm:'create ' , rowClass , ' ?') ifFalse:[^self].
+ cls := superclass subclass:rowClass asSymbol
instanceVariableNames:''
classVariableNames:''
poolDictionaries:''
@@ -2292,18 +2456,90 @@
doPasteColumn
"paste clipboard copy column after selected column or at left (nothing selected)"
- |label list|
+ |col lbl|
self checkMenuItemModified ifFalse: [^nil].
- list := self seqList.
- label := self class clipboard label.
- columns add: self class clipboard deepCopy afterIndex:selectedColumnIndex.
- self seqList add: label afterIndex:selectedColumnIndex.
+ col := self class clipboard deepCopy.
+ lbl := self labelFromColumn:col.
+
+ columns add:col afterIndex:selectedColumnIndex.
+ self seqList add:lbl afterIndex:selectedColumnIndex.
hasChanged := true.
- self valueOfEnablingCommitButtons value ifFalse:[self selectedColumnModel value:selectedColumnIndex + 1].
+ self valueOfEnablingCommitButtons value ifFalse:[
+ self selectedColumnModel value:selectedColumnIndex + 1
+ ].
self updateColumnView.
self updateInputFields.
+!
+
+doPickColumns
+
+ |view cls|
+
+ view := Screen current viewFromUser.
+ cls := view class.
+
+ (cls == DSVColumnView or:[cls == DataSetView or:[cls == DSVLabelView]]) ifTrue:[
+ self columns:(view columnView columnDescriptors)
+ ]
+!
+
+doSave
+ |cls dst spc idx category mthd excla code resourceType|
+
+ (columns size ~~ 0 and:[super doSave]) ifFalse:[
+ ^ nil
+ ].
+ cls := self resolveName:specClass.
+ dst := columns collect:[:aCol| aCol literalArrayEncoding ].
+ spc := WriteStream on:String new.
+ UISpecification prettyPrintSpecArray:dst asArray on:spc indent:4.
+ spc := spc contents.
+ idx := (spc indexOfNonSeparatorStartingAt:1) - 2.
+
+ spc at:idx put:$^.
+
+ "/ if that method already exists, do not overwrite the category
+
+ resourceType := self class resourceType.
+ category := resourceType, ' specs'.
+
+ (mthd := cls class compiledMethodAt:specSelector) notNil ifTrue:[
+ category := mthd category.
+ ].
+
+ excla := Character excla asString.
+
+ code := excla
+ , (cls name , ' class methodsFor:' , category storeString)
+ , excla , '\\'
+
+ , specSelector , '\'
+ , (self class codeGenerationComment replChar:$!! withString:'!!!!')
+ , '\\ "\'
+ , (' DataSetBuilder new openOnClass:' , cls name , ' andSelector:#' , specSelector , '\')
+ , ' "\'.
+
+ code := code
+ , '\'
+ , ' <resource: #', resourceType, '>\\'
+ , spc
+ , '\'
+ , (excla , ' ' , excla)
+ , '\\'.
+
+ code := code withCRs.
+ (ReadStream on:code) fileIn.
+
+"/ self isStandAlone ifTrue: [self helpTool installHelpSpecsOnClass:self specClass].
+
+ self updateHistory.
+ self updateInfoLabel.
+
+ hasSaved := true.
+ modified := false.
+
! !
!DataSetBuilder class methodsFor:'documentation'!