ui/gtk/list.c

changeset 778
85b6cef7fcba
parent 777
622efebfab37
child 779
b84cbe57e0bd
equal deleted inserted replaced
777:622efebfab37 778:85b6cef7fcba
93 tableview->selection.count = 0; 93 tableview->selection.count = 0;
94 tableview->selection.rows = NULL; 94 tableview->selection.rows = NULL;
95 tableview->current_row = -1; 95 tableview->current_row = -1;
96 tableview->getstyle = args->getstyle; 96 tableview->getstyle = args->getstyle;
97 tableview->getstyledata = args->getstyledata; 97 tableview->getstyledata = args->getstyledata;
98 tableview->onsave = args->onsave;
99 tableview->onsavedata = args->onsavedata;
98 100
99 if(args->getvalue2) { 101 if(args->getvalue2) {
100 tableview->getvalue = args->getvalue2; 102 tableview->getvalue = args->getvalue2;
101 tableview->getvaluedata = args->getvalue2data; 103 tableview->getvaluedata = args->getvalue2data;
102 } else if(args->getvalue) { 104 } else if(args->getvalue) {
140 obj->i = i; 142 obj->i = i;
141 return obj; 143 return obj;
142 } 144 }
143 145
144 /* END GObject wrapper for generic pointers */ 146 /* END GObject wrapper for generic pointers */
147
148 typedef struct UiCellEntry {
149 GtkEntry *entry;
150 UiListView *listview;
151 char *previous_value;
152 int row;
153 int col;
154 } UiCellEntry;
155
156 static void cell_save_value(UiCellEntry *data, int restore) {
157 if(data->listview && data->listview->onsave) {
158 UiVar *var = data->listview->var;
159 UiList *list = var ? var->value : NULL;
160 const char *str = ENTRY_GET_TEXT(data->entry);
161 UiCellValue value;
162 value.string = str;
163 if(data->listview->onsave(list, data->row, data->col, value, data->listview->onsavedata)) {
164 free(data->previous_value);
165 data->previous_value = strdup(str);
166 } else if(restore) {
167 ENTRY_SET_TEXT(data->entry, data->previous_value);
168 }
169 }
170 }
171
172 static void cell_entry_leave_focus(
173 GtkEventControllerFocus *self,
174 UiCellEntry *data)
175 {
176 // TODO: use a different singal to track focus
177 // we only want to call cell_save_value, when another entry is selected,
178 // not when the window loses focus or something like that
179 cell_save_value(data, TRUE);
180 }
181
182 static void cell_entry_destroy(GtkWidget *object, UiCellEntry *data) {
183 free(data->previous_value);
184 free(data);
185 }
186
187 static void cell_entry_unmap(GtkWidget *w, UiCellEntry *data) {
188 const char *text = ENTRY_GET_TEXT(w);
189 cell_save_value(data, FALSE);
190 }
191
192 static void cell_entry_activate(
193 GtkEntry *self,
194 UiCellEntry *data)
195 {
196 cell_save_value(data, TRUE);
197 }
145 198
146 static void column_factory_setup(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) { 199 static void column_factory_setup(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) {
147 UiColData *col = userdata; 200 UiColData *col = userdata;
148 UiModel *model = col->listview->model; 201 UiModel *model = col->listview->model;
149 UiModelType type = model->types[col->model_column]; 202 UiModelType type = model->types[col->model_column];
161 gtk_list_item_set_child(item, image); 214 gtk_list_item_set_child(item, image);
162 } else if(type == UI_STRING_EDITABLE) { 215 } else if(type == UI_STRING_EDITABLE) {
163 GtkWidget *textfield = gtk_entry_new(); 216 GtkWidget *textfield = gtk_entry_new();
164 gtk_widget_add_css_class(textfield, "ui-table-entry"); 217 gtk_widget_add_css_class(textfield, "ui-table-entry");
165 gtk_list_item_set_child(item, textfield); 218 gtk_list_item_set_child(item, textfield);
219
220 UiCellEntry *entry_data = malloc(sizeof(UiCellEntry));
221 entry_data->entry = GTK_ENTRY(textfield);
222 entry_data->listview = NULL;
223 entry_data->previous_value = NULL;
224 entry_data->col = 0;
225 entry_data->row = 0;
226 g_object_set_data(G_OBJECT(textfield), "ui_entry_data", entry_data);
227
228 g_signal_connect(
229 textfield,
230 "destroy",
231 G_CALLBACK(cell_entry_destroy),
232 entry_data);
233 g_signal_connect(
234 textfield,
235 "activate",
236 G_CALLBACK(cell_entry_activate),
237 entry_data);
238 g_signal_connect(
239 textfield,
240 "unmap",
241 G_CALLBACK(cell_entry_unmap),
242 entry_data);
243
244 GtkEventController *focus_controller = gtk_event_controller_focus_new();
245 g_signal_connect(focus_controller, "leave", G_CALLBACK(cell_entry_leave_focus), entry_data);
246 gtk_widget_add_controller(textfield, focus_controller);
166 } else { 247 } else {
167 GtkWidget *label = gtk_label_new(NULL); 248 GtkWidget *label = gtk_label_new(NULL);
168 gtk_label_set_xalign(GTK_LABEL(label), 0); 249 gtk_label_set_xalign(GTK_LABEL(label), 0);
169 gtk_list_item_set_child(item, label); 250 gtk_list_item_set_child(item, label);
170 } 251 }
296 free(data2); 377 free(data2);
297 } 378 }
298 break; 379 break;
299 } 380 }
300 case UI_STRING_EDITABLE: { 381 case UI_STRING_EDITABLE: {
382 UiCellEntry *entry = g_object_get_data(G_OBJECT(child), "ui_entry_data");
383 if(entry) {
384 entry->listview = col->listview;
385 entry->row = obj->i;
386 entry->col = col->data_column;
387 entry->previous_value = strdup(data);
388 }
301 ENTRY_SET_TEXT(child, data); 389 ENTRY_SET_TEXT(child, data);
302 break; 390 break;
303 } 391 }
304 } 392 }
305 393
318 row->bound--; 406 row->bound--;
319 if(row->bound == 0) { 407 if(row->bound == 0) {
320 cxMapRemove(listview->bound_rows, row_key); 408 cxMapRemove(listview->bound_rows, row_key);
321 } 409 }
322 } // else: should not happen 410 } // else: should not happen
411
412 GtkWidget *child = gtk_list_item_get_child(item);
413 UiCellEntry *entry = g_object_get_data(G_OBJECT(child), "ui_entry_data");
414 if(entry) {
415 cell_save_value(entry, FALSE);
416 entry->listview = NULL;
417 free(entry->previous_value);
418 entry->previous_value = NULL;
419 }
323 } 420 }
324 421
325 422
326 static GtkSelectionModel* create_selection_model(UiListView *listview, GListStore *liststore, bool multiselection) { 423 static GtkSelectionModel* create_selection_model(UiListView *listview, GListStore *liststore, bool multiselection) {
327 GtkSelectionModel *selection_model; 424 GtkSelectionModel *selection_model;

mercurial