| 3152 gtk_widget_set_visible(child->row, child_visible); |
3152 gtk_widget_set_visible(child->row, child_visible); |
| 3153 listbox2_node_children_update_visibility(child, child_visible); |
3153 listbox2_node_children_update_visibility(child, child_visible); |
| 3154 } |
3154 } |
| 3155 } |
3155 } |
| 3156 |
3156 |
| |
3157 static void listbox2_toggle_node(UiListBox2Row *rowdata) { |
| |
3158 rowdata->expanded = !rowdata->expanded; |
| |
3159 if(rowdata->expanded) { |
| |
3160 IMAGE_SET_ICON(rowdata->expander, "pan-down-symbolic"); |
| |
3161 } else { |
| |
3162 IMAGE_SET_ICON(rowdata->expander, "pan-end-symbolic"); |
| |
3163 } |
| |
3164 listbox2_node_children_update_visibility(rowdata, rowdata->expanded); |
| |
3165 } |
| |
3166 |
| 3157 #if GTK_CHECK_VERSION(4, 0, 0) |
3167 #if GTK_CHECK_VERSION(4, 0, 0) |
| 3158 |
3168 |
| 3159 void listbox2_node_expand( |
3169 static void listbox2_node_expand( |
| 3160 GtkGestureClick *self, |
3170 GtkGestureClick *self, |
| 3161 gint n_press, |
3171 gint n_press, |
| 3162 gdouble x, |
3172 gdouble x, |
| 3163 gdouble y, |
3173 gdouble y, |
| 3164 UiListBox2Row *rowdata) |
3174 UiListBox2Row *rowdata) |
| 3165 { |
3175 { |
| 3166 rowdata->expanded = !rowdata->expanded; |
3176 listbox2_toggle_node(rowdata); |
| 3167 if(rowdata->expanded) { |
|
| 3168 gtk_image_set_from_icon_name(GTK_IMAGE(rowdata->expander), "pan-down-symbolic"); |
|
| 3169 } else { |
|
| 3170 gtk_image_set_from_icon_name(GTK_IMAGE(rowdata->expander), "pan-end-symbolic"); |
|
| 3171 } |
|
| 3172 listbox2_node_children_update_visibility(rowdata, rowdata->expanded); |
|
| 3173 } |
3177 } |
| 3174 |
3178 |
| 3175 #endif |
3179 #endif |
| 3176 #if GTK_MAJOR_VERSION == 3 |
3180 #if GTK_MAJOR_VERSION == 3 |
| |
3181 |
| |
3182 static gboolean listbox2_node_expand( |
| |
3183 GtkWidget *widget, |
| |
3184 GdkEventButton *event, |
| |
3185 UiListBox2Row *rowdata) |
| |
3186 { |
| |
3187 listbox2_toggle_node(rowdata); |
| |
3188 return TRUE; |
| |
3189 } |
| 3177 |
3190 |
| 3178 #endif |
3191 #endif |
| 3179 |
3192 |
| 3180 #define LISTBOX2_ITEM_HBOX_SPACING 10 |
3193 #define LISTBOX2_ITEM_HBOX_SPACING 10 |
| 3181 static void listbox2_update_item(UiListBox2Row *rowdata, GtkWidget *row, UiSourceListItem *item, int identation) { |
3194 static void listbox2_update_item(UiListBox2Row *rowdata, GtkWidget *row, UiSourceListItem *item, int identation) { |
| 3182 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, LISTBOX2_ITEM_HBOX_SPACING); |
3195 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, LISTBOX2_ITEM_HBOX_SPACING); |
| 3183 |
3196 |
| 3184 rowdata->expanded = 1; |
3197 rowdata->expanded = 1; |
| 3185 GtkWidget *expander = gtk_image_new_from_icon_name("pan-down-symbolic"); |
3198 GtkWidget *expander = gtk_image_new(); |
| |
3199 GtkWidget *expander0 = expander; |
| |
3200 IMAGE_SET_ICON(expander, "pan-down-symbolic"); |
| 3186 int exp_width = 0; |
3201 int exp_width = 0; |
| 3187 #if GTK_CHECK_VERSION(4, 0, 0) |
3202 #if GTK_CHECK_VERSION(4, 0, 0) |
| 3188 gtk_widget_measure(expander, |
3203 gtk_widget_measure(expander, |
| 3189 GTK_ORIENTATION_HORIZONTAL, |
3204 GTK_ORIENTATION_HORIZONTAL, |
| 3190 -1, |
3205 -1, |
| 3197 gtk_widget_add_controller(expander, GTK_EVENT_CONTROLLER(click)); |
3212 gtk_widget_add_controller(expander, GTK_EVENT_CONTROLLER(click)); |
| 3198 g_signal_connect(click, "released", G_CALLBACK(listbox2_node_expand), rowdata); |
3213 g_signal_connect(click, "released", G_CALLBACK(listbox2_node_expand), rowdata); |
| 3199 #else |
3214 #else |
| 3200 int exp_height; |
3215 int exp_height; |
| 3201 gtk_widget_get_preferred_width(expander, &exp_width, &exp_height); |
3216 gtk_widget_get_preferred_width(expander, &exp_width, &exp_height); |
| |
3217 |
| |
3218 expander0 = gtk_event_box_new(); |
| |
3219 gtk_container_add(GTK_CONTAINER(expander0), expander); |
| |
3220 |
| |
3221 gtk_widget_set_events(expander, GDK_BUTTON_PRESS_MASK); |
| |
3222 g_signal_connect( |
| |
3223 expander0, |
| |
3224 "button-release-event", |
| |
3225 G_CALLBACK(listbox2_node_expand), |
| |
3226 rowdata); |
| 3202 #endif |
3227 #endif |
| 3203 gtk_widget_set_margin_start(hbox, identation * (exp_width+LISTBOX2_ITEM_HBOX_SPACING)); |
3228 gtk_widget_set_margin_start(hbox, identation * (exp_width+LISTBOX2_ITEM_HBOX_SPACING)); |
| 3204 |
3229 |
| 3205 WIDGET_NO_SHOW_ALL(expander); |
3230 WIDGET_NO_SHOW_ALL(expander); |
| 3206 gtk_widget_set_visible(expander, FALSE); |
3231 gtk_widget_set_visible(expander, FALSE); |
| 3207 // normal items have the expander icon in the front |
3232 // normal items have the expander icon in the front |
| 3208 if(!item->is_header) { |
3233 if(!item->is_header) { |
| 3209 BOX_ADD(hbox, expander); |
3234 BOX_ADD(hbox, expander0); |
| 3210 } |
3235 } |
| 3211 rowdata->expander = expander; |
3236 rowdata->expander = expander; |
| 3212 |
3237 |
| 3213 if(item->icon) { |
3238 if(item->icon) { |
| 3214 GtkWidget *icon = ICON_IMAGE(item->icon); |
3239 GtkWidget *icon = ICON_IMAGE(item->icon); |
| 3237 g_object_set_data(G_OBJECT(row), "ui-listbox-row-button", button); |
3262 g_object_set_data(G_OBJECT(row), "ui-listbox-row-button", button); |
| 3238 } |
3263 } |
| 3239 |
3264 |
| 3240 // headings have the expander at the end |
3265 // headings have the expander at the end |
| 3241 if(item->is_header) { |
3266 if(item->is_header) { |
| 3242 BOX_ADD(hbox, expander); |
3267 BOX_ADD(hbox, expander0); |
| 3243 WIDGET_ADD_CSS_CLASS(label, "ui-listbox-header-row"); |
3268 WIDGET_ADD_CSS_CLASS(label, "ui-listbox-header-row"); |
| 3244 rowdata->heading = TRUE; |
3269 rowdata->heading = TRUE; |
| 3245 } |
3270 } |
| 3246 |
3271 |
| 3247 LISTBOX_ROW_SET_CHILD(row, hbox); |
3272 LISTBOX_ROW_SET_CHILD(row, hbox); |
| 3248 g_object_set_data(G_OBJECT(row), "ui-listbox-row-data", rowdata); |
3273 g_object_set_data(G_OBJECT(row), "ui-listbox-row-data", rowdata); |
| 3249 } |
3274 } |
| 3250 |
3275 |
| |
3276 static void listbox2_remove_all(UiListBox2 *listbox) { |
| |
3277 CxIterator i = cxListIterator(listbox->rows); |
| |
3278 cx_foreach(UiListBox2Row *, row, i) { |
| |
3279 LISTBOX_REMOVE(listbox->listbox, row->row); |
| |
3280 } |
| |
3281 cxListClear(listbox->rows); |
| |
3282 } |
| |
3283 |
| 3251 static void listbox2_update_all(UiListBox2 *listbox) { |
3284 static void listbox2_update_all(UiListBox2 *listbox) { |
| 3252 gtk_list_box_remove_all(listbox->listbox); |
3285 listbox2_remove_all(listbox); |
| 3253 cxListClear(listbox->rows); |
|
| 3254 if(!listbox->var) { |
3286 if(!listbox->var) { |
| 3255 return; |
3287 return; |
| 3256 } |
3288 } |
| 3257 UiList *list = listbox->var->value; |
3289 UiList *list = listbox->var->value; |
| 3258 if(!list) { |
3290 if(!list) { |
| 3282 gtk_widget_set_events(GTK_WIDGET(row), GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); |
3314 gtk_widget_set_events(GTK_WIDGET(row), GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); |
| 3283 g_signal_connect(row, "enter-notify-event", G_CALLBACK(listbox_row_enter), NULL); |
3315 g_signal_connect(row, "enter-notify-event", G_CALLBACK(listbox_row_enter), NULL); |
| 3284 g_signal_connect(row, "leave-notify-event", G_CALLBACK(listbox_row_leave), NULL); |
3316 g_signal_connect(row, "leave-notify-event", G_CALLBACK(listbox_row_leave), NULL); |
| 3285 #endif |
3317 #endif |
| 3286 |
3318 |
| 3287 gtk_list_box_append(listbox->listbox, row); |
3319 gtk_list_box_insert(listbox->listbox, row, -1); |
| 3288 UiListBox2Row row_data = {0}; |
3320 UiListBox2Row row_data = {0}; |
| 3289 row_data.listbox = listbox; |
3321 row_data.listbox = listbox; |
| 3290 row_data.row = row; |
3322 row_data.row = row; |
| 3291 row_data.index = index; |
3323 row_data.index = index; |
| 3292 row_data.depth = item.depth; |
3324 row_data.depth = item.depth; |