How to dynamically resize widgets
I haven't posted an honest to goodness example in awhile - here's how to accomplish the common UI need to "zoom" a widget. I didn't come up with this code myself - in the finest Smalltalk tradition, I stole the code from the file viewer, which supports this as well.
In BottomFeeder, you can zoom the HTML pane to cover the entire item view/html view area. To do that, you need to figure out where your new widget bounds are, and then use them. Here's the "outer" method in Bf that either zooms or unzooms, as appropriate:
actuallyZoomHTMLView: htmlView topLayout: topLayout splitter: splitter2 top: top | sub myDivider | sub := self widgetAt: #feedID. myDivider := (self getComponentFromSubcanvas: sub withID: #Divider2). (self isZoomed: top) ifTrue: [self unzoomHTMLView: htmlView topLayout: topLayout splitter: splitter2 top: top. myDivider beVisible] ifFalse: [self zoomHTMLView: htmlView splitter: splitter2 top: top. htmlView takeKeyboardFocus. myDivider beInvisible]. self currentBuilder window refresh. htmlView beVisible
Now, there are a couple of curious things in there, including the #getComponentFromSubcanvas: message send. In Wrapper (as opposed to Pollock), it can be a pain in the butt to grab a wrapped UI if you haven't kept the builder around. in Bf, I wrote a convenience method to deal with that.
The arguments coming into that method are the wrappers for the html pane, the layout for the item grid (or list) pane, and the wrapper for the splitter. All the wrappers are retrieved like this:
wrapper := self builder componentAt: #widgetIDHere.
while the layout is retrieved:
wrapper := self builder componentAt: #splitterID. layout := wrapper component layout.
Having all that, we now have enough information to actually resize the pane. That code is a simple convenience method in BottomFeeder:
zoomHTMLView: htmlView splitter: splitter2 top: top "zooms the HTML view, covering the item pane" top beInvisible. splitter2 beInvisible. (htmlView component layout) leftFraction: 0; leftOffset: 0; topOffset: 0; topFraction: 0
The unzoom method looks similar:
unzoomHTMLView: htmlView topLayout: topLayout splitter: splitter2 top: top "unzooms the HTML view, exposing the item pane again" (htmlView component layout) leftFraction: 0; leftOffset: 0; topFraction: topLayout bottomFraction; topOffset: topLayout bottomOffset. top beVisible. splitter2 beVisible
What you are doing here is handing the wrapper a new layout frame to live in (thus the four arguments, telling it what the edges are). This is easy enough to extend to any widget or set of widgets, and, in fact, the code in Bf should be more generalized. It works though, and I haven't had a strong desire to muck with code that works well :)
You should be able to adapt this idea to your own UIs easily - and if you need an in image example, have a look at class Tools.FileTools.FileBrowser - specifically, at the #toggleZoom method.
