<div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000;text-align: left" dir="ltr">
                                        <img id="f3b9c509-5b07-4588-b539-648fb068ec88" src="cid:145d7042-97f7-4715-a1ba-4247c930a7a6" width="309" height="314"></img><br><div class="mb_sig"></div>
                                        <blockquote class="history_container" type="cite" style="border-left-style: solid;border-width: 1px;margin-top: 20px;margin-left: 0px;padding-left: 10px;min-width: 500px">
                        <p style="color: #AAAAAA; margin-top: 10px;">Am 11.01.2021 17:36:52 schrieb commits@source.squeak.org <commits@source.squeak.org>:</p><div style="font-family:Arial,Helvetica,sans-serif">Marcel Taeumel uploaded a new version of ToolBuilder-Morphic to project The Trunk:<br>http://source.squeak.org/trunk/ToolBuilder-Morphic-mt.270.mcz<br><br>==================== Summary ====================<br><br>Name: ToolBuilder-Morphic-mt.270<br>Author: mt<br>Time: 11 January 2021, 5:36:43.295446 pm<br>UUID: 5171b75b-ee89-b14f-8ec9-a27cdfaa52bb<br>Ancestors: ToolBuilder-Morphic-mt.269<br><br>To pluggable dialogs, add an expand button if the model supports #preferredExtent. Also tweaks a list-chooser's initial extent show 5 to 15 items which each about 10 to 20 characters, depending on the list's content.<br><br>This commit addresses the concerns raised in ToolBuilder-Morphic-cbc.270 (inbox).<br>See http://forum.world.st/The-Inbox-ToolBuilder-Morphic-cbc-270-mcz-tp5126045.html<br><br>=============== Diff against ToolBuilder-Morphic-mt.269 ===============<br><br>Item was changed:<br>  ----- Method: ListChooser>>buildWith: (in category 'building') -----<br>  buildWith: builder<br>  <br>        | dialogSpec searchBarHeight listSpec fieldSpec |<br>     <br>+     searchBarHeight := self searchBarHeight.<br>-     searchBarHeight := Preferences standardDefaultTextFont height * 1.75.<br>         <br>      dialogSpec := builder pluggableDialogSpec new<br>                 model: self;<br>                  title: #title;<br>                closeAction: #closed;<br>                 extent: self initialExtent;<br>           autoCancel: true; "Behave like a pop-up menu. Historical reasons."<br>                  children: OrderedCollection new;<br>              buttons: OrderedCollection new;<br>               yourself.<br>     <br>      listSpec := builder pluggableListSpec new.<br>    listSpec <br>             model: self;<br>                  list: #items; <br>                getIndex: #selectedIndex; <br>            setIndex: #selectedIndex:; <br>           doubleClick: #accept;<br>                 "keystrokePreview: #keyStrokeFromList:;"<br>            autoDeselect: false;<br>                  filterableList: true;<br>                 clearFilterAutomatically: false;<br>              name: #list;<br>                  frame: (LayoutFrame fractions: (0@0 corner: 1@1) offsets: (0@searchBarHeight corner: 0@0)).<br>   dialogSpec children add: listSpec.<br>    <br>      fieldSpec := builder pluggableInputFieldSpec new.<br>     fieldSpec <br>            model: self;<br>                  name: #searchText ;<br>           getText: #searchText;<br>                 editText: #searchText:;<br>               setText: #acceptText:;<br>                selection: #textSelection;<br>            menu: nil;<br>            indicateUnacceptedChanges: false;<br>             askBeforeDiscardingEdits: false;<br>              help: (self addAllowed ifTrue: ['Type new or filter existing...' translated] ifFalse: ['Type to filter existing...' translated]);<br>             frame: (LayoutFrame fractions: (0@0 corner: 1@0) offsets: (0@0 corner: 0@searchBarHeight)).<br>   dialogSpec children add: fieldSpec.<br>   <br>      "Buttons"<br>   dialogSpec buttons add: (<br>             builder pluggableButtonSpec new<br>                       model: self; <br>                         label: #acceptLabel;<br>                          action: #accept;<br>                      enabled: #canAcceptOrAdd;<br>                     color: #acceptColor).<br>  <br>     dialogSpec buttons add: (<br>             builder pluggableButtonSpec new<br>                       model: self; <br>                         label: 'Cancel';<br>                      action: #cancel;<br>                      color: #cancelColor).<br>                 <br>      dialogMorph := builder build: dialogSpec.<br>     dialogMorph addKeyboardCaptureFilter: self ; positionOverWidgetNamed: #searchText.<br>    listMorph := builder widgetAt: #list.<br>         listMorph allowEmptyFilterResult: true.<br>       <br>      ^ dialogMorph!<br><br>Item was changed:<br>  ----- Method: ListChooser>>initialExtent (in category 'building') -----<br>  initialExtent<br>  <br>+    | listFont itemCount maxItemSize cellSize |<br>-  | listFont |<br>          listFont := Preferences standardListFont.<br>+    itemCount := items size.<br>+     maxItemSize := items inject: 0 into: [:max :item | max max: item size].<br>+      cellSize := (listFont widthOf: $m) @ listFont height.<br>+        <br>+     ^ ((maxItemSize + 1 "breathing space" min: 20 max: 10)<br>+             @ (itemCount + 1 "breathing space" min: 15 max: 5)<br>+                 * cellSize) + (0@ self searchBarHeight)!<br>-     ^ (20 * (listFont widthOf: $m))@(15 * listFont height)!<br><br>Item was added:<br>+ ----- Method: ListChooser>>preferredExtent (in category 'building') -----<br>+ preferredExtent<br>+ <br>+         | listFont cellSize |<br>+        listFont := Preferences standardListFont.<br>+    cellSize := (listFont widthOf: $m) @ listFont height.<br>+        <br>+     ^  ((items inject: 0 into: [:max :item | max max: (listFont widthOfString: item)])<br>+           @ (items size * listFont height))<br>+                    + ((1@1) * cellSize) "breathing space"<br>+                     + (0@ self searchBarHeight)!<br><br>Item was added:<br>+ ----- Method: ListChooser>>searchBarHeight (in category 'building') -----<br>+ searchBarHeight<br>+ <br>+    ^ Preferences standardDefaultTextFont height * 1.75!<br><br>Item was changed:<br>  ----- Method: ListMultipleChooser>>initialExtent (in category 'toolbuilder') -----<br>  initialExtent<br>  <br>+   | listFont itemCount maxItemSize cellSize |<br>-  | listFont |<br>          listFont := Preferences standardListFont.<br>+    itemCount := labels size.<br>+    maxItemSize := labels inject: 0 into: [:max :item | max max: item size].<br>+     cellSize := (listFont widthOf: $m) @ listFont height.<br>+        <br>+     ^ ((maxItemSize + 1 "breathing space" min: 20 max: 10)<br>+             @ (itemCount + 1 "breathing space" min: 15 max: 5)<br>+                 * cellSize)!<br>-         ^ (20 * (listFont widthOf: $m))@(15 * listFont height)!<br><br>Item was added:<br>+ ----- Method: ListMultipleChooser>>preferredExtent (in category 'toolbuilder') -----<br>+ preferredExtent<br>+ <br>+      | listFont cellSize |<br>+        listFont := Preferences standardListFont.<br>+    cellSize := (listFont widthOf: $m) @ listFont height.<br>+        <br>+     ^  ((labels inject: 0 into: [:max :item | max max: (listFont widthOfString: item)])<br>+          @ (labels size * listFont height))<br>+                   + ((1@1) * cellSize) "breathing space"!<br><br>Item was changed:<br>  ----- Method: MorphicToolBuilder>>buildPluggableDialog: (in category 'widgets optional') -----<br>  buildPluggableDialog: aSpec<br>  <br>     | widget |<br>  <br>        widget := self dialogClass new.<br>       self register: widget id: aSpec name.<br>         <br>      widget model: aSpec model.<br>  <br>        "Set child dependent layout properties. The pane morph holds the special contents."<br>         widget paneMorph wantsPaneSplitters: (aSpec wantsResizeHandles ifNil: [true]).<br>        self setLayoutHintsFor: widget paneMorph spec: aSpec.<br>         widget paneMorph layoutInset: (aSpec padding ifNil: [ProportionalSplitterMorph gripThickness]).<br>       widget paneMorph cellGap: (aSpec spacing ifNil: [ProportionalSplitterMorph gripThickness]).<br>   widget paneMorph wantsPaneSplitters ifTrue: [<br>                 widget paneMorph addCornerGrips"addEdgeGrips".<br>              widget paneMorph grips do: [:ea | ea showHandle: true]].<br>  <br>          "Now create the children."<br>          panes := OrderedCollection new.<br>       aSpec children isSymbol<br>               ifTrue: [<br>                     widget getChildrenSelector: aSpec children.<br>                   widget update: aSpec children]<br>                ifFalse: [<br>                    self buildAll: aSpec children in: widget paneMorph].<br>  <br>      "Now create the buttons."<br>   aSpec buttons isSymbol<br>                ifTrue: [<br>                     widget getButtonsSelector: aSpec buttons.<br>                     widget update: aSpec buttons]<br>                 ifFalse: [<br>                    self buildAll: aSpec buttons in: widget buttonRowMorph.<br>                       widget updateButtonProperties].<br>  <br>   aSpec title ifNotNil: [:label |<br>               label isSymbol <br>                       ifTrue:[widget getTitleSelector: label; update: label]<br>                        ifFalse:[widget title: label]].<br>       aSpec message ifNotNil: [:label |<br>             label isSymbol <br>                       ifTrue:[widget getMessageSelector: label; update: label]<br>                      ifFalse:[widget message: label]].<br>     <br>      "Interaction behavior."<br>     aSpec autoCancel ifNotNil: [:b | widget autoCancel: b].<br>       aSpec exclusive ifNotNil: [:b | widget exclusive: b].<br>                 <br>      widget closeDialogSelector: aSpec closeAction.<br>        self buildHelpFor: widget spec: aSpec. <br>  <br>   "Everything is shrink-wrapped around the pane morph."<br>+      widget paneMorph extent: (aSpec extent ifNil:[widget initialExtent])<br>+                 + (widget paneMorph layoutInset * 2) asPoint.<br>-        widget paneMorph extent: (aSpec extent ifNil:[widget initialExtent]).<br>  <br>     ^ widget!<br><br>Item was added:<br>+ ----- Method: PluggableDialogWindow>>createTitle: (in category 'initialization') -----<br>+ createTitle: aString<br>+         "Overridden to add an extra expand button. Yet, it depends on the model's interface whether that button will be visible. See #model:."<br>+ <br>+         | box expandButton|<br>+  super createTitle: aString.<br>+ <br>+      expandButton := SystemWindowButton new<br>+               name: #expandButton;<br>+                 color: Color transparent;<br>+            target: self;<br>+                actionSelector: #expandDialogPane;<br>+           balloonText: 'Expand this dialog' translated;<br>+                borderWidth: 0;<br>+              yourself.<br>+    SystemWindow expandBoxImage scaleIconToDisplay in: [:icon |<br>+          expandButton labelGraphic: icon; extent: icon extent].<br>+       <br>+     box := self submorphNamed: #title.<br>+   box addMorphBack: expandButton.!<br><br>Item was added:<br>+ ----- Method: PluggableDialogWindow>>expandDialogPane (in category 'running') -----<br>+ expandDialogPane<br>+         "Expand the dialog pane to its preferred extent. Honor the visible area in the world."<br>+ <br>+         | visibleArea decorationOffset expandedExtent |<br>+      visibleArea := self currentWorld visibleClearArea.<br>+   decorationOffset := self extent - self paneMorph extent.<br>+     expandedExtent := self model preferredExtent + (self paneMorph layoutInset * 2) asPoint.<br>+     <br>+     self paneMorph extent: (expandedExtent min: visibleArea extent - decorationOffset).<br>+ <br>+      self fullBounds.<br>+     self moveToPreferredPosition.!<br><br>Item was changed:<br>  ----- Method: PluggableDialogWindow>>model: (in category 'accessing') -----<br>+ model: newModel<br>- model: anObject<br>  <br>    model ifNotNil: [model removeDependent: self].<br>+       newModel ifNotNil: [<br>+                 newModel addDependent: self.<br>+                 (newModel respondsTo: #preferredExtent)<br>+                      ifFalse: [((self submorphNamed: #title) submorphNamed: #expandButton) delete]].<br>+      model := newModel.!<br>-  anObject ifNotNil: [anObject addDependent: self].<br>-    model := anObject.!<br><br><br></div></blockquote></div>