Search code examples
cgtkgtk3glade

GTK expanders one at at time


I have made a glade interface where there are three expanders. I only want one to be open at any given time. So when the signal "activate" is used it calls a function expandlights() and all other expanders should close. I cant figure out how to affect the other expanders from the function. below was my best try, its clearly very wrong. I'm SO new to this.

MAIN:

int main(int argc, char *argv[])
{   
GtkBuilder      *builder; 
GtkWidget       *window;
gtk_init(&argc, &argv);

builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "interface.ui", NULL);

window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
gtk_builder_connect_signals(builder, NULL);

g_object_unref(builder);

gtk_widget_show(window);                
gtk_main();

return 0;
}

this is the function i attempted which clearly fails

void expandlights(  GtkWidget    *expander1,
                    GtkWidget    *expander2,
                    GtkWidget    *expander3)
{
    gtk_expander_set_expanded(expander2, FALSE);
    gtk_expander_set_expanded(expander3, FALSE);
}

I dont know if im on the right track or way off here. Could use a schoolin!

Glade file:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
  <requires lib="gtk+" version="3.12"/>
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkExpander" id="expander1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <signal name="activate" handler="expandlights" swapped="no"/>
            <child>
              <object class="GtkLabel" id="label4">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">lighting stuff</property>
              </object>
            </child>
            <child type="label">
              <object class="GtkLabel" id="label1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Lights</property>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkExpander" id="expander2">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <signal name="activate" handler="expandalarm" swapped="no"/>
            <child>
              <object class="GtkLabel" id="label5">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Alarm stuff</property>
              </object>
            </child>
            <child type="label">

Solution

  • Your activate handler must have the signature defined for the activate signal.

    void
    expandlights (GtkExpander *expander, gpointer user_data);
    

    To be able to modify the other expanders from this function you'll need to use the user_data pointer: typically it's made to point to a struct that contains pointers to all widgets you may need. You can set the pointer value with gtk_builder_connect_signals() in your initialization when using glade if I recall correctly.

    You should be able to use the same handler for all three expanders if you code it carefully (if the expander is being expanded then unexpand all of the expanders except the one that emitted the signal). Note that when you call gtk_expander_set_expanded() the activate signal handler for that expander will be called. This shouldn't be a problem for your case but keep it in mind -- don't create a never-ending expand loop.