PyMaemo/UI tutorial/Data selection: Difference between revisions

From Maemo Wiki
Jump to navigationJump to search
imported>amigadave
add C documentation link
 
(12 intermediate revisions by 4 users not shown)
Line 1: Line 1:
= Data selection =
{{main|Legacy Maemo 5 Documentation/Graphical UI Tutorial/Data selection}}
 
Hildon provides a set of widgets for data selection specially designed for touchscreens that allows to build simple and easy-to-use interfaces.
Hildon provides a set of widgets for data selection specially designed for touchscreens that allows to build simple and easy-to-use interfaces.


Line 6: Line 7:
In addition, Hildon also provides a specialized dialog and a specialized button to be used in combination with a selector.
In addition, Hildon also provides a specialized dialog and a specialized button to be used in combination with a selector.


==Touch selector==


==Touch selector ==
<code>HildonTouchSelector</code> is the mentioned selector widget. This widget can display several pannable columns. Each column is represented by a <code>GtkTreeModel</code> and single or multiple selection is allowed.
HildonTouchSelector is the mentioned selector widget. This widget can display several pannable columns. Each column is represented by a GtkTreeModel and single or multiple selection is allowed.


===Text Columns Example===


===Text Columns Example===
This is the simplest example: a selector that shows a single text column.
This is the simplest example: a selector that shows a single text column.


Line 17: Line 18:


[[Image:example-single-text-column-selector.png|400px]]
[[Image:example-single-text-column-selector.png|400px]]
<source lang="python">
# Based on C code from:
# "Hildon Tutorial" version 2009-04-28
# Example 5.6, "Example of a single-column selector"
import gtk
import hildon


    # Based on C code from:
def selection_changed(selector, user_data):
    # "Hildon Tutorial" version 2009-04-28
    current_selection = selector.get_current_text()
    # Example 5.6, "Example of a single-column selector"
    print "Current selection : %s" % (current_selection)
   
 
    import gtk
def create_simple_selector():
    import hildon
    #Create a HildonTouchSelector with a single text column
   
    selector = hildon.TouchSelector(text = True)
    def selection_changed(selector, user_data):
 
        current_selection = selector.get_current_text()
     # Set a handler to "changed" signal
        print "Current selection : %s" % (current_selection)
    selector.connect("changed", selection_changed)
   
 
    def create_simple_selector():
     # Populate selector
        #Create a HildonTouchSelector with a single text column
    for i in range(10):
        selector = hildon.TouchSelector(text = True)
        label = "Item %d" % i
      
        # Add item to the column
        # Set a handler to "changed" signal  
        selector.append_text(label)
        selector.connect("changed", selection_changed)
 
      
    # Set selection mode to allow multiple selection
        # Populate selector  
    selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
        for i in range(10):
 
            label = "Item %d" % i
    return selector
            # Add item to the column  
            selector.append_text(label)
        # Set selection mode to allow multiple selection
        selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)


        return selector
def app_quit(widget, data=None):
   
    gtk.main_quit()
    def app_quit(widget, data=None):
        gtk.main_quit()
   
    def main():
        program = hildon.Program.get_instance()
        gtk.set_application_name("hildon-touch-selector example program")
   
        window = hildon.StackableWindow()
        program.add_window(window)
   
        # Create touch selector
        selector = create_simple_selector()
        window.add(selector)
   
        window.connect("destroy", app_quit)
   
        window.show_all()
   
        gtk.main()
   
    if __name__ == "__main__":
        main()


def main():
    program = hildon.Program.get_instance()
    gtk.set_application_name("hildon-touch-selector example program")


A HildonTouchSelector with a single text column is created in this program using the following convenience constructor.
    window = hildon.StackableWindow()
    program.add_window(window)


     hildon.touch_selector_new_text()
     # Create touch selector
    selector = create_simple_selector()
    window.add(selector)


    window.connect("destroy", app_quit)


To add text to a selector created by calling the constructor above, use the function.
    window.show_all()


     def append(self, text):
     gtk.main()


if __name__ == "__main__":
    main()
</source>
A HildonTouchSelector with a single text column is created in this program using the following convenience constructor.
<source lang="python">
hildon.TouchSelector(text = True)
</source>
To add text to a selector created by calling the constructor above, use the function.
<source lang="python">
def append(self, text):
</source>
Alternatively, you can use <code>prepend_text()</code> or <code>insert_text()</code> to add text to the selector in different positions.
Alternatively, you can use <code>prepend_text()</code> or <code>insert_text()</code> to add text to the selector in different positions.


You can set the desired selection with the function. In the example, the mode was set to allow multiple selection.
You can set the desired selection with the function. In the example, the mode was set to allow multiple selection.
 
<source lang="python">
    def set_column_selection_mode(self, mode):
def set_column_selection_mode(self, mode):
 
</source>
This example shows a very common use case of this widget. Next section shows how to build a more complex selector with several columns of different types.
This example shows a very common use case of this widget. Next section shows how to build a more complex selector with several columns of different types.


Line 92: Line 92:


To change how the text representation is generated, set your own function by  calling <code>set_print_func()</code> and using the following signature for the function:
To change how the text representation is generated, set your own function by  calling <code>set_print_func()</code> and using the following signature for the function:
<source lang="python">
def user_function (selector):
</source>
===Custom columns===


    def user_function (selector):
In the previous section, a selector with a text column was created. That is probably the most common use case of touch selectors. Convenience functions to deal with text columns were used. However, you can also set other type of columns.


===Custom columns===
As each column is basically a treeview, you can use the same display for different data. You can also show information in different ways as you would do with a <code>GtkTreeView</code>. Thus, you can use the <code>GtkCellRenderer</code>s available in GTK+ to display the data on each cell.
 
This section explains how to build a selector within a column displaying stock icons. Firstly, let us take a look on the function used for appending new columns to a touchable selector.
<source lang="python">
def append_column(self, model, cell_renderer):
</source>
This functions adds a new column to the widget whose data is obtained from the passed model. A <code>GtkCellRenderer</code> is also necessary.
 
This function basically adds a <code>GtkTreeView</code> to the widget. For more information about how <code>GtkTreeView</code>s work, see [http://library.gnome.org/devel/pygtk/stable/class-gtktreeview.html GTK+ widgets] before.
The following example shows how to set a column to display images in a selector.
 
'''Example 6.2. Example of a selector with a custom column'''
 
[[Image:example-single-column-selector.png|400px]]
<source lang="python">
# Based on C code from:
# "Hildon Tutorial" version 2009-04-28
# Example 6.2 "Example of a selector with a custom column"


In the previous section, a selector with a text column was created. That is probably the most common use case of touch selectors. Convenience functions to deal with text columns was used. However, you can also set other type of columns.
import gtk
import hildon
import gobject


Because each column is basically a treeview, you can use the same display to different data and in different ways as you would do with a GtkTreeview. Thus, you can use the GtkCellRenderers available in GTK+ to display the data on each cell.
def selection_changed(selector, user_data):
    current_selection = selector.get_current_text()
    print "Current selection : %s" % (current_selection)


This section explains how to build a selector within a column displaying stock icons. Firstly, let us take a look on the function which used for appending new columns to a touchable selector.
def create_customized_selector():
    # Create a touch selector  
    selector = hildon.TouchSelector()


    def append_column(self, model, cell_renderer, ...):
    # Stock icons will be used for the example
    icon_list = gtk.stock_list_ids()


This functions adds a new column to the widget whose data is obtained from the passed model. Pass also a GtkCellRenderer and a list of pairs property/value which is set as attributes of the renderer.
    # Create model to store selector's items
    store_icons = gtk.ListStore(gobject.TYPE_STRING)


This function basically adds a GtkTreeView to the widget. For more information on how GtkTreeviews work, see [http://library.gnome.org/devel/pygtk/stable/class-gtktreeview.html GTK+ widgets] before.
    # Populate model
The following example shows how to set a column to display images in a selector. For clarity, only the function which creates the selector is shown.
    for item in icon_list:
        new_iter = store_icons.append()
        store_icons.set(new_iter, 0, item)


'''Example 6.2. Example of a selector with a custom column'''
    # Create and set up a pixbuf renderer to use in the selector
    renderer = gtk.CellRendererPixbuf()
    renderer.set_fixed_size(-1, 100)


[[Image:example-single-column-selector.png|400px]]


     # Based on C code from:
     # Add the column to the selector
    # "Hildon Tutorial" version 2009-04-28
    column = selector.append_column(store_icons, renderer, stock_id = 0)
    # Example 6.2 "Example of a selector with a custom column"
   
    import gtk
    import hildon
    import gobject
   
    def selection_changed(selector, user_data):
        current_selection = selector.get_current_text()
        print "Current selection : %s" % (current_selection)
   
    def create_customized_selector():
        # Create a touch selector
        selector = hildon.TouchSelector()
   
        # Stock icons will be used for the example
        icon_list = gtk.stock_list_ids()
   
        # Create model to store selector's items
        store_icons = gtk.ListStore(gobject.TYPE_STRING);
   
        # Populate model
        for item in icon_list:
            new_iter = store_icons.append()
            store_icons.set(new_iter, 0, item)
   
        # Create and set up a pixbuf renderer to use in the selector
        renderer = gtk.CellRendererPixbuf()
        renderer.set_fixed_size(-1, 100)
   
   
        # Add the column to the selector
        # FIXME: bug 4646
        #column = selector.append_column(store_icons, renderer, "stock-id", 0)
   
        # Set the selection mode
        selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
   
        # Set the property "text-column" that indicates the column
        # of the model to get the string from
        column.set_property("text-column", 0)
   
        return selector
   
    def app_quit(widget, data=None):
        gtk.main_quit()
   
    def main():
        program = hildon.hildon_program_get_instance()
        gtk.set_application_name("hildon-touch-selector example program")
   
        window = hildon.StackableWindow()
        program.add_window(window)
   
        # Create touch selector
        selector = create_customized_selector()
        window.add(selector)
   
        window.connect("destroy", app_quit)
   
        window.show_all()


        gtk.main()
     # Set the selection mode
      
     selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
     if __name__ == "__main__":
        main()


    # Set the property "text-column" that indicates the column
    # of the model to get the string from
    column.set_property("text-column", 0)


The first step in the example is to create and populate a GtkTreeModel. A GtkListStore is used in the example. In most use cases of the touchable selectors a GtkListStore fits well as selectors were designed to allow users to select from a list of items.
    return selector


In this case, the model stores a list of GTK+ stock icons identifiers. The following call creates a list store with one column to store strings.
def app_quit(widget, data=None):
    gtk.main_quit()


     store_icons = gtk.ListStore(G_TYPE_STRING);
def main():
     program = hildon.Program.get_instance()
    gtk.set_application_name("hildon-touch-selector example program")


    window = hildon.StackableWindow()
    program.add_window(window)


The following loop appends all stock identifiers in the newly created model. The identifiers were previously retrieved using
    # Create touch selector
    selector = create_customized_selector()
    window.add(selector)


     for item in icon_list:
     window.connect("destroy", app_quit)
        new_iter = store_icons.append()
        store_icons.set(new_iter, 0, item)


The next step is to set up the renderer which renders each row of the new column. We need a GtkCellRendererPixbuf to display the stock icons.
    window.show_all()


     renderer = gtk.CellRendererPixbuf()
     gtk.main()


Finally, we create and append the new column, using the model and renderer previously created.
if __name__ == "__main__":
    main()
</source>


This call also sets the property "stock-id" of the GtkCellrendererPixbuf. The value is set to 0 which is the number of the column in the GtkTreeModel that stores the stock-id.
The first step in the example is to create and populate a <code>GtkTreeModel</code>. A <code>GtkListStore</code> is used in the example. In most use cases of the touchable selectors a <code>GtkListStore</code> fits well as selectors were designed to allow users to select from a list of items.


     column = selector.append_column(store_icons, renderer, "stock-id", 0)
In this case, the model stores a list of GTK+ stock icons identifiers. The following call creates a list store with one column to store strings.
<source lang="python">
     store_icons = gtk.ListStore(gobject.TYPE_STRING)
</source>


To summarize, setting a new custom column in a touchable selector is quite similar to setting a new column in a normal GtkTreeview. Create a model to store the data and a cell renderer to properly show this data in each row, and finally add the new column.
The following loop appends all stock identifiers in the newly created model. The identifiers were previously retrieved using
<source lang="python">
    for item in icon_list:
        new_iter = store_icons.append()
        store_icons.set(new_iter, 0, item)
</source>
The next step is to set up the renderer which renders each row of the new column. We need a <code>GtkCellRendererPixbuf</code> to display the stock icons.
<source lang="python">
    renderer = gtk.CellRendererPixbuf()
</source>
Finally, we create and append the new column, using the model and renderer previously created.
<source lang="python">
    column = selector.append_column(store_icons, renderer, stock_id = 0)
</source>
To summarize, setting a new custom column in a touchable selector is quite similar to setting a new column in a normal <code>GtkTreeView</code>. Create a model to store the data and a cell renderer to properly show this data in each row, and finally add the new column.


==Picker dialog and picker buttons ==
==Picker dialog and picker buttons ==
Normally, you use HildonTouchSelector together with a HildonPickerDialog activated from a button. For most common cases you use HildonPickerButton.
 
Normally, you use <code>HildonTouchSelector</code> together with a <code>HildonPickerDialog</code> activated from a button. For most common cases you use <code>HildonPickerButton</code>.


This is the usual way to present a selector to the user. The picker button opens a dialog which presents the selector and properly manages user interaction.
This is the usual way to present a selector to the user. The picker button opens a dialog which presents the selector and properly manages user interaction.
Line 215: Line 213:
'''Example'''
'''Example'''


Previous sections showed you how to create a touchable selector. In most cases the next step is to attach the selector to a HildonPickerButton.
Previous sections showed you how to create a touchable selector. In most cases the next step is to attach the selector to a <code>HildonPickerButton</code>.


A HildonPickerButton is a special GtkButton which displays two labels, title and value, and brings up a HildonPickerDialog. The user chooses one or several items. A string representation of the chosen items is displayed in the value label of the picker button.
A HildonPickerButton is a special GtkButton which displays two labels, title and value, and brings up a HildonPickerDialog. The user chooses one or several items. A string representation of the chosen items is displayed in the value label of the picker button.
Line 224: Line 222:


'''Example 6.3. Example of a Hildon picker button'''
'''Example 6.3. Example of a Hildon picker button'''
<source lang="python">
# Based on C code from:
# "Hildon Tutorial" version 2009-04-28
# Example 6.3, "Example of a Hildon picker button"
import gtk
import hildon
import gobject
def on_picker_value_changed(button, user_data=None):
    print "Newly selected value: %s\n" % button.get_value()
def app_quit(widget, data=None):
    gtk.main_quit()
def create_customized_selector():
    # Create a touch selector
    selector = hildon.TouchSelector()


     # Based on C code from:
     # Stock icons will be used for the example
    # "Hildon Tutorial" version 2009-04-28
    icon_list = gtk.stock_list_ids()
    # Example 6.3, "Example of a Hildon picker button"
   
    import gtk
    import hildon
    import gobject
   
    def on_picker_value_changed(button, user_data=None):
        print "Newly selected value: %s\n" % button.get_value()
   
    def app_quit(widget, data=None):
        gtk.main_quit()
   
    def create_customized_selector():
        # Create a touch selector
        selector = hildon.TouchSelector()
   
        # Stock icons will be used for the example
        icon_list = gtk.stock_list_ids()
       
        print icon_list
   
        # Create model to store selector's items
        store_icons = gtk.ListStore(gobject.TYPE_STRING)
   
        # Populate model
        for item in icon_list:
            new_iter = store_icons.append()
            store_icons.set_value(new_iter, 0, item)
   
        # Create and set up a text renderer to use in the selector
        renderer = gtk.CellRendererPixbuf()
        renderer.set_fixed_size(-1, 100)
   
        # Add the column to the selector
        column = selector.append_column(store_icons, renderer, stock_id=0)
   
        # Set the selection mode
        selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
   
        # Set the property "text-column" that indicates the column
        # of the model to get the string from
        column.set_property("text-column", 0)
   
        return selector
   
    def main ():
        program = hildon.Program.get_instance()
        gtk.set_application_name("hildon-touch-selector example program")
   
        window = hildon.StackableWindow()
        program.add_window(window)
   
        # Create touch selector
        selector = create_customized_selector()
   
        # Create a picker button
        picker_button = hildon.PickerButton(gtk.HILDON_SIZE_AUTO,
                                            hildon.BUTTON_ARRANGEMENT_VERTICAL)
   
        # Set a title to the button
        picker_button.set_title("Select an item")
   
        # Attach the touch selector to the picker button
        picker_button.set_selector(selector)
   
        # Attach callback to the "value-changed" signal
        picker_button.connect("value-changed", on_picker_value_changed)
   
        # Add button to main window
        window.add(picker_button)
   
        window.connect("destroy", app_quit)
        window.show_all()
        gtk.main()
   
    if __name__ == "__main__":
        main()
      
      
    print icon_list
    # Create model to store selector's items
    store_icons = gtk.ListStore(gobject.TYPE_STRING)
    # Populate model
    for item in icon_list:
        new_iter = store_icons.append()
        store_icons.set_value(new_iter, 0, item)
    # Create and set up a text renderer to use in the selector
    renderer = gtk.CellRendererPixbuf()
    renderer.set_fixed_size(-1, 100)
    # Add the column to the selector
    column = selector.append_column(store_icons, renderer, stock_id=0)
    # Set the selection mode
    selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
    # Set the property "text-column" that indicates the column
    # of the model to get the string from
    column.set_property("text-column", 0)
    return selector
def main ():
    program = hildon.Program.get_instance()
    gtk.set_application_name("hildon-touch-selector example program")
    window = hildon.StackableWindow()
    program.add_window(window)
    # Create touch selector
    selector = create_customized_selector()
    # Create a picker button
    picker_button = hildon.PickerButton(gtk.HILDON_SIZE_AUTO,
                                        hildon.BUTTON_ARRANGEMENT_VERTICAL)
    # Set a title to the button
    picker_button.set_title("Select an item")
    # Attach the touch selector to the picker button
    picker_button.set_selector(selector)
    # Attach callback to the "value-changed" signal
    picker_button.connect("value-changed", on_picker_value_changed)
    # Add button to main window
    window.add(picker_button)
    window.connect("destroy", app_quit)
    window.show_all()
    gtk.main()


In the above example a picker button is created. The reference to the attached selector is stored in the property "touch-selector" of the picker button. To retrieve the attached selector , use function <code>hildon.PickerButton()</code>. To attach the selector, use the function <code>picker_button.set_selector()</code>.
if __name__ == "__main__":
    main()
</source>
In the above example a picker button is created. The reference to the attached selector is stored in the property "touch-selector" of the picker button. To retrieve the attached selector, use function <code>hildon.PickerButton()</code>. To attach the selector, use the function <code>picker_button.set_selector()</code>.


Note that you do not need to take care of the HildonPickerDialog. The dialog is automatically brought up when users click the picker button and closed when the selection is done.
Note that you do not need to take care of the <code>HildonPickerDialog</code>. The dialog is automatically brought up when users click the picker button and closed when the selection is done.


The dialog shows a button "Done" to allow users finish the selection when the touchable selector allows multiple selection. When the selector allows only single selection, the dialog does not show any button and closes when the user taps on one item.
The dialog shows a button "Done" to allow users finish the selection when the touchable selector allows multiple selection. When the selector allows only single selection, the dialog does not show any button and closes when the user taps on one item.
Line 319: Line 316:


==Touch selector entry ==
==Touch selector entry ==
The HildonTouchSelectorEntry is a selector widget with a text entry that allows users to select an item from a predefined list or to enter a different one in a HildonEntry. Items can also be searched and selected by typing in the entry.


An additional feature is that the HildonEntry is auto-completed with the list's items as the user types their name.
The <code>HildonTouchSelectorEntry</code> is a selector widget with a text entry that allows users to select an item from a predefined list or to enter a different one in a <code>HildonEntry</code>. Items can also be searched and selected by typing in the entry.
 
An additional feature is that the <code>HildonEntry</code> is auto-completed with the list's items as the user types their name.


Example below shows how to build a selector to pick a word in a list of words.
Example below shows how to build a selector to pick a word in a list of words.
Line 328: Line 326:


'''Example 6.4. Example of a Hildon picker button with a selector entry'''
'''Example 6.4. Example of a Hildon picker button with a selector entry'''
<source lang="python">
# Based on C code from:
# "Hildon Tutorial" version 2009-04-28
# Example 6.4, "Hildon picker button with a selector entry"
import gtk
import hildon
def app_quit(widget, data=None):
    gtk.main_quit()
def main ():
    artists = [
        "AC/DC",
        "Aerosmith",
        "Alice in Chains",
        "Black Sabbath",
        "Carcass",
        "Danzig",
        "Deep Purple",
        "Dream Theater",
        "Eric Clapton",
    ]
    program = hildon.Program.get_instance()
    gtk.set_application_name("hildon-touch-selector example program")
    window = hildon.StackableWindow()
    program.add_window(window)


     # Based on C code from:
     # Create a picker button
    # "Hildon Tutorial" version 2009-04-28
    picker_button = hildon.PickerButton(gtk.HILDON_SIZE_AUTO,
    # Example 6.4, "Hildon picker button with a selector entry"
                                        hildon.BUTTON_ARRANGEMENT_VERTICAL)
   
 
    import gtk
     # Set a title to the button  
    import hildon
    picker_button.set_title("Pick a band!")
   
 
    def app_quit(widget, data=None):
     # Create a touch selector entry
        gtk.main_quit()
    selector = hildon.TouchSelectorEntry(text=True)
   
     
    def main ():
    # Populate the selector
        artists = [
    for artist in artists:
            "AC/DC",
        selector.append_text(artist)
            "Aerosmith",
 
            "Alice in Chains",
     # Attach the touch selector to the picker button
            "Black Sabbath",
    picker_button.set_selector(selector)
            "Carcass",
            "Danzig",
            "Deep Purple",
            "Dream Theater",
            "Eric Clapton",
        ]
   
        program = hildon.Program.get_instance()
        gtk.set_application_name("hildon-touch-selector example program")
   
        window = hildon.StackableWindow()
        program.add_window(window)
   
        # Create a picker button
        picker_button = hildon.PickerButton(gtk.HILDON_SIZE_AUTO,
                                            hildon.BUTTON_ARRANGEMENT_VERTICAL)
      
        # Set a title to the button  
        picker_button.set_title("Pick a band!")
      
        # Create a touch selector entry
        selector = hildon.TouchSelectorEntry(text=True)
         
        # Populate the selector
        for artist in artists:
            selector.append_text(artist)
      
        # Attach the touch selector to the picker button
        picker_button.set_selector(selector)
   
        # Add button to main window
        window.add(picker_button)
   
        window.connect("destroy", app_quit)
        window.show_all()
        gtk.main()
   
    if __name__ == "__main__":
        main()


    # Add button to main window
    window.add(picker_button)


    window.connect("destroy", app_quit)
    window.show_all()
    gtk.main()


if __name__ == "__main__":
    main()
</source>
As you can see in the example above, the use of this widget is similar to using a normal touchable selector.
As you can see in the example above, the use of this widget is similar to using a normal touchable selector.


You can also use custom columns in a HildonTouchableEntry but at least one column must be a text column. The text column is indicated by the property "text_column" which you set with <code>set_text_column()</code>.
You can also use custom columns in a HildonTouchableEntry but at least one column must be a text column. The text column is indicated by the property "text_column" which you set with <code>set_text_column()</code>.


==Pre-built selectors ==
==Pre-built selectors==
The widgets HildonDateButton and HildonTimeButton are buttons displaying and allowing the selection of date and time, respectively. Developers can use them directly instead of building their own date or time selectors.
 
The widgets <code>HildonDateButton</code> and <code>HildonTimeButton</code> are buttons displaying and allowing the selection of date and time, respectively. Developers can use them directly instead of building their own date or time selectors.


Both widgets are specialized picker buttons with a convenient touchable selector attached that you can use directly in your application.
Both widgets are specialized picker buttons with a convenient touchable selector attached that you can use directly in your application.


Here is a simple application using a HildonDateButton.
Here is a simple application using a <code>HildonDateButton</code>.


'''Example 6.5. Example of a Hildon date button'''
'''Example 6.5. Example of a Hildon date button'''
<source lang="python">
# Based on C code from:
# "Hildon Tutorial" version 2009-04-28
# Example 6.5, "Example of a Hildon date button"


    # Based on C code from:
import gtk
    # "Hildon Tutorial" version 2009-04-28
import hildon
    # Example 6.5, "Example of a Hildon date button"
 
   
def app_quit(widget, data=None):
    import gtk
    gtk.main_quit()
    import hildon
 
   
def main ():
    def app_quit(widget, data=None):
    program = hildon.Program.get_instance()
        gtk.main_quit()
    gtk.set_application_name("hildon-touch-selector example program")
   
 
    def main ():
     window = hildon.StackableWindow()
        program = hildon.Program.get_instance()
    program.add_window(window)
        gtk.set_application_name("hildon-touch-selector example program")
 
      
     # Create a date picker
        window = hildon.StackableWindow()
    date_button = hildon.DateButton(gtk.HILDON_SIZE_AUTO,
        program.add_window(window)
                                    hildon.BUTTON_ARRANGEMENT_VERTICAL)
      
 
        # Create a date picker
     # Set a title to the button
        date_button = hildon.DateButton(gtk.HILDON_SIZE_AUTO,
    date_button.set_title("Select an item")
                                        hildon.BUTTON_ARRANGEMENT_VERTICAL)
 
      
     # Add button to main window  
        # Set a title to the button
    window.add(date_button)
        date_button.set_title("Select an item")
 
      
       
        # Add button to main window  
    window.connect("destroy", app_quit)
        window.add(date_button)
    window.show_all()
   
    gtk.main()
           
 
        window.connect("destroy", app_quit)
if __name__ == "__main__":
        window.show_all()
    main()
        gtk.main()
</source>
   
 
    if __name__ == "__main__":
[[Category:Python]]
        main()

Latest revision as of 11:34, 7 October 2010


Hildon provides a set of widgets for data selection specially designed for touchscreens that allows to build simple and easy-to-use interfaces.

The key widget is a selector widget that allows users to select items from one to many predefined lists. It is similar to a combo box but allows several individual pannable columns.

In addition, Hildon also provides a specialized dialog and a specialized button to be used in combination with a selector.

Touch selector

HildonTouchSelector is the mentioned selector widget. This widget can display several pannable columns. Each column is represented by a GtkTreeModel and single or multiple selection is allowed.

Text Columns Example

This is the simplest example: a selector that shows a single text column.

Example 6.1. Example of a single-column selector

<source lang="python">

  1. Based on C code from:
  2. "Hildon Tutorial" version 2009-04-28
  3. Example 5.6, "Example of a single-column selector"

import gtk import hildon

def selection_changed(selector, user_data):

   current_selection = selector.get_current_text()
   print "Current selection : %s" % (current_selection)

def create_simple_selector():

   #Create a HildonTouchSelector with a single text column
   selector = hildon.TouchSelector(text = True)
   # Set a handler to "changed" signal
   selector.connect("changed", selection_changed)
   # Populate selector
   for i in range(10):
       label = "Item %d" % i
       # Add item to the column
       selector.append_text(label)
   # Set selection mode to allow multiple selection
   selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
   return selector

def app_quit(widget, data=None):

   gtk.main_quit()

def main():

   program = hildon.Program.get_instance()
   gtk.set_application_name("hildon-touch-selector example program")
   window = hildon.StackableWindow()
   program.add_window(window)
   # Create touch selector
   selector = create_simple_selector()
   window.add(selector)
   window.connect("destroy", app_quit)
   window.show_all()
   gtk.main()

if __name__ == "__main__":

   main()

</source> A HildonTouchSelector with a single text column is created in this program using the following convenience constructor. <source lang="python">

hildon.TouchSelector(text = True)

</source> To add text to a selector created by calling the constructor above, use the function. <source lang="python"> def append(self, text): </source> Alternatively, you can use prepend_text() or insert_text() to add text to the selector in different positions.

You can set the desired selection with the function. In the example, the mode was set to allow multiple selection. <source lang="python"> def set_column_selection_mode(self, mode): </source> This example shows a very common use case of this widget. Next section shows how to build a more complex selector with several columns of different types.

Also a simple function was set as a handler for the "changed" signal which is emitted each time the selected items change.

The callback retrieves a text representation of the currently selected items in the selector by calling get_current_text(). By default this function returns a concatenation of the items selected, separated by a comma.

To change how the text representation is generated, set your own function by calling set_print_func() and using the following signature for the function: <source lang="python"> def user_function (selector): </source>

Custom columns

In the previous section, a selector with a text column was created. That is probably the most common use case of touch selectors. Convenience functions to deal with text columns were used. However, you can also set other type of columns.

As each column is basically a treeview, you can use the same display for different data. You can also show information in different ways as you would do with a GtkTreeView. Thus, you can use the GtkCellRenderers available in GTK+ to display the data on each cell.

This section explains how to build a selector within a column displaying stock icons. Firstly, let us take a look on the function used for appending new columns to a touchable selector. <source lang="python"> def append_column(self, model, cell_renderer): </source> This functions adds a new column to the widget whose data is obtained from the passed model. A GtkCellRenderer is also necessary.

This function basically adds a GtkTreeView to the widget. For more information about how GtkTreeViews work, see GTK+ widgets before. The following example shows how to set a column to display images in a selector.

Example 6.2. Example of a selector with a custom column

<source lang="python">

  1. Based on C code from:
  2. "Hildon Tutorial" version 2009-04-28
  3. Example 6.2 "Example of a selector with a custom column"

import gtk import hildon import gobject

def selection_changed(selector, user_data):

   current_selection = selector.get_current_text()
   print "Current selection : %s" % (current_selection)

def create_customized_selector():

   # Create a touch selector 
   selector = hildon.TouchSelector()
   # Stock icons will be used for the example
   icon_list = gtk.stock_list_ids()
   # Create model to store selector's items 
   store_icons = gtk.ListStore(gobject.TYPE_STRING)
   # Populate model
   for item in icon_list:
       new_iter = store_icons.append()
       store_icons.set(new_iter, 0, item)
   # Create and set up a pixbuf renderer to use in the selector 
   renderer = gtk.CellRendererPixbuf() 
   renderer.set_fixed_size(-1, 100)


   # Add the column to the selector
   column = selector.append_column(store_icons, renderer, stock_id = 0)
   # Set the selection mode
   selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
   # Set the property "text-column" that indicates the column
   # of the model to get the string from
   column.set_property("text-column", 0)
   return selector

def app_quit(widget, data=None):

   gtk.main_quit()

def main():

   program = hildon.Program.get_instance()
   gtk.set_application_name("hildon-touch-selector example program")
   window = hildon.StackableWindow()
   program.add_window(window)
   # Create touch selector
   selector = create_customized_selector()
   window.add(selector)
   window.connect("destroy", app_quit)
   window.show_all()
   gtk.main()

if __name__ == "__main__":

   main()

</source>

The first step in the example is to create and populate a GtkTreeModel. A GtkListStore is used in the example. In most use cases of the touchable selectors a GtkListStore fits well as selectors were designed to allow users to select from a list of items.

In this case, the model stores a list of GTK+ stock icons identifiers. The following call creates a list store with one column to store strings. <source lang="python">

   store_icons = gtk.ListStore(gobject.TYPE_STRING)

</source>

The following loop appends all stock identifiers in the newly created model. The identifiers were previously retrieved using <source lang="python">

   for item in icon_list:
       new_iter = store_icons.append()
       store_icons.set(new_iter, 0, item)

</source> The next step is to set up the renderer which renders each row of the new column. We need a GtkCellRendererPixbuf to display the stock icons. <source lang="python">

   renderer = gtk.CellRendererPixbuf()

</source> Finally, we create and append the new column, using the model and renderer previously created. <source lang="python">

   column = selector.append_column(store_icons, renderer, stock_id = 0)

</source> To summarize, setting a new custom column in a touchable selector is quite similar to setting a new column in a normal GtkTreeView. Create a model to store the data and a cell renderer to properly show this data in each row, and finally add the new column.

Picker dialog and picker buttons

Normally, you use HildonTouchSelector together with a HildonPickerDialog activated from a button. For most common cases you use HildonPickerButton.

This is the usual way to present a selector to the user. The picker button opens a dialog which presents the selector and properly manages user interaction.

Example

Previous sections showed you how to create a touchable selector. In most cases the next step is to attach the selector to a HildonPickerButton.

A HildonPickerButton is a special GtkButton which displays two labels, title and value, and brings up a HildonPickerDialog. The user chooses one or several items. A string representation of the chosen items is displayed in the value label of the picker button.

Below, a modified version of the previous main function is shown, in which you can check how a HildonPickerButton is created and attached to a selector. Also a callback to catch the signal "value-changed" emitted is added.

Example 6.3. Example of a Hildon picker button <source lang="python">

  1. Based on C code from:
  2. "Hildon Tutorial" version 2009-04-28
  3. Example 6.3, "Example of a Hildon picker button"

import gtk import hildon import gobject

def on_picker_value_changed(button, user_data=None):

   print "Newly selected value: %s\n" % button.get_value()

def app_quit(widget, data=None):

   gtk.main_quit()

def create_customized_selector():

   # Create a touch selector 
   selector = hildon.TouchSelector()
   # Stock icons will be used for the example
   icon_list = gtk.stock_list_ids()
   
   print icon_list
   # Create model to store selector's items
   store_icons = gtk.ListStore(gobject.TYPE_STRING)
   # Populate model
   for item in icon_list:
       new_iter = store_icons.append()
       store_icons.set_value(new_iter, 0, item)
   # Create and set up a text renderer to use in the selector
   renderer = gtk.CellRendererPixbuf()
   renderer.set_fixed_size(-1, 100)
   # Add the column to the selector
   column = selector.append_column(store_icons, renderer, stock_id=0)
   # Set the selection mode
   selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
   # Set the property "text-column" that indicates the column
   # of the model to get the string from
   column.set_property("text-column", 0)
   return selector

def main ():

   program = hildon.Program.get_instance()
   gtk.set_application_name("hildon-touch-selector example program")
   window = hildon.StackableWindow()
   program.add_window(window)
   # Create touch selector
   selector = create_customized_selector()
   # Create a picker button
   picker_button = hildon.PickerButton(gtk.HILDON_SIZE_AUTO,
                                       hildon.BUTTON_ARRANGEMENT_VERTICAL)
   # Set a title to the button 
   picker_button.set_title("Select an item")
   # Attach the touch selector to the picker button
   picker_button.set_selector(selector)
   # Attach callback to the "value-changed" signal
   picker_button.connect("value-changed", on_picker_value_changed)
   # Add button to main window
   window.add(picker_button)
   window.connect("destroy", app_quit)
   window.show_all()
   gtk.main()

if __name__ == "__main__":

   main()

</source> In the above example a picker button is created. The reference to the attached selector is stored in the property "touch-selector" of the picker button. To retrieve the attached selector, use function hildon.PickerButton(). To attach the selector, use the function picker_button.set_selector().

Note that you do not need to take care of the HildonPickerDialog. The dialog is automatically brought up when users click the picker button and closed when the selection is done.

The dialog shows a button "Done" to allow users finish the selection when the touchable selector allows multiple selection. When the selector allows only single selection, the dialog does not show any button and closes when the user taps on one item.

The label of the button "Done" can be set by using set_done_button_text() and retrieved by using get_done_button_text().

When users finish their selection, the value label on the button automatically changes to show a textual representation of the item or items selected.

In most cases you want to perform any action when selection is finished. To do that, add a handler to the signal "value-changed" of the picker button. In this example the handler attached to "value-changed" signal retrieves the value label of the button and prints a debug message.

Touch selector entry

The HildonTouchSelectorEntry is a selector widget with a text entry that allows users to select an item from a predefined list or to enter a different one in a HildonEntry. Items can also be searched and selected by typing in the entry.

An additional feature is that the HildonEntry is auto-completed with the list's items as the user types their name.

Example below shows how to build a selector to pick a word in a list of words.

Example 6.4. Example of a Hildon picker button with a selector entry <source lang="python">

  1. Based on C code from:
  2. "Hildon Tutorial" version 2009-04-28
  3. Example 6.4, "Hildon picker button with a selector entry"

import gtk import hildon

def app_quit(widget, data=None):

   gtk.main_quit()

def main ():

   artists = [
       "AC/DC",
       "Aerosmith",
       "Alice in Chains",
       "Black Sabbath",
       "Carcass",
       "Danzig",
       "Deep Purple",
       "Dream Theater",
       "Eric Clapton",
   ]
   program = hildon.Program.get_instance()
   gtk.set_application_name("hildon-touch-selector example program")
   window = hildon.StackableWindow()
   program.add_window(window)
   # Create a picker button
   picker_button = hildon.PickerButton(gtk.HILDON_SIZE_AUTO,
                                       hildon.BUTTON_ARRANGEMENT_VERTICAL)
   # Set a title to the button 
   picker_button.set_title("Pick a band!")
   # Create a touch selector entry
   selector = hildon.TouchSelectorEntry(text=True)
      
   # Populate the selector
   for artist in artists:
       selector.append_text(artist)
   # Attach the touch selector to the picker button
   picker_button.set_selector(selector)
   # Add button to main window
   window.add(picker_button)
   window.connect("destroy", app_quit)
   window.show_all()
   gtk.main()

if __name__ == "__main__":

   main()

</source> As you can see in the example above, the use of this widget is similar to using a normal touchable selector.

You can also use custom columns in a HildonTouchableEntry but at least one column must be a text column. The text column is indicated by the property "text_column" which you set with set_text_column().

Pre-built selectors

The widgets HildonDateButton and HildonTimeButton are buttons displaying and allowing the selection of date and time, respectively. Developers can use them directly instead of building their own date or time selectors.

Both widgets are specialized picker buttons with a convenient touchable selector attached that you can use directly in your application.

Here is a simple application using a HildonDateButton.

Example 6.5. Example of a Hildon date button <source lang="python">

  1. Based on C code from:
  2. "Hildon Tutorial" version 2009-04-28
  3. Example 6.5, "Example of a Hildon date button"

import gtk import hildon

def app_quit(widget, data=None):

   gtk.main_quit()

def main ():

   program = hildon.Program.get_instance()
   gtk.set_application_name("hildon-touch-selector example program")
   window = hildon.StackableWindow()
   program.add_window(window)
   # Create a date picker
   date_button = hildon.DateButton(gtk.HILDON_SIZE_AUTO,
                                   hildon.BUTTON_ARRANGEMENT_VERTICAL)
   # Set a title to the button
   date_button.set_title("Select an item")
   # Add button to main window 
   window.add(date_button)


   window.connect("destroy", app_quit)
   window.show_all()
   gtk.main()

if __name__ == "__main__":

   main()

</source>