Today we look at the TabControl, which after all our other HOW-TOs, seems pretty simple.
Design
We'll create a window with a TabControl in it, then we'll add pages to the TabControl using previous work, and then show how to make the pages display well.
As always, we start off with a subclass of UserInterface:
Smalltalk defineClass: #TabControlWork
superclass: #{Widgetry.UserInterface}
indexedType: #none
private: false
instanceVariableNames: 'tabControl '
classInstanceVariableNames: ''
imports: 'private Widgetry.*'
category: '(none)'
Now we'll add our TabControl in a #createInterface method:
createInterface
tabControl := TabControl new.
tabControl frame: (FractionalFrame
fractionLeft: 0.05
right: 0.95
top: 0.05
bottom: 0.95).
self addComponent: tabControl
Now if we execute TabControlWork open, this is what we see:
While that's not very exciting, there is one thing to note here. When there are no tabs, the area of the TabControl is just the full page. One of the options of the TabControl is to not show tabs at all with #displayTabs: false. The default is true.
If you do turn off displaying of tabs then the TabControl can be used as the basis of a Wizard. You fill up your TabControl with pages, and then use the #showPage: anInteger API to change the page. More on that in our Extra Credit
Like Sand Through An Hourglass
To add tabs to a TabControl, we add pages. A page is made up of a Form and optional tab features. The features are a label and/or an image, and if both an optional flag to display the image on the right or left.
We'll use the knowledge we gained last time to turn existing UserInterface subclasses into Forms, and add pages with the result. We'll start off with our last work: MoreFormWork and use that as our first page. Here is the #hookupInterface method:
hookupInterface
tabControl addPage: (Form new addComponentsFromClass: MoreFormWork).
Now if we open our example, this is what it looks like:
We see that spindly tab up there, but the page we added didn't show. This is not a bug. By default, the initial tab is page 0, or no page. If we go ahead and click on our first tab up there, this is now what we see:
That's better. Since total size of the form was created for a window that was 200 @ 200 in size, all that falls outside that in the TabControl's page is clipped. If you resize the window, the rest of the page will show as the TabControl resizes because of the FractionalFrame we used.
The Prisoner
Let's add another page, this time using RadioButtonWork from way back, and this time we'll add a label for the page:
hookupInterface
tabControl addPage: (Form new addComponentsFromClass: MoreFormWork).
tabControl
addPage: (Form new addComponentsFromClass: RadioButtonWork)
label: 'Radio Buttons'
And now reopening and selecting the Radio Buttons tab, we see:
Again, you would have to resize the window to see all of the page.
The Cool Kids
Now we'll add another page, this time using ListBoxWork, and we'll use an image instead of a label. For fun, we'll just take the balloon image that is supplied by the ListIconLibrary class:
hookupInterface
tabControl addPage: (Form new addComponentsFromClass: MoreFormWork).
tabControl
addPage: (Form new addComponentsFromClass: RadioButtonWork)
label: 'Radio Buttons'.
tabControl
addPage: (Form new addComponentsFromClass: ListBoxWork)
image: (ListIconLibrary visualFor: #balloon)
And this is what that looks like when the balloon tab is selected.
Get The Lead Out
Now we'll add a page using the ResizingSplitterWork, and we'll have both a label and an image. This time, we'll use the bug image:
hookupInterface
tabControl addPage: (Form new addComponentsFromClass: MoreFormWork).
tabControl
addPage: (Form new addComponentsFromClass: RadioButtonWork)
label: 'Radio Buttons'.
tabControl
addPage: (Form new addComponentsFromClass: ListBoxWork)
image: (ListIconLibrary visualFor: #balloon).
tabControl
addPage: (Form new addComponentsFromClass: ResizingSplitterWork)
label: 'Mini Browser'
image: (ListIconLibrary visualFor: #bug).
Now on opening our work, this is what we initially see:
The size of all the tabs is too big to show in our window, so the scroll arrow buttons now show. If we click on the right arrow button, this is what we see:
It seems that the total size of the remaining tabs is still too big to show with a single scroll. Let's click that right arrow button again, and this is what we see:
Ah, that's better. Now we click on our Mini Browser tab:
Reverse
We'll now add a page using the DropDownListWork, and we'll do the label and image thing, but this time, we'll tell it to put the image on the right, and we'll use the name space image:
hookupInterface
tabControl addPage: (Form new addComponentsFromClass: MoreFormWork).
tabControl
addPage: (Form new addComponentsFromClass: RadioButtonWork)
label: 'Radio Buttons'.
tabControl
addPage: (Form new addComponentsFromClass: ListBoxWork)
image: (ListIconLibrary visualFor: #balloon).
tabControl
addPage: (Form new addComponentsFromClass: ResizingSplitterWork)
label: 'Mini Browser'
image: (ListIconLibrary visualFor: #bug).
tabControl
addPage: (Form new addComponentsFromClass: DropDownListWork)
label: 'Drop Downs'
image: (ListIconLibrary visualFor: #name space)
imageOnRight: true
Now after opening our work, and navigating to the last tab, this is what we see:
Extra Credit
For extra credit, we'll make our window much wider when we open it, and then tell the TabControl to show the second page which will then be seen when we open it:
hookupWindow
self mainWindow frame specifiedSize: 400 @ 250.
hookupInterface
tabControl addPage: (Form new addComponentsFromClass: MoreFormWork).
tabControl
addPage: (Form new addComponentsFromClass: RadioButtonWork)
label: 'Radio Buttons'.
tabControl
addPage: (Form new addComponentsFromClass: ListBoxWork)
image: (ListIconLibrary visualFor: #balloon).
tabControl
addPage: (Form new addComponentsFromClass: ResizingSplitterWork)
label: 'Mini Browser'
image: (ListIconLibrary visualFor: #bug).
tabControl
addPage: (Form new addComponentsFromClass: DropDownListWork)
label: 'Drop Downs'
image: (ListIconLibrary visualFor: #name space)
imageOnRight: true.
tabControl showPage: 2.
Isn't that pretty?
Pane In The Neck
This is the last of our How To examples for working with Widgetry Panes. We've covered all the Panes in Widgetry, if not all the features of every Pane.
It is time to move on to a new topic. Next time, we'll start looking at how to create a custom Pane in Widgetry.
And So It GoesSames