I ran across an interesting requirement today - I needed to enable/disable individual settings in the BottomFeeder settings tool. That tool is simply a user of the new settings framework created by Vassili. In a typical VW interface, enabling/disabling widgets isn't hard - you do something like this:
(self builder componentAt: #idOfWidgetHere) enable.
It gets trickier when the widget is in a subcanvas - the builder used to create the subcanvas isn't typically kept, and the widgets in it aren't tracked by the builder in the outer UI. Typically, one solves that by grabbing a copy of the builder used for the subcanvas and caching it. Each page of the settings tool, is a subcanvas, so I had to accomplish the same thing. Here's where I had to do some digging. In class SettingsManager, there's a method that swaps the pages:
pageSelected | page tree | page := self pageListHolder selection. page isNil ifTrue: [^self]. tree := self pageListHolder list. ((tree isExpandable: page) and: [(tree isExpanded: page) not]) ifTrue: [tree expand: self pageListHolder selectionIndex]. (self widgetAt: #GroupBox) label: ((TreeViewIndentedLabelAndIcon with: page label) icon: page listIcon). "This is the only kind of label with a sane icon positioning." page builder: nil. (self widgetAt: #Subcanvas) client: page spec: page spec builder: self builder newSubBuilder. self updatePageSubcanvasScrollbar
The actual swapping happens in the #client:spec:builder: message send. So, to do what I needed to do, I changed that section as follows by overriding that method in my subclass:
newBuilder := self builder newSubBuilder. (self widgetAt: #Subcanvas) client: page spec: page spec builder: newBuilder. self updatePageSubcanvasScrollbar. self possiblyAdjustEnablementFor: newBuilder onPage: page
By holding a reference to the builder, I can call out to a new method and check which page we are on - and also check the applicable application state. From there, I can grab the relevant widgets and enable/disable them. Here's what that method looks like:
possiblyAdjustEnablementFor: newBuilder onPage: page "if we are in certain application states, disable some settings" RSS.RSSFeedManager default isUpdating ifFalse: [^self]. page id = #(#rss #network) ifFalse: [^self]. "This grabs each wrapper for the thread options and disables them if we are in the update cycle" #(#'-rss-network-runThreadedUpdates' #'-rss-network-shouldSpreadUpdates' #'-rss-network-shouldThrottleThreads') do: [:each | (newBuilder componentAt: each) disable]
Those ID's are not pretty - they are manufactured by the settings framework, and I figured out what they were with a breakpoint and an inspector. In any case, the method checks the application state and the page, and then toggles the appropriate settings based on those. In this case, I'm making sure that the threading/non-threading of updates cannot be mucked with while the update process is awake and running. In general, it looks like it's easy enough for any application to enable/disable settings options via this strategy.