1 /* A rowview in a workspace ... not a widget, part of column
2 */
3
4 /*
5
6 Copyright (C) 1991-2003 The National Gallery
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
22 */
23
24 /*
25
26 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
27
28 */
29
30 /*
31 #define DEBUG
32 */
33
34 #include "ip.h"
35
36 static ModelClass *parent_class = NULL;
37
38 enum {
39 ROWVIEW_TARGET_STRING,
40 };
41
42 static GtkTargetEntry rowview_target_table[] = {
43 { "STRING", 0, ROWVIEW_TARGET_STRING },
44 { "text/plain", 0, ROWVIEW_TARGET_STRING }
45 };
46
47 /* Just one popup for all tally buttons.
48 */
49 static GtkWidget *rowview_popup_menu = NULL;
50
51 static void
rowview_destroy(GtkObject * object)52 rowview_destroy( GtkObject *object )
53 {
54 Rowview *rview;
55
56 g_return_if_fail( object != NULL );
57 g_return_if_fail( IS_ROWVIEW( object ) );
58
59 rview = ROWVIEW( object );
60
61 #ifdef DEBUG
62 printf( "rowview_destroy: " );
63 row_name_print( ROW( VOBJECT( rview )->iobject ) );
64 printf( "\n" );
65 #endif /*DEBUG*/
66
67 IM_FREE( rview->last_tooltip );
68
69 /* Kill children ... must do this ourselves, since we are not a
70 * self-contained widget.
71 */
72 DESTROY_GTK( rview->but );
73 DESTROY_GTK( rview->spin );
74 DESTROY_GTK( rview->led );
75
76 GTK_OBJECT_CLASS( parent_class )->destroy( object );
77 }
78
79 static void
rowview_attach(Rowview * rview,GtkWidget * child,int x,GtkAttachOptions xoptions,GtkAttachOptions yoptions)80 rowview_attach( Rowview *rview, GtkWidget *child, int x,
81 GtkAttachOptions xoptions, GtkAttachOptions yoptions )
82 {
83 Subcolumnview *sview = rview->sview;
84
85 gtk_widget_ref( child );
86
87 if( child->parent )
88 gtk_container_remove( GTK_CONTAINER( sview->table ), child );
89 gtk_table_attach( GTK_TABLE( sview->table ), child,
90 x, x + 1, rview->rnum, rview->rnum + 1,
91 xoptions, yoptions, 0, 0 );
92
93 gtk_widget_unref( child );
94 }
95
96 static void
rowview_update_widgets(Rowview * rview)97 rowview_update_widgets( Rowview *rview )
98 {
99 Row *row = ROW( VOBJECT( rview )->iobject );
100 int pos = ICONTAINER( row )->pos;
101 gboolean editable = row->ws->mode != WORKSPACE_MODE_NOEDIT;
102
103 #ifdef DEBUG
104 printf( "rowview_refresh: " );
105 row_name_print( row );
106 printf( "\n" );
107 printf( "\teditable == %d\n", editable );
108 #endif /*DEBUG*/
109
110 /* Attach widgets to parent in new place.
111 */
112 if( rview->rnum != pos ) {
113 #ifdef DEBUG
114 printf( "rowview_refresh: move from row %d to row %d\n",
115 rview->rnum, pos );
116 #endif /*DEBUG*/
117
118 rview->rnum = pos;
119
120 rowview_attach( rview, rview->spin,
121 0, GTK_FILL, GTK_FILL );
122 rowview_attach( rview, rview->but,
123 1, GTK_FILL, GTK_EXPAND | GTK_FILL );
124 rowview_attach( rview, rview->led,
125 2, GTK_FILL, GTK_EXPAND | GTK_FILL );
126 if( rview->rhsview )
127 rowview_attach( rview, GTK_WIDGET( rview->rhsview ),
128 3,
129 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL );
130 }
131
132 /* Set colours.
133 */
134 if( CALC_DISPLAY_LED ) {
135 char *stock_id;
136
137 stock_id = STOCK_LED_OFF;
138 if( row->selected )
139 stock_id = STOCK_LED_GREEN;
140 else if( row->show == ROW_SHOW_PARENT )
141 stock_id = STOCK_LED_CYAN;
142 else if( row->show == ROW_SHOW_CHILD )
143 stock_id = STOCK_LED_BLUE;
144 else if( row->err )
145 stock_id = STOCK_LED_RED;
146 else if( row->dirty )
147 stock_id = STOCK_LED_YELLOW;
148
149 gtk_image_set_from_stock( GTK_IMAGE( rview->led ),
150 stock_id, GTK_ICON_SIZE_MENU );
151 }
152 else {
153 gchar *name = "";
154
155 if( row->selected )
156 name = "selected_widget";
157 else if( row->show == ROW_SHOW_PARENT )
158 name = "parent_widget";
159 else if( row->show == ROW_SHOW_CHILD )
160 name = "child_widget";
161 else if( row->err )
162 name = "error_widget";
163 else if( row->dirty )
164 name = "dirty_widget";
165
166 gtk_widget_set_name( rview->but, name );
167 }
168 widget_visible( rview->led,
169 rview->visible && CALC_DISPLAY_LED && editable );
170
171 /* Update button.
172 */
173 set_glabel( rview->label, "%s", row_name( row ) );
174 widget_visible( rview->but, rview->visible && editable );
175
176 /* Spin visible only if this is a class.
177 */
178 widget_visible( rview->spin,
179 rview->visible && row->is_class && editable );
180
181 if( rview->rhsview )
182 widget_visible( GTK_WIDGET( rview->rhsview ), rview->visible );
183 }
184
185 static void
rowview_reset(View * view)186 rowview_reset( View *view )
187 {
188 Rowview *rview = ROWVIEW( view );
189
190 rowview_update_widgets( rview );
191
192 VIEW_CLASS( parent_class )->reset( view );
193 }
194
195 static void
rowview_refresh(vObject * vobject)196 rowview_refresh( vObject *vobject )
197 {
198 Rowview *rview = ROWVIEW( vobject );
199
200 rowview_update_widgets( rview );
201
202 VOBJECT_CLASS( parent_class )->refresh( vobject );
203 }
204
205 /* Single click on button callback.
206 */
207 static void
rowview_single_cb(GtkWidget * wid,GdkEvent * event,Rowview * rview)208 rowview_single_cb( GtkWidget *wid, GdkEvent *event, Rowview *rview )
209 {
210 Row *row = ROW( VOBJECT( rview )->iobject );
211
212 row_select_modifier( row, event->button.state );
213 }
214
215 /* Edit our object.
216 */
217 static gboolean
rowview_edit(Rowview * rview)218 rowview_edit( Rowview *rview )
219 {
220 Row *row = ROW( VOBJECT( rview )->iobject );
221 Model *graphic = row->child_rhs->graphic;
222
223 if( graphic )
224 model_edit( GTK_WIDGET( rview->sview ), graphic );
225
226 return( TRUE );
227 }
228
229 /* Double click on button callback.
230 */
231 static void
rowview_double_cb(GtkWidget * button,GdkEvent * event,Rowview * rview)232 rowview_double_cb( GtkWidget *button, GdkEvent *event, Rowview *rview )
233 {
234 if( !rowview_edit( rview ) )
235 iwindow_alert( button, GTK_MESSAGE_ERROR );
236 }
237
238 /* Edit in menu.
239 */
240 static void
rowview_edit_cb(GtkWidget * menu,GtkWidget * button,Rowview * rview)241 rowview_edit_cb( GtkWidget *menu, GtkWidget *button, Rowview *rview )
242 {
243 if( !rowview_edit( rview ) )
244 iwindow_alert( button, GTK_MESSAGE_ERROR );
245 }
246
247 /* Show info.
248 */
249 static gboolean
rowview_header(Rowview * rview)250 rowview_header( Rowview *rview )
251 {
252 Row *row = ROW( VOBJECT( rview )->iobject );
253 Model *graphic = row->child_rhs->graphic;
254
255 if( graphic )
256 model_header( GTK_WIDGET( rview->sview ), graphic );
257
258 return( TRUE );
259 }
260
261 /* Info in menu.
262 */
263 static void
rowview_header_cb(GtkWidget * menu,GtkWidget * button,Rowview * rview)264 rowview_header_cb( GtkWidget *menu, GtkWidget *button, Rowview *rview )
265 {
266 if( !rowview_header( rview ) )
267 iwindow_alert( button, GTK_MESSAGE_ERROR );
268 }
269
270 /* Clone the current item.
271 */
272 static void
rowview_clone_cb(GtkWidget * menu,GtkWidget * button,Rowview * rview)273 rowview_clone_cb( GtkWidget *menu, GtkWidget *button, Rowview *rview )
274 {
275 Row *row = ROW( VOBJECT( rview )->iobject );
276 Workspace *ws = row->top_col->ws;
277
278 /* Only allow clone of top level rows.
279 */
280 if( row->top_row != row ) {
281 error_top( _( "Can't duplicate." ) );
282 error_sub( "%s",
283 _( "You can only duplicate top level rows." ) );
284 iwindow_alert( button, GTK_MESSAGE_INFO );
285 return;
286 }
287
288 workspace_deselect_all( ws );
289 row_select( row );
290 if( !workspace_selected_duplicate( ws ) )
291 iwindow_alert( button, GTK_MESSAGE_ERROR );
292 workspace_deselect_all( ws );
293
294 symbol_recalculate_all();
295 }
296
297 /* Ungroup the current item.
298 */
299 static void
rowview_ungroup_cb(GtkWidget * menu,GtkWidget * button,Rowview * rview)300 rowview_ungroup_cb( GtkWidget *menu, GtkWidget *button, Rowview *rview )
301 {
302 Row *row = ROW( VOBJECT( rview )->iobject );
303
304 workspace_deselect_all( row->ws );
305 row_select( row );
306 if( !workspace_selected_ungroup( row->ws ) )
307 iwindow_alert( button, GTK_MESSAGE_ERROR );
308 symbol_recalculate_all();
309 }
310
311 /* Save the current item.
312 */
313 static void
rowview_save_cb(GtkWidget * menu,GtkWidget * button,Rowview * rview)314 rowview_save_cb( GtkWidget *menu, GtkWidget *button, Rowview *rview )
315 {
316 iWindow *iwnd = IWINDOW( view_get_toplevel( VIEW( rview ) ) );
317 Row *row = ROW( VOBJECT( rview )->iobject );
318 Model *graphic = row->child_rhs->graphic;
319
320 if( graphic )
321 classmodel_graphic_save( CLASSMODEL( graphic ),
322 GTK_WIDGET( iwnd ) );
323 }
324
325 /* Replace the current item.
326 */
327 static void
rowview_replace_cb(GtkWidget * menu,GtkWidget * button,Rowview * rview)328 rowview_replace_cb( GtkWidget *menu, GtkWidget *button, Rowview *rview )
329 {
330 iWindow *iwnd = IWINDOW( view_get_toplevel( VIEW( rview ) ) );
331 Row *row = ROW( VOBJECT( rview )->iobject );
332 Model *graphic = row->child_rhs->graphic;
333
334 if( graphic )
335 classmodel_graphic_replace( CLASSMODEL( graphic ),
336 GTK_WIDGET( iwnd ) );
337 }
338
339 /* Recalculate the current item.
340 */
341 static void
rowview_recalc_cb(GtkWidget * menu,GtkWidget * button,Rowview * rview)342 rowview_recalc_cb( GtkWidget *menu, GtkWidget *button, Rowview *rview )
343 {
344 Row *row = ROW( VOBJECT( rview )->iobject );
345 Workspace *ws = row->top_col->ws;
346
347 /* Mark dirty from this sym on, and force a recalc even if recalc is
348 * off.
349 */
350 workspace_deselect_all( ws );
351 row_select( row );
352 if( !workspace_selected_recalc( ws ) )
353 iwindow_alert( button, GTK_MESSAGE_ERROR );
354 workspace_deselect_all( ws );
355
356 /* Now ... pick up any errors.
357 */
358 if( row->sym &&
359 !symbol_recalculate_check( row->sym ) )
360 iwindow_alert( button, GTK_MESSAGE_ERROR );
361 }
362
363 /* Reset the current item.
364 */
365 static void
rowview_clear_edited_cb(GtkWidget * menu,GtkWidget * button,Rowview * rview)366 rowview_clear_edited_cb( GtkWidget *menu, GtkWidget *button, Rowview *rview )
367 {
368 Row *row = ROW( VOBJECT( rview )->iobject );
369
370 (void) icontainer_map_all( ICONTAINER( row ),
371 (icontainer_map_fn) model_clear_edited, NULL );
372 symbol_recalculate_all();
373 }
374
375 /* Remove the current item.
376 */
377 static void
rowview_remove_cb(GtkWidget * menu,GtkWidget * button,Rowview * rview)378 rowview_remove_cb( GtkWidget *menu, GtkWidget *button, Rowview *rview )
379 {
380 Row *row = ROW( VOBJECT( rview )->iobject );
381 Workspace *ws = row->top_col->ws;
382
383 workspace_deselect_all( ws );
384 row_select( row );
385 workspace_selected_remove_yesno( ws, button );
386 }
387
388 /* Callback for up/down spin button.
389 */
390 static void
rowview_spin_up_cb(GtkWidget * widget,gpointer client)391 rowview_spin_up_cb( GtkWidget *widget, gpointer client )
392 {
393 Rowview *rview = ROWVIEW( client );
394 Row *row = ROW( VOBJECT( rview )->iobject );
395 Rhs *rhs = row->child_rhs;
396
397 rhs_vislevel_down( rhs );
398 workspace_set_modified( row->ws, TRUE );
399 }
400
401 static void
rowview_spin_down_cb(GtkWidget * widget,gpointer client)402 rowview_spin_down_cb( GtkWidget *widget, gpointer client )
403 {
404 Rowview *rview = ROWVIEW( client );
405 Row *row = ROW( VOBJECT( rview )->iobject );
406 Rhs *rhs = row->child_rhs;
407
408 rhs_vislevel_up( rhs );
409 workspace_set_modified( row->ws, TRUE );
410 }
411
412 /* Scroll to make tally entry visible.
413 */
414 static void
rowview_scrollto(View * view,ModelScrollPosition position)415 rowview_scrollto( View *view, ModelScrollPosition position )
416 {
417 Rowview *rview = ROWVIEW( view );
418 Columnview *cview = view_get_columnview( VIEW( rview ) );
419 Workspaceview *wview = cview->wview;
420
421 int x, y, w, h;
422
423 /* Extract position of tally row in RC widget.
424 */
425 rowview_get_position( rview, &x, &y, &w, &h );
426 workspaceview_scroll( wview, x, y, w, h );
427 }
428
429 static void
rowview_drag(Rowview * rview_from,Rowview * rview_to)430 rowview_drag( Rowview *rview_from, Rowview *rview_to )
431 {
432 Row *row_from = ROW( VOBJECT( rview_from )->iobject );
433 Row *row_to = ROW( VOBJECT( rview_to )->iobject );
434
435 if( row_from->top_col != row_to->top_col ) {
436 error_top( _( "Not implemented." ) );
437 error_sub( _( "Drag between columns not yet implemented." ) );
438 iwindow_alert( GTK_WIDGET( rview_from ), GTK_MESSAGE_ERROR );
439 return;
440 }
441
442 icontainer_child_move( ICONTAINER( row_from ),
443 ICONTAINER( row_to )->pos );
444
445 /* Refresh all the rows, to make sure we move all rows to their new
446 * slots.
447 */
448 icontainer_map( ICONTAINER( row_from->scol ),
449 (icontainer_map_fn) iobject_changed, NULL, NULL );
450
451 workspace_deselect_all( row_from->ws );
452 }
453
454 static void
rowview_drag_data_get(GtkWidget * but,GdkDragContext * context,GtkSelectionData * selection_data,guint info,guint time,Rowview * rview)455 rowview_drag_data_get( GtkWidget *but,
456 GdkDragContext *context, GtkSelectionData *selection_data,
457 guint info, guint time, Rowview *rview )
458 {
459 if( info == ROWVIEW_TARGET_STRING ) {
460 /* Send a pointer to us.
461 */
462 gtk_selection_data_set( selection_data,
463 selection_data->target,
464 8, (const guchar *) &rview, sizeof( Rowview * ) );
465 }
466 }
467
468 static void
rowview_drag_data_received(GtkWidget * but,GdkDragContext * context,gint x,gint y,GtkSelectionData * data,guint info,guint time,Rowview * rview_to)469 rowview_drag_data_received( GtkWidget *but,
470 GdkDragContext *context, gint x, gint y,
471 GtkSelectionData *data, guint info, guint time, Rowview *rview_to )
472 {
473 if( data->length == sizeof( Rowview * ) && data->format == 8 &&
474 info == ROWVIEW_TARGET_STRING ) {
475 Rowview *rview_from = *((Rowview **) data->data);
476
477 if( IS_ROWVIEW( rview_from ) ) {
478 rowview_drag( rview_from, rview_to );
479 gtk_drag_finish( context, TRUE, FALSE, time );
480 return;
481 }
482 }
483
484 gtk_drag_finish( context, FALSE, FALSE, time );
485 }
486
487 /* Attach the rowview menu to a widget ... also used by iimageview
488 */
489 guint
rowview_menu_attach(Rowview * rview,GtkWidget * widget)490 rowview_menu_attach( Rowview *rview, GtkWidget *widget )
491 {
492 return( popup_attach( widget, rowview_popup_menu, rview ) );
493 }
494
495 static void
rowview_link(View * view,Model * model,View * parent)496 rowview_link( View *view, Model *model, View *parent )
497 {
498 Row *row = ROW( model );
499 Rowview *rview = ROWVIEW( view );
500 Subcolumnview *sview = SUBCOLUMNVIEW( parent );
501
502 VIEW_CLASS( parent_class )->link( view, model, parent );
503
504 rview->sview = sview;
505
506 /* Only drag n drop top level rows.
507 */
508 if( row->top_row == row ) {
509 gtk_drag_source_set( rview->but, GDK_BUTTON1_MASK,
510 rowview_target_table, IM_NUMBER( rowview_target_table ),
511 GDK_ACTION_COPY );
512 gtk_signal_connect( GTK_OBJECT( rview->but ), "drag_data_get",
513 GTK_SIGNAL_FUNC( rowview_drag_data_get ), rview );
514
515 gtk_drag_dest_set( rview->but, GTK_DEST_DEFAULT_ALL,
516 rowview_target_table, IM_NUMBER( rowview_target_table ),
517 GDK_ACTION_COPY );
518 gtk_signal_connect( GTK_OBJECT( rview->but ),
519 "drag_data_received",
520 GTK_SIGNAL_FUNC( rowview_drag_data_received ), rview );
521 }
522
523 rowview_menu_attach( rview, rview->but );
524 }
525
526 static void
rowview_child_add(View * parent,View * child)527 rowview_child_add( View *parent, View *child )
528 {
529 Rowview *rowview = ROWVIEW( parent );
530
531 g_assert( IS_RHSVIEW( child ) );
532 g_assert( !rowview->rhsview );
533
534 rowview->rhsview = RHSVIEW( child );
535
536 VIEW_CLASS( parent_class )->child_add( parent, child );
537 }
538
539 static void
rowview_child_remove(View * parent,View * child)540 rowview_child_remove( View *parent, View *child )
541 {
542 Rowview *rowview = ROWVIEW( parent );
543
544 g_assert( IS_RHSVIEW( child ) );
545 g_assert( rowview->rhsview );
546
547 rowview->rhsview = NULL;
548
549 VIEW_CLASS( parent_class )->child_remove( parent, child );
550 }
551
552 static void
rowview_class_init(RowviewClass * class)553 rowview_class_init( RowviewClass *class )
554 {
555 GtkObjectClass *object_class = (GtkObjectClass *) class;
556 vObjectClass *vobject_class = (vObjectClass *) class;
557 ViewClass *view_class = (ViewClass *) class;
558
559 GtkWidget *pane;
560
561 parent_class = g_type_class_peek_parent( class );
562
563 /* Create signals.
564 */
565
566 /* Init methods.
567 */
568 object_class->destroy = rowview_destroy;
569
570 vobject_class->refresh = rowview_refresh;
571
572 view_class->link = rowview_link;
573 view_class->child_add = rowview_child_add;
574 view_class->child_remove = rowview_child_remove;
575 view_class->reset = rowview_reset;
576 view_class->scrollto = rowview_scrollto;
577
578 /* Other init.
579 */
580 pane = rowview_popup_menu = popup_build( _( "Row menu" ) );
581 popup_add_but( pane, _( "_Edit" ),
582 POPUP_FUNC( rowview_edit_cb ) );
583 popup_add_but( pane, _( "_Header" ),
584 POPUP_FUNC( rowview_header_cb ) );
585 popup_add_but( pane, STOCK_DUPLICATE,
586 POPUP_FUNC( rowview_clone_cb ) );
587 popup_add_but( pane, _( "U_ngroup" ),
588 POPUP_FUNC( rowview_ungroup_cb ) );
589 popup_add_but( pane, GTK_STOCK_SAVE_AS,
590 POPUP_FUNC( rowview_save_cb ) );
591 popup_add_but( pane, _( "Replace From _File" ),
592 POPUP_FUNC( rowview_replace_cb ) );
593 popup_add_but( pane, _( "_Recalculate" ),
594 POPUP_FUNC( rowview_recalc_cb ) );
595 popup_add_but( pane, _( "Re_set" ),
596 POPUP_FUNC( rowview_clear_edited_cb ) );
597 menu_add_sep( pane );
598 popup_add_but( pane, GTK_STOCK_DELETE,
599 POPUP_FUNC( rowview_remove_cb ) );
600 }
601
602 static void
rowview_enter_cb(GtkWidget * widget,Rowview * rview)603 rowview_enter_cb( GtkWidget *widget, Rowview *rview )
604 {
605 Row *row = ROW( VOBJECT( rview )->iobject );
606
607 row_set_status( row );
608 row_show_dependents( row );
609 }
610
611 static void
rowview_leave_cb(GtkWidget * widget,Rowview * rview)612 rowview_leave_cb( GtkWidget *widget, Rowview *rview )
613 {
614 Row *row = ROW( VOBJECT( rview )->iobject );
615
616 row_hide_dependents( row );
617 }
618
619 static gboolean
rowview_focus_cb(GtkWidget * widget,GtkDirectionType dir,Rowview * rview)620 rowview_focus_cb( GtkWidget *widget, GtkDirectionType dir, Rowview *rview )
621 {
622 view_scrollto( VIEW( rview ), MODEL_SCROLL_TOP );
623
624 return( FALSE );
625 }
626
627 static void
rowview_tooltip_generate(GtkWidget * widget,VipsBuf * buf,Rowview * rview)628 rowview_tooltip_generate( GtkWidget *widget, VipsBuf *buf, Rowview *rview )
629 {
630 Row *row = ROW( VOBJECT( rview )->iobject );
631
632 iobject_info( IOBJECT( row ), buf );
633 vips_buf_removec( buf, '\n' );
634 }
635
636 static void
rowview_init(Rowview * rview)637 rowview_init( Rowview *rview )
638 {
639 rview->visible = TRUE;
640 rview->rnum = -1;
641 rview->last_tooltip = NULL;
642
643 /* Make leds.
644 */
645 rview->led = gtk_image_new_from_stock( STOCK_LED_OFF,
646 GTK_ICON_SIZE_MENU );
647 gtk_misc_set_alignment( GTK_MISC( rview->led ), 0.5, 0.0 );
648 gtk_misc_set_padding( GTK_MISC( rview->led ), 2, 2 );
649
650 /* Make fold/unfold button.
651 */
652 rview->spin = spin_new();
653 gtk_signal_connect( GTK_OBJECT( rview->spin ), "up_click",
654 GTK_SIGNAL_FUNC( rowview_spin_up_cb ), rview );
655 gtk_signal_connect( GTK_OBJECT( rview->spin ), "down_click",
656 GTK_SIGNAL_FUNC( rowview_spin_down_cb ), rview );
657 gtk_widget_show( rview->spin );
658 set_tooltip( rview->spin, _( "Click to open or close class" ) );
659
660 /* Make name button.
661 */
662 rview->but = gtk_button_new();
663 gtk_widget_show( rview->but );
664 doubleclick_add( rview->but, FALSE,
665 DOUBLECLICK_FUNC( rowview_single_cb ), rview,
666 DOUBLECLICK_FUNC( rowview_double_cb ), rview );
667 rview->label = gtk_label_new( "" );
668 gtk_misc_set_alignment( GTK_MISC( rview->label ), 1, 0 );
669 gtk_misc_set_padding( GTK_MISC( rview->label ), 2, 0 );
670 gtk_container_add( GTK_CONTAINER( rview->but ), rview->label );
671 gtk_widget_show( rview->label );
672 gtk_signal_connect( GTK_OBJECT( rview->but ), "enter",
673 GTK_SIGNAL_FUNC( rowview_enter_cb ), rview );
674 gtk_signal_connect( GTK_OBJECT( rview->but ), "leave",
675 GTK_SIGNAL_FUNC( rowview_leave_cb ), rview );
676 gtk_signal_connect( GTK_OBJECT( rview->but ), "focus",
677 GTK_SIGNAL_FUNC( rowview_focus_cb ), rview );
678 set_tooltip_generate( rview->but,
679 (TooltipGenerateFn) rowview_tooltip_generate, rview, NULL );
680 }
681
682 GtkType
rowview_get_type(void)683 rowview_get_type( void )
684 {
685 static GtkType rowview_type = 0;
686
687 if( !rowview_type ) {
688 static const GtkTypeInfo rview_info = {
689 "Rowview",
690 sizeof( Rowview ),
691 sizeof( RowviewClass ),
692 (GtkClassInitFunc) rowview_class_init,
693 (GtkObjectInitFunc) rowview_init,
694 /* reserved_1 */ NULL,
695 /* reserved_2 */ NULL,
696 (GtkClassInitFunc) NULL,
697 };
698
699 rowview_type = gtk_type_unique( TYPE_VIEW, &rview_info );
700 }
701
702 return( rowview_type );
703 }
704
705 View *
rowview_new(void)706 rowview_new( void )
707 {
708 Rowview *rview = gtk_type_new( TYPE_ROWVIEW );
709
710 return( VIEW( rview ) );
711 }
712
713 /* Find the position and size of a row in the enclosing GtkFixed.
714 */
715 void
rowview_get_position(Rowview * rview,int * x,int * y,int * w,int * h)716 rowview_get_position( Rowview *rview, int *x, int *y, int *w, int *h )
717 {
718 Columnview *cview = view_get_columnview( VIEW( rview ) );
719
720 if( GTK_WIDGET_VISIBLE( rview->spin ) ) {
721 *x = rview->spin->allocation.x;
722 *y = rview->spin->allocation.y;
723 *w = rview->spin->allocation.width;
724 *h = rview->spin->allocation.height;
725 }
726 else {
727 *x = rview->but->allocation.x;
728 *y = rview->but->allocation.y;
729 *w = 0;
730 *h = 0;
731 }
732
733 *w += rview->but->allocation.width;
734 *h = IM_MAX( rview->but->allocation.height, *h );
735
736 if( GTK_WIDGET_VISIBLE( rview->led ) ) {
737 *w += rview->led->allocation.width;
738 *h = IM_MAX( rview->led->allocation.height, *h );
739 }
740
741 *w += GTK_WIDGET( rview->rhsview )->allocation.width;
742 *h = IM_MAX( GTK_WIDGET( rview->rhsview )->allocation.height, *h );
743
744 /* Title bar, plus separator.
745 */
746 *y += cview->title->allocation.height + 2;
747
748 *x += cview->main->allocation.x;
749 *y += cview->main->allocation.y;
750
751 #ifdef DEBUG
752 printf( "rowview_get_position: " );
753 row_name_print( ROW( VOBJECT( rview )->iobject ) );
754 printf( ": x = %d, y = %d, w = %d, h = %d\n", *x, *y, *w, *h );
755 #endif /*DEBUG*/
756 }
757
758 /* Hide/show a row.
759 */
760 void
rowview_set_visible(Rowview * rview,gboolean visible)761 rowview_set_visible( Rowview *rview, gboolean visible )
762 {
763 if( rview->visible != visible ) {
764 rview->visible = visible;
765 rowview_update_widgets( rview );
766 }
767 }
768
769 gboolean
rowview_get_visible(Rowview * rview)770 rowview_get_visible( Rowview *rview )
771 {
772 return( rview->visible );
773 }
774