diff -r aa1663b8c2ab -r b895330fc7aa DataSetBuilder.st --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DataSetBuilder.st Wed Oct 15 12:59:56 1997 +0200 @@ -0,0 +1,1529 @@ +" + COPYRIGHT (c) 1997 by eXept Software AG / Claus Gittinger + All Rights Reserved + + This software is furnished under a license and may be used + only in accordance with the terms of that license and with the + inclusion of the above copyright notice. This software may not + be provided or otherwise made available to, or used by, any + other person. No title to or ownership of the software is + hereby transferred. +" + + + + + +ApplicationModel subclass:#DataSetBuilder + instanceVariableNames:'className superclassName hasChanged columnView columns + selectedColumnIndex tabSelectionIndex aspects isModified' + classVariableNames:'Number' + poolDictionaries:'' + category:'Interface-UIPainter' +! + +!DataSetBuilder class methodsFor:'documentation'! + +copyright +" + COPYRIGHT (c) 1997 by eXept Software AG / Claus Gittinger + All Rights Reserved + + This software is furnished under a license and may be used + only in accordance with the terms of that license and with the + inclusion of the above copyright notice. This software may not + be provided or otherwise made available to, or used by, any + other person. No title to or ownership of the software is + hereby transferred. +" + + + + +! + +documentation +" + create and modify or inspect dataset columns; used by UIPainter (DataSetColumnSpec) + + [see also:] + DataSetColumnSpec + DataSetSpec + DataSetView + DataSetColumn + + [author:] + Claus Atzkern +" + +! ! + +!DataSetBuilder class methodsFor:'columns specs'! + +basicsEditSpec + "this window spec was automatically generated by the ST/X UIPainter" + + "do not manually edit this - the painter/builder may not be able to + handle the specification if its corrupted." + + " + UIPainter new openOnClass:DataSetBuilder andSelector:#basicsEditSpec + DataSetBuilder new openInterface:#basicsEditSpec + " + + + + ^ + + #(#FullSpec + #'window:' + #(#WindowSpec + #'name:' 'DataSet Basic' + #'layout:' #(#LayoutFrame 197 0 172 0 485 0 427 0) + #'label:' 'DataSet Basic' + #'min:' #(#Point 10 10) + #'max:' #(#Point 1280 1024) + #'bounds:' #(#Rectangle 197 172 486 428) + ) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#LabelSpec + #'name:' 'labelLabel' + #'layout:' #(#AlignmentOrigin 84 0 29 0 1 0.5) + #'label:' 'Label:' + #'adjust:' #right + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'labelField' + #'layout:' #(#LayoutFrame 86 0 20 0 -12 1.0 40 0) + #'model:' #label + ) + #(#FramedBoxSpec + #'name:' 'typesFrame' + #'layout:' #(#LayoutFrame 0 0.0 51 0 0 1.0 131 0) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#LabelSpec + #'name:' 'rendererLabel' + #'layout:' #(#AlignmentOrigin 84 0 26 0 1 0.5) + #'label:' 'Renderer:' + #'resizeForLabel:' true + ) + #(#ComboListSpec + #'name:' 'rendererField' + #'layout:' #(#LayoutFrame 86 0 16 0 17 1.0 36 0) + #'model:' #rendererType + #'comboList:' #rendererTypeList + #'useIndex:' false + ) + #(#LabelSpec + #'name:' 'editorLabel' + #'layout:' #(#AlignmentOrigin 84 0 50 0 1 0.5) + #'label:' 'Editor:' + #'resizeForLabel:' true + ) + #(#ComboBoxSpec + #'name:' 'editorField' + #'layout:' #(#LayoutFrame 86 0 41 0 17 1.0 61 0) + #'model:' #editorType + #'type:' #symbolOrNil + #'comboList:' #editorTypeList + #'useIndex:' false + ) + ) + ) + #'label:' 'Types:' + #'labelPosition:' #topLeft + ) + #(#FramedBoxSpec + #'name:' 'selectorsFrame' + #'layout:' #(#LayoutFrame 0 0.0 143 0 0 1.0 245 0) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#LabelSpec + #'name:' 'readLabel' + #'layout:' #(#AlignmentOrigin 84 0 25 0 1 0.5) + #'label:' 'Read:' + #'adjust:' #right + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'readSelector' + #'layout:' #(#LayoutFrame 86 0 16 0 17 1.0 36 0) + #'model:' #readSelector + #'type:' #symbolOrNil + ) + #(#LabelSpec + #'name:' 'menuLabel' + #'layout:' #(#AlignmentOrigin 84 0 51 0 1 0.5) + #'label:' 'Menu:' + #'adjust:' #right + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'menuField' + #'layout:' #(#LayoutFrame 86 0 41 0 17 1.0 61 0) + #'model:' #menu + #'type:' #symbolOrNil + ) + #(#LabelSpec + #'name:' 'printLabel' + #'layout:' #(#AlignmentOrigin 84 0 75 0 1 0.5) + #'label:' 'Print:' + #'adjust:' #right + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'printSelector' + #'layout:' #(#LayoutFrame 86 0 66 0 17 1.0 86 0) + #'model:' #printSelector + #'type:' #symbolOrNil + ) + ) + ) + #'label:' 'Selectors:' + #'labelPosition:' #topLeft + ) + ) + ) + ) +! + +detailsEditSpec + "this window spec was automatically generated by the ST/X UIPainter" + + "do not manually edit this - the painter/builder may not be able to + handle the specification if its corrupted." + + " + UIPainter new openOnClass:DataSetBuilder andSelector:#detailsEditSpec + DataSetBuilder new openInterface:#detailsEditSpec + " + + + + ^ + + #(#FullSpec + #'window:' + #(#WindowSpec + #'name:' 'DataSet Details' + #'layout:' #(#LayoutFrame 197 0 172 0 487 0 385 0) + #'label:' 'DataSet Details' + #'min:' #(#Point 10 10) + #'max:' #(#Point 1280 1024) + #'bounds:' #(#Rectangle 197 172 488 386) + ) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#LabelSpec + #'name:' 'textDescription' + #'layout:' #(#Point 10 15) + #'label:' 'Text Description:' + #'resizeForLabel:' true + ) + #(#LabelSpec + #'name:' 'formatLabel' + #'layout:' #(#AlignmentOrigin 83 0 47 0 1 0.5) + #'label:' 'Format:' + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'formatField' + #'layout:' #(#LayoutFrame 87 0 37 0 -19 1.0 59 0) + #'model:' #formatString + ) + #(#LabelSpec + #'name:' 'inpFieldDescription' + #'layout:' #(#Point 10 80) + #'label:' 'InputField Description:' + #'resizeForLabel:' true + ) + #(#LabelSpec + #'name:' 'typeLabel' + #'layout:' #(#AlignmentOrigin 83 0 111 0 1 0.5) + #'label:' 'Type:' + #'resizeForLabel:' true + ) + #(#ComboListSpec + #'name:' 'typeCombo' + #'layout:' #(#LayoutFrame 87 0 102 0 289 0 122 0) + #'model:' #type + #'comboList:' #typeList + #'useIndex:' false + ) + #(#LabelSpec + #'name:' 'sizeLabel' + #'layout:' #(#AlignmentOrigin 83 0 136 0 1 0.5) + #'label:' 'Size:' + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'sizeField' + #'layout:' #(#LayoutFrame 87 0 126 0 -19 1.0 148 0) + #'model:' #size + #'type:' #numberOrNil + ) + #(#LabelSpec + #'name:' 'choicesLabel' + #'layout:' #(#Point 10 165) + #'label:' 'Choices:' + #'resizeForLabel:' true + ) + #(#LabelSpec + #'name:' 'selectorLabel' + #'layout:' #(#AlignmentOrigin 83 0 198 0 1 0.5) + #'label:' 'Selector:' + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'choiceField' + #'layout:' #(#LayoutFrame 87 0 188 0 -19 1.0 210 0) + #'model:' #choices + #'type:' #symbolOrNil + ) + ) + ) + ) +! + +dimensionEditSpec + "this window spec was automatically generated by the ST/X UIPainter" + + "do not manually edit this - the painter/builder may not be able to + handle the specification if its corrupted." + + " + UIPainter new openOnClass:DataSetBuilder andSelector:#dimensionEditSpec + DataSetBuilder new openInterface:#dimensionEditSpec + " + + + + ^ + + #(#FullSpec + #'window:' + #(#WindowSpec + #'name:' 'DataSet Dimension' + #'layout:' #(#LayoutFrame 197 0 172 0 487 0 385 0) + #'label:' 'DataSet Dimension' + #'min:' #(#Point 10 10) + #'max:' #(#Point 1280 1024) + #'bounds:' #(#Rectangle 197 172 488 386) + ) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#FramedBoxSpec + #'name:' 'columnWidthFrame' + #'layout:' #(#LayoutFrame 0 0.0 20 0 0 1.0 107 0) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#LabelSpec + #'name:' 'widthLabel' + #'layout:' #(#AlignmentOrigin 68 0.0 27 0 1 0.5) + #'label:' 'width:' + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'widthField' + #'layout:' #(#LayoutFrame 70 0 17 0 0 1.0 39 0) + #'model:' #width + #'type:' #numberOrNil + ) + #(#LabelSpec + #'name:' 'minWidthLabel' + #'layout:' #(#AlignmentOrigin 68 0.0 56 0 1 0.5) + #'label:' 'minWidth:' + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'minWidthField' + #'layout:' #(#LayoutFrame 70 0 46 0 0 1.0 68 0) + #'model:' #minWidth + #'type:' #numberOrNil + ) + ) + ) + #'label:' 'Column Width:' + #'labelPosition:' #topLeft + ) + #(#FramedBoxSpec + #'name:' 'rowHeightFrame' + #'layout:' #(#LayoutFrame 0 0.0 134 0 0 1.0 194 0) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#LabelSpec + #'name:' 'heightLabel' + #'layout:' #(#AlignmentOrigin 68 0.0 29 0 1 0.5) + #'label:' 'height:' + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'heightField' + #'layout:' #(#LayoutFrame 70 0 19 0 0 1.0 41 0) + #'model:' #height + #'type:' #numberOrNil + ) + ) + ) + #'label:' 'Row Height:' + #'labelPosition:' #topLeft + ) + ) + ) + ) +! + +miscEditSpec + "this window spec was automatically generated by the ST/X UIPainter" + + "do not manually edit this - the painter/builder may not be able to + handle the specification if its corrupted." + + " + UIPainter new openOnClass:DataSetBuilder andSelector:#miscEditSpec + DataSetBuilder new openInterface:#miscEditSpec + " + + + + ^ + + #(#FullSpec + #'window:' + #(#WindowSpec + #'name:' 'DataSet Misc' + #'layout:' #(#LayoutFrame 197 0 172 0 487 0 385 0) + #'label:' 'DataSet Misc' + #'min:' #(#Point 10 10) + #'max:' #(#Point 1280 1024) + #'bounds:' #(#Rectangle 197 172 488 386) + ) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#CheckBoxSpec + #'name:' 'canSelect' + #'layout:' #(#Point 17 21) + #'model:' #canSelect + #'label:' 'Is Selectable' + ) + #(#LabelSpec + #'name:' 'separatorsLabel' + #'layout:' #(#AlignmentOrigin 84 0 154 0 1 0.5) + #'label:' 'Separators:' + #'resizeForLabel:' true + ) + #(#CheckBoxSpec + #'name:' 'showRowSeparator' + #'layout:' #(#AlignmentOrigin 86 0 156 0 0 0.5) + #'model:' #showRowSeparator + #'label:' 'Show Row-Separator' + ) + #(#CheckBoxSpec + #'name:' 'showColSeparator' + #'layout:' #(#AlignmentOrigin 86 0 182 0 0 0.5) + #'model:' #showColSeparator + #'label:' 'Show Column-Separator' + ) + ) + ) + ) +! ! + +!DataSetBuilder class methodsFor:'images'! + +iconCreateItem + ^ MenuEditor iconCreateItem + + +! ! + +!DataSetBuilder class methodsFor:'interface specs'! + +defineClassNameSpec + "this window spec was automatically generated by the ST/X UIPainter" + + "do not manually edit this - the painter/builder may not be able to + handle the specification if its corrupted." + + " + UIPainter new openOnClass:DataSetBuilder andSelector:#defineClassNameSpec + DataSetBuilder new openInterface:#defineClassNameSpec + " + + + + ^ + + #(#FullSpec + #'window:' + #(#WindowSpec + #'name:' 'Class Definition' + #'layout:' #(#LayoutFrame 76 0 249 0 401 0 378 0) + #'label:' 'Class Definition' + #'min:' #(#Point 10 10) + #'max:' #(#Point 1152 900) + #'bounds:' #(#Rectangle 76 249 402 379) + ) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#LabelSpec + #'name:' 'classLabel' + #'layout:' #(#AlignmentOrigin 50 0.11 50 0 1 0.5) + #'label:' 'class:' + #'adjust:' #right + #'resizeForLabel:' true + ) + #(#LabelSpec + #'name:' 'superClassLabel' + #'layout:' #(#AlignmentOrigin 50 0.11 77 0 1 0.5) + #'label:' 'superclass:' + #'adjust:' #right + #'resizeForLabel:' true + ) + #(#LabelSpec + #'name:' 'topLabel' + #'layout:' #(#Point 2 10) + #'label:' 'class for code:' + #'adjust:' #left + #'resizeForLabel:' true + ) + #(#InputFieldSpec + #'name:' 'classNameField' + #'layout:' #(#LayoutFrame 51 0.11 39 0 -2 1.0 61 0) + #'tabable:' true + #'model:' #classNameChannel + ) + #(#HorizontalPanelViewSpec + #'name:' 'commitPanel' + #'layout:' #(#LayoutFrame 2 0.0 -30 1.0 -2 1.0 -2 1.0) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#ActionButtonSpec + #'name:' 'button1' + #'label:' 'cancel' + #'tabable:' true + #'model:' #cancel + #'extent:' #(#Point 156 22) + ) + #(#ActionButtonSpec + #'name:' 'button2' + #'label:' 'ok' + #'tabable:' true + #'isDefault:' true + #'model:' #accept + #'extent:' #(#Point 157 22) + ) + ) + ) + #'horizontalLayout:' #fitSpace + #'verticalLayout:' #fitSpace + #'horizontalSpace:' 3 + #'verticalSpace:' 3 + ) + #(#InputFieldSpec + #'name:' 'inputField1' + #'layout:' #(#LayoutFrame 51 0.11 67 0 -2 1.0 89 0) + #'tabable:' true + #'model:' #superclassNameChannel + ) + ) + ) + ) +! + +slices + ^ #( (Basics basicsEditSpec) + (Details detailsEditSpec) + (Misc miscEditSpec) + (Dimension dimensionEditSpec) + ) +! + +windowSpec + "this window spec was automatically generated by the ST/X UIPainter" + + "do not manually edit this - the painter/builder may not be able to + handle the specification if its corrupted." + + " + UIPainter new openOnClass:DataSetBuilder andSelector:#windowSpec + DataSetBuilder new openInterface:#windowSpec + " + "DataSetBuilder open" + + + + ^ + + #(#FullSpec + #'window:' + #(#WindowSpec + #'name:' 'unnamed canvas' + #'layout:' #(#LayoutFrame 197 0 172 0 668 0 512 0) + #'label:' 'unnamed canvas' + #'min:' #(#Point 10 10) + #'max:' #(#Point 1152 900) + #'bounds:' #(#Rectangle 197 172 669 513) + ) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#MenuPanelSpec + #'name:' 'mainMenu' + #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 25 0) + #'menu:' #mainMenu + ) + #(#VariableHorizontalPanelSpec + #'name:' 'VariablePanel' + #'layout:' #(#LayoutFrame 0 0.0 25 0.0 0 1.0 0 1.0) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#ViewSpec + #'name:' 'labelsView' + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#MenuPanelSpec + #'name:' 'subMenu' + #'layout:' #(#LayoutFrame 0 0.0 0 0.0 0 1.0 35 0) + #'menu:' #subMenu + ) + #(#SequenceViewSpec + #'name:' 'columnView' + #'layout:' #(#LayoutFrame 0 0.0 35 0.0 0 1.0 0 1.0) + #'model:' #selectedColumnModel + #'menu:' #columnMenu + #'hasVerticalScrollBar:' true + #'useIndex:' true + #'sequenceList:' #seqList + ) + ) + ) + ) + #(#ViewSpec + #'name:' 'specView' + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#TabViewSpec + #'name:' 'tabView' + #'layout:' #(#LayoutFrame 0 0.0 0 0 0 1.0 35 0) + #'model:' #tabModel + #'menu:' #tabList + #'useIndex:' true + ) + #(#SubCanvasSpec + #'name:' 'specCanvas' + #'layout:' #(#LayoutFrame 0 0.0 35 0.0 0 1.0 -30 1.0) + #'specHolder:' #specChannel + ) + #(#HorizontalPanelViewSpec + #'name:' 'modifyPanel' + #'layout:' #(#LayoutFrame 0 0.0 -30 1.0 0 1.0 0 1.0) + #'component:' + #(#SpecCollection + #'collection:' + #( + #(#ActionButtonSpec + #'name:' 'cancelButton' + #'label:' 'cancel' + #'model:' #cancel + #'enableChannel:' #modifiedChannel + #'extent:' #(#Point 150 24) + ) + #(#ActionButtonSpec + #'name:' 'acceptButton' + #'label:' 'ok' + #'model:' #accept + #'enableChannel:' #modifiedChannel + #'extent:' #(#Point 151 24) + ) + ) + ) + #'horizontalLayout:' #fitSpace + #'verticalLayout:' #fitSpace + #'horizontalSpace:' 3 + #'verticalSpace:' 3 + ) + ) + ) + #'borderWidth:' 1 + ) + ) + ) + #'handles:' #(#Any 0.334746 1.0) + ) + ) + ) + ) +! ! + +!DataSetBuilder class methodsFor:'menu specs'! + +columnMenu + "this window spec was automatically generated by the ST/X MenuEditor" + + "do not manually edit this - the builder may not be able to + handle the specification if its corrupted." + + " + MenuEditor new openOnClass:DataSetBuilder andSelector:#columnMenu + (Menu new fromLiteralArrayEncoding:(DataSetBuilder columnMenu)) startUp + " + + + + ^ + + #(#Menu + + #( + #(#MenuItem + #'label:' 'cut' + #'value:' #doCutColumn + ) + ) nil + nil + ) +! + +mainMenu + "this window spec was automatically generated by the ST/X MenuEditor" + + "do not manually edit this - the builder may not be able to + handle the specification if its corrupted." + + " + MenuEditor new openOnClass:DataSetBuilder andSelector:#mainMenu + (Menu new fromLiteralArrayEncoding:(DataSetBuilder mainMenu)) startUp + " + + + + ^ + + #(#Menu + + #( + #(#MenuItem + #'label:' 'file' + #'submenu:' + #(#Menu + + #( + #(#MenuItem + #'label:' 'close' + #'value:' #closeRequest + ) + ) nil + nil + ) + ) + #(#MenuItem + #'label:' 'code' + #'submenu:' + #(#Menu + + #( + #(#MenuItem + #'label:' 'class' + #'value:' #doDefineClass + ) + #(#MenuItem + #'label:' 'generate code' + #'value:' #doGenerateCode + ) + #(#MenuItem + #'label:' '-' + ) + #(#MenuItem + #'label:' 'browse class' + #'value:' #doBrowseClass + ) + ) nil + nil + ) + ) + ) nil + nil + ) +! + +subMenu + "this window spec was automatically generated by the ST/X MenuEditor" + + "do not manually edit this - the builder may not be able to + handle the specification if its corrupted." + + " + MenuEditor new openOnClass:DataSetBuilder andSelector:#subMenu + (Menu new fromLiteralArrayEncoding:(DataSetBuilder subMenu)) startUp + " + + + + ^ + + #(#Menu + + #( + #(#MenuItem + #'label:' 'createColumn' + #'value:' #doCreateColumn + #'enabled:' #isNotModified + #'labelImage:' #(#ResourceRetriever #MenuEditor #iconCreateItem) + ) + #(#MenuItem + #'label:' '-' + ) + #(#MenuItem + #'label:' '' + ) + #(#MenuItem + #'label:' '-' + ) + #(#MenuItem + #'label:' 'stepUp' + #'value:' #'doMoveColumn:' + #'enabled:' #isNotModified + #'argument:' #up + #'labelImage:' #(#ResourceRetriever #UIPainter #iconStepUp) + ) + #(#MenuItem + #'label:' '-' + ) + #(#MenuItem + #'label:' 'stepDown' + #'value:' #'doMoveColumn:' + #'enabled:' #notModified + #'argument:' #down + #'labelImage:' #(#ResourceRetriever #UIPainter #iconStepDown) + ) + #(#MenuItem + #'label:' '-' + ) + ) nil + nil + ) +! ! + +!DataSetBuilder methodsFor:'accessing'! + +className + ^ (Smalltalk resolveName:className inClass:self class) notNil ifTrue:[className] ifFalse:[nil] +! + +className:aClassName + |cls| + + superclassName := nil. + + (className := aClassName) notNil ifTrue:[ + (cls := self resolveClassNamed) notNil ifTrue:[ + superclassName := cls superclass name asString. + ] ifFalse:[ + superclassName := 'Object' + ] + ] +! + +columns + "returns list of columns + " + ^ columns +! + +columns:aListOfColumns fromView:aColumnView + "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:[:aCol| + columns add:(aCol copy). + aCol rendererType == #rowSelector ifFalse:[list add:(aCol label)] + ifTrue:[list add:'Row Selector']. + ] + ]. +! ! + +!DataSetBuilder methodsFor:'accessing menu'! + +columnMenu + "this window spec was automatically generated by the UI Builder" + + ^ self class columnMenu + + +! + +doBrowseClass + |cls| + + (cls := self resolveClassNamed) notNil ifTrue:[ + SystemBrowser openInClass:cls + ] ifFalse:[ + self information:'no class yet'. + ]. + + + +! + +doCreateColumn + "create a new column after selected column or at left (nothing selected) + " + |label list| + + list := self seqList. + label := 'column ', list size printString. + columns add:(DataSetColumnSpec label:label selector:#ToBeDefined) afterIndex:selectedColumnIndex. + self seqList add:label afterIndex:selectedColumnIndex. + hasChanged := true. + + self modified ifFalse:[ + self selectedColumnModel value:(selectedColumnIndex + 1) + ]. + self updateColumnView. + +! + +doCutColumn + "remove selected column + " + |idx| + + (idx := selectedColumnIndex) ~~ 0 ifTrue:[ + self selectedColumnModel value:0. + self seqList removeIndex:idx. + ]. +! + +doDefineClass + "launch a dialog to define class and superclass + " + |aspects cls oldClass oldSuper| + + aspects := IdentityDictionary new. + oldClass := className. + oldSuper := superclassName. + + [true] whileTrue:[ + className notNil ifTrue:[ + (cls := self resolveClassNamed) notNil ifTrue:[ + superclassName := cls superclass name asString. + ]. + aspects at:#classNameChannel put:className asValue + ] ifFalse:[ + aspects at:#classNameChannel put:'DSVRow' asValue + ]. + + superclassName notNil ifTrue:[ + aspects at:#superclassNameChannel put:superclassName asValue + ] ifFalse:[ + aspects at:#superclassNameChannel put:'Object' asValue + ]. + + (self openDialogInterface:#defineClassNameSpec withBindings:aspects) ifFalse:[ + className := oldClass. + superclassName := oldSuper. + ^ self + ]. + className := ((aspects at:#classNameChannel) value) withoutSeparators. + superclassName := ((aspects at:#superclassNameChannel) value) withoutSeparators. + + className size == 0 ifTrue:[ + className := nil. + self information:'no valid className'. + ] ifFalse:[ + cls := self resolveClassNamed. + + cls notNil ifTrue:[ + cls := cls superclass name asString + ]. + + superclassName size == 0 ifTrue:[ + cls notNil ifTrue:[ + superclassName := cls + ] ifFalse:[ + superclassName := '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, '.\\' , + 'Check and try again if that is not what you want.') withCRs. + + superclassName := cls. + ] + ] + ] +! + +doGenerateCode + |cls superclass| + + className isNil ifTrue:[ + ^ self information:'no class defined' + ]. + cls := self resolveClassNamed. + + cls isNil ifTrue:[ + superclass := Smalltalk resolveName:superclassName inClass:self class. + + superclass isNil ifTrue:[ + ^ self information:'no superclass defined' + ]. + (self confirm:'create ' , className , ' ?') ifFalse:[ + ^ self + ]. + cls := superclass subclass:(className asSymbol) + instanceVariableNames:'' + classVariableNames:'' + poolDictionaries:'' + category:'Applications'. + ]. + + self generateChoicesIn:cls. + self generateMenuIn:cls. + self generatePrintSelectorIn:cls. + self generateReadSelectorIn:cls. + self generateWriteSelectorIn:cls. +! + +doMoveColumn:upOrDown + "move selected column up or down + " + |idx list label col size| + + (idx := selectedColumnIndex) == 0 ifTrue:[ + ^ self + ]. + list := self seqList. + size := list size. + + size == 1 ifTrue:[ + ^ self + ]. + hasChanged := true. + selectedColumnIndex := 0. + label := list at:idx. + col := columns at:idx. + list removeIndex:idx. + columns removeIndex:idx. + + upOrDown == #up ifTrue:[ + idx == 1 ifTrue:[idx := size] + ifFalse:[idx := idx - 1] + ] ifFalse:[ + idx == size ifTrue:[idx := 1] + ifFalse:[idx := idx + 1] + ]. + columns add:col beforeIndex:idx. + list add:label beforeIndex:idx. + self selectedColumnModel value:idx. + self updateColumnView. +! + +mainMenu + "this window spec was automatically generated by the UI Builder" + + ^ self class mainMenu + + +! + +subMenu + "this window spec was automatically generated by the UI Builder" + + ^ self class subMenu + + +! ! + +!DataSetBuilder methodsFor:'actions'! + +accept + "accept changes made + " + |column type| + + self modifiedChannel value == false ifTrue:[ + ^ self + ]. + isModified := true. + + (column := self selectedColumn) isNil ifTrue:[ + ^ self cancel + ]. + + type := (aspects at:#rendererType) value. + + type == #rowSelector ifTrue:[ + #( label width minWidth editorType choices readSelector printSelector + formatString type size height canSelect + ) 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 updateColumnView. + self cancel +! + +cancel + "remove all changes and reload selected column + " + |column| + + isModified := true. + (column := self selectedColumn) isNil ifTrue:[ + self tabModel value:0. + ] ifFalse:[ + aspects keysAndValuesDo:[:aKey :aModel| + aModel value:(column perform:aKey) + ]. + tabSelectionIndex == 0 ifTrue:[self tabModel value:1]. + ]. + self modifiedChannel value:false. + self isNotModified value:true. + isModified := false. +! ! + +!DataSetBuilder methodsFor:'aspects'! + +aspectFor:aKey + "returns aspect for a key or nil + " + ^ aspects at:aKey ifAbsent:[ super aspectFor:aKey ] + + +! + +editorTypeList + "generate list of supported editor types + " + |list| + + (list := builder bindingAt:#editorTypeList) isNil ifTrue:[ + list := OrderedCollection new. + DataSetColumnSpec slices do:[:aSlice||type| + type := aSlice at:1. + (list includes:type) ifFalse:[list add:type]. + ]. + builder aspectAt:#editorTypeList put:list. + + ]. + ^ list +! + +isNotModified + "returns a boolean value holder which is set to true if something is modified + and not accepted + " + ^ builder valueAspectFor:#isNotModified initialValue:true + + + +! + +modifiedChannel + "returns a boolean value holder which is set to true if something is modified + and not accepted + " + ^ builder booleanValueAspectFor:#modifiedChannel + + + +! + +rendererTypeList + "generate list of supported renderer types + " + |list| + + (list := builder bindingAt:#rendererTypeList) isNil ifTrue:[ + list := OrderedCollection new. + DataSetColumnSpec slices do:[:aSlice||type| + type := aSlice at:2. + (list includes:type) ifFalse:[list add:type]. + ]. + builder aspectAt:#rendererTypeList put:list. + + ]. + ^ list +! + +selectedColumnModel + "automatically generated by UIPainter ..." + + |holder| + + (holder := builder bindingAt:#selectedColumnModel) isNil ifTrue:[ + holder := AspectAdaptor new subject:self; forAspect:#selectedColumnIndex. + builder aspectAt:#selectedColumnModel put:holder. + ]. + ^ holder +! + +seqList + "automatically generated by UIPainter ..." + + |list| + + (list := builder bindingAt:#seqList) isNil ifTrue:[ + builder aspectAt:#seqList put:(list := List new). + ]. + ^ list +! + +specChannel + "automatically generated by UIPainter ..." + + |holder| + + (holder := builder bindingAt:#specChannel) isNil ifTrue:[ + builder aspectAt:#specChannel put:(holder := ValueHolder new). + ]. + ^ holder +! + +tabList + "automatically generated by UIPainter ..." + + ^ self class slices collect:[:aSlice| aSlice first ] + +! + +tabModel + "returns a value holder which keeps the index of the current selected tab or 0 + " + |holder| + + (holder := builder bindingAt:#tabModel) isNil ifTrue:[ + holder := AspectAdaptor new subject:self; forAspect:#tabSelectionIndex. + builder aspectAt:#tabModel put:holder. + ]. + ^ holder +! + +typeList + "automatically generated by UIPainter ..." + + ^ #( string password number numberOrNil symbolOrNil ) +! ! + +!DataSetBuilder methodsFor:'change & update'! + +update:something with:aParameter from:someObject + "one of my aspects has changed; update modified channel + " + isModified ifFalse:[ + isModified := hasChanged := true. + self modifiedChannel value:true. + self isNotModified value:false. + ] +! ! + +!DataSetBuilder methodsFor:'code generation'! + +compile:aCode forClass:aClass inCategory:aCategory + "compile method for class in a category + " + ByteCodeCompiler compile:aCode withCRs forClass:aClass inCategory:aCategory +! + +generateChoicesIn:aClass + "generate code for #choices + " + |sel catg code| + + catg := 'accessing choices' asSymbol. + code := '\' + , ' "automatically generated by DataSetBuilder ..."\' + , '\' + , ' "get choices for visual editor; (a list of labels)\' + , '\' + , ' ^ nil' + . + + columns do:[:aColumn| + ( aColumn canSelect + and:[aColumn rendererType ~~ #rowSelector + and:[(sel := aColumn choices) notNil + and:[(aClass implements:sel) not]]] + ) ifTrue:[ + self compile:(sel asString, code) forClass:aClass inCategory:catg + ] + ] +! + +generateMenuIn:aClass + "generate code for #menu + " + |sel catg code| + + catg := 'accessing menus' asSymbol. + code := '\' + , ' "automatically generated by DataSetBuilder ..."\' + , '\' + , ' "get middleButton menu for selected cell in column"\' + , '\' + , ' ^ nil' + . + + columns do:[:aColumn| + ( aColumn canSelect + and:[(sel := aColumn menu) notNil + and:[(aClass implements:sel) not]] + ) ifTrue:[ + self compile:(sel asString, code) forClass:aClass inCategory:catg + ] + ] +! + +generatePrintSelectorIn:aClass + "generate code for #printSelector + " + |sel catg code| + + catg := 'accessing printSelector' asSymbol. + code := 'aGC\' + , ' "automatically generated by DataSetBuilder ..."\' + , '\' + , ' "get drawable image or text on a gc"\' + , '\' + , ' ^ nil' + . + + columns do:[:aColumn| + ( aColumn rendererType ~~ #rowSelector + and:[(sel := aColumn printSelector) notNil + and:[(aClass implements:sel) not]] + ) ifTrue:[ + self compile:(sel asString, code) forClass:aClass inCategory:catg + ] + ] +! + +generateReadSelectorIn:aClass + "generate code for #readSelector + " + |sel catg code bCode| + + catg := 'accessing readSelector' asSymbol. + code := '\' + , ' "automatically generated by DataSetBuilder ..."\' + , '\' + , ' "get value"\' + , '\' + . + + columns do:[:aColumn| + ( aColumn rendererType ~~ #rowSelector + and:[(sel := aColumn readSelector) notNil + and:[(aClass implements:sel) not]] + ) ifTrue:[ + (aColumn printSelector isNil or:[aColumn canSelect]) ifTrue:[ + bCode := sel asString, code. + aColumn rendererType == #CheckToggle ifFalse:[ + bCode := bCode, ' ^ nil' + ] ifTrue:[ + bCode := bCode, ' ^ true' + ]. + self compile:bCode forClass:aClass inCategory:catg + ] + ] + ] +! + +generateWriteSelectorIn:aClass + "generate code for #writeSelector + " + |sel catg code| + + catg := 'accessing writeSelector' asSymbol. + code := 'aValue\' + , ' "automatically generated by DataSetBuilder ..."\' + , '\' + , ' "set value"\' + . + + columns do:[:aColumn| + ( (sel := aColumn writeSelector) notNil + and:[(aClass implements:sel) not] + ) ifTrue:[ + self compile:(sel asString, code) forClass:aClass inCategory:catg + ] + ] +! ! + +!DataSetBuilder methodsFor:'initialization'! + +initialize + "setup aspects used by column description specifications + " + |holder| + + super initialize. + selectedColumnIndex := 0. + tabSelectionIndex := 0. + columns := OrderedCollection new. + aspects := IdentityDictionary new. + hasChanged := false. + isModified := false. + + #( + label + canSelect + choices + editorType + formatString + size + type + width + minWidth + height + menu + printSelector + readSelector + rendererType + showColSeparator + showRowSeparator + + ) do:[:aKey| + aspects at:aKey put:(holder := ValueHolder new). + holder addDependent:self. + ]. + +! ! + +!DataSetBuilder methodsFor:'private'! + +resolveClassNamed + "returns current class or nil + " + ^ Smalltalk resolveName:className inClass:self class. + +! + +updateColumnView + "update column view from column descriptions + " + columnView notNil ifTrue:[ + columnView columnDescriptors:columns. + ]. +! ! + +!DataSetBuilder methodsFor:'queries'! + +hasChanged + "returns true if changes are done to the original column description + " + ^ hasChanged +! + +modified + "returns true if current specification is modified + " + ^ self modifiedChannel value +! ! + +!DataSetBuilder methodsFor:'selection'! + +selectedColumn + "returns selected column or nil + " + ^ selectedColumnIndex == 0 ifFalse:[columns at:selectedColumnIndex] + ifTrue:[nil] +! + +selectedColumnIndex + "returns selected column index or 0 + " + ^ selectedColumnIndex +! + +selectedColumnIndex:something + "change selected column and update specifications + " + something == selectedColumnIndex ifFalse:[ + selectedColumnIndex := something ? 0. + self cancel. + ]. + +! + +tabSelectionIndex + "returns selected tab index or 0 + " + ^ tabSelectionIndex +! + +tabSelectionIndex:something + "change selected tab and set corresponding specification + " + |specSelector| + + something == tabSelectionIndex ifTrue:[ + ^ self + ]. + self selectedColumn isNil ifTrue:[ + tabSelectionIndex == 0 ifTrue:[^ self ]. + tabSelectionIndex := 0 + ] ifFalse:[ + (tabSelectionIndex := something) ~~ 0 ifTrue:[ + specSelector := (self class slices at:tabSelectionIndex) last. + ] + ]. + self specChannel value:specSelector + + +! ! + +!DataSetBuilder class methodsFor:'documentation'! + +version + ^ '$Header$' +! !