1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2
3 /*
4 * gimv_elist.c - a set of clist and edit area widget.
5 * Copyright (C) 2001-2002 Takuro Ashie
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 3S30, Boston, MA 02111-1307, USA.
20 *
21 * $Id: gimv_elist.c,v 1.6 2004/09/22 15:37:11 makeinu Exp $
22 */
23
24 #include "gimv_elist.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "intl.h"
30 #include "gimv_marshal.h"
31
32
33 enum {
34 LIST_UPDATED_SIGNAL,
35 EDIT_AREA_SET_DATA_SIGNAL,
36 ACTION_CONFIRM_SIGNAL,
37 LAST_SIGNAL
38 };
39
40
41 #if (GTK_MAJOR_VERSION >= 2)
42
43 #include <gobject/gvaluecollector.h>
44
45 #define list_widget_get_row_num(widget) \
46 gtk_tree_model_iter_n_children (gtk_tree_view_get_model (GTK_TREE_VIEW (widget)), NULL);
47
48 #define ROWDATA(columns) columns
49 #define ROWDESTROY(columns) columns + 1
50 #define ALL_COLUMNS(columns) columns + 2
51
52 #else /* (GTK_MAJOR_VERSION >= 2) */
53
54 #define list_widget_get_row_num(widget) GTK_CLIST (widget)->rows;
55
56 #endif /* (GTK_MAJOR_VERSION >= 2) */
57
58
59 static void gimv_elist_init (GimvEList *editlist);
60 static void gimv_elist_class_init (GimvEListClass *klass);
61 #ifdef USE_GTK2
62 static void gimv_elist_finalize (GObject *object);
63 #else
64 static void gimv_elist_finalize (GtkObject *object);
65 #endif
66
67 /* private */
68 static void gimv_elist_set_move_button_sensitive (GimvEList *editlist);
69 static void gimv_elist_set_sensitive (GimvEList *editlist);
70 static void gimv_elist_edit_area_set_data (GimvEList *editlist,
71 gint row);
72 static gchar **gimv_elist_edit_area_get_data (GimvEList *editlist,
73 GimvEListActionType type);
74 static void gimv_elist_edit_area_reset (GimvEList *editlist);
75
76
77 static GtkVBoxClass *parent_class = NULL;
78 static gint gimv_elist_signals[LAST_SIGNAL] = {0};
79
80
81 GtkType
gimv_elist_get_type(void)82 gimv_elist_get_type (void)
83 {
84 static GtkType gimv_elist_type = 0;
85
86 #if (GTK_MAJOR_VERSION >= 2)
87 if (!gimv_elist_type) {
88 static const GTypeInfo gimv_elist_info = {
89 sizeof (GimvEListClass),
90 NULL, /* base_init */
91 NULL, /* base_finalize */
92 (GClassInitFunc) gimv_elist_class_init,
93 NULL, /* class_finalize */
94 NULL, /* class_data */
95 sizeof (GimvEList),
96 0, /* n_preallocs */
97 (GInstanceInitFunc) gimv_elist_init,
98 };
99
100 gimv_elist_type = g_type_register_static (GTK_TYPE_VBOX,
101 "GimvEList",
102 &gimv_elist_info,
103 0);
104 }
105 #else /* (GTK_MAJOR_VERSION >= 2) */
106 if (!gimv_elist_type) {
107 static const GtkTypeInfo gimv_elist_info = {
108 "GimvEList",
109 sizeof (GimvEList),
110 sizeof (GimvEListClass),
111 (GtkClassInitFunc) gimv_elist_class_init,
112 (GtkObjectInitFunc) gimv_elist_init,
113 NULL,
114 NULL,
115 (GtkClassInitFunc) NULL,
116 };
117
118 gimv_elist_type = gtk_type_unique (gtk_vbox_get_type (),
119 &gimv_elist_info);
120 }
121 #endif /* (GTK_MAJOR_VERSION >= 2) */
122
123 return gimv_elist_type;
124 }
125
126
127 static void
gimv_elist_init(GimvEList * editlist)128 gimv_elist_init (GimvEList *editlist)
129 {
130 editlist->clist = NULL;
131 editlist->new_button = NULL;
132 editlist->add_button = NULL;
133 editlist->change_button = NULL;
134 editlist->del_button = NULL;
135 editlist->up_button = NULL;
136 editlist->down_button = NULL;
137 editlist->edit_area = NULL;
138 editlist->move_button_area = NULL;
139 editlist->action_button_area = NULL;
140
141 editlist->max_row = -1;
142 editlist->columns = 0;
143 editlist->rows = 0;
144 editlist->selected = -1;
145 editlist->dest_row = -1;
146
147 editlist->edit_area_flags = GIMV_ELIST_EDIT_AREA_VALUE_INITIALIZED;
148 editlist->column_func_tables = NULL;
149 editlist->get_rowdata_fn = NULL;
150
151 #if (GTK_MAJOR_VERSION >= 2)
152 editlist->rowdata_table
153 = g_hash_table_new (g_direct_hash, g_direct_equal);
154 editlist->rowdata_destroy_fn_table
155 = g_hash_table_new (g_direct_hash, g_direct_equal);
156 #endif /* (GTK_MAJOR_VERSION >= 2) */
157 }
158
159
160 static void
gimv_elist_class_init(GimvEListClass * klass)161 gimv_elist_class_init (GimvEListClass *klass)
162 {
163 GtkObjectClass *object_class;
164
165 object_class = (GtkObjectClass *) klass;
166 parent_class = gtk_type_class (gtk_vbox_get_type ());
167
168 gimv_elist_signals[LIST_UPDATED_SIGNAL]
169 = gtk_signal_new ("list-updated",
170 GTK_RUN_FIRST,
171 GTK_CLASS_TYPE(object_class),
172 GTK_SIGNAL_OFFSET (GimvEListClass, list_updated),
173 gtk_signal_default_marshaller,
174 GTK_TYPE_NONE, 0);
175
176 gimv_elist_signals[EDIT_AREA_SET_DATA_SIGNAL]
177 = gtk_signal_new ("edit-area-set-data",
178 GTK_RUN_FIRST,
179 GTK_CLASS_TYPE(object_class),
180 GTK_SIGNAL_OFFSET (GimvEListClass, edit_area_set_data),
181 gtk_signal_default_marshaller,
182 GTK_TYPE_NONE, 0);
183
184 gimv_elist_signals[ACTION_CONFIRM_SIGNAL]
185 = gtk_signal_new ("action-confirm",
186 GTK_RUN_LAST,
187 GTK_CLASS_TYPE(object_class),
188 GTK_SIGNAL_OFFSET (GimvEListClass, action_confirm),
189 gtk_marshal_NONE__INT_INT_POINTER,
190 GTK_TYPE_NONE, 3, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER);
191
192 gtk_object_class_add_signals (object_class, gimv_elist_signals, LAST_SIGNAL);
193
194 OBJECT_CLASS_SET_FINALIZE_FUNC (klass, gimv_elist_finalize);
195 }
196
197
198 static void
gimv_elist_updated(GimvEList * editlist)199 gimv_elist_updated (GimvEList *editlist)
200 {
201 g_return_if_fail (GIMV_IS_ELIST (editlist));
202
203 gtk_signal_emit (GTK_OBJECT (editlist),
204 gimv_elist_signals[LIST_UPDATED_SIGNAL]);
205 }
206
207
208
209 /*******************************************************************************
210 *
211 * Object class functions.
212 *
213 *******************************************************************************/
214 #if (GTK_MAJOR_VERSION >= 2)
215 static void
free_rowdata(gpointer key,gpointer value,gpointer data)216 free_rowdata (gpointer key, gpointer value, gpointer data)
217 {
218 GimvEList *editlist = data;
219 GtkDestroyNotify destroy;
220
221 destroy = g_hash_table_lookup (editlist->rowdata_destroy_fn_table, value);
222 if (destroy)
223 destroy (value);
224 }
225 #endif /* (GTK_MAJOR_VERSION >= 2) */
226
227
228 static void
229 #ifdef USE_GTK2
gimv_elist_finalize(GObject * object)230 gimv_elist_finalize (GObject *object)
231 #else
232 gimv_elist_finalize (GtkObject *object)
233 #endif
234 {
235 GimvEList *editlist = GIMV_ELIST (object);
236 gint i;
237
238 /* remove column funcs */
239 for (i = 0; i < editlist->columns; i++) {
240 GimvEListColumnFuncTable *table = editlist->column_func_tables[i];
241 if (table->destroy_fn)
242 table->destroy_fn (table->coldata);
243 g_free (table);
244 editlist->column_func_tables[i] = NULL;
245 }
246 g_free (editlist->column_func_tables);
247 editlist->column_func_tables = NULL;
248
249 #if (GTK_MAJOR_VERSION >= 2)
250 g_hash_table_foreach (editlist->rowdata_table, free_rowdata, editlist);
251 g_hash_table_destroy (editlist->rowdata_table);
252 g_hash_table_destroy (editlist->rowdata_destroy_fn_table);
253 #endif /* (GTK_MAJOR_VERSION >= 2) */
254
255 OBJECT_CLASS_FINALIZE_SUPER (parent_class, object);
256 }
257
258
259
260 /*******************************************************************************
261 *
262 * Callback functions for child widget.
263 *
264 *******************************************************************************/
265 #if (GTK_MAJOR_VERSION >= 2)
266
267 static void
cb_editlist_cursor_changed(GtkTreeView * treeview,gpointer data)268 cb_editlist_cursor_changed (GtkTreeView *treeview, gpointer data)
269 {
270 GimvEList *editlist = data;
271 GtkTreeSelection *selection;
272 GtkTreeModel *model = NULL;
273 GtkTreeIter iter;
274 gboolean success;
275
276 g_return_if_fail (treeview);
277 g_return_if_fail (editlist);
278
279 selection = gtk_tree_view_get_selection (treeview);
280 success = gtk_tree_selection_get_selected (selection, &model, &iter);
281
282 if (success) {
283 GtkTreePath *treepath = gtk_tree_model_get_path (model, &iter);
284 gchar *path = gtk_tree_path_to_string (treepath);
285
286 editlist->selected = atoi (path);
287
288 gtk_tree_path_free (treepath);
289 g_free (path);
290 } else {
291 editlist->selected = -1;
292 }
293
294 gimv_elist_edit_area_set_data (editlist, editlist->selected);
295
296 gimv_elist_set_sensitive (editlist);
297 }
298
299
300 static void
cb_editlist_row_changed(GtkTreeModel * model,GtkTreePath * treepath,GtkTreeIter * iter,gpointer data)301 cb_editlist_row_changed (GtkTreeModel *model,
302 GtkTreePath *treepath,
303 GtkTreeIter *iter,
304 gpointer data)
305 {
306 GimvEList *editlist = data;
307
308 gimv_elist_updated (editlist);
309
310 gimv_elist_set_sensitive (editlist);
311 }
312
313
314 static void
cb_editlist_row_deleted(GtkTreeModel * model,GtkTreePath * treepath,gpointer data)315 cb_editlist_row_deleted (GtkTreeModel *model,
316 GtkTreePath *treepath,
317 gpointer data)
318 {
319 GimvEList *editlist = data;
320
321 gimv_elist_updated (editlist);
322
323 if (editlist->dest_row < 0) {
324 editlist->selected = -1;
325 gimv_elist_set_sensitive (editlist);
326 }
327 editlist->dest_row = -1;
328
329 gimv_elist_edit_area_set_data (editlist, editlist->selected);
330
331 gimv_elist_set_sensitive (editlist);
332 }
333
334 #else /* (GTK_MAJOR_VERSION >=2) */
335
336 static void
cb_editlist_select_row(GtkCList * clist,gint row,gint col,GdkEventButton * event,gpointer data)337 cb_editlist_select_row (GtkCList *clist, gint row, gint col,
338 GdkEventButton *event, gpointer data)
339 {
340 GimvEList *editlist = data;
341
342 editlist->selected = row;
343
344 gimv_elist_edit_area_set_data (editlist, row);
345
346 gimv_elist_set_sensitive (editlist);
347 }
348
349
350 static void
cb_editlist_unselect_row(GtkCList * clist,gint row,gint col,GdkEventButton * event,gpointer data)351 cb_editlist_unselect_row (GtkCList *clist, gint row, gint col,
352 GdkEventButton *event, gpointer data)
353 {
354 GimvEList *editlist = data;
355
356 editlist->selected = -1;
357
358 gimv_elist_edit_area_set_data (editlist, -1);
359
360 gimv_elist_set_sensitive (editlist);
361 }
362
363
364 static gint
idle_editlist_row_move(gpointer data)365 idle_editlist_row_move (gpointer data)
366 {
367 GimvEList *editlist = data;
368
369 gimv_elist_updated (editlist);
370 gimv_elist_set_sensitive (editlist);
371
372 return FALSE;
373 }
374
375
376 static void
cb_editlist_row_move(GtkCList * clist,gint arg1,gint arg2,gpointer data)377 cb_editlist_row_move (GtkCList *clist, gint arg1, gint arg2, gpointer data)
378 {
379 GimvEList *editlist = data;
380 gint src, dest = editlist->dest_row;
381 gint selected = editlist->selected;
382
383 if (editlist->dest_row >= 0) {
384 dest = editlist->dest_row;
385 src = arg1 == dest ? arg2 : arg1;
386 } else {
387 src = arg1;
388 dest = arg2;
389 }
390
391 if (selected >= 0) {
392 if (selected == src) {
393 editlist->selected = dest;
394 } else if (selected >= MIN (src, dest) && selected <= MAX (src, dest)) {
395 if (src < dest)
396 editlist->selected--;
397 else
398 editlist->selected++;
399 }
400 }
401
402 editlist->dest_row = -1;
403
404 gtk_idle_add (idle_editlist_row_move, editlist);
405 }
406
407 #endif /* (GTK_MAJOR_VERSION >=2) */
408
409
410 static void
cb_editlist_up_button(GtkButton * button,gpointer data)411 cb_editlist_up_button (GtkButton *button, gpointer data)
412 {
413 GimvEList *editlist = data;
414
415 gint selected = editlist->selected;
416 gint rows = editlist->rows;
417
418 g_return_if_fail (button && editlist);
419
420 if (selected < 1 || selected > rows - 1) return;
421
422 editlist->dest_row = editlist->selected - 1;
423
424 #if (GTK_MAJOR_VERSION >= 2)
425 {
426 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
427 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
428 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
429 GtkTreePath *treepath;
430 GtkTreeIter iter, prev_iter, dest_iter;
431 gboolean success;
432
433 GValue *values;
434 gint i, colnum = gtk_tree_model_get_n_columns (model);
435
436 /* get src row */
437 selection = gtk_tree_view_get_selection (treeview);
438 success = gtk_tree_selection_get_selected (selection, &model, &iter);
439 if (!success) return;
440 treepath = gtk_tree_model_get_path (model, &iter);
441
442 /* get prev row */
443 success = gtk_tree_path_prev (treepath);
444 if (!success) {
445 gtk_tree_path_free (treepath);
446 return;
447 }
448 gtk_tree_model_get_iter (model, &prev_iter, treepath);
449
450 /* get src data */
451 values = g_new0 (GValue, colnum);
452 for (i = 0; i < colnum; i++) {
453 gtk_tree_model_get_value (model, &iter, i, &values[i]);
454 }
455
456 /* insert dest row before prev */
457 gtk_list_store_insert_before (GTK_LIST_STORE (model),
458 &dest_iter, &prev_iter);
459 for (i = 0; i < colnum; i++) {
460 gtk_list_store_set_value (GTK_LIST_STORE (model), &dest_iter,
461 i, &values[i]);
462 g_value_unset (&values[i]);
463 }
464 g_free (values);
465
466 /* delete src */
467 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
468
469 /* select dest */
470 gtk_tree_path_free (treepath);
471 treepath = gtk_tree_model_get_path (model, &dest_iter);
472 gtk_tree_view_set_cursor (treeview, treepath, NULL, FALSE);
473
474 /* clean */
475 gtk_tree_path_free (treepath);
476 }
477 #else /* (GTK_MAJOR_VERSION >= 2) */
478 {
479 gtk_clist_swap_rows (GTK_CLIST (editlist->clist), selected, selected - 1);
480 gtk_clist_moveto (GTK_CLIST (editlist->clist), selected - 1, 0, 0, 0);
481 }
482 #endif /* (GTK_MAJOR_VERSION >= 2) */
483 }
484
485
486 static void
cb_editlist_down_button(GtkButton * button,gpointer data)487 cb_editlist_down_button (GtkButton *button, gpointer data)
488 {
489 GimvEList *editlist = data;
490 gint selected = editlist->selected;
491 gint rows = editlist->rows;
492
493 g_return_if_fail (button && editlist);
494
495 if (selected < 0 || selected > rows - 2) return;
496
497 editlist->dest_row = editlist->selected + 1;
498
499 #if (GTK_MAJOR_VERSION >= 2)
500 {
501 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
502 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
503 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
504 GtkTreeIter iter, next_iter, dest_iter;
505 GtkTreePath *treepath;
506 gboolean success;
507
508 GValue *values;
509 gint i, colnum = gtk_tree_model_get_n_columns (model);
510
511 /* get src row */
512 selection = gtk_tree_view_get_selection (treeview);
513 success = gtk_tree_selection_get_selected (selection, &model, &iter);
514 if (!success) return;
515
516 /* get prev row */
517 next_iter = iter;
518 success = gtk_tree_model_iter_next (model, &next_iter);
519 if (!success) return;
520
521 /* get src data */
522 values = g_new0 (GValue, colnum);
523 for (i = 0; i < colnum; i++) {
524 gtk_tree_model_get_value (model, &iter, i, &values[i]);
525 }
526
527 /* insert dest row before prev */
528 gtk_list_store_insert_after (GTK_LIST_STORE (model),
529 &dest_iter, &next_iter);
530 for (i = 0; i < colnum; i++) {
531 gtk_list_store_set_value (GTK_LIST_STORE (model), &dest_iter,
532 i, &values[i]);
533 g_value_unset (&values[i]);
534 }
535 g_free (values);
536
537 /* delete src */
538 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
539
540 /* select dest */
541 treepath = gtk_tree_model_get_path (model, &dest_iter);
542 gtk_tree_view_set_cursor (treeview, treepath, NULL, FALSE);
543
544 /* clean */
545 gtk_tree_path_free (treepath);
546 }
547 #else /* (GTK_MAJOR_VERSION >= 2) */
548 {
549 gtk_clist_swap_rows (GTK_CLIST (editlist->clist), selected, selected + 1);
550 gtk_clist_moveto (GTK_CLIST (editlist->clist), selected + 1, 0, 0, 0);
551 }
552 #endif /* (GTK_MAJOR_VERSION >= 2) */
553 }
554
555
556 static void
cb_editlist_new_button(GtkButton * button,gpointer data)557 cb_editlist_new_button (GtkButton *button, gpointer data)
558 {
559 GimvEList *editlist = data;
560 GimvEListConfirmFlags flags;
561
562 flags = gimv_elist_action_confirm (editlist, GIMV_ELIST_ACTION_RESET);
563 if (flags & GIMV_ELIST_CONFIRM_CANNOT_NEW) return;
564
565 gimv_elist_unselect_all (editlist);
566 gimv_elist_edit_area_reset (editlist);
567 gimv_elist_set_sensitive (editlist);
568 }
569
570
571 static void
cb_editlist_add_button(GtkButton * button,gpointer data)572 cb_editlist_add_button (GtkButton *button, gpointer data)
573 {
574 GimvEList *editlist = data;
575 GimvEListConfirmFlags flags;
576 gint row;
577 gchar **text;
578 gpointer rowdata = NULL;
579 GtkDestroyNotify destroy_fn = NULL;
580 gboolean set_rowdata = FALSE;
581
582 g_return_if_fail (GIMV_IS_ELIST (editlist));
583
584 flags = gimv_elist_action_confirm (editlist, GIMV_ELIST_ACTION_ADD);
585 if (flags & GIMV_ELIST_CONFIRM_CANNOT_ADD) return;
586
587 text = gimv_elist_edit_area_get_data (editlist, GIMV_ELIST_ACTION_ADD);
588 g_return_if_fail (text);
589
590 row = gimv_elist_append_row (editlist, text);
591 g_strfreev (text);
592
593 if (editlist->get_rowdata_fn)
594 set_rowdata = editlist->get_rowdata_fn (editlist,
595 GIMV_ELIST_ACTION_ADD,
596 &rowdata, &destroy_fn);
597 if (set_rowdata) {
598 gimv_elist_set_row_data_full (editlist, row, rowdata, destroy_fn);
599 }
600
601 gimv_elist_updated (editlist);
602
603 gimv_elist_edit_area_reset (editlist);
604 gimv_elist_set_sensitive (editlist);
605 }
606
607
608 static void
cb_editlist_change_button(GtkButton * button,gpointer data)609 cb_editlist_change_button (GtkButton *button, gpointer data)
610 {
611 GimvEList *editlist = data;
612 GimvEListConfirmFlags flags;
613 gchar **text;
614 gint i;
615 gpointer rowdata = NULL;
616 GtkDestroyNotify destroy_fn = NULL;
617 gboolean set_rowdata = FALSE;
618
619 g_return_if_fail (GIMV_IS_ELIST (editlist));
620
621 if (editlist->selected < 0 || editlist->selected >= editlist->rows) return;
622
623 flags = gimv_elist_action_confirm (editlist, GIMV_ELIST_ACTION_CHANGE);
624 if (flags & GIMV_ELIST_CONFIRM_CANNOT_CHANGE) return;
625
626 text = gimv_elist_edit_area_get_data (editlist,
627 GIMV_ELIST_ACTION_CHANGE);
628 g_return_if_fail (text);
629
630 #ifdef ENABLE_TREEVIEW
631 {
632 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
633 GtkTreeModel *model;
634 GtkTreeSelection *selection;
635 GtkTreeIter iter;
636 gboolean success;
637
638 selection = gtk_tree_view_get_selection (treeview);
639 success = gtk_tree_selection_get_selected (selection, &model, &iter);
640 if (!success) {
641 g_strfreev (text);
642 return;
643 }
644
645 for (i = 0; i < editlist->columns; i++) {
646 gtk_list_store_set (GTK_LIST_STORE (model), &iter, i, text[i], -1);
647 }
648 }
649 #else /* ENABLE_TREEVIEW */
650 {
651 GtkCList *clist = GTK_CLIST (editlist->clist);
652
653 for (i = 0; i < editlist->columns; i++) {
654 gtk_clist_set_text (clist, editlist->selected, i, text[i]);
655 }
656 }
657 #endif /* ENABLE_TREEVIEW */
658
659 g_strfreev (text);
660
661 if (editlist->get_rowdata_fn)
662 set_rowdata = editlist->get_rowdata_fn (editlist,
663 GIMV_ELIST_ACTION_CHANGE,
664 &rowdata, &destroy_fn);
665 if (set_rowdata) {
666 gimv_elist_set_row_data_full (editlist, editlist->selected,
667 rowdata, destroy_fn);
668 }
669
670 gimv_elist_updated (editlist);
671
672 editlist->edit_area_flags &= ~GIMV_ELIST_EDIT_AREA_VALUE_CHANGED;
673
674 gimv_elist_set_sensitive (editlist);
675 }
676
677
678 static void
cb_editlist_delete_button(GtkButton * button,gpointer data)679 cb_editlist_delete_button (GtkButton *button, gpointer data)
680 {
681 GimvEList *editlist = data;
682 GimvEListConfirmFlags flags;
683
684 g_return_if_fail (GIMV_IS_ELIST (editlist));
685 g_return_if_fail (editlist->selected >= 0);
686
687 flags = gimv_elist_action_confirm (editlist, GIMV_ELIST_ACTION_DELETE);
688 if (flags & GIMV_ELIST_CONFIRM_CANNOT_DELETE) return;
689
690 gimv_elist_remove_row (editlist, editlist->selected);
691
692 gimv_elist_updated (editlist);
693
694 gimv_elist_set_sensitive (editlist);
695 }
696
697
698 /*******************************************************************************
699 *
700 * Private functions.
701 *
702 *******************************************************************************/
703 static void
gimv_elist_set_move_button_sensitive(GimvEList * editlist)704 gimv_elist_set_move_button_sensitive (GimvEList *editlist)
705 {
706 gint rownum = editlist->rows;
707 gint selected = editlist->selected;
708 gboolean reorderble = gimv_elist_get_reorderable (editlist);
709
710 if (!reorderble || selected < 0) {
711 gtk_widget_set_sensitive (editlist->up_button, FALSE);
712 gtk_widget_set_sensitive (editlist->down_button, FALSE);
713
714 } else {
715 /* up button */
716 if (selected == 0)
717 gtk_widget_set_sensitive (editlist->up_button, FALSE);
718 else
719 gtk_widget_set_sensitive (editlist->up_button, TRUE);
720
721 /* down button */
722 if (selected < rownum - 1)
723 gtk_widget_set_sensitive (editlist->down_button, TRUE);
724 else
725 gtk_widget_set_sensitive (editlist->down_button, FALSE);
726 }
727 }
728
729
730 static void
gimv_elist_set_sensitive(GimvEList * editlist)731 gimv_elist_set_sensitive (GimvEList *editlist)
732 {
733 gimv_elist_set_move_button_sensitive (editlist);
734 gimv_elist_set_action_button_sensitive (editlist);
735 }
736
737
738 static GtkWidget *
gimv_elist_create_list_widget(GimvEList * editlist,gint colnum)739 gimv_elist_create_list_widget (GimvEList *editlist, gint colnum)
740 {
741 GtkWidget *clist;
742
743 #if (GTK_MAJOR_VERSION >= 2)
744 GtkListStore *store;
745 GtkTreeViewColumn *col;
746 GtkCellRenderer *render;
747 GType *types;
748 gint i;
749
750 store = gtk_list_store_new (1, G_TYPE_STRING); /* this column is dummy */
751
752 /*
753 * types[colnum] is row data
754 * types[colnum+1] is GtkDestroyNotify
755 */
756 types = g_new0 (GType, ALL_COLUMNS(colnum));
757 for (i = 0; i < colnum; i++)
758 types[i] = G_TYPE_STRING;
759 types[ROWDATA(colnum)] = G_TYPE_POINTER;
760 types[ROWDESTROY(colnum)] = G_TYPE_POINTER;
761 gtk_list_store_set_column_types (store, ALL_COLUMNS (colnum), types);
762 g_free (types);
763
764 clist = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
765 editlist->clist = clist;
766 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (clist), TRUE);
767 gtk_tree_view_set_reorderable (GTK_TREE_VIEW (clist), TRUE);
768
769 g_signal_connect (G_OBJECT (store), "row_changed",
770 G_CALLBACK (cb_editlist_row_changed),
771 editlist);
772 g_signal_connect (G_OBJECT (store), "row_deleted",
773 G_CALLBACK (cb_editlist_row_deleted),
774 editlist);
775 g_signal_connect (G_OBJECT (clist),"cursor_changed",
776 G_CALLBACK (cb_editlist_cursor_changed),
777 editlist);
778
779 /* set column */
780 for (i = 0; i < colnum; i++) {
781 col = gtk_tree_view_column_new();
782 gtk_tree_view_column_set_resizable (col, TRUE);
783 render = gtk_cell_renderer_text_new ();
784 gtk_tree_view_column_pack_start (col, render, TRUE);
785 gtk_tree_view_column_add_attribute (col, render, "text", i);
786 gtk_tree_view_append_column (GTK_TREE_VIEW (clist), col);
787 }
788 #else /* (GTK_MAJOR_VERSION >= 2) */
789 clist = editlist->clist = gtk_clist_new (colnum);
790 gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_SINGLE);
791 gtk_clist_set_reorderable (GTK_CLIST (clist), TRUE);
792 gtk_clist_set_use_drag_icons (GTK_CLIST (clist), FALSE);
793
794 gtk_signal_connect (GTK_OBJECT (clist),"row_move",
795 GTK_SIGNAL_FUNC (cb_editlist_row_move), editlist);
796 gtk_signal_connect (GTK_OBJECT (editlist->clist), "select_row",
797 GTK_SIGNAL_FUNC (cb_editlist_select_row), editlist);
798 gtk_signal_connect (GTK_OBJECT (editlist->clist), "unselect_row",
799 GTK_SIGNAL_FUNC (cb_editlist_unselect_row), editlist);
800 #endif /* (GTK_MAJOR_VERSION >= 2) */
801
802 editlist->columns = colnum;
803
804 return clist;
805 }
806
807
808 static GimvEListColumnFuncTable *
gimv_elist_column_func_table_new(void)809 gimv_elist_column_func_table_new (void)
810 {
811 GimvEListColumnFuncTable *table;
812 table = g_new0 (GimvEListColumnFuncTable, 1);
813 table->widget = NULL;
814 table->coldata = NULL;
815 table->destroy_fn = NULL;
816 table->set_data_fn = NULL;
817 table->get_data_fn = NULL;
818 table->reset_fn = NULL;
819
820 return table;
821 }
822
823
824 static void
gimv_elist_edit_area_set_data(GimvEList * editlist,gint row)825 gimv_elist_edit_area_set_data (GimvEList *editlist, gint row)
826 {
827 gint i;
828
829 g_return_if_fail (row < editlist->rows);
830
831 gtk_signal_emit (GTK_OBJECT (editlist),
832 gimv_elist_signals[EDIT_AREA_SET_DATA_SIGNAL]);
833
834 for (i = 0; i < editlist->columns; i++) {
835 GimvEListColumnFuncTable *table = editlist->column_func_tables[i];
836 gchar *text = NULL;
837
838 if (!table) continue;
839 if (!table->set_data_fn) continue;
840
841 if (row >= 0) {
842 #if (GTK_MAJOR_VERSION >= 2)
843 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
844 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
845 GtkTreeIter iter;
846 gboolean success;
847
848 success = gtk_tree_model_iter_nth_child (model, &iter, NULL, row);
849 if (success) {
850 gtk_tree_model_get (model, &iter, i, &text, -1);
851 }
852 #else /* (GTK_MAJOR_VERSION >= 2) */
853 gtk_clist_get_text (GTK_CLIST (editlist->clist), row, i, &text);
854 if (text) text = g_strdup (text);
855 #endif /* (GTK_MAJOR_VERSION >= 2) */
856 }
857
858 table->set_data_fn (editlist, table->widget, row, i,
859 text, table->coldata);
860
861 g_free (text);
862 }
863
864 editlist->edit_area_flags &= ~GIMV_ELIST_EDIT_AREA_VALUE_INITIALIZED;
865 editlist->edit_area_flags &= ~GIMV_ELIST_EDIT_AREA_VALUE_CHANGED;
866
867 gimv_elist_set_sensitive (editlist);
868 }
869
870
871 static gchar **
gimv_elist_edit_area_get_data(GimvEList * editlist,GimvEListActionType type)872 gimv_elist_edit_area_get_data (GimvEList *editlist, GimvEListActionType type)
873 {
874 gint i;
875 gchar **text;
876
877 g_return_val_if_fail (GIMV_IS_ELIST (editlist), NULL);
878 g_return_val_if_fail (editlist->columns > 0, NULL);
879
880 text = g_new0 (gchar *, editlist->columns + 1);
881
882 for (i = 0; i < editlist->columns; i++) {
883 GimvEListColumnFuncTable *table = editlist->column_func_tables[i];
884
885 text[i] = NULL;
886
887 if (!table) {
888 g_warning ("GimvEList: function table for column %d is not found", i);
889 continue;
890 }
891 if (!table->get_data_fn) {
892 g_warning ("GimvEList: get_data_fn method for column %d is notimplemented", i);
893 continue;
894 }
895
896 text[i] = table->get_data_fn (editlist, type, table->widget, table->coldata);
897 }
898 text[editlist->columns] = NULL;
899
900 return text;
901 }
902
903
904 static void
gimv_elist_edit_area_reset(GimvEList * editlist)905 gimv_elist_edit_area_reset (GimvEList *editlist)
906 {
907 gint i;
908
909 for (i = 0; i < editlist->columns; i++) {
910 GimvEListColumnFuncTable *table = editlist->column_func_tables[i];
911
912 if (!table) continue;
913 if (!table->reset_fn) continue;
914
915 table->reset_fn (editlist, table->widget, table->coldata);
916 }
917
918 editlist->edit_area_flags |= GIMV_ELIST_EDIT_AREA_VALUE_INITIALIZED;
919 editlist->edit_area_flags &= ~GIMV_ELIST_EDIT_AREA_VALUE_CHANGED;
920
921 gimv_elist_set_sensitive (editlist);
922 }
923
924
925
926 /*******************************************************************************
927 *
928 * Public functions.
929 *
930 *******************************************************************************/
931 GtkWidget *
gimv_elist_new(gint colnum)932 gimv_elist_new (gint colnum)
933 {
934 GimvEList *editlist;
935 GtkWidget *main_vbox;
936 GtkWidget *vbox, *vbox1, *hbox, *hbox1, *scrollwin;
937 GtkWidget *clist, *button, *arrow;
938 gint i;
939
940 g_return_val_if_fail (colnum > 0, NULL);
941
942 #if (GTK_MAJOR_VERSION >= 2)
943 editlist = g_object_new (gimv_elist_get_type (), NULL);
944 #else /* (GTK_MAJOR_VERSION >= 2) */
945 editlist = gtk_type_new (gimv_elist_get_type ());
946 #endif /* (GTK_MAJOR_VERSION >= 2) */
947 main_vbox = GTK_WIDGET (editlist);
948
949 /* clist */
950 hbox = gtk_hbox_new (FALSE, 0);
951 gtk_container_set_border_width(GTK_CONTAINER (hbox), 0);
952 gtk_box_pack_start (GTK_BOX (main_vbox), hbox, TRUE, TRUE, 0);
953 gtk_widget_show (hbox);
954
955 scrollwin = gtk_scrolled_window_new (NULL, NULL);
956 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin),
957 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
958 #ifdef USE_GTK2
959 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin),
960 GTK_SHADOW_IN);
961 #endif /* USE_GTK2 */
962 gtk_container_set_border_width(GTK_CONTAINER (scrollwin), 5);
963 gtk_box_pack_start (GTK_BOX (hbox), scrollwin, TRUE, TRUE, 0);
964 gtk_widget_set_usize (scrollwin, -1, 120);
965 gtk_widget_show (scrollwin);
966
967 clist = gimv_elist_create_list_widget (editlist, colnum);
968 gtk_container_add (GTK_CONTAINER (scrollwin), clist);
969 gtk_widget_show (clist);
970
971
972 /* move buttons */
973 vbox = editlist->move_button_area = gtk_vbox_new (TRUE, 0);
974 gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 2);
975 gtk_widget_show (vbox);
976
977 vbox1 = gtk_vbox_new (TRUE, 0);
978 gtk_box_pack_start (GTK_BOX (vbox), vbox1, FALSE, FALSE, 2);
979 gtk_widget_show (vbox1);
980
981 button = editlist->up_button = gtk_button_new ();
982 #ifdef USE_ARROW
983 arrow = gtk_arrow_new (GTK_ARROW_UP, GTK_SHADOW_NONE);
984 #else /* USE_ARROW */
985 arrow = gtk_label_new (_("Up"));
986 gtk_misc_set_alignment (GTK_MISC (arrow), 0.5, 0.5);
987 #endif /* USE_ARROW */
988 gtk_container_add (GTK_CONTAINER (button), arrow);
989 gtk_widget_show (arrow);
990 gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2);
991 gtk_widget_show (button);
992
993 button = editlist->down_button = gtk_button_new ();
994 #ifdef USE_ARROW
995 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
996 #else /* USE_ARROW */
997 arrow = gtk_label_new (_("Down"));
998 gtk_misc_set_alignment (GTK_MISC (arrow), 0.5, 0.5);
999 #endif /* USE_ARROW */
1000 gtk_container_add (GTK_CONTAINER (button), arrow);
1001 gtk_widget_show (arrow);
1002 gtk_box_pack_start (GTK_BOX (vbox1), button, FALSE, FALSE, 2);
1003 gtk_widget_show (button);
1004
1005
1006 /* edit area */
1007 editlist->edit_area = gtk_hbox_new (FALSE, 0);
1008 gtk_container_set_border_width (GTK_CONTAINER (editlist->edit_area), 5);
1009 gtk_box_pack_start (GTK_BOX (main_vbox), editlist->edit_area,
1010 FALSE, TRUE, 0);
1011 gtk_widget_show (editlist->edit_area);
1012
1013
1014 /* edit buttons */
1015 hbox = editlist->action_button_area = gtk_hbox_new (FALSE, 0);
1016 gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
1017 gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
1018 gtk_widget_show (hbox);
1019
1020 hbox1 = gtk_hbox_new (TRUE, 0);
1021 gtk_box_pack_end (GTK_BOX (hbox), hbox1, FALSE, TRUE, 0);
1022 gtk_widget_show (hbox1);
1023
1024 button = editlist->new_button = gtk_button_new_with_label (_("New"));
1025 gtk_box_pack_start (GTK_BOX (hbox1), button, FALSE, TRUE, 2);
1026 gtk_widget_show (button);
1027
1028 button = editlist->add_button = gtk_button_new_with_label (_("Add"));
1029 gtk_box_pack_start (GTK_BOX (hbox1), button, FALSE, TRUE, 2);
1030 gtk_widget_show (button);
1031
1032 button = editlist->change_button = gtk_button_new_with_label (_("Change"));
1033 gtk_box_pack_start (GTK_BOX (hbox1), button, FALSE, TRUE, 2);
1034 gtk_widget_show (button);
1035
1036 button = editlist->del_button = gtk_button_new_with_label (_("Delete"));
1037 gtk_box_pack_start (GTK_BOX (hbox1), button, FALSE, TRUE, 2);
1038 gtk_widget_show (button);
1039
1040
1041 #if (GTK_MAJOR_VERSION >= 2)
1042
1043 #ifdef USE_ARROW
1044 gtk_widget_set_size_request (editlist->up_button, 20, 20);
1045 gtk_widget_set_size_request (editlist->down_button, 20, 20);
1046 #endif /* USE_ARROW */
1047 gtk_widget_set_size_request (editlist->new_button, 70, -1);
1048
1049 g_signal_connect (G_OBJECT (editlist->up_button), "clicked",
1050 G_CALLBACK (cb_editlist_up_button), editlist);
1051 g_signal_connect (G_OBJECT (editlist->down_button), "clicked",
1052 G_CALLBACK (cb_editlist_down_button), editlist);
1053 g_signal_connect (G_OBJECT (editlist->new_button), "clicked",
1054 G_CALLBACK (cb_editlist_new_button), editlist);
1055 g_signal_connect (G_OBJECT (editlist->add_button), "clicked",
1056 G_CALLBACK (cb_editlist_add_button), editlist);
1057 g_signal_connect (G_OBJECT (editlist->change_button), "clicked",
1058 G_CALLBACK (cb_editlist_change_button), editlist);
1059 g_signal_connect (G_OBJECT (editlist->del_button), "clicked",
1060 G_CALLBACK (cb_editlist_delete_button), editlist);
1061
1062 #else /* (GTK_MAJOR_VERSION >= 2) */
1063
1064 #ifdef USE_ARROW
1065 gtk_widget_set_usize (editlist->up_button, 20, 20);
1066 gtk_widget_set_usize (editlist->down_button, 20, 20);
1067 #endif /* USE_ARROW */
1068 gtk_widget_set_usize (editlist->new_button, 70, -1);
1069
1070 gtk_signal_connect (GTK_OBJECT (editlist->up_button), "clicked",
1071 GTK_SIGNAL_FUNC (cb_editlist_up_button), editlist);
1072 gtk_signal_connect (GTK_OBJECT (editlist->down_button), "clicked",
1073 GTK_SIGNAL_FUNC (cb_editlist_down_button), editlist);
1074 gtk_signal_connect (GTK_OBJECT (editlist->new_button), "clicked",
1075 GTK_SIGNAL_FUNC (cb_editlist_new_button), editlist);
1076 gtk_signal_connect (GTK_OBJECT (editlist->add_button), "clicked",
1077 GTK_SIGNAL_FUNC (cb_editlist_add_button), editlist);
1078 gtk_signal_connect (GTK_OBJECT (editlist->change_button), "clicked",
1079 GTK_SIGNAL_FUNC (cb_editlist_change_button), editlist);
1080 gtk_signal_connect (GTK_OBJECT (editlist->del_button), "clicked",
1081 GTK_SIGNAL_FUNC (cb_editlist_delete_button), editlist);
1082
1083 #endif /* (GTK_MAJOR_VERSION >= 2) */
1084
1085 /* initialize column func tables */
1086 editlist->column_func_tables
1087 = g_new0 (GimvEListColumnFuncTable *, editlist->columns);
1088 for (i = 0; i < colnum; i++) {
1089 editlist->column_func_tables[i]
1090 = gimv_elist_column_func_table_new ();
1091 }
1092
1093 gimv_elist_set_sensitive (editlist);
1094
1095 return main_vbox;
1096 }
1097
1098
1099 GtkWidget *
gimv_elist_new_with_titles(gint colnum,gchar * titles[])1100 gimv_elist_new_with_titles (gint colnum, gchar *titles[])
1101 {
1102 GimvEList *editlist;
1103 gint i;
1104
1105 editlist = GIMV_ELIST (gimv_elist_new (colnum));
1106
1107 #if (GTK_MAJOR_VERSION >= 2)
1108 {
1109 GList *list, *node;
1110 list = gtk_tree_view_get_columns (GTK_TREE_VIEW (editlist->clist));
1111 for (node = list, i = 0; node; node = g_list_next (node), i++) {
1112 GtkTreeViewColumn *col = node->data;
1113 gtk_tree_view_column_set_title (col, titles[i]);
1114 }
1115 }
1116 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (editlist->clist), TRUE);
1117 #else /* (GTK_MAJOR_VERSION >= 2) */
1118 for (i = 0; i < colnum; i++) {
1119 gtk_clist_set_column_title (GTK_CLIST (editlist->clist),
1120 i, titles[i]);
1121 gtk_clist_set_column_auto_resize (GTK_CLIST (editlist->clist),
1122 i, TRUE);
1123 }
1124 gtk_clist_column_titles_show (GTK_CLIST (editlist->clist));
1125 #endif /* (GTK_MAJOR_VERSION >= 2) */
1126
1127 return GTK_WIDGET (editlist);
1128 }
1129
1130
1131 void
gimv_elist_set_column_title_visible(GimvEList * editlist,gboolean visible)1132 gimv_elist_set_column_title_visible (GimvEList *editlist, gboolean visible)
1133 {
1134 g_return_if_fail (GIMV_IS_ELIST (editlist));
1135
1136 #if (GTK_MAJOR_VERSION >= 2)
1137 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (editlist->clist), visible);
1138 #else /* (GTK_MAJOR_VERSION >= 2) */
1139 if (visible)
1140 gtk_clist_column_titles_show (GTK_CLIST (editlist->clist));
1141 else
1142 gtk_clist_column_titles_hide (GTK_CLIST (editlist->clist));
1143 #endif /* (GTK_MAJOR_VERSION >= 2) */
1144 }
1145
1146
1147 void
gimv_elist_set_reorderable(GimvEList * editlist,gboolean reorderble)1148 gimv_elist_set_reorderable (GimvEList *editlist, gboolean reorderble)
1149 {
1150 g_return_if_fail (GIMV_IS_ELIST (editlist));
1151
1152 #if (GTK_MAJOR_VERSION >= 2)
1153 gtk_tree_view_set_reorderable (GTK_TREE_VIEW (editlist->clist), reorderble);
1154 #else /* (GTK_MAJOR_VERSION >= 2) */
1155 gtk_clist_set_reorderable (GTK_CLIST (editlist->clist), reorderble);
1156 #endif /* (GTK_MAJOR_VERSION >= 2) */
1157
1158 if (reorderble)
1159 gtk_widget_show (editlist->move_button_area);
1160 else
1161 gtk_widget_hide (editlist->move_button_area);
1162 }
1163
1164
1165 void
gimv_elist_set_auto_sort(GimvEList * editlist,gint column)1166 gimv_elist_set_auto_sort (GimvEList *editlist, gint column)
1167 {
1168 g_return_if_fail (GIMV_IS_ELIST (editlist));
1169 g_return_if_fail (column < editlist->columns);
1170
1171 #if (GTK_MAJOR_VERSION >= 2)
1172 {
1173 GList *list, *node;
1174 list = gtk_tree_view_get_columns (GTK_TREE_VIEW (editlist->clist));
1175
1176 for (node = list; node; node = g_list_next (node)) {
1177 GtkTreeViewColumn *treecolumn = node->data;
1178 gtk_tree_view_column_set_reorderable (treecolumn, FALSE);
1179 }
1180
1181 if (column >= 0) {
1182 GtkTreeViewColumn *treecolumn;
1183 node = g_list_nth (list, column);
1184 treecolumn = node->data;
1185 gtk_tree_view_column_set_reorderable (treecolumn, TRUE);
1186 gtk_tree_view_column_set_sort_column_id (treecolumn, column);
1187 gtk_tree_view_column_set_sort_order (treecolumn, GTK_SORT_ASCENDING);
1188 }
1189
1190 g_list_free (list);
1191 }
1192 #else /* (GTK_MAJOR_VERSION >= 2) */
1193 if (column < 0)
1194 gtk_clist_set_auto_sort (GTK_CLIST (editlist->clist), FALSE);
1195 else
1196 gtk_clist_set_auto_sort (GTK_CLIST (editlist->clist), TRUE);
1197
1198 gtk_clist_set_sort_column (GTK_CLIST (editlist->clist), column);
1199 #endif /* (GTK_MAJOR_VERSION >= 2) */
1200 }
1201
1202
1203 gboolean
gimv_elist_get_reorderable(GimvEList * editlist)1204 gimv_elist_get_reorderable (GimvEList *editlist)
1205 {
1206 g_return_val_if_fail (GIMV_IS_ELIST (editlist), FALSE);
1207
1208 #if (GTK_MAJOR_VERSION >= 2)
1209 return gtk_tree_view_get_reorderable (GTK_TREE_VIEW (editlist->clist));
1210 #else /* (GTK_MAJOR_VERSION >= 2) */
1211 return GTK_CLIST_REORDERABLE (GTK_CLIST (editlist->clist));
1212 #endif /* (GTK_MAJOR_VERSION >= 2) */
1213 }
1214
1215
1216 gint
gimv_elist_append_row(GimvEList * editlist,gchar * data[])1217 gimv_elist_append_row (GimvEList *editlist, gchar *data[])
1218 {
1219 gint retval;
1220
1221 g_return_val_if_fail (GIMV_IS_ELIST (editlist), -1);
1222 g_return_val_if_fail (editlist->max_row < 0
1223 || editlist->rows <= editlist->max_row, -1);
1224
1225 #if (GTK_MAJOR_VERSION >= 2)
1226
1227 {
1228 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
1229 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1230 GtkListStore *store = GTK_LIST_STORE (model);
1231 GtkTreeIter iter;
1232 gint i;
1233
1234 gtk_list_store_append (store, &iter);
1235
1236 for (i = 0; i < editlist->columns; i++) {
1237 gtk_list_store_set (store, &iter, i, data[i], -1);
1238 }
1239 }
1240 editlist->rows = list_widget_get_row_num(editlist->clist);
1241 retval = editlist->rows - 1;
1242
1243 #else /* (GTK_MAJOR_VERSION >= 2) */
1244
1245 retval = gtk_clist_append (GTK_CLIST (editlist->clist), data);
1246 editlist->rows = list_widget_get_row_num(editlist->clist);
1247
1248 #endif /* (GTK_MAJOR_VERSION >= 2) */
1249
1250 gimv_elist_set_sensitive (editlist);
1251
1252 return retval;
1253 }
1254
1255
1256 void
gimv_elist_remove_row(GimvEList * editlist,gint row)1257 gimv_elist_remove_row (GimvEList *editlist, gint row)
1258 {
1259 g_return_if_fail (GIMV_IS_ELIST (editlist));
1260 g_return_if_fail (row >= 0 && row < editlist->rows);
1261
1262 gimv_elist_set_row_data (editlist, row, NULL);
1263
1264 #if (GTK_MAJOR_VERSION >= 2)
1265 {
1266 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
1267 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1268 GtkListStore *store = GTK_LIST_STORE (model);
1269 GtkTreeIter iter;
1270 gboolean success;
1271
1272 success = gtk_tree_model_iter_nth_child (model, &iter, NULL, row);
1273 if (success) {
1274 gtk_list_store_remove (store, &iter);
1275 editlist->selected = -1;
1276 }
1277 }
1278 #else /* (GTK_MAJOR_VERSION >= 2) */
1279 gtk_clist_remove (GTK_CLIST (editlist->clist), row);
1280 #endif /* (GTK_MAJOR_VERSION >= 2) */
1281
1282 editlist->rows = list_widget_get_row_num(editlist->clist);
1283
1284 gimv_elist_updated (editlist);
1285 gimv_elist_set_sensitive (editlist);
1286 }
1287
1288
1289 gint
gimv_elist_get_n_rows(GimvEList * editlist)1290 gimv_elist_get_n_rows (GimvEList *editlist)
1291 {
1292 g_return_val_if_fail (GIMV_IS_ELIST (editlist), -1);
1293
1294 return editlist->rows;
1295 }
1296
1297
1298 gint
gimv_elist_get_selected_row(GimvEList * editlist)1299 gimv_elist_get_selected_row (GimvEList *editlist)
1300 {
1301 g_return_val_if_fail (GIMV_IS_ELIST (editlist), -1);
1302
1303 return editlist->selected;
1304 }
1305
1306
1307 gchar **
gimv_elist_get_row_text(GimvEList * editlist,gint row)1308 gimv_elist_get_row_text (GimvEList *editlist, gint row)
1309 {
1310 gchar **text;
1311 gint i;
1312
1313 g_return_val_if_fail (GIMV_IS_ELIST (editlist), NULL);
1314 g_return_val_if_fail (row >= 0 && row < editlist->rows, NULL);
1315 g_return_val_if_fail (editlist->columns > 0, NULL);
1316
1317 text = g_new0 (gchar *, editlist->columns + 1);
1318
1319 #if (GTK_MAJOR_VERSION >= 2)
1320
1321 {
1322 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
1323 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1324 GtkTreeIter iter;
1325 gboolean success;
1326
1327 success = gtk_tree_model_iter_nth_child (model, &iter, NULL, row);
1328 g_return_val_if_fail (success, NULL);
1329
1330 for (i = 0; i < editlist->columns; i++) {
1331 text[i] = NULL;
1332 gtk_tree_model_get (model, &iter, i, &text[i], -1);
1333 if (!text[i])
1334 text[i] = g_strdup ("");
1335 }
1336 }
1337
1338 #else /* (GTK_MAJOR_VERSION >= 2) */
1339
1340 for (i = 0; i < editlist->columns; i++) {
1341 text[i] = NULL;
1342 gtk_clist_get_text (GTK_CLIST (editlist->clist), row, i, &text[i]);
1343 if (text[i])
1344 text[i] = g_strdup (text[i]);
1345 else
1346 text[i] = g_strdup ("");
1347 }
1348
1349 #endif /* (GTK_MAJOR_VERSION >= 2) */
1350
1351 text[editlist->columns] = NULL;
1352
1353 return text;
1354 }
1355
1356
1357 gchar *
gimv_elist_get_cell_text(GimvEList * editlist,gint row,gint col)1358 gimv_elist_get_cell_text (GimvEList *editlist, gint row, gint col)
1359 {
1360 gchar *text = NULL;
1361
1362 g_return_val_if_fail (GIMV_IS_ELIST (editlist), NULL);
1363 g_return_val_if_fail (row >= 0 && row < editlist->rows, NULL);
1364 g_return_val_if_fail (editlist->columns > 0, NULL);
1365 g_return_val_if_fail (col < editlist->columns, NULL);
1366
1367 #if (GTK_MAJOR_VERSION >= 2)
1368
1369 {
1370 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
1371 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1372 GtkTreeIter iter;
1373 gboolean success;
1374
1375 success = gtk_tree_model_iter_nth_child (model, &iter, NULL, row);
1376 g_return_val_if_fail (success, NULL);
1377
1378 gtk_tree_model_get (model, &iter, col, &text, -1);
1379 }
1380
1381 #else /* (GTK_MAJOR_VERSION >= 2) */
1382
1383 {
1384 gboolean success;
1385 success = gtk_clist_get_text (GTK_CLIST (editlist->clist),
1386 row, col, &text);
1387 if (!success) return NULL;
1388 text = g_strdup (text);
1389 }
1390
1391 #endif /* (GTK_MAJOR_VERSION >= 2) */
1392
1393 return text;
1394 }
1395
1396
1397 void
gimv_elist_set_row_data(GimvEList * editlist,gint row,gpointer data)1398 gimv_elist_set_row_data (GimvEList *editlist,
1399 gint row,
1400 gpointer data)
1401 {
1402 g_return_if_fail (GIMV_IS_ELIST (editlist));
1403 g_return_if_fail (row >= 0 && row < editlist->rows);
1404
1405 gimv_elist_set_row_data_full (editlist, row, data, NULL);
1406 }
1407
1408
1409 void
gimv_elist_set_row_data_full(GimvEList * editlist,gint row,gpointer data,GtkDestroyNotify destroy_fn)1410 gimv_elist_set_row_data_full (GimvEList *editlist,
1411 gint row,
1412 gpointer data,
1413 GtkDestroyNotify destroy_fn)
1414 {
1415 g_return_if_fail (GIMV_IS_ELIST (editlist));
1416 g_return_if_fail (row >= 0 && row < editlist->rows);
1417
1418 #if (GTK_MAJOR_VERSION >= 2)
1419 {
1420 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
1421 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1422 GtkTreeIter iter;
1423 GtkDestroyNotify destroy;
1424 gboolean success;
1425 gpointer rowdata = gimv_elist_get_row_data (editlist, row);
1426
1427 if (rowdata) {
1428 destroy = g_hash_table_lookup (editlist->rowdata_destroy_fn_table,
1429 rowdata);
1430 if (destroy) {
1431 destroy (rowdata);
1432 g_hash_table_remove (editlist->rowdata_destroy_fn_table, rowdata);
1433 }
1434
1435 g_hash_table_remove (editlist->rowdata_table, rowdata);
1436 }
1437
1438 success = gtk_tree_model_iter_nth_child (model, &iter, NULL, row);
1439 g_return_if_fail (success);
1440
1441 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
1442 ROWDATA(editlist->columns), data,
1443 ROWDESTROY(editlist->columns), destroy_fn,
1444 -1);
1445
1446 if (data) {
1447 g_hash_table_insert (editlist->rowdata_table,
1448 data, data);
1449 g_hash_table_insert (editlist->rowdata_destroy_fn_table,
1450 data, destroy_fn);
1451 }
1452 }
1453 #else /* (GTK_MAJOR_VERSION >= 2) */
1454 gtk_clist_set_row_data_full (GTK_CLIST (editlist->clist), row,
1455 data, destroy_fn);
1456 #endif /* (GTK_MAJOR_VERSION >= 2) */
1457
1458 gimv_elist_updated (editlist);
1459 }
1460
1461
1462 gpointer
gimv_elist_get_row_data(GimvEList * editlist,gint row)1463 gimv_elist_get_row_data (GimvEList *editlist,
1464 gint row)
1465 {
1466 g_return_val_if_fail (GIMV_IS_ELIST (editlist), NULL);
1467 g_return_val_if_fail (row >= 0 && row < editlist->rows, NULL);
1468
1469 #if (GTK_MAJOR_VERSION >= 2)
1470 {
1471 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
1472 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
1473 GtkTreeIter iter;
1474 gboolean success;
1475 gpointer data;
1476
1477 success = gtk_tree_model_iter_nth_child (model, &iter, NULL, row);
1478 if (!success) return NULL;
1479
1480 gtk_tree_model_get (model, &iter,
1481 ROWDATA (editlist->columns), &data, -1);
1482
1483 return data;
1484 }
1485 #else /* (GTK_MAJOR_VERSION >= 2) */
1486 return gtk_clist_get_row_data (GTK_CLIST (editlist->clist), row);
1487 #endif /* (GTK_MAJOR_VERSION >= 2) */
1488 }
1489
1490
1491 void
gimv_elist_unselect_all(GimvEList * editlist)1492 gimv_elist_unselect_all (GimvEList *editlist)
1493 {
1494 g_return_if_fail (GIMV_IS_ELIST (editlist));
1495
1496 #if (GTK_MAJOR_VERSION >= 2)
1497 {
1498 GtkTreeView *treeview = GTK_TREE_VIEW (editlist->clist);
1499 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
1500
1501 gtk_tree_selection_unselect_all (selection);
1502 editlist->selected = -1;
1503 }
1504 #else /* (GTK_MAJOR_VERSION >= 2) */
1505 gtk_clist_unselect_all (GTK_CLIST (editlist->clist));
1506 #endif /* (GTK_MAJOR_VERSION >= 2) */
1507
1508 gimv_elist_set_sensitive (editlist);
1509 }
1510
1511
1512 void
gimv_elist_set_max_row(GimvEList * editlist,gint rownum)1513 gimv_elist_set_max_row (GimvEList *editlist, gint rownum)
1514 {
1515 g_return_if_fail (GIMV_IS_ELIST (editlist));
1516
1517 editlist->max_row = rownum;
1518 }
1519
1520
1521 void
gimv_elist_set_column_funcs(GimvEList * editlist,GtkWidget * widget,gint column,GimvEListSetDataFn set_data_fn,GimvEListGetDataFn get_data_fn,GimvEListResetFn reset_fn,gpointer coldata,GtkDestroyNotify destroy_fn)1522 gimv_elist_set_column_funcs (GimvEList *editlist,
1523 GtkWidget *widget,
1524 gint column,
1525 GimvEListSetDataFn set_data_fn,
1526 GimvEListGetDataFn get_data_fn,
1527 GimvEListResetFn reset_fn,
1528 gpointer coldata,
1529 GtkDestroyNotify destroy_fn)
1530 {
1531 GimvEListColumnFuncTable *table;
1532
1533 g_return_if_fail (GIMV_IS_ELIST (editlist));
1534 g_return_if_fail (column >= 0 && column < editlist->columns);
1535
1536 table = editlist->column_func_tables[column];
1537
1538 table->widget = widget;
1539 table->coldata = coldata;
1540 table->destroy_fn = destroy_fn;
1541
1542 table->set_data_fn = set_data_fn;
1543 table->get_data_fn = get_data_fn;
1544 table->reset_fn = reset_fn;
1545 }
1546
1547
1548 void
gimv_elist_set_get_row_data_func(GimvEList * editlist,GimvEListGetRowDataFn get_rowdata_func)1549 gimv_elist_set_get_row_data_func (GimvEList *editlist,
1550 GimvEListGetRowDataFn get_rowdata_func)
1551 {
1552 g_return_if_fail (GIMV_IS_ELIST (editlist));
1553
1554 editlist->get_rowdata_fn = get_rowdata_func;
1555 }
1556
1557
1558 void
gimv_elist_edit_area_set_value_changed(GimvEList * editlist)1559 gimv_elist_edit_area_set_value_changed (GimvEList *editlist)
1560 {
1561 g_return_if_fail (GIMV_IS_ELIST (editlist));
1562
1563 editlist->edit_area_flags &= ~GIMV_ELIST_EDIT_AREA_VALUE_INITIALIZED;
1564 editlist->edit_area_flags |= GIMV_ELIST_EDIT_AREA_VALUE_CHANGED;
1565
1566 gimv_elist_set_sensitive (editlist);
1567 }
1568
1569
1570 GimvEListConfirmFlags
gimv_elist_action_confirm(GimvEList * editlist,GimvEListActionType type)1571 gimv_elist_action_confirm (GimvEList *editlist,
1572 GimvEListActionType type)
1573 {
1574 GimvEListConfirmFlags retval = 0;
1575
1576 g_return_val_if_fail (GIMV_IS_ELIST (editlist), retval);
1577
1578 if (editlist->edit_area_flags & GIMV_ELIST_EDIT_AREA_VALUE_INITIALIZED)
1579 retval |= GIMV_ELIST_CONFIRM_CANNOT_NEW;
1580
1581 if (editlist->max_row >= 0 && editlist->rows >= editlist->max_row)
1582 retval |= GIMV_ELIST_CONFIRM_CANNOT_ADD;
1583
1584 if (!(editlist->edit_area_flags & GIMV_ELIST_EDIT_AREA_VALUE_CHANGED))
1585 retval |= GIMV_ELIST_CONFIRM_CANNOT_CHANGE;
1586
1587 if (editlist->selected < 0 || editlist->selected >= editlist->rows) {
1588 retval |= GIMV_ELIST_CONFIRM_CANNOT_CHANGE;
1589 retval |= GIMV_ELIST_CONFIRM_CANNOT_DELETE;
1590 }
1591
1592 gtk_signal_emit (GTK_OBJECT (editlist),
1593 gimv_elist_signals[ACTION_CONFIRM_SIGNAL],
1594 type,
1595 editlist->selected,
1596 &retval);
1597
1598 return retval;
1599 }
1600
1601
1602 void
gimv_elist_set_action_button_sensitive(GimvEList * editlist)1603 gimv_elist_set_action_button_sensitive (GimvEList *editlist)
1604 {
1605 GimvEListConfirmFlags flags;
1606
1607 g_return_if_fail (GIMV_IS_ELIST (editlist));
1608
1609 flags = gimv_elist_action_confirm (editlist,
1610 GIMV_ELIST_ACTION_SET_SENSITIVE);
1611
1612 gtk_widget_set_sensitive (editlist->new_button,
1613 !(flags & GIMV_ELIST_CONFIRM_CANNOT_NEW));
1614 gtk_widget_set_sensitive (editlist->add_button,
1615 !(flags & GIMV_ELIST_CONFIRM_CANNOT_ADD));
1616 gtk_widget_set_sensitive (editlist->change_button,
1617 !(flags & GIMV_ELIST_CONFIRM_CANNOT_CHANGE));
1618 gtk_widget_set_sensitive (editlist->del_button,
1619 !(flags & GIMV_ELIST_CONFIRM_CANNOT_DELETE));
1620 }
1621
1622
1623
1624 /*******************************************************************************
1625 *
1626 * convenient function to create entry.
1627 *
1628 *******************************************************************************/
1629 typedef struct GimvEListEntryData_Tag
1630 {
1631 GimvEList *editlist;
1632 GtkWidget *entry;
1633 gchar *init_string;
1634 gboolean allow_empty;
1635 } GimvEListEntryData;
1636
1637
1638 static void
cb_editlist_entry_set_data(GimvEList * editlist,GtkWidget * widget,gint row,gint col,const gchar * text,gpointer coldata)1639 cb_editlist_entry_set_data (GimvEList *editlist, GtkWidget *widget,
1640 gint row, gint col,
1641 const gchar *text, gpointer coldata)
1642 {
1643 GimvEListEntryData *entry_data = coldata;
1644
1645 g_return_if_fail (GIMV_IS_ELIST (editlist));
1646 g_return_if_fail (GTK_IS_ENTRY (widget));
1647 g_return_if_fail (entry_data);
1648
1649 if (text)
1650 gtk_entry_set_text (GTK_ENTRY (widget), text);
1651 }
1652
1653
1654 static gchar *
cb_editlist_entry_get_data(GimvEList * editlist,GimvEListActionType type,GtkWidget * widget,gpointer coldata)1655 cb_editlist_entry_get_data (GimvEList *editlist,
1656 GimvEListActionType type,
1657 GtkWidget *widget,
1658 gpointer coldata)
1659 {
1660 GimvEListEntryData *entry_data = coldata;
1661 const gchar *text;
1662
1663 g_return_val_if_fail (GIMV_IS_ELIST (editlist), NULL);
1664 g_return_val_if_fail (GTK_IS_ENTRY (widget), NULL);
1665 g_return_val_if_fail (entry_data, NULL);
1666
1667 text = gtk_entry_get_text (GTK_ENTRY (widget));
1668
1669 if (text)
1670 return g_strdup (text);
1671 else
1672 return NULL;
1673 }
1674
1675
1676 static void
cb_editlist_entry_reset(GimvEList * editlist,GtkWidget * widget,gpointer coldata)1677 cb_editlist_entry_reset (GimvEList *editlist,
1678 GtkWidget *widget,
1679 gpointer coldata)
1680 {
1681 GimvEListEntryData *entry_data = coldata;
1682
1683 g_return_if_fail (GIMV_IS_ELIST (editlist));
1684 g_return_if_fail (GTK_IS_ENTRY (widget));
1685 g_return_if_fail (entry_data);
1686
1687 gtk_entry_set_text (GTK_ENTRY (widget), entry_data->init_string);
1688 }
1689
1690
1691 static void
cb_editlist_entry_changed(GtkEntry * entry,gpointer data)1692 cb_editlist_entry_changed (GtkEntry *entry, gpointer data)
1693 {
1694 GimvEListEntryData *entry_data = data;
1695 GimvEList *editlist;
1696 const gchar *text;
1697
1698 g_return_if_fail (entry_data);
1699 g_return_if_fail (GIMV_IS_ELIST (entry_data->editlist));
1700
1701 editlist = entry_data->editlist;
1702
1703 text = gtk_entry_get_text (entry);
1704
1705 gimv_elist_edit_area_set_value_changed (editlist);
1706 }
1707
1708
1709 static void
editlist_entry_destroy(gpointer data)1710 editlist_entry_destroy (gpointer data)
1711 {
1712 GimvEListEntryData *entry_data = data;
1713
1714 g_free (entry_data->init_string);
1715 g_free (entry_data);
1716 }
1717
1718
1719 static void
cb_editlist_entry_confirm(GimvEList * editlist,GimvEListActionType type,gint selected_row,GimvEListConfirmFlags * flags,gpointer data)1720 cb_editlist_entry_confirm (GimvEList *editlist,
1721 GimvEListActionType type,
1722 gint selected_row,
1723 GimvEListConfirmFlags *flags,
1724 gpointer data)
1725 {
1726 GimvEListEntryData *entry_data = data;
1727 const gchar *text;
1728
1729 text = gtk_entry_get_text (GTK_ENTRY (entry_data->entry));
1730 if (!entry_data->allow_empty && (!text || !*text)) {
1731 *flags |= GIMV_ELIST_CONFIRM_CANNOT_ADD;
1732 *flags |= GIMV_ELIST_CONFIRM_CANNOT_CHANGE;
1733 }
1734
1735 return;
1736 }
1737
1738
1739 GtkWidget *
gimv_elist_create_entry(GimvEList * editlist,gint column,const gchar * init_string,gboolean allow_empty)1740 gimv_elist_create_entry (GimvEList *editlist, gint column,
1741 const gchar *init_string,
1742 gboolean allow_empty)
1743 {
1744 GimvEListEntryData *entry_data;
1745 GtkWidget *entry;
1746
1747 g_return_val_if_fail (GIMV_IS_ELIST (editlist), NULL);
1748 g_return_val_if_fail (column >= 0 && column < editlist->columns, NULL);
1749
1750 entry_data = g_new0 (GimvEListEntryData, 1);
1751 entry_data->editlist = editlist;
1752 if (!init_string || !*init_string)
1753 entry_data->init_string = g_strdup ("\0");
1754 else
1755 entry_data->init_string = g_strdup (init_string);
1756 entry_data->allow_empty = allow_empty;
1757
1758 entry_data->entry = entry = gtk_entry_new ();
1759
1760 gtk_entry_set_text (GTK_ENTRY (entry_data->entry), entry_data->init_string);
1761
1762 gimv_elist_set_column_funcs (editlist,
1763 entry, column,
1764 cb_editlist_entry_set_data,
1765 cb_editlist_entry_get_data,
1766 cb_editlist_entry_reset,
1767 entry_data,
1768 editlist_entry_destroy);
1769
1770 #if (GTK_MAJOR_VERSION >= 2)
1771 g_signal_connect (G_OBJECT (editlist), "action_confirm",
1772 G_CALLBACK (cb_editlist_entry_confirm),
1773 entry_data);
1774 g_signal_connect (G_OBJECT (entry),"changed",
1775 G_CALLBACK (cb_editlist_entry_changed),
1776 entry_data);
1777 #else /* (GTK_MAJOR_VERSION >= 2) */
1778 gtk_signal_connect (GTK_OBJECT (editlist), "action_confirm",
1779 GTK_SIGNAL_FUNC (cb_editlist_entry_confirm),
1780 entry_data);
1781 gtk_signal_connect (GTK_OBJECT (entry),"changed",
1782 GTK_SIGNAL_FUNC (cb_editlist_entry_changed),
1783 entry_data);
1784 #endif /* (GTK_MAJOR_VERSION >= 2) */
1785
1786 gimv_elist_set_sensitive (editlist);
1787
1788 return entry;
1789 }
1790
1791
1792
1793 /*******************************************************************************
1794 *
1795 * convenient function to create check button.
1796 *
1797 *******************************************************************************/
1798 typedef struct GimvEListCheckButtonData_Tag
1799 {
1800 GimvEList *editlist;
1801 gboolean init_value;
1802 gchar *true_string;
1803 gchar *false_string;
1804 } GimvEListCheckButtonData;
1805
1806 static void
cb_editlist_check_button_set_data(GimvEList * editlist,GtkWidget * widget,gint row,gint col,const gchar * text,gpointer coldata)1807 cb_editlist_check_button_set_data (GimvEList *editlist, GtkWidget *widget,
1808 gint row, gint col,
1809 const gchar *text, gpointer coldata)
1810 {
1811 GimvEListCheckButtonData *button_data = coldata;
1812
1813 g_return_if_fail (GIMV_IS_ELIST (editlist));
1814 g_return_if_fail (GTK_IS_CHECK_BUTTON (widget));
1815 g_return_if_fail (button_data);
1816
1817 if (row < 0) return;
1818
1819 if (text && *text && !strcmp (text, button_data->true_string)) {
1820 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
1821 } else {
1822 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
1823 }
1824 }
1825
1826
1827 static gchar *
cb_editlist_check_button_get_data(GimvEList * editlist,GimvEListActionType type,GtkWidget * widget,gpointer coldata)1828 cb_editlist_check_button_get_data (GimvEList *editlist,
1829 GimvEListActionType type,
1830 GtkWidget *widget,
1831 gpointer coldata)
1832 {
1833 GimvEListCheckButtonData *button_data = coldata;
1834
1835 g_return_val_if_fail (GIMV_IS_ELIST (editlist), NULL);
1836 g_return_val_if_fail (GTK_IS_CHECK_BUTTON (widget), NULL);
1837 g_return_val_if_fail (button_data, NULL);
1838
1839 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1840 return g_strdup (button_data->true_string);
1841 else
1842 return g_strdup (button_data->false_string);
1843 }
1844
1845
1846 static void
cb_editlist_check_button_reset(GimvEList * editlist,GtkWidget * widget,gpointer coldata)1847 cb_editlist_check_button_reset (GimvEList *editlist,
1848 GtkWidget *widget,
1849 gpointer coldata)
1850 {
1851 GimvEListCheckButtonData *button_data = coldata;
1852
1853 g_return_if_fail (GIMV_IS_ELIST (editlist));
1854 g_return_if_fail (GTK_IS_CHECK_BUTTON (widget));
1855
1856 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
1857 button_data->init_value);
1858 }
1859
1860
1861 static void
cb_editlist_check_button_toggled(GtkCheckButton * check_button,gpointer data)1862 cb_editlist_check_button_toggled (GtkCheckButton *check_button, gpointer data)
1863 {
1864 GimvEListCheckButtonData *button_data = data;
1865 gimv_elist_edit_area_set_value_changed (button_data->editlist);
1866 }
1867
1868
1869 static void
editlist_check_button_destroy(gpointer data)1870 editlist_check_button_destroy (gpointer data)
1871 {
1872 GimvEListCheckButtonData *button_data = data;
1873
1874 g_free (button_data->true_string);
1875 g_free (button_data->false_string);
1876 g_free (button_data);
1877 }
1878
1879
1880 GtkWidget *
gimv_elist_create_check_button(GimvEList * editlist,gint column,const gchar * label,gboolean init_value,const gchar * true_string,const gchar * false_string)1881 gimv_elist_create_check_button (GimvEList *editlist, gint column,
1882 const gchar *label,
1883 gboolean init_value,
1884 const gchar *true_string,
1885 const gchar *false_string)
1886 {
1887 GimvEListCheckButtonData *button_data;
1888 GtkWidget *check_button;
1889
1890 g_return_val_if_fail (GIMV_IS_ELIST (editlist), NULL);
1891 g_return_val_if_fail (column >= 0 && column < editlist->columns, NULL);
1892 g_return_val_if_fail (true_string && *true_string, NULL);
1893 g_return_val_if_fail (false_string && *false_string, NULL);
1894
1895 button_data = g_new0 (GimvEListCheckButtonData, 1);
1896 button_data->editlist = editlist;
1897 button_data->init_value = init_value;
1898 button_data->true_string = g_strdup (true_string);
1899 button_data->false_string = g_strdup (false_string);
1900
1901 if (label)
1902 check_button = gtk_check_button_new_with_label (label);
1903 else
1904 check_button = gtk_check_button_new ();
1905
1906 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
1907 button_data->init_value);
1908
1909 gimv_elist_set_column_funcs (GIMV_ELIST (editlist),
1910 check_button, column,
1911 cb_editlist_check_button_set_data,
1912 cb_editlist_check_button_get_data,
1913 cb_editlist_check_button_reset,
1914 button_data,
1915 editlist_check_button_destroy);
1916
1917 #if (GTK_MAJOR_VERSION >= 2)
1918 g_signal_connect (G_OBJECT (check_button),"toggled",
1919 G_CALLBACK (cb_editlist_check_button_toggled),
1920 button_data);
1921 #else /* (GTK_MAJOR_VERSION >= 2) */
1922 gtk_signal_connect (GTK_OBJECT (check_button),"toggled",
1923 GTK_SIGNAL_FUNC (cb_editlist_check_button_toggled),
1924 button_data);
1925 #endif /* (GTK_MAJOR_VERSION >= 2) */
1926
1927 gimv_elist_set_sensitive (editlist);
1928
1929 return check_button;
1930 }
1931