The absolute beginners guide - Part VII - for gnu-smalltalk/gtk (ComboBoxes)

Tagged:  •    •    •    •  

After I got now through the creation of combo-boxes, I just want today explain the creation-process.

Update warning:
|-
|Currently, I use 2 extensions to the GTK.GtkComboBox instance in this example. But I currently don't know, if there should be another way or if these changes will go into the original distribution. If that will be clear one day, i might update this thread accordingly.
Might be updated in the future...

For creating of ComboBoxes, we have 2 possibilities, a simple one and a bit more object-oriented way of creation. First we will have - of course - a look into the simple way and afterwards, I will explain the bit more complicated one.

The simple way

The simple way can only handle text-strings, and handles only one column per combo-box.

If you read the other blog-posts before, you know how the application is structured. For this example we add another instance-variable named simplecombo and call the createSimpleCombo method from the initialization method and pack the simplecombo into the container.

The interesting part starts in the createSimpleCombo method which is - because it's simple - relatively short...:

createSimpleCombo [
    simplecombo := GTK.GtkComboBox newText.
    simplecombo appendText: 'entry 1';
                appendText: 'entry 2';
                appendText: 'entry 3'.
    simplecombo setActive: 2.

    simplecombo connectSignal: 'changed' to: self selector: #simpleComboChanged
]

We create the ComboBox with the newText'' method, add 3 entries to the ComboBox and preselected the 2nd entry (we have to start from 0 here - so it's actually the 3rd entry) and connected the changed signal''' to a callback-method. The changed-signal does what it says, it informs us, if the selection of the ComboBox would change.

To see the callback working, we also create the callback-method:

simpleComboChanged [
    ('changed index to: ', simplecombo getActive printString) printNl
]

That was realy a one-minute task.

No let's go on with object way...

The "object" way

Here I have 2 examples for this. One, that resembles the first ComboBox and the other one, which will show you, how you could present more than one column to the user.

The start is the same, we create an additional instance-variable called combobox, call the createCombobox method from our initialize one and pack the combobox into the container.

And here's the createCombobox method:

createCombobox [
    | listModel iterator col rend |

    listModel := GTK.GtkListStore new: 1 varargs: {GTK.GValue gTypeString}.

    iterator := GTK.GtkTreeIter new.
    listModel append: iterator.
    listModel setOop: iterator column: 0 value: 'One'.

    iterator := GTK.GtkTreeIter new.
    listModel append: iterator.
    listModel setOop: iterator column: 0 value: 'Two'.

    iterator := GTK.GtkTreeIter new.
    listModel append: iterator.
    listModel setOop: iterator column: 0 value: 'Three'.

    combobox := GTK.GtkComboBox newWithModel: listModel.

    rend := GTK.GtkCellRendererText new.
    combobox packStart: rend expand: true;
        addAttribute: rend attribute: 'text' column: 0;
        setActive: 0;

        connectSignal: 'changed' to: self selector: #comboboxChanged
]

comboboxChanged [
    ('changed index to: ', combobox getActive printString) printNl
]

This type of version works with the view (GtkComboBox) and a Model (in this case a GtkListStore).
Each row we want to add, must have an iterator which should be appended first. Afterwards, we could set our data for the specified column.

After our model is populated, I created the ComboBox itself, with the model as a parameter. You could also set the model later on with the setModel: method, but here, I choosed this way.

Each column of the ComboBox must have it's own CellRenderer, so we created the GtkCellRendererText and pack it to the ComboBox. Both methods packStart: and addAttribute: is the extension to the ComboBox which I use. See the code here:

GTK.GtkComboBox extend [

    packStart: cell expand: expand [
        <cCall: 'gtk_cell_layout_pack_start' returning: #void
            args: #( #self #cObject #boolean )>
    ]

    addAttribute: cell attribute: attribute column: column [
        <cCall: 'gtk_cell_layout_add_attribute' returning: #void
            args: #( #self #cObject #string  #int)>
    ]

]

The second example for the OO-way

In this second example, we will create a ComboBox with 2 columns, the first column contains a number and the second one a textual representation. So let's have a look at the source:

createMultiColCB [
    | listModel iterator col rend1 rend2 |

    multicol := GTK.GtkComboBox new.
    rend1 := GTK.GtkCellRendererText new.
    rend2 := GTK.GtkCellRendererText new.
    multicol packStart: rend1 expand: true.
    multicol addAttribute: rend1 attribute: 'text' column: 0.
    multicol packStart: rend2 expand: true.
    multicol addAttribute: rend2 attribute: 'text' column: 1.

    listModel := GTK.GtkListStore new: 2
        varargs: {GTK.GValue gTypeInt. GTK.GValue gTypeString}.
    multicol setModel: listModel.

    iterator := GTK.GtkTreeIter new.
    listModel append: iterator.
    listModel setOop: iterator column: 0 value: 1.
    listModel setOop: iterator column: 1 value: 'Italy'.

    iterator := GTK.GtkTreeIter new.
    listModel append: iterator.
    listModel setOop: iterator column: 0 value: 2.
    listModel setOop: iterator column: 1 value: 'France'.

    iterator := GTK.GtkTreeIter new.
    listModel append: iterator.
    listModel setOop: iterator column: 0 value: 3.
    listModel setOop: iterator column: 1 value: 'Swiss'.

    multicol setActive: 0.
]

In this example I ordered the source a bit, that you see, that there's no dependency in the order of creating the objects. Only this, that a objects has first to be created before I add it to the CombBox or list.

We also need 2 CellRenderer (even a text-renderer for our number column) because our ListStore has also 2 columns, one of type gTypeInt and the other one of the type gTypeString.

That's all for today and for the ComboBoxes.

Happy coding!
Joachim.

User login