1 /* This version of GtkSheet has been *heavily* modified, for the specific
2 requirements of PSPPIRE. */
4 /* GtkSheet widget for Gtk+.
5 * Copyright (C) 1999-2001 Adrian E. Feiguin <adrian@ifir.ifir.edu.ar>
7 * Based on GtkClist widget by Jay Painter, but major changes.
8 * Memory allocation routines inspired on SC (Spreadsheet Calculator)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 * @short_description: spreadsheet widget for gtk2
28 * GtkSheet is a matrix widget for GTK+. It consists of an scrollable grid of
29 * cells where you can allocate text. Cell contents can be edited interactively
30 * through a specially designed entry, GtkItemEntry. It is also a container
31 * subclass, allowing you to display buttons, curves, pixmaps and any other
34 * You can also set many attributes as: border, foreground and background color,
35 * text justification, and more.
37 * The testgtksheet program shows how easy is to create a spreadsheet-like GUI
45 #include <gdk/gdkkeysyms.h>
46 #include <gtk/gtksignal.h>
47 #include <gtk/gtklabel.h>
48 #include <gtk/gtkbutton.h>
49 #include <gtk/gtkadjustment.h>
50 #include <gtk/gtktable.h>
51 #include <gtk/gtkbox.h>
52 #include <gtk/gtkmain.h>
53 #include <gtk/gtktypeutils.h>
54 #include <gtk/gtkentry.h>
55 #include <gtk/gtkcontainer.h>
56 #include <gtk/gtkpixmap.h>
57 #include <pango/pango.h>
58 #include "gtkitementry.h"
60 #include "gtkextra-marshal.h"
61 #include "gsheetmodel.h"
67 GTK_SHEET_IS_LOCKED = 1 << 0,
68 GTK_SHEET_IS_FROZEN = 1 << 1,
69 GTK_SHEET_IN_XDRAG = 1 << 2,
70 GTK_SHEET_IN_YDRAG = 1 << 3,
71 GTK_SHEET_IN_DRAG = 1 << 4,
72 GTK_SHEET_IN_SELECTION = 1 << 5,
73 GTK_SHEET_IN_RESIZE = 1 << 6,
74 GTK_SHEET_IN_CLIP = 1 << 7,
75 GTK_SHEET_REDRAW_PENDING = 1 << 8,
78 #define GTK_SHEET_FLAGS(sheet) (GTK_SHEET (sheet)->flags)
79 #define GTK_SHEET_SET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) |= (flag))
80 #define GTK_SHEET_UNSET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) &= ~(flag))
82 #define GTK_SHEET_IS_LOCKED(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_LOCKED)
85 #define GTK_SHEET_IS_FROZEN(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN)
86 #define GTK_SHEET_IN_XDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG)
87 #define GTK_SHEET_IN_YDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG)
88 #define GTK_SHEET_IN_DRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_DRAG)
89 #define GTK_SHEET_IN_SELECTION(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_SELECTION)
90 #define GTK_SHEET_IN_RESIZE(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_RESIZE)
91 #define GTK_SHEET_IN_CLIP(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_CLIP)
92 #define GTK_SHEET_REDRAW_PENDING(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_REDRAW_PENDING)
94 #define CELL_SPACING 1
96 #define TIMEOUT_SCROLL 20
97 #define TIMEOUT_FLASH 200
98 #define TIME_INTERVAL 8
99 #define COLUMN_MIN_WIDTH 10
104 #define DEFAULT_COLUMN_WIDTH 80
107 static gboolean gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col);
110 void dispose_string (const GtkSheet *sheet, gchar *text)
112 GSheetModel *model = gtk_sheet_get_model(sheet);
117 if (g_sheet_model_free_strings(model))
122 guint DEFAULT_ROW_HEIGHT(GtkWidget *widget)
124 if(!widget->style->font_desc) return 24;
126 PangoContext *context = gtk_widget_get_pango_context(widget);
127 PangoFontMetrics *metrics = pango_context_get_metrics(context,
128 widget->style->font_desc,
129 pango_context_get_language(context));
130 guint val = pango_font_metrics_get_descent(metrics) +
131 pango_font_metrics_get_ascent(metrics);
132 pango_font_metrics_unref(metrics);
133 return PANGO_PIXELS(val)+2*CELLOFFSET;
136 static inline guint DEFAULT_FONT_ASCENT(GtkWidget *widget)
138 if(!widget->style->font_desc) return 12;
140 PangoContext *context = gtk_widget_get_pango_context(widget);
141 PangoFontMetrics *metrics = pango_context_get_metrics(context,
142 widget->style->font_desc,
143 pango_context_get_language(context));
144 guint val = pango_font_metrics_get_ascent(metrics);
145 pango_font_metrics_unref(metrics);
146 return PANGO_PIXELS(val);
149 static inline guint STRING_WIDTH(GtkWidget *widget,
150 const PangoFontDescription *font, const gchar *text)
155 layout = gtk_widget_create_pango_layout (widget, text);
156 pango_layout_set_font_description (layout, font);
158 pango_layout_get_extents (layout, NULL, &rect);
160 g_object_unref(G_OBJECT(layout));
161 return PANGO_PIXELS(rect.width);
164 static inline guint DEFAULT_FONT_DESCENT(GtkWidget *widget)
166 if(!widget->style->font_desc) return 12;
168 PangoContext *context = gtk_widget_get_pango_context(widget);
169 PangoFontMetrics *metrics = pango_context_get_metrics(context,
170 widget->style->font_desc,
171 pango_context_get_language(context));
172 guint val = pango_font_metrics_get_descent(metrics);
173 pango_font_metrics_unref(metrics);
174 return PANGO_PIXELS(val);
180 yyy_row_is_visible(GtkSheet *sheet, gint row)
182 GSheetRow *row_geo = sheet->row_geometry;
184 return g_sheet_row_get_visibility(row_geo, row, sheet);
189 yyy_row_is_sensitive(GtkSheet *sheet, gint row)
191 GSheetRow *row_geo = sheet->row_geometry;
193 return g_sheet_row_get_sensitivity(row_geo, row, sheet);
199 yyy_row_count(const GtkSheet *sheet)
201 GSheetRow *row_geo = sheet->row_geometry;
203 return g_sheet_row_get_row_count(row_geo, sheet);
207 yyy_row_height(const GtkSheet *sheet, gint row)
209 GSheetRow *row_geo = sheet->row_geometry;
211 return g_sheet_row_get_height(row_geo, row, sheet);
215 yyy_row_top_ypixel(GtkSheet *sheet, gint row)
217 GSheetRow *geo = sheet->row_geometry;
219 gint y = g_sheet_row_start_pixel(geo, row, sheet);
221 if ( sheet->column_titles_visible )
222 y += sheet->column_title_area.height;
228 /* Return the row containing pixel Y */
230 yyy_row_ypixel_to_row(GtkSheet *sheet, gint y)
232 GSheetRow *geo = sheet->row_geometry;
234 gint cy = sheet->voffset;
236 if(sheet->column_titles_visible)
237 cy += sheet->column_title_area.height;
242 return g_sheet_row_pixel_to_row(geo, y - cy, sheet);
246 /* gives the top pixel of the given row in context of
247 * the sheet's voffset */
249 ROW_TOP_YPIXEL(GtkSheet *sheet, gint row)
251 return (sheet->voffset + yyy_row_top_ypixel(sheet, row));
255 /* returns the row index from a y pixel location in the
256 * context of the sheet's voffset */
258 ROW_FROM_YPIXEL(GtkSheet *sheet, gint y)
260 return (yyy_row_ypixel_to_row(sheet, y));
263 static inline GtkSheetButton *
264 xxx_column_button(GtkSheet *sheet, gint col)
266 GSheetColumn *col_geo = sheet->column_geometry;
268 return g_sheet_column_get_button(col_geo, col, sheet);
273 xxx_column_left_xpixel(GtkSheet *sheet, gint col)
275 GSheetColumn *geo = sheet->column_geometry;
277 gint x = g_sheet_column_start_pixel(geo, col, sheet);
279 if ( sheet->row_titles_visible )
280 x += sheet->row_title_area.width;
286 xxx_column_width(const GtkSheet *sheet, gint col)
288 GSheetColumn *col_geo = sheet->column_geometry;
290 return g_sheet_column_get_width(col_geo, col, sheet);
295 xxx_set_column_width(GtkSheet *sheet, gint col, gint width)
297 if ( sheet->column_geometry )
298 g_sheet_column_set_width(sheet->column_geometry, col, width, sheet);
302 xxx_column_set_left_column(GtkSheet *sheet, gint col, gint i)
304 GSheetColumn *col_geo = sheet->column_geometry;
306 g_sheet_column_set_left_text_column(col_geo, col, i, sheet);
310 xxx_column_left_column(const GtkSheet *sheet, gint col)
312 GSheetColumn *col_geo = sheet->column_geometry;
314 return g_sheet_column_get_left_text_column(col_geo, col, sheet);
318 xxx_column_set_right_column(GtkSheet *sheet, gint col, gint i)
320 GSheetColumn *col_geo = sheet->column_geometry;
322 g_sheet_column_set_right_text_column(col_geo, col, i, sheet);
326 xxx_column_right_column(const GtkSheet *sheet, gint col)
328 GSheetColumn *col_geo = sheet->column_geometry;
330 return g_sheet_column_get_right_text_column(col_geo, col, sheet);
333 static inline GtkJustification
334 xxx_column_justification(const GtkSheet *sheet, gint col)
336 GSheetColumn *col_geo = sheet->column_geometry;
338 return g_sheet_column_get_justification(col_geo, col, sheet);
342 xxx_column_is_visible(GtkSheet *sheet, gint col)
344 GSheetColumn *col_geo = sheet->column_geometry;
346 return g_sheet_column_get_visibility(col_geo, col, sheet);
351 xxx_column_is_sensitive(GtkSheet *sheet, gint col)
353 GSheetColumn *col_geo = sheet->column_geometry;
355 return g_sheet_column_get_sensitivity(col_geo, col, sheet);
359 /* gives the left pixel of the given column in context of
360 * the sheet's hoffset */
362 COLUMN_LEFT_XPIXEL(GtkSheet *sheet, gint ncol)
364 return (sheet->hoffset + xxx_column_left_xpixel(sheet, ncol));
368 xxx_column_count(const GtkSheet *sheet)
370 GSheetColumn *col_geo = sheet->column_geometry;
372 return g_sheet_column_get_column_count(col_geo, sheet);
375 /* returns the column index from a x pixel location in the
376 * context of the sheet's hoffset */
378 COLUMN_FROM_XPIXEL (GtkSheet * sheet,
384 if( sheet->row_titles_visible )
385 cx += sheet->row_title_area.width;
388 for (i = 0; i < xxx_column_count(sheet); i++)
390 if (x >= cx && x <= (cx + xxx_column_width(sheet, i)) &&
391 xxx_column_is_visible(sheet, i))
393 if( xxx_column_is_visible(sheet, i))
394 cx += xxx_column_width(sheet, i);
398 return xxx_column_count(sheet) - 1;
401 /* returns the total height of the sheet */
402 static inline gint SHEET_HEIGHT(GtkSheet *sheet)
404 const gint n_rows = yyy_row_count(sheet);
406 return yyy_row_top_ypixel(sheet, n_rows - 1) +
407 yyy_row_height(sheet, n_rows - 1);
411 static inline GtkSheetButton *
412 yyy_row_button(GtkSheet *sheet, gint row)
414 GSheetRow *row_geo = sheet->row_geometry;
416 return g_sheet_row_get_button(row_geo, row, sheet);
423 yyy_set_row_height(GtkSheet *sheet, gint row, gint height)
425 if ( sheet->row_geometry )
426 g_sheet_row_set_height(sheet->row_geometry, row, height, sheet);
431 /* returns the total width of the sheet */
432 static inline gint SHEET_WIDTH(GtkSheet *sheet)
436 cx = ( sheet->row_titles_visible ? sheet->row_title_area.width : 0);
438 for (i=0; i < xxx_column_count(sheet); i++)
439 if(xxx_column_is_visible(sheet, i)) cx += xxx_column_width(sheet, i);
444 #define MIN_VISIBLE_ROW(sheet) sheet->view.row0
445 #define MAX_VISIBLE_ROW(sheet) sheet->view.rowi
446 #define MIN_VISIBLE_COLUMN(sheet) sheet->view.col0
447 #define MAX_VISIBLE_COLUMN(sheet) sheet->view.coli
451 POSSIBLE_XDRAG(GtkSheet *sheet, gint x, gint *drag_column)
455 column=COLUMN_FROM_XPIXEL(sheet, x);
458 xdrag=COLUMN_LEFT_XPIXEL(sheet,column)+CELL_SPACING;
459 if(x <= xdrag+DRAG_WIDTH/2 && column != 0){
460 while(! xxx_column_is_visible(sheet, column-1) && column>0) column--;
461 *drag_column=column-1;
462 return xxx_column_is_sensitive(sheet, column-1);
465 xdrag+= xxx_column_width(sheet, column);
466 if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag+DRAG_WIDTH/2)
467 return xxx_column_is_sensitive(sheet, column);
473 POSSIBLE_YDRAG(GtkSheet *sheet, gint y, gint *drag_row)
477 row=ROW_FROM_YPIXEL(sheet, y);
480 ydrag=ROW_TOP_YPIXEL(sheet,row)+CELL_SPACING;
481 if(y <= ydrag+DRAG_WIDTH/2 && row != 0){
482 while(!yyy_row_is_visible(sheet, row-1) && row>0) row--;
484 return yyy_row_is_sensitive(sheet, row-1);
487 ydrag+=yyy_row_height(sheet, row);
489 if(y >= ydrag-DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2)
490 return yyy_row_is_sensitive(sheet, row);
496 static inline gint POSSIBLE_DRAG(GtkSheet *sheet, gint x, gint y,
497 gint *drag_row, gint *drag_column)
501 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
502 *drag_row=ROW_FROM_YPIXEL(sheet,y);
504 if(x>=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0)-DRAG_WIDTH/2 &&
505 x<=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
506 xxx_column_width(sheet, sheet->range.coli) + DRAG_WIDTH/2){
507 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.row0);
508 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
509 *drag_row=sheet->range.row0;
512 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
513 yyy_row_height(sheet, sheet->range.rowi);
514 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
515 *drag_row=sheet->range.rowi;
520 if(y>=ROW_TOP_YPIXEL(sheet,sheet->range.row0)-DRAG_WIDTH/2 &&
521 y<=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
522 yyy_row_height(sheet, sheet->range.rowi)+DRAG_WIDTH/2){
523 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0);
524 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
525 *drag_column=sheet->range.col0;
528 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
529 xxx_column_width(sheet, sheet->range.coli);
530 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
531 *drag_column=sheet->range.coli;
538 static inline gint POSSIBLE_RESIZE(GtkSheet *sheet, gint x, gint y,
539 gint *drag_row, gint *drag_column)
543 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
544 xxx_column_width(sheet, sheet->range.coli);
546 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
547 yyy_row_height(sheet, sheet->range.rowi);
549 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
550 ydrag = ROW_TOP_YPIXEL(sheet, sheet->view.row0);
552 if(sheet->state == GTK_SHEET_ROW_SELECTED)
553 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0);
555 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
556 *drag_row=ROW_FROM_YPIXEL(sheet,y);
558 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2 &&
559 y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2) return TRUE;
564 static void gtk_sheet_class_init (GtkSheetClass * klass);
565 static void gtk_sheet_init (GtkSheet * sheet);
566 static void gtk_sheet_destroy (GtkObject * object);
567 static void gtk_sheet_finalize (GObject * object);
568 static void gtk_sheet_style_set (GtkWidget *widget,
569 GtkStyle *previous_style);
570 static void gtk_sheet_realize (GtkWidget * widget);
571 static void gtk_sheet_unrealize (GtkWidget * widget);
572 static void gtk_sheet_map (GtkWidget * widget);
573 static void gtk_sheet_unmap (GtkWidget * widget);
574 static gint gtk_sheet_expose (GtkWidget * widget,
575 GdkEventExpose * event);
576 static void gtk_sheet_forall (GtkContainer *container,
577 gboolean include_internals,
578 GtkCallback callback,
579 gpointer callback_data);
581 static void gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
582 GtkAdjustment *hadjustment,
583 GtkAdjustment *vadjustment);
585 static gint gtk_sheet_button_press (GtkWidget * widget,
586 GdkEventButton * event);
587 static gint gtk_sheet_button_release (GtkWidget * widget,
588 GdkEventButton * event);
589 static gint gtk_sheet_motion (GtkWidget * widget,
590 GdkEventMotion * event);
591 static gint gtk_sheet_entry_key_press (GtkWidget *widget,
593 static gint gtk_sheet_key_press (GtkWidget *widget,
595 static void gtk_sheet_size_request (GtkWidget * widget,
596 GtkRequisition * requisition);
597 static void gtk_sheet_size_allocate (GtkWidget * widget,
598 GtkAllocation * allocation);
602 static gint gtk_sheet_range_isvisible (GtkSheet * sheet,
603 GtkSheetRange range);
604 static gint gtk_sheet_cell_isvisible (GtkSheet * sheet,
605 gint row, gint column);
608 static gint gtk_sheet_scroll (gpointer data);
609 static gint gtk_sheet_flash (gpointer data);
611 /* Drawing Routines */
613 /* draw cell background and frame */
614 static void gtk_sheet_cell_draw_default (GtkSheet *sheet,
615 gint row, gint column);
617 /* draw cell border */
618 static void gtk_sheet_cell_draw_border (GtkSheet *sheet,
619 gint row, gint column,
622 /* draw cell contents */
623 static void gtk_sheet_cell_draw_label (GtkSheet *sheet,
624 gint row, gint column);
626 /* draw visible part of range. If range==NULL then draw the whole screen */
627 static void gtk_sheet_range_draw (GtkSheet *sheet,
628 const GtkSheetRange *range);
630 /* highlight the visible part of the selected range */
631 static void gtk_sheet_range_draw_selection (GtkSheet *sheet,
632 GtkSheetRange range);
636 static gint gtk_sheet_move_query (GtkSheet *sheet,
637 gint row, gint column);
638 static void gtk_sheet_real_select_range (GtkSheet * sheet,
639 GtkSheetRange * range);
640 static void gtk_sheet_real_unselect_range (GtkSheet * sheet,
641 const GtkSheetRange * range);
642 static void gtk_sheet_extend_selection (GtkSheet *sheet,
643 gint row, gint column);
644 static void gtk_sheet_new_selection (GtkSheet *sheet,
645 GtkSheetRange *range);
646 static void gtk_sheet_draw_border (GtkSheet *sheet,
647 GtkSheetRange range);
648 static void gtk_sheet_draw_corners (GtkSheet *sheet,
649 GtkSheetRange range);
652 /* Active Cell handling */
654 static void gtk_sheet_entry_changed (GtkWidget *widget,
656 static gboolean gtk_sheet_deactivate_cell (GtkSheet *sheet);
657 static void gtk_sheet_hide_active_cell (GtkSheet *sheet);
658 static gboolean gtk_sheet_activate_cell (GtkSheet *sheet,
660 static void gtk_sheet_draw_active_cell (GtkSheet *sheet);
661 static void gtk_sheet_show_active_cell (GtkSheet *sheet);
662 static void gtk_sheet_click_cell (GtkSheet *sheet,
669 static void gtk_sheet_make_backing_pixmap (GtkSheet *sheet,
670 guint width, guint height);
671 static void gtk_sheet_draw_backing_pixmap (GtkSheet *sheet,
672 GtkSheetRange range);
675 static void adjust_scrollbars (GtkSheet * sheet);
676 static void vadjustment_changed (GtkAdjustment * adjustment,
678 static void hadjustment_changed (GtkAdjustment * adjustment,
680 static void vadjustment_value_changed (GtkAdjustment * adjustment,
682 static void hadjustment_value_changed (GtkAdjustment * adjustment,
686 static void draw_xor_vline (GtkSheet * sheet);
687 static void draw_xor_hline (GtkSheet * sheet);
688 static void draw_xor_rectangle (GtkSheet *sheet,
689 GtkSheetRange range);
690 static void gtk_sheet_draw_flashing_range (GtkSheet *sheet,
691 GtkSheetRange range);
692 static guint new_column_width (GtkSheet * sheet,
695 static guint new_row_height (GtkSheet * sheet,
700 static void create_global_button (GtkSheet *sheet);
701 static void global_button_clicked (GtkWidget *widget,
705 static void create_sheet_entry (GtkSheet *sheet);
706 static void gtk_sheet_size_allocate_entry (GtkSheet *sheet);
707 static void gtk_sheet_entry_set_max_size (GtkSheet *sheet);
709 /* Sheet button gadgets */
711 static void size_allocate_column_title_buttons (GtkSheet * sheet);
712 static void size_allocate_row_title_buttons (GtkSheet * sheet);
715 static void gtk_sheet_button_draw (GtkSheet *sheet,
716 gint row, gint column);
717 static void size_allocate_global_button (GtkSheet *sheet);
718 static void gtk_sheet_button_size_request (GtkSheet *sheet,
719 const GtkSheetButton *button,
720 GtkRequisition *requisition);
722 /* Attributes routines */
723 static void init_attributes (GtkSheet *sheet, gint col,
724 GtkSheetCellAttr *attributes);
727 /* Memory allocation routines */
728 static void gtk_sheet_real_range_clear (GtkSheet *sheet,
729 const GtkSheetRange *range,
731 static void gtk_sheet_real_cell_clear (GtkSheet *sheet,
737 /* Container Functions */
738 static void gtk_sheet_remove (GtkContainer *container,
740 static void gtk_sheet_realize_child (GtkSheet *sheet,
741 GtkSheetChild *child);
742 static void gtk_sheet_position_child (GtkSheet *sheet,
743 GtkSheetChild *child);
744 static void gtk_sheet_position_children (GtkSheet *sheet);
745 static void gtk_sheet_child_show (GtkSheetChild *child);
746 static void gtk_sheet_child_hide (GtkSheetChild *child);
747 static void gtk_sheet_column_size_request (GtkSheet *sheet,
750 static void gtk_sheet_row_size_request (GtkSheet *sheet,
758 _gtkextra_signal_emit(GtkObject *object, guint signal_id, ...);
780 static GtkContainerClass *parent_class = NULL;
781 static guint sheet_signals[LAST_SIGNAL] = {0};
785 gtk_sheet_get_type ()
787 static GType sheet_type = 0;
791 static const GTypeInfo sheet_info =
793 sizeof (GtkSheetClass),
796 (GClassInitFunc) gtk_sheet_class_init,
801 (GInstanceInitFunc) gtk_sheet_init,
805 g_type_register_static (GTK_TYPE_CONTAINER, "GtkSheet",
811 static GtkSheetRange*
812 gtk_sheet_range_copy (const GtkSheetRange *range)
814 GtkSheetRange *new_range;
816 g_return_val_if_fail (range != NULL, NULL);
818 new_range = g_new (GtkSheetRange, 1);
826 gtk_sheet_range_free (GtkSheetRange *range)
828 g_return_if_fail (range != NULL);
834 gtk_sheet_range_get_type (void)
836 static GType sheet_range_type=0;
838 if(!sheet_range_type)
840 sheet_range_type = g_boxed_type_register_static("GtkSheetRange", (GBoxedCopyFunc)gtk_sheet_range_copy, (GBoxedFreeFunc)gtk_sheet_range_free);
842 return sheet_range_type;
847 gtk_sheet_class_init (GtkSheetClass * klass)
849 GtkObjectClass *object_class;
850 GtkWidgetClass *widget_class;
851 GtkContainerClass *container_class;
852 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
854 object_class = (GtkObjectClass *) klass;
855 widget_class = (GtkWidgetClass *) klass;
856 container_class = (GtkContainerClass *) klass;
858 parent_class = g_type_class_peek_parent (klass);
861 * GtkSheet::select-row
862 * @sheet: the sheet widget that emitted the signal
863 * @row: the newly selected row index
865 * A row has been selected.
867 sheet_signals[SELECT_ROW] =
868 gtk_signal_new ("select-row",
870 GTK_CLASS_TYPE(object_class),
871 GTK_SIGNAL_OFFSET (GtkSheetClass, select_row),
873 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
876 * GtkSheet::select-column
877 * @sheet: the sheet widget that emitted the signal
878 * @column: the newly selected column index
880 * A column has been selected.
882 sheet_signals[SELECT_COLUMN] =
883 gtk_signal_new ("select-column",
885 GTK_CLASS_TYPE(object_class),
886 GTK_SIGNAL_OFFSET (GtkSheetClass, select_column),
888 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
892 * GtkSheet::double-click-row
893 * @sheet: the sheet widget that emitted the signal
894 * @row: the row that was double clicked.
896 * A row's title button has been double clicked
898 sheet_signals[DOUBLE_CLICK_ROW] =
899 gtk_signal_new ("double-click-row",
901 GTK_CLASS_TYPE(object_class),
904 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
908 * GtkSheet::double-click-column
909 * @sheet: the sheet widget that emitted the signal
910 * @column: the column that was double clicked.
912 * A column's title button has been double clicked
914 sheet_signals[DOUBLE_CLICK_COLUMN] =
915 gtk_signal_new ("double-click-column",
917 GTK_CLASS_TYPE(object_class),
920 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
922 sheet_signals[SELECT_RANGE] =
923 gtk_signal_new ("select-range",
925 GTK_CLASS_TYPE(object_class),
926 GTK_SIGNAL_OFFSET (GtkSheetClass, select_range),
927 gtkextra_VOID__BOXED,
928 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
930 sheet_signals[CLIP_RANGE] =
931 gtk_signal_new ("clip-range",
933 GTK_CLASS_TYPE(object_class),
934 GTK_SIGNAL_OFFSET (GtkSheetClass, clip_range),
935 gtkextra_VOID__BOXED,
936 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
938 sheet_signals[RESIZE_RANGE] =
939 gtk_signal_new ("resize-range",
941 GTK_CLASS_TYPE(object_class),
942 GTK_SIGNAL_OFFSET (GtkSheetClass, resize_range),
943 gtkextra_VOID__BOXED_BOXED,
944 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
945 sheet_signals[MOVE_RANGE] =
946 gtk_signal_new ("move-range",
948 GTK_CLASS_TYPE(object_class),
949 GTK_SIGNAL_OFFSET (GtkSheetClass, move_range),
950 gtkextra_VOID__BOXED_BOXED,
951 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
952 sheet_signals[TRAVERSE] =
953 gtk_signal_new ("traverse",
955 GTK_CLASS_TYPE(object_class),
956 GTK_SIGNAL_OFFSET (GtkSheetClass, traverse),
957 gtkextra_BOOLEAN__INT_INT_POINTER_POINTER,
958 GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT,
959 GTK_TYPE_POINTER, GTK_TYPE_POINTER);
961 sheet_signals[DEACTIVATE] =
962 gtk_signal_new ("deactivate",
964 GTK_CLASS_TYPE(object_class),
965 GTK_SIGNAL_OFFSET (GtkSheetClass, deactivate),
966 gtkextra_BOOLEAN__INT_INT,
967 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
969 sheet_signals[ACTIVATE] =
970 gtk_signal_new ("activate",
972 GTK_CLASS_TYPE(object_class),
973 GTK_SIGNAL_OFFSET (GtkSheetClass, activate),
974 gtkextra_BOOLEAN__INT_INT,
975 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
977 sheet_signals[SET_CELL] =
978 gtk_signal_new ("set-cell",
980 GTK_CLASS_TYPE(object_class),
981 GTK_SIGNAL_OFFSET (GtkSheetClass, set_cell),
982 gtkextra_VOID__INT_INT,
983 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
985 sheet_signals[CLEAR_CELL] =
986 gtk_signal_new ("clear-cell",
988 GTK_CLASS_TYPE(object_class),
989 GTK_SIGNAL_OFFSET (GtkSheetClass, clear_cell),
990 gtkextra_VOID__INT_INT,
991 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
993 sheet_signals[CHANGED] =
994 gtk_signal_new ("changed",
996 GTK_CLASS_TYPE(object_class),
997 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
998 gtkextra_VOID__INT_INT,
999 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1001 sheet_signals[NEW_COL_WIDTH] =
1002 gtk_signal_new ("new-column-width",
1004 GTK_CLASS_TYPE(object_class),
1005 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1006 gtkextra_VOID__INT_INT,
1007 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1009 sheet_signals[NEW_ROW_HEIGHT] =
1010 gtk_signal_new ("new-row-height",
1012 GTK_CLASS_TYPE(object_class),
1013 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1014 gtkextra_VOID__INT_INT,
1015 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1017 widget_class->set_scroll_adjustments_signal =
1018 gtk_signal_new ("set-scroll-adjustments",
1020 GTK_CLASS_TYPE(object_class),
1021 GTK_SIGNAL_OFFSET (GtkSheetClass, set_scroll_adjustments),
1022 gtkextra_VOID__OBJECT_OBJECT,
1023 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1026 container_class->add = NULL;
1027 container_class->remove = gtk_sheet_remove;
1028 container_class->forall = gtk_sheet_forall;
1030 object_class->destroy = gtk_sheet_destroy;
1031 gobject_class->finalize = gtk_sheet_finalize;
1033 widget_class->realize = gtk_sheet_realize;
1034 widget_class->unrealize = gtk_sheet_unrealize;
1035 widget_class->map = gtk_sheet_map;
1036 widget_class->unmap = gtk_sheet_unmap;
1037 widget_class->style_set = gtk_sheet_style_set;
1038 widget_class->button_press_event = gtk_sheet_button_press;
1039 widget_class->button_release_event = gtk_sheet_button_release;
1040 widget_class->motion_notify_event = gtk_sheet_motion;
1041 widget_class->key_press_event = gtk_sheet_key_press;
1042 widget_class->expose_event = gtk_sheet_expose;
1043 widget_class->size_request = gtk_sheet_size_request;
1044 widget_class->size_allocate = gtk_sheet_size_allocate;
1045 widget_class->focus_in_event = NULL;
1046 widget_class->focus_out_event = NULL;
1048 klass->set_scroll_adjustments = gtk_sheet_set_scroll_adjustments;
1049 klass->select_row = NULL;
1050 klass->select_column = NULL;
1051 klass->select_range = NULL;
1052 klass->clip_range = NULL;
1053 klass->resize_range = NULL;
1054 klass->move_range = NULL;
1055 klass->traverse = NULL;
1056 klass->deactivate = NULL;
1057 klass->activate = NULL;
1058 klass->set_cell = NULL;
1059 klass->clear_cell = NULL;
1060 klass->changed = NULL;
1065 gtk_sheet_init (GtkSheet *sheet)
1067 sheet->column_geometry = NULL;
1068 sheet->row_geometry = NULL;
1070 sheet->children = NULL;
1073 sheet->selection_mode = GTK_SELECTION_BROWSE;
1074 sheet->freeze_count = 0;
1075 sheet->state = GTK_SHEET_NORMAL;
1077 GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW);
1078 GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS);
1080 sheet->view.row0 = 0;
1081 sheet->view.col0 = 0;
1082 sheet->view.rowi = 0;
1083 sheet->view.coli = 0;
1085 sheet->column_title_window=NULL;
1086 sheet->column_title_area.x=0;
1087 sheet->column_title_area.y=0;
1088 sheet->column_title_area.width=0;
1089 sheet->column_title_area.height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
1091 sheet->row_title_window=NULL;
1092 sheet->row_title_area.x=0;
1093 sheet->row_title_area.y=0;
1094 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1095 sheet->row_title_area.height=0;
1098 sheet->active_cell.row=0;
1099 sheet->active_cell.col=0;
1100 sheet->selection_cell.row=0;
1101 sheet->selection_cell.col=0;
1103 sheet->sheet_entry=NULL;
1106 sheet->range.row0=0;
1107 sheet->range.rowi=0;
1108 sheet->range.col0=0;
1109 sheet->range.coli=0;
1111 sheet->state=GTK_SHEET_NORMAL;
1113 sheet->sheet_window = NULL;
1114 sheet->sheet_window_width = 0;
1115 sheet->sheet_window_height = 0;
1116 sheet->sheet_entry = NULL;
1117 sheet->button = NULL;
1122 sheet->hadjustment = NULL;
1123 sheet->vadjustment = NULL;
1125 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
1126 sheet->xor_gc = NULL;
1127 sheet->fg_gc = NULL;
1128 sheet->bg_gc = NULL;
1132 gdk_color_parse("white", &sheet->bg_color);
1133 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1134 gdk_color_parse("gray", &sheet->grid_color);
1135 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1136 sheet->show_grid = TRUE;
1140 /* Callback which occurs whenever columns are inserted/deleted in the model */
1142 columns_inserted_deleted_callback (GSheetModel *model, gint first_column, gint n_columns,
1145 GtkSheet *sheet = GTK_SHEET(data);
1147 GtkSheetRange range;
1148 gint model_columns = g_sheet_model_get_column_count(model);
1151 /* Need to update all the columns starting from the first column and onwards.
1152 * Previous column are unchanged, so don't need to be updated.
1154 range.col0 = first_column;
1156 range.coli = xxx_column_count(sheet) - 1;
1157 range.rowi = yyy_row_count(sheet) - 1;
1159 if (sheet->active_cell.col >= model_columns)
1160 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, model_columns - 1);
1162 gtk_sheet_range_draw(sheet, &range);
1166 /* Callback which occurs whenever rows are inserted/deleted in the model */
1168 rows_inserted_deleted_callback (GSheetModel *m, gint first_row, gint n_rows,
1171 GtkSheet *sheet = GTK_SHEET(data);
1173 GtkSheetRange range;
1175 /* Need to update all the rows starting from the first row and onwards.
1176 * Previous rows are unchanged, so don't need to be updated.
1178 range.row0 = first_row;
1180 range.rowi = yyy_row_count(sheet) - 1;
1181 range.coli = xxx_column_count(sheet) - 1;
1183 gtk_sheet_range_draw(sheet, &range);
1188 If row0 or rowi are negative, then all rows will be updated.
1189 If col0 or coli are negative, then all columns will be updated.
1192 range_update_callback (GSheetModel *m, gint row0, gint col0,
1193 gint rowi, gint coli, gpointer data)
1195 GtkSheet *sheet = GTK_SHEET(data);
1197 GtkSheetRange range;
1204 if( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
1206 gtk_sheet_range_draw(sheet, NULL);
1209 else if ( row0 < 0 || rowi < 0 )
1211 range.row0=MIN_VISIBLE_ROW(sheet);
1212 range.rowi=MAX_VISIBLE_ROW(sheet);
1214 else if ( col0 < 0 || coli < 0 )
1216 range.col0=MIN_VISIBLE_COLUMN(sheet);
1217 range.coli=MAX_VISIBLE_COLUMN(sheet);
1220 gtk_sheet_range_draw(sheet, &range);
1224 static void gtk_sheet_construct (GtkSheet *sheet,
1227 const gchar *title);
1232 * @rows: initial number of rows
1233 * @columns: initial number of columns
1234 * @title: sheet title
1235 * @model: the model to use for the sheet data
1237 * Creates a new sheet widget with the given number of rows and columns.
1239 * Returns: the new sheet widget
1242 gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, const gchar *title,
1247 widget = gtk_type_new (gtk_sheet_get_type ());
1249 gtk_sheet_construct(GTK_SHEET(widget), vgeo, hgeo, title);
1252 gtk_sheet_set_model(GTK_SHEET(widget), model);
1260 * gtk_sheet_set_model
1261 * @sheet: the sheet to set the model for
1262 * @model: the model to use for the sheet data
1264 * Sets the model for a GtkSheet
1268 gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model)
1270 g_return_if_fail (GTK_IS_SHEET (sheet));
1271 g_return_if_fail (G_IS_SHEET_MODEL (model));
1273 sheet->model = model;
1275 g_signal_connect(model, "range_changed",
1276 G_CALLBACK(range_update_callback), sheet);
1278 g_signal_connect(model, "rows_inserted",
1279 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1281 g_signal_connect(model, "rows_deleted",
1282 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1284 g_signal_connect(model, "columns_inserted",
1285 G_CALLBACK(columns_inserted_deleted_callback), sheet);
1287 g_signal_connect(model, "columns_deleted",
1288 G_CALLBACK(columns_inserted_deleted_callback), sheet);
1295 column_titles_changed(GtkWidget *w, gint first, gint n_columns, gpointer data)
1297 GtkSheet *sheet = GTK_SHEET(data);
1300 if(!GTK_SHEET_IS_FROZEN(sheet)){
1302 for ( i = first ; i <= MAX_VISIBLE_COLUMN(sheet) ; ++i )
1304 gtk_sheet_button_draw(sheet, -1, i);
1305 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, i);
1311 gtk_sheet_construct (GtkSheet *sheet,
1316 g_return_if_fail(G_IS_SHEET_COLUMN(hgeo));
1317 g_return_if_fail(G_IS_SHEET_ROW(vgeo));
1319 sheet->column_geometry = hgeo;
1320 sheet->row_geometry = vgeo;
1323 sheet->columns_resizable = TRUE;
1324 sheet->rows_resizable = TRUE;
1326 sheet->row_titles_visible = TRUE;
1327 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1329 sheet->column_titles_visible = TRUE;
1330 sheet->autoscroll = TRUE;
1331 sheet->justify_entry = TRUE;
1334 /* create sheet entry */
1335 sheet->entry_type = 0;
1336 create_sheet_entry (sheet);
1338 /* create global selection button */
1339 create_global_button(sheet);
1342 sheet->name = g_strdup(title);
1344 g_signal_connect(sheet->column_geometry, "columns_changed",
1345 G_CALLBACK(column_titles_changed), sheet);
1351 gtk_sheet_new_with_custom_entry (GSheetRow *rows, GSheetColumn *columns, const gchar *title,
1356 widget = gtk_type_new (gtk_sheet_get_type ());
1358 gtk_sheet_construct_with_custom_entry(GTK_SHEET(widget),
1359 rows, columns, title, entry_type);
1365 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet,
1371 gtk_sheet_construct(sheet, vgeo, hgeo, title);
1373 sheet->entry_type = entry_type;
1374 create_sheet_entry(sheet);
1380 gtk_sheet_change_entry(GtkSheet *sheet, GtkType entry_type)
1384 g_return_if_fail (sheet != NULL);
1385 g_return_if_fail (GTK_IS_SHEET (sheet));
1387 state = sheet->state;
1389 if(sheet->state == GTK_SHEET_NORMAL)
1390 gtk_sheet_hide_active_cell(sheet);
1392 sheet->entry_type = entry_type;
1394 create_sheet_entry(sheet);
1396 if(state == GTK_SHEET_NORMAL)
1398 gtk_sheet_show_active_cell(sheet);
1399 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
1401 G_CALLBACK(gtk_sheet_entry_changed),
1410 gtk_sheet_show_grid(GtkSheet *sheet, gboolean show)
1412 g_return_if_fail (sheet != NULL);
1413 g_return_if_fail (GTK_IS_SHEET (sheet));
1415 if(show == sheet->show_grid) return;
1417 sheet->show_grid = show;
1419 if(!GTK_SHEET_IS_FROZEN(sheet))
1420 gtk_sheet_range_draw(sheet, NULL);
1424 gtk_sheet_grid_visible(GtkSheet *sheet)
1426 g_return_val_if_fail (sheet != NULL, 0);
1427 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1429 return sheet->show_grid;
1433 gtk_sheet_set_background(GtkSheet *sheet, GdkColor *color)
1435 g_return_if_fail (sheet != NULL);
1436 g_return_if_fail (GTK_IS_SHEET (sheet));
1439 gdk_color_parse("white", &sheet->bg_color);
1440 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1442 sheet->bg_color = *color;
1444 if(!GTK_SHEET_IS_FROZEN(sheet))
1445 gtk_sheet_range_draw(sheet, NULL);
1449 gtk_sheet_set_grid(GtkSheet *sheet, GdkColor *color)
1451 g_return_if_fail (sheet != NULL);
1452 g_return_if_fail (GTK_IS_SHEET (sheet));
1455 gdk_color_parse("black", &sheet->grid_color);
1456 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1458 sheet->grid_color = *color;
1460 if(!GTK_SHEET_IS_FROZEN(sheet))
1461 gtk_sheet_range_draw(sheet, NULL);
1465 gtk_sheet_get_columns_count(GtkSheet *sheet)
1467 g_return_val_if_fail (sheet != NULL, 0);
1468 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1470 return xxx_column_count(sheet);
1474 gtk_sheet_get_rows_count(GtkSheet *sheet)
1476 g_return_val_if_fail (sheet != NULL, 0);
1477 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1479 return yyy_row_count(sheet);
1483 gtk_sheet_get_state(GtkSheet *sheet)
1485 g_return_val_if_fail (sheet != NULL, 0);
1486 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1488 return (sheet->state);
1492 gtk_sheet_set_selection_mode(GtkSheet *sheet, gint mode)
1494 g_return_if_fail (sheet != NULL);
1495 g_return_if_fail (GTK_IS_SHEET (sheet));
1497 if(GTK_WIDGET_REALIZED(sheet))
1498 gtk_sheet_real_unselect_range(sheet, NULL);
1500 sheet->selection_mode = mode;
1504 gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize)
1506 g_return_if_fail (sheet != NULL);
1507 g_return_if_fail (GTK_IS_SHEET (sheet));
1509 sheet->autoresize = autoresize;
1513 gtk_sheet_autoresize (GtkSheet *sheet)
1515 g_return_val_if_fail (sheet != NULL, FALSE);
1516 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1518 return sheet->autoresize;
1522 gtk_sheet_set_column_width (GtkSheet * sheet,
1528 gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
1530 gint text_width = 0;
1533 g_return_if_fail (sheet != NULL);
1534 g_return_if_fail (GTK_IS_SHEET (sheet));
1535 if (column >= xxx_column_count(sheet) || column < 0) return;
1537 for (row = 0; row < yyy_row_count(sheet); row++)
1539 gchar *text = gtk_sheet_cell_get_text(sheet, row, column);
1540 if (text && strlen(text) > 0){
1541 GtkSheetCellAttr attributes;
1543 gtk_sheet_get_attributes(sheet, row, column, &attributes);
1544 if(attributes.is_visible){
1545 gint width = STRING_WIDTH(GTK_WIDGET(sheet),
1546 attributes.font_desc,
1548 + 2*CELLOFFSET + attributes.border.width;
1549 text_width = MAX (text_width, width);
1552 dispose_string(sheet, text);
1555 if(text_width > xxx_column_width(sheet, column) )
1557 gtk_sheet_set_column_width(sheet, column, text_width);
1558 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
1564 gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll)
1566 g_return_if_fail (sheet != NULL);
1567 g_return_if_fail (GTK_IS_SHEET (sheet));
1569 sheet->autoscroll = autoscroll;
1573 gtk_sheet_autoscroll (GtkSheet *sheet)
1575 g_return_val_if_fail (sheet != NULL, FALSE);
1576 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1578 return sheet->autoscroll;
1582 gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text)
1584 g_return_if_fail (sheet != NULL);
1585 g_return_if_fail (GTK_IS_SHEET (sheet));
1587 sheet->clip_text = clip_text;
1591 gtk_sheet_clip_text (GtkSheet *sheet)
1593 g_return_val_if_fail (sheet != NULL, FALSE);
1594 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1596 return sheet->clip_text;
1600 gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify)
1602 g_return_if_fail (sheet != NULL);
1603 g_return_if_fail (GTK_IS_SHEET (sheet));
1605 sheet->justify_entry = justify;
1609 gtk_sheet_justify_entry (GtkSheet *sheet)
1611 g_return_val_if_fail (sheet != NULL, FALSE);
1612 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1614 return sheet->justify_entry;
1618 gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked)
1620 g_return_if_fail (sheet != NULL);
1621 g_return_if_fail (GTK_IS_SHEET (sheet));
1625 GTK_SHEET_SET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
1626 gtk_widget_hide(sheet->sheet_entry);
1627 gtk_widget_unmap(sheet->sheet_entry);
1631 GTK_SHEET_UNSET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
1632 if (GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)))
1634 gtk_widget_show (sheet->sheet_entry);
1635 gtk_widget_map (sheet->sheet_entry);
1639 gtk_entry_set_editable(GTK_ENTRY(sheet->sheet_entry), locked);
1644 gtk_sheet_locked (const GtkSheet *sheet)
1646 g_return_val_if_fail (sheet != NULL, FALSE);
1647 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1649 return GTK_SHEET_IS_LOCKED(sheet);
1652 /* This routine has problems with gtk+-1.2 related with the
1653 * label/button drawing - I think it's a bug in gtk+-1.2 */
1656 gtk_sheet_set_title(GtkSheet *sheet, const gchar *title)
1658 /* GtkWidget *old_widget;
1659 */ GtkWidget *label;
1661 g_return_if_fail (sheet != NULL);
1662 g_return_if_fail (title != NULL);
1663 g_return_if_fail (GTK_IS_SHEET (sheet));
1666 g_free (sheet->name);
1668 sheet->name = g_strdup (title);
1670 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) || !title) return;
1672 if(GTK_BIN(sheet->button)->child)
1673 label = GTK_BIN(sheet->button)->child;
1675 gtk_label_set_text(GTK_LABEL(label), title);
1677 size_allocate_global_button(sheet);
1679 /* remove and destroy the old widget */
1681 old_widget = GTK_BIN (sheet->button)->child;
1684 gtk_container_remove (GTK_CONTAINER (sheet->button), old_widget);
1687 label = gtk_label_new (title);
1688 gtk_misc_set_alignment(GTK_MISC(label), 0.5 , 0.5 );
1690 gtk_container_add (GTK_CONTAINER (sheet->button), label);
1691 gtk_widget_show (label);
1693 size_allocate_global_button(sheet);
1695 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, -1);
1698 gtk_widget_destroy (old_widget);
1703 gtk_sheet_freeze (GtkSheet *sheet)
1705 g_return_if_fail (sheet != NULL);
1706 g_return_if_fail (GTK_IS_SHEET (sheet));
1708 sheet->freeze_count++;
1709 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1713 gtk_sheet_thaw(GtkSheet *sheet)
1715 g_return_if_fail (sheet != NULL);
1716 g_return_if_fail (GTK_IS_SHEET (sheet));
1718 if(sheet->freeze_count == 0) return;
1720 sheet->freeze_count--;
1721 if(sheet->freeze_count > 0) return;
1723 adjust_scrollbars(sheet);
1725 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1727 sheet->old_vadjustment = -1.;
1728 sheet->old_hadjustment = -1.;
1730 if(sheet->hadjustment)
1731 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1733 if(sheet->vadjustment)
1734 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1737 if(sheet->state == GTK_STATE_NORMAL)
1738 if(sheet->sheet_entry && GTK_WIDGET_MAPPED(sheet->sheet_entry)){
1739 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
1741 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
1743 (GtkSignalFunc)gtk_sheet_entry_changed,
1744 GTK_OBJECT(GTK_WIDGET(sheet)));
1745 gtk_sheet_show_active_cell(sheet);
1752 gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width)
1754 if(width < COLUMN_MIN_WIDTH) return;
1756 sheet->row_title_area.width = width;
1757 sheet->view.col0 = COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
1758 sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
1761 adjust_scrollbars(sheet);
1763 sheet->old_hadjustment = -1.;
1764 if(sheet->hadjustment)
1765 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1767 size_allocate_global_button(sheet);
1771 gtk_sheet_set_column_titles_height(GtkSheet *sheet, guint height)
1773 if(height < DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))) return;
1775 sheet->column_title_area.height = height;
1776 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
1777 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
1779 adjust_scrollbars(sheet);
1781 sheet->old_vadjustment = -1.;
1782 if(sheet->vadjustment)
1783 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1785 size_allocate_global_button(sheet);
1789 gtk_sheet_show_column_titles(GtkSheet *sheet)
1793 if(sheet->column_titles_visible) return;
1795 sheet->column_titles_visible = TRUE;
1798 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1799 gdk_window_show(sheet->column_title_window);
1800 gdk_window_move_resize (sheet->column_title_window,
1801 sheet->column_title_area.x,
1802 sheet->column_title_area.y,
1803 sheet->column_title_area.width,
1804 sheet->column_title_area.height);
1806 for(col = MIN_VISIBLE_COLUMN(sheet);
1807 col <= MAX_VISIBLE_COLUMN(sheet);
1810 GtkSheetButton *button = xxx_column_button(sheet, col);
1811 GtkSheetChild *child = button->child;
1813 gtk_sheet_child_show(child);
1814 gtk_sheet_button_free(button);
1816 adjust_scrollbars(sheet);
1819 sheet->old_vadjustment = -1.;
1820 if(sheet->vadjustment)
1821 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1823 size_allocate_global_button(sheet);
1828 gtk_sheet_show_row_titles(GtkSheet *sheet)
1832 if(sheet->row_titles_visible) return;
1834 sheet->row_titles_visible = TRUE;
1837 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1838 gdk_window_show(sheet->row_title_window);
1839 gdk_window_move_resize (sheet->row_title_window,
1840 sheet->row_title_area.x,
1841 sheet->row_title_area.y,
1842 sheet->row_title_area.width,
1843 sheet->row_title_area.height);
1845 for(row = MIN_VISIBLE_ROW(sheet);
1846 row <= MAX_VISIBLE_ROW(sheet);
1849 const GtkSheetButton *button = yyy_row_button(sheet, row);
1850 GtkSheetChild *child = button->child;
1853 gtk_sheet_child_show(child);
1856 adjust_scrollbars(sheet);
1859 sheet->old_hadjustment = -1.;
1860 if(sheet->hadjustment)
1861 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1863 size_allocate_global_button(sheet);
1867 gtk_sheet_hide_column_titles(GtkSheet *sheet)
1871 if(!sheet->column_titles_visible) return;
1873 sheet->column_titles_visible = FALSE;
1875 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1876 if(sheet->column_title_window)
1877 gdk_window_hide(sheet->column_title_window);
1878 if(GTK_WIDGET_VISIBLE(sheet->button))
1879 gtk_widget_hide(sheet->button);
1881 for(col = MIN_VISIBLE_COLUMN(sheet);
1882 col <= MAX_VISIBLE_COLUMN(sheet);
1885 GtkSheetButton *button = xxx_column_button(sheet, col);
1886 GtkSheetChild *child = button->child;
1888 gtk_sheet_child_hide(child);
1889 gtk_sheet_button_free(button);
1891 adjust_scrollbars(sheet);
1894 sheet->old_vadjustment = -1.;
1895 if(sheet->vadjustment)
1896 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1901 gtk_sheet_hide_row_titles(GtkSheet *sheet)
1905 if(!sheet->row_titles_visible) return;
1907 sheet->row_titles_visible = FALSE;
1910 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1911 if(sheet->row_title_window)
1912 gdk_window_hide(sheet->row_title_window);
1913 if(GTK_WIDGET_VISIBLE(sheet->button))
1914 gtk_widget_hide(sheet->button);
1915 for(row = MIN_VISIBLE_ROW(sheet);
1916 row <= MAX_VISIBLE_ROW(sheet);
1919 const GtkSheetButton *button = yyy_row_button(sheet, row);
1920 GtkSheetChild *child = button->child;
1923 gtk_sheet_child_hide(child);
1925 adjust_scrollbars(sheet);
1928 sheet->old_hadjustment = -1.;
1929 if(sheet->hadjustment)
1930 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1935 gtk_sheet_column_titles_visible(GtkSheet *sheet)
1937 g_return_val_if_fail (sheet != NULL, FALSE);
1938 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1939 return sheet->column_titles_visible;
1943 gtk_sheet_row_titles_visible(GtkSheet *sheet)
1945 g_return_val_if_fail (sheet != NULL, FALSE);
1946 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1947 return sheet->row_titles_visible;
1953 gtk_sheet_moveto (GtkSheet * sheet,
1960 guint width, height;
1962 gint min_row, min_col;
1964 g_return_if_fail (sheet != NULL);
1965 g_return_if_fail (GTK_IS_SHEET (sheet));
1966 g_return_if_fail (sheet->hadjustment != NULL);
1967 g_return_if_fail (sheet->vadjustment != NULL);
1969 if (row < 0 || row >= yyy_row_count(sheet))
1971 if (column < 0 || column >= xxx_column_count(sheet))
1974 height = sheet->sheet_window_height;
1975 width = sheet->sheet_window_width;
1977 /* adjust vertical scrollbar */
1979 if (row >= 0 && row_align >=0.)
1982 y = ROW_TOP_YPIXEL(sheet, row) - sheet->voffset -
1984 (1.-row_align)*yyy_row_height(sheet, row);
1986 y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
1987 - (gint) ( row_align*height + (1. - row_align) * yyy_row_height(sheet, row));
1989 /* This forces the sheet to scroll when you don't see the entire cell */
1992 if(row_align == 1.){
1993 while(min_row >= 0 && min_row > MIN_VISIBLE_ROW(sheet)){
1994 if(yyy_row_is_visible(sheet, min_row))
1995 adjust += yyy_row_height(sheet, min_row);
1996 if(adjust >= height){
2001 min_row = MAX(min_row, 0);
2002 y = ROW_TOP_YPIXEL(sheet, min_row) - sheet->voffset +
2003 yyy_row_height(sheet, min_row) - 1;
2007 sheet->vadjustment->value = 0.0;
2009 sheet->vadjustment->value = y;
2011 sheet->old_vadjustment = -1.;
2012 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
2017 /* adjust horizontal scrollbar */
2018 if (column >= 0 && col_align >= 0.)
2021 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset -
2023 (1.-col_align)*sheet->column[column].width;
2025 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
2026 - (gint) ( col_align*width + (1.-col_align)*
2027 xxx_column_width(sheet, column));
2030 /* This forces the sheet to scroll when you don't see the entire cell */
2033 if(col_align == 1.){
2034 while(min_col >= 0 && min_col > MIN_VISIBLE_COLUMN(sheet)){
2035 if(xxx_column_is_visible(sheet, min_col))
2036 adjust += xxx_column_width(sheet, min_col);
2038 if(adjust >= width){
2043 min_col = MAX(min_col, 0);
2044 x = COLUMN_LEFT_XPIXEL(sheet, min_col) - sheet->hoffset +
2045 xxx_column_width(sheet, min_col) - 1;
2049 sheet->hadjustment->value = 0.0;
2051 sheet->hadjustment->value = x;
2053 sheet->old_vadjustment = -1.;
2054 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
2062 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
2064 g_return_if_fail (sheet != NULL);
2065 g_return_if_fail (GTK_IS_SHEET (sheet));
2067 sheet->columns_resizable = resizable;
2071 gtk_sheet_columns_resizable (GtkSheet *sheet)
2073 g_return_val_if_fail (sheet != NULL, FALSE);
2074 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2076 return sheet->columns_resizable;
2081 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
2083 g_return_if_fail (sheet != NULL);
2084 g_return_if_fail (GTK_IS_SHEET (sheet));
2086 sheet->rows_resizable = resizable;
2090 gtk_sheet_rows_resizable (GtkSheet *sheet)
2092 g_return_val_if_fail (sheet != NULL, FALSE);
2093 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2095 return sheet->rows_resizable;
2100 gtk_sheet_select_row (GtkSheet * sheet,
2103 g_return_if_fail (sheet != NULL);
2104 g_return_if_fail (GTK_IS_SHEET (sheet));
2106 if (row < 0 || row >= yyy_row_count(sheet))
2109 if(sheet->state != GTK_SHEET_NORMAL)
2110 gtk_sheet_real_unselect_range(sheet, NULL);
2113 gboolean veto = TRUE;
2114 veto = gtk_sheet_deactivate_cell(sheet);
2118 sheet->state=GTK_SHEET_ROW_SELECTED;
2119 sheet->range.row0=row;
2120 sheet->range.col0=0;
2121 sheet->range.rowi=row;
2122 sheet->range.coli = xxx_column_count(sheet) - 1;
2123 sheet->active_cell.row=row;
2124 sheet->active_cell.col=0;
2126 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_ROW], row);
2127 gtk_sheet_real_select_range(sheet, NULL);
2133 gtk_sheet_select_column (GtkSheet * sheet,
2137 g_return_if_fail (sheet != NULL);
2138 g_return_if_fail (GTK_IS_SHEET (sheet));
2140 if (column < 0 || column >= xxx_column_count(sheet))
2143 if(sheet->state != GTK_SHEET_NORMAL)
2144 gtk_sheet_real_unselect_range(sheet, NULL);
2147 gboolean veto = TRUE;
2148 veto = gtk_sheet_deactivate_cell(sheet);
2152 sheet->state=GTK_SHEET_COLUMN_SELECTED;
2153 sheet->range.row0=0;
2154 sheet->range.col0=column;
2155 sheet->range.rowi= yyy_row_count(sheet) - 1;
2156 sheet->range.coli=column;
2157 sheet->active_cell.row=0;
2158 sheet->active_cell.col=column;
2160 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_COLUMN], column);
2161 gtk_sheet_real_select_range(sheet, NULL);
2166 gtk_sheet_clip_range (GtkSheet *sheet, const GtkSheetRange *range)
2169 g_return_if_fail (sheet != NULL);
2170 g_return_if_fail (GTK_IS_SHEET (sheet));
2172 if(GTK_SHEET_IN_CLIP(sheet)) return;
2174 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2177 sheet->clip_range = sheet->range;
2179 sheet->clip_range=*range;
2182 sheet->clip_timer=gtk_timeout_add(TIMEOUT_FLASH, gtk_sheet_flash, sheet);
2184 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CLIP_RANGE],
2185 &sheet->clip_range);
2190 gtk_sheet_unclip_range(GtkSheet *sheet)
2193 g_return_if_fail (sheet != NULL);
2194 g_return_if_fail (GTK_IS_SHEET (sheet));
2196 if(!GTK_SHEET_IN_CLIP(sheet)) return;
2198 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2199 gtk_timeout_remove(sheet->clip_timer);
2200 gtk_sheet_range_draw(sheet, &sheet->clip_range);
2202 if(gtk_sheet_range_isvisible(sheet, sheet->range))
2203 gtk_sheet_range_draw(sheet, &sheet->range);
2207 gtk_sheet_in_clip (GtkSheet *sheet)
2209 g_return_val_if_fail (sheet != NULL, FALSE);
2210 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2212 return GTK_SHEET_IN_CLIP(sheet);
2216 gtk_sheet_flash(gpointer data)
2219 gint x,y,width,height;
2220 GdkRectangle clip_area;
2222 sheet=GTK_SHEET(data);
2224 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return TRUE;
2225 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return TRUE;
2226 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return TRUE;
2227 if(GTK_SHEET_IN_XDRAG(sheet)) return TRUE;
2228 if(GTK_SHEET_IN_YDRAG(sheet)) return TRUE;
2230 GDK_THREADS_ENTER();
2232 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2233 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2234 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2235 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2236 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2237 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2239 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2240 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2241 clip_area.width=sheet->sheet_window_width;
2242 clip_area.height=sheet->sheet_window_height;
2248 if(width>clip_area.width) width=clip_area.width+10;
2253 if(height>clip_area.height) height=clip_area.height+10;
2255 gdk_draw_pixmap(sheet->sheet_window,
2256 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2262 gdk_draw_pixmap(sheet->sheet_window,
2263 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2269 gdk_draw_pixmap(sheet->sheet_window,
2270 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2276 gdk_draw_pixmap(sheet->sheet_window,
2277 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2284 sheet->interval=sheet->interval+1;
2285 if(sheet->interval==TIME_INTERVAL) sheet->interval=0;
2287 gdk_gc_set_dashes(sheet->xor_gc, sheet->interval, (gint8*)"\4\4", 2);
2288 gtk_sheet_draw_flashing_range(sheet,sheet->clip_range);
2289 gdk_gc_set_dashes(sheet->xor_gc, 0, (gint8*)"\4\4", 2);
2291 GDK_THREADS_LEAVE();
2298 gtk_sheet_draw_flashing_range(GtkSheet *sheet, GtkSheetRange range)
2300 GdkRectangle clip_area;
2301 gint x,y,width,height;
2303 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return;
2305 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2306 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2307 clip_area.width=sheet->sheet_window_width;
2308 clip_area.height=sheet->sheet_window_height;
2310 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
2312 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2313 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2314 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2315 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2316 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2317 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2323 if(width>clip_area.width) width=clip_area.width+10;
2328 if(height>clip_area.height) height=clip_area.height+10;
2330 gdk_gc_set_line_attributes(sheet->xor_gc, 1, 1, 0 ,0 );
2332 gdk_draw_rectangle(sheet->sheet_window, sheet->xor_gc, FALSE,
2336 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 0, 0, 0);
2338 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
2343 gtk_sheet_range_isvisible (GtkSheet * sheet,
2344 GtkSheetRange range)
2346 g_return_val_if_fail (sheet != NULL, FALSE);
2348 if (range.row0 < 0 || range.row0 >= yyy_row_count(sheet))
2351 if (range.rowi < 0 || range.rowi >= yyy_row_count(sheet))
2354 if (range.col0 < 0 || range.col0 >= xxx_column_count(sheet))
2357 if (range.coli < 0 || range.coli >= xxx_column_count(sheet))
2360 if (range.rowi < MIN_VISIBLE_ROW (sheet))
2363 if (range.row0 > MAX_VISIBLE_ROW (sheet))
2366 if (range.coli < MIN_VISIBLE_COLUMN (sheet))
2369 if (range.col0 > MAX_VISIBLE_COLUMN (sheet))
2376 gtk_sheet_cell_isvisible (GtkSheet * sheet,
2377 gint row, gint column)
2379 GtkSheetRange range;
2382 range.col0 = column;
2384 range.coli = column;
2386 return gtk_sheet_range_isvisible(sheet, range);
2390 gtk_sheet_get_visible_range(GtkSheet *sheet, GtkSheetRange *range)
2393 g_return_if_fail (sheet != NULL);
2394 g_return_if_fail (GTK_IS_SHEET (sheet)) ;
2395 g_return_if_fail (range != NULL);
2397 range->row0 = MIN_VISIBLE_ROW(sheet);
2398 range->col0 = MIN_VISIBLE_COLUMN(sheet);
2399 range->rowi = MAX_VISIBLE_ROW(sheet);
2400 range->coli = MAX_VISIBLE_COLUMN(sheet);
2405 gtk_sheet_get_vadjustment (GtkSheet * sheet)
2407 g_return_val_if_fail (sheet != NULL, NULL);
2408 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2410 return sheet->vadjustment;
2414 gtk_sheet_get_hadjustment (GtkSheet * sheet)
2416 g_return_val_if_fail (sheet != NULL, NULL);
2417 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2419 return sheet->hadjustment;
2423 gtk_sheet_set_vadjustment (GtkSheet *sheet,
2424 GtkAdjustment *adjustment)
2426 GtkAdjustment *old_adjustment;
2428 g_return_if_fail (sheet != NULL);
2429 g_return_if_fail (GTK_IS_SHEET (sheet));
2431 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2433 if (sheet->vadjustment == adjustment)
2436 old_adjustment = sheet->vadjustment;
2438 if (sheet->vadjustment)
2440 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2441 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2444 sheet->vadjustment = adjustment;
2446 if (sheet->vadjustment)
2448 gtk_object_ref (GTK_OBJECT (sheet->vadjustment));
2449 gtk_object_sink (GTK_OBJECT (sheet->vadjustment));
2451 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "changed",
2452 (GtkSignalFunc) vadjustment_changed,
2454 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "value_changed",
2455 (GtkSignalFunc) vadjustment_value_changed,
2459 if (!sheet->vadjustment || !old_adjustment)
2461 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2465 sheet->old_vadjustment = sheet->vadjustment->value;
2469 gtk_sheet_set_hadjustment (GtkSheet *sheet,
2470 GtkAdjustment *adjustment)
2472 GtkAdjustment *old_adjustment;
2474 g_return_if_fail (sheet != NULL);
2475 g_return_if_fail (GTK_IS_SHEET (sheet));
2477 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2479 if (sheet->hadjustment == adjustment)
2482 old_adjustment = sheet->hadjustment;
2484 if (sheet->hadjustment)
2486 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2487 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2490 sheet->hadjustment = adjustment;
2492 if (sheet->hadjustment)
2494 gtk_object_ref (GTK_OBJECT (sheet->hadjustment));
2495 gtk_object_sink (GTK_OBJECT (sheet->hadjustment));
2497 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "changed",
2498 (GtkSignalFunc) hadjustment_changed,
2500 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "value_changed",
2501 (GtkSignalFunc) hadjustment_value_changed,
2505 if (!sheet->hadjustment || !old_adjustment)
2507 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2511 sheet->old_hadjustment = sheet->hadjustment->value;
2515 gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
2516 GtkAdjustment *hadjustment,
2517 GtkAdjustment *vadjustment)
2519 if(sheet->hadjustment != hadjustment)
2520 gtk_sheet_set_hadjustment (sheet, hadjustment);
2521 if(sheet->vadjustment != vadjustment)
2522 gtk_sheet_set_vadjustment (sheet, vadjustment);
2526 gtk_sheet_finalize (GObject * object)
2530 g_return_if_fail (object != NULL);
2531 g_return_if_fail (GTK_IS_SHEET (object));
2533 sheet = GTK_SHEET (object);
2535 /* get rid of all the cells */
2536 gtk_sheet_range_clear (sheet, NULL);
2537 gtk_sheet_range_delete(sheet, NULL);
2540 g_free(sheet->name);
2544 if (G_OBJECT_CLASS (parent_class)->finalize)
2545 (*G_OBJECT_CLASS (parent_class)->finalize) (object);
2549 gtk_sheet_destroy (GtkObject * object)
2554 g_return_if_fail (object != NULL);
2555 g_return_if_fail (GTK_IS_SHEET (object));
2557 sheet = GTK_SHEET (object);
2559 /* destroy the entry */
2560 if(sheet->sheet_entry && GTK_IS_WIDGET(sheet->sheet_entry)){
2561 gtk_widget_destroy (sheet->sheet_entry);
2562 sheet->sheet_entry = NULL;
2565 /* destroy the global selection button */
2566 if(sheet->button && GTK_IS_WIDGET(sheet->button)){
2567 gtk_widget_destroy (sheet->button);
2568 sheet->button = NULL;
2572 gtk_timeout_remove(sheet->timer);
2576 if(sheet->clip_timer){
2577 gtk_timeout_remove(sheet->clip_timer);
2578 sheet->clip_timer = 0;
2581 /* unref adjustments */
2582 if (sheet->hadjustment)
2584 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2585 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2586 sheet->hadjustment = NULL;
2588 if (sheet->vadjustment)
2590 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2591 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2592 sheet->vadjustment = NULL;
2595 children = sheet->children;
2597 GtkSheetChild *child = (GtkSheetChild *)children->data;
2598 if(child && child->widget)
2599 gtk_sheet_remove(GTK_CONTAINER(sheet), child->widget);
2600 children = sheet->children;
2602 sheet->children = NULL;
2604 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2605 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2609 gtk_sheet_style_set (GtkWidget *widget,
2610 GtkStyle *previous_style)
2614 g_return_if_fail (widget != NULL);
2615 g_return_if_fail (GTK_IS_SHEET (widget));
2617 if (GTK_WIDGET_CLASS (parent_class)->style_set)
2618 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
2620 sheet = GTK_SHEET (widget);
2622 if(GTK_WIDGET_REALIZED(widget))
2624 gtk_style_set_background (widget->style, widget->window, widget->state);
2630 gtk_sheet_realize (GtkWidget * widget)
2633 GdkWindowAttr attributes;
2634 gint attributes_mask;
2635 GdkGCValues values, auxvalues;
2636 GdkColormap *colormap;
2638 GtkSheetChild *child;
2641 g_return_if_fail (widget != NULL);
2642 g_return_if_fail (GTK_IS_SHEET (widget));
2644 sheet = GTK_SHEET (widget);
2646 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2648 attributes.window_type = GDK_WINDOW_CHILD;
2649 attributes.x = widget->allocation.x;
2650 attributes.y = widget->allocation.y;
2651 attributes.width = widget->allocation.width;
2652 attributes.height = widget->allocation.height;
2653 attributes.wclass = GDK_INPUT_OUTPUT;
2655 attributes.visual = gtk_widget_get_visual (widget);
2656 attributes.colormap = gtk_widget_get_colormap (widget);
2658 attributes.event_mask = gtk_widget_get_events (widget);
2659 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2660 GDK_BUTTON_PRESS_MASK |
2661 GDK_BUTTON_RELEASE_MASK |
2662 GDK_KEY_PRESS_MASK |
2663 GDK_POINTER_MOTION_MASK |
2664 GDK_POINTER_MOTION_HINT_MASK);
2665 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
2668 attributes.cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
2671 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2673 gdk_window_set_user_data (widget->window, sheet);
2675 widget->style = gtk_style_attach (widget->style, widget->window);
2677 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2680 if(sheet->row_titles_visible)
2681 attributes.x = sheet->row_title_area.width;
2683 attributes.width = sheet->column_title_area.width;
2684 attributes.height = sheet->column_title_area.height;
2686 /* column-title window */
2687 sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2688 gdk_window_set_user_data (sheet->column_title_window, sheet);
2689 gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL);
2693 if(sheet->column_titles_visible)
2694 attributes.y = sheet->column_title_area.height;
2695 attributes.width = sheet->row_title_area.width;
2696 attributes.height = sheet->row_title_area.height;
2698 /* row-title window */
2699 sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2700 gdk_window_set_user_data (sheet->row_title_window, sheet);
2701 gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL);
2704 attributes.cursor = gdk_cursor_new(GDK_PLUS);
2708 attributes.width = sheet->sheet_window_width,
2709 attributes.height = sheet->sheet_window_height;
2711 sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2712 gdk_window_set_user_data (sheet->sheet_window, sheet);
2714 gdk_cursor_unref(attributes.cursor);
2716 gdk_window_set_background (sheet->sheet_window, &widget->style->white);
2717 gdk_window_show (sheet->sheet_window);
2719 /* backing_pixmap */
2720 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
2724 gdk_gc_unref(sheet->fg_gc);
2726 gdk_gc_unref(sheet->bg_gc);
2727 sheet->fg_gc = gdk_gc_new (widget->window);
2728 sheet->bg_gc = gdk_gc_new (widget->window);
2730 colormap = gtk_widget_get_colormap(widget);
2732 gdk_color_white(colormap, &widget->style->white);
2733 gdk_color_black(colormap, &widget->style->black);
2735 gdk_gc_get_values(sheet->fg_gc, &auxvalues);
2737 values.foreground = widget->style->white;
2738 values.function = GDK_INVERT;
2739 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2741 gdk_gc_unref(sheet->xor_gc);
2742 sheet->xor_gc = gdk_gc_new_with_values (widget->window,
2748 if(sheet->sheet_entry->parent){
2749 gtk_widget_ref(sheet->sheet_entry);
2750 gtk_widget_unparent(sheet->sheet_entry);
2752 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
2753 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
2755 if(sheet->button && sheet->button->parent){
2756 gtk_widget_ref(sheet->button);
2757 gtk_widget_unparent(sheet->button);
2759 gtk_widget_set_parent_window(sheet->button, sheet->sheet_window);
2760 gtk_widget_set_parent(sheet->button, GTK_WIDGET(sheet));
2763 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
2765 if(!sheet->cursor_drag)
2766 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
2768 if(sheet->column_titles_visible)
2769 gdk_window_show(sheet->column_title_window);
2770 if(sheet->row_titles_visible)
2771 gdk_window_show(sheet->row_title_window);
2773 size_allocate_row_title_buttons(sheet);
2774 size_allocate_column_title_buttons(sheet);
2776 name = g_strdup(sheet->name);
2777 gtk_sheet_set_title(sheet, name);
2781 children = sheet->children;
2784 child = children->data;
2785 children = children->next;
2787 gtk_sheet_realize_child(sheet, child);
2792 create_global_button(GtkSheet *sheet)
2794 sheet->button = gtk_button_new_with_label(" ");
2796 gtk_signal_connect (GTK_OBJECT (sheet->button),
2798 (GtkSignalFunc) global_button_clicked,
2803 size_allocate_global_button(GtkSheet *sheet)
2805 GtkAllocation allocation;
2807 if(!sheet->column_titles_visible) return;
2808 if(!sheet->row_titles_visible) return;
2810 gtk_widget_size_request(sheet->button, NULL);
2814 allocation.width=sheet->row_title_area.width;
2815 allocation.height=sheet->column_title_area.height;
2817 gtk_widget_size_allocate(sheet->button, &allocation);
2818 gtk_widget_show(sheet->button);
2822 global_button_clicked(GtkWidget *widget, gpointer data)
2826 gtk_sheet_click_cell(GTK_SHEET(data), -1, -1, &veto);
2827 gtk_widget_grab_focus(GTK_WIDGET(data));
2832 gtk_sheet_unrealize (GtkWidget * widget)
2836 g_return_if_fail (widget != NULL);
2837 g_return_if_fail (GTK_IS_SHEET (widget));
2839 sheet = GTK_SHEET (widget);
2841 gdk_cursor_destroy (sheet->cursor_drag);
2843 gdk_gc_destroy (sheet->xor_gc);
2844 gdk_gc_destroy (sheet->fg_gc);
2845 gdk_gc_destroy (sheet->bg_gc);
2847 gdk_window_destroy (sheet->sheet_window);
2848 gdk_window_destroy (sheet->column_title_window);
2849 gdk_window_destroy (sheet->row_title_window);
2852 g_object_unref(sheet->pixmap);
2853 sheet->pixmap = NULL;
2856 sheet->column_title_window=NULL;
2857 sheet->sheet_window = NULL;
2858 sheet->cursor_drag = NULL;
2859 sheet->xor_gc = NULL;
2860 sheet->fg_gc = NULL;
2861 sheet->bg_gc = NULL;
2863 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2864 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2868 gtk_sheet_map (GtkWidget * widget)
2871 GtkSheetChild *child;
2874 g_return_if_fail (widget != NULL);
2875 g_return_if_fail (GTK_IS_SHEET (widget));
2877 sheet = GTK_SHEET (widget);
2879 if (!GTK_WIDGET_MAPPED (widget))
2881 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2883 if(!sheet->cursor_drag) sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
2885 gdk_window_show (widget->window);
2887 gdk_window_show (sheet->sheet_window);
2889 if(sheet->column_titles_visible){
2890 size_allocate_column_title_buttons(sheet);
2891 gdk_window_show (sheet->column_title_window);
2893 if(sheet->row_titles_visible){
2894 size_allocate_row_title_buttons(sheet);
2895 gdk_window_show (sheet->row_title_window);
2898 if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)
2899 && ! gtk_sheet_locked(sheet)
2900 && sheet->active_cell.row >=0
2901 && sheet->active_cell.col >=0 )
2903 gtk_widget_show (sheet->sheet_entry);
2904 gtk_widget_map (sheet->sheet_entry);
2907 if (GTK_WIDGET_VISIBLE (sheet->button) &&
2908 !GTK_WIDGET_MAPPED (sheet->button)){
2909 gtk_widget_show(sheet->button);
2910 gtk_widget_map (sheet->button);
2913 if(GTK_BIN(sheet->button)->child)
2914 if (GTK_WIDGET_VISIBLE (GTK_BIN(sheet->button)->child) &&
2915 !GTK_WIDGET_MAPPED (GTK_BIN(sheet->button)->child))
2916 gtk_widget_map (GTK_BIN(sheet->button)->child);
2918 gtk_sheet_range_draw(sheet, NULL);
2919 gtk_sheet_activate_cell(sheet,
2920 sheet->active_cell.row,
2921 sheet->active_cell.col);
2923 children = sheet->children;
2926 child = children->data;
2927 children = children->next;
2929 if (GTK_WIDGET_VISIBLE (child->widget) &&
2930 !GTK_WIDGET_MAPPED (child->widget)){
2931 gtk_widget_map (child->widget);
2932 gtk_sheet_position_child(sheet, child);
2940 gtk_sheet_unmap (GtkWidget * widget)
2943 GtkSheetChild *child;
2946 g_return_if_fail (widget != NULL);
2947 g_return_if_fail (GTK_IS_SHEET (widget));
2949 sheet = GTK_SHEET (widget);
2951 if (GTK_WIDGET_MAPPED (widget))
2953 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2955 gdk_window_hide (sheet->sheet_window);
2956 if(sheet->column_titles_visible)
2957 gdk_window_hide (sheet->column_title_window);
2958 if(sheet->row_titles_visible)
2959 gdk_window_hide (sheet->row_title_window);
2960 gdk_window_hide (widget->window);
2962 if (GTK_WIDGET_MAPPED (sheet->sheet_entry))
2963 gtk_widget_unmap (sheet->sheet_entry);
2965 if (GTK_WIDGET_MAPPED (sheet->button))
2966 gtk_widget_unmap (sheet->button);
2968 children = sheet->children;
2971 child = children->data;
2972 children = children->next;
2974 if (GTK_WIDGET_VISIBLE (child->widget) &&
2975 GTK_WIDGET_MAPPED (child->widget))
2977 gtk_widget_unmap (child->widget);
2986 gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
2989 GdkGC *fg_gc, *bg_gc;
2990 GtkSheetCellAttr attributes;
2993 g_return_if_fail (sheet != NULL);
2995 /* bail now if we arn't drawable yet */
2996 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
2998 if (row < 0 || row >= yyy_row_count(sheet)) return;
2999 if (col < 0 || col >= xxx_column_count(sheet)) return;
3000 if (! xxx_column_is_visible(sheet, col)) return;
3001 if (! yyy_row_is_visible(sheet, row)) return;
3003 widget = GTK_WIDGET (sheet);
3005 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3007 /* select GC for background rectangle */
3008 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3009 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3011 fg_gc = sheet->fg_gc;
3012 bg_gc = sheet->bg_gc;
3014 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3015 area.y=ROW_TOP_YPIXEL(sheet,row);
3016 area.width= xxx_column_width(sheet, col);
3017 area.height=yyy_row_height(sheet, row);
3019 gdk_draw_rectangle (sheet->pixmap,
3027 gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0);
3029 if(sheet->show_grid){
3030 gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color);
3032 gdk_draw_rectangle (sheet->pixmap,
3036 area.width, area.height);
3041 gtk_sheet_cell_draw_border (GtkSheet *sheet, gint row, gint col, gint mask)
3044 GdkGC *fg_gc, *bg_gc;
3045 GtkSheetCellAttr attributes;
3049 g_return_if_fail (sheet != NULL);
3051 /* bail now if we arn't drawable yet */
3052 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
3054 if (row < 0 || row >= yyy_row_count(sheet)) return;
3055 if (col < 0 || col >= xxx_column_count(sheet)) return;
3056 if (!xxx_column_is_visible(sheet, col)) return;
3057 if (!yyy_row_is_visible(sheet, row)) return;
3059 widget = GTK_WIDGET (sheet);
3061 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3063 /* select GC for background rectangle */
3064 gdk_gc_set_foreground (sheet->fg_gc, &attributes.border.color);
3065 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3067 fg_gc = sheet->fg_gc;
3068 bg_gc = sheet->bg_gc;
3070 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3071 area.y=ROW_TOP_YPIXEL(sheet,row);
3072 area.width=xxx_column_width(sheet, col);
3073 area.height=yyy_row_height(sheet, row);
3075 width = attributes.border.width;
3076 gdk_gc_set_line_attributes(sheet->fg_gc, attributes.border.width,
3077 attributes.border.line_style,
3078 attributes.border.cap_style,
3079 attributes.border.join_style);
3082 if(attributes.border.mask & GTK_SHEET_LEFT_BORDER & mask)
3083 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3084 area.x, area.y-width/2,
3085 area.x, area.y+area.height+width/2+1);
3087 if(attributes.border.mask & GTK_SHEET_RIGHT_BORDER & mask)
3088 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3089 area.x+area.width, area.y-width/2,
3091 area.y+area.height+width/2+1);
3093 if(attributes.border.mask & GTK_SHEET_TOP_BORDER & mask)
3094 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3095 area.x-width/2,area.y,
3096 area.x+area.width+width/2+1,
3099 if(attributes.border.mask & GTK_SHEET_BOTTOM_BORDER & mask)
3100 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3101 area.x-width/2, area.y+area.height,
3102 area.x+area.width+width/2+1,
3103 area.y+area.height);
3110 gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
3113 GdkRectangle area, clip_area;
3115 gint text_width, text_height, y;
3117 gint size, sizel, sizer;
3118 GdkGC *fg_gc, *bg_gc;
3119 GtkSheetCellAttr attributes;
3120 PangoLayout *layout;
3121 PangoRectangle rect;
3122 PangoRectangle logical_rect;
3123 PangoLayoutLine *line;
3124 PangoFontMetrics *metrics;
3125 PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet));
3126 gint ascent, descent, y_pos;
3130 g_return_if_fail (sheet != NULL);
3132 /* bail now if we aren't drawable yet */
3133 if (!GTK_WIDGET_DRAWABLE (sheet))
3136 label = gtk_sheet_cell_get_text(sheet, row, col);
3140 if (row < 0 || row >= yyy_row_count(sheet)) return;
3141 if (col < 0 || col >= xxx_column_count(sheet)) return;
3142 if (! xxx_column_is_visible(sheet, col)) return;
3143 if (!yyy_row_is_visible(sheet, row)) return;
3146 widget = GTK_WIDGET(sheet);
3148 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3150 /* select GC for background rectangle */
3151 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3152 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3154 fg_gc = sheet->fg_gc;
3155 bg_gc = sheet->bg_gc;
3157 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3158 area.y=ROW_TOP_YPIXEL(sheet,row);
3159 area.width = xxx_column_width(sheet, col);
3160 area.height = yyy_row_height(sheet, row);
3164 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label);
3165 dispose_string(sheet, label);
3166 pango_layout_set_font_description (layout, attributes.font_desc);
3168 pango_layout_get_pixel_extents (layout, NULL, &rect);
3170 line = pango_layout_get_lines (layout)->data;
3171 pango_layout_line_get_extents (line, NULL, &logical_rect);
3173 metrics = pango_context_get_metrics(context,
3174 attributes.font_desc,
3175 pango_context_get_language(context));
3177 ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
3178 descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
3180 pango_font_metrics_unref(metrics);
3182 /* Align primarily for locale's ascent/descent */
3184 logical_rect.height /= PANGO_SCALE;
3185 logical_rect.y /= PANGO_SCALE;
3186 y_pos = area.height - logical_rect.height;
3188 if (logical_rect.height > area.height)
3189 y_pos = (logical_rect.height - area.height - 2*CELLOFFSET) / 2;
3192 else if (y_pos + logical_rect.height > area.height)
3193 y_pos = area.height - logical_rect.height;
3195 text_width = rect.width;
3196 text_height = rect.height;
3197 y = area.y + y_pos - CELLOFFSET;
3199 switch(attributes.justification){
3200 case GTK_JUSTIFY_RIGHT:
3203 if(!gtk_sheet_clip_text(sheet)){
3204 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3205 if( !gtk_sheet_cell_empty(sheet, row, i)) break;
3206 if(size>=text_width+CELLOFFSET) break;
3207 size+=xxx_column_width(sheet, i);
3208 xxx_column_set_right_column(sheet, i,
3210 xxx_column_right_column(sheet, i)));
3215 xoffset+=area.width-text_width - 2 * CELLOFFSET -
3216 attributes.border.width/2;
3218 case GTK_JUSTIFY_CENTER:
3221 area.x+=area.width/2;
3222 if(!gtk_sheet_clip_text(sheet)){
3223 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3224 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3225 if(sizer>=text_width/2) break;
3226 sizer+= xxx_column_width(sheet, i);
3227 xxx_column_set_left_column(sheet, i,
3230 xxx_column_left_column(sheet, i)));
3232 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3233 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3234 if(sizel>=text_width/2) break;
3235 sizel+=xxx_column_width(sheet, i);
3236 xxx_column_set_right_column(sheet, i,
3238 xxx_column_right_column(sheet, i)));
3240 size=MIN(sizel, sizer);
3243 xoffset+= sizel - text_width/2 - CELLOFFSET;
3244 area.width=sizel+sizer;
3246 case GTK_JUSTIFY_LEFT:
3249 if(!gtk_sheet_clip_text(sheet)){
3250 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3251 if(! gtk_sheet_cell_empty(sheet, row, i)) break;
3252 if(size>=text_width+CELLOFFSET) break;
3253 size+=xxx_column_width(sheet, i);
3254 xxx_column_set_left_column(sheet, i,
3257 xxx_column_left_column(sheet, i)));
3262 xoffset += attributes.border.width/2;
3266 if(!gtk_sheet_clip_text(sheet)) clip_area = area;
3267 gdk_gc_set_clip_rectangle(fg_gc, &clip_area);
3270 gdk_draw_layout (sheet->pixmap, fg_gc,
3271 area.x + xoffset + CELLOFFSET,
3275 gdk_gc_set_clip_rectangle(fg_gc, NULL);
3276 g_object_unref(G_OBJECT(layout));
3278 gdk_draw_pixmap(sheet->sheet_window,
3279 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3293 gtk_sheet_range_draw(GtkSheet *sheet, const GtkSheetRange *range)
3296 GtkSheetRange drawing_range;
3299 g_return_if_fail(sheet != NULL);
3300 g_return_if_fail(GTK_SHEET(sheet));
3302 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
3303 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3304 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
3308 drawing_range.row0=MIN_VISIBLE_ROW(sheet);
3309 drawing_range.col0=MIN_VISIBLE_COLUMN(sheet);
3310 drawing_range.rowi=MAX_VISIBLE_ROW(sheet);
3311 drawing_range.coli=MAX_VISIBLE_COLUMN(sheet);
3313 gdk_draw_rectangle (sheet->pixmap,
3314 GTK_WIDGET(sheet)->style->white_gc,
3317 sheet->sheet_window_width,sheet->sheet_window_height);
3322 drawing_range.row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
3323 drawing_range.col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
3324 drawing_range.rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
3325 drawing_range.coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
3329 if(drawing_range.coli == xxx_column_count(sheet) - 1)
3331 area.x=COLUMN_LEFT_XPIXEL(sheet,
3332 xxx_column_count(sheet) - 1) +
3333 xxx_column_width(sheet, xxx_column_count(sheet) - 1) + 1;
3337 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3339 gdk_draw_rectangle (sheet->pixmap,
3343 sheet->sheet_window_width - area.x,
3344 sheet->sheet_window_height);
3346 gdk_draw_pixmap(sheet->sheet_window,
3347 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3353 sheet->sheet_window_width - area.x,
3354 sheet->sheet_window_height);
3357 if(drawing_range.rowi == yyy_row_count(sheet) - 1){
3359 area.y=ROW_TOP_YPIXEL(sheet,
3360 yyy_row_count(sheet) - 1) +
3361 yyy_row_height(sheet, yyy_row_count(sheet) - 1) + 1;
3363 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3365 gdk_draw_rectangle (sheet->pixmap,
3369 sheet->sheet_window_width,
3370 sheet->sheet_window_height - area.y);
3372 gdk_draw_pixmap(sheet->sheet_window,
3373 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3379 sheet->sheet_window_width,
3380 sheet->sheet_window_height - area.y);
3383 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3384 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3385 gtk_sheet_cell_draw_default(sheet, i, j);
3388 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3389 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3390 gtk_sheet_cell_draw_border(sheet, i-1, j, GTK_SHEET_BOTTOM_BORDER);
3391 gtk_sheet_cell_draw_border(sheet, i+1, j, GTK_SHEET_TOP_BORDER);
3392 gtk_sheet_cell_draw_border(sheet, i, j-1, GTK_SHEET_RIGHT_BORDER);
3393 gtk_sheet_cell_draw_border(sheet, i, j+1, GTK_SHEET_LEFT_BORDER);
3394 gtk_sheet_cell_draw_border(sheet, i, j, 15);
3397 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3398 for(j=drawing_range.col0; j<=drawing_range.coli; j++)
3399 gtk_sheet_cell_draw_label (sheet, i, j);
3401 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3402 for(j= xxx_column_left_column(sheet, drawing_range.col0);
3403 j<drawing_range.col0; j++)
3404 gtk_sheet_cell_draw_label (sheet, i, j);
3406 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3407 for(j = drawing_range.coli+1;
3408 j <= xxx_column_right_column(sheet, drawing_range.coli);
3410 gtk_sheet_cell_draw_label (sheet, i, j);
3412 gtk_sheet_draw_backing_pixmap(sheet, drawing_range);
3414 if(sheet->state != GTK_SHEET_NORMAL && gtk_sheet_range_isvisible(sheet, sheet->range))
3415 gtk_sheet_range_draw_selection(sheet, drawing_range);
3417 if(sheet->state == GTK_STATE_NORMAL &&
3418 sheet->active_cell.row >= drawing_range.row0 &&
3419 sheet->active_cell.row <= drawing_range.rowi &&
3420 sheet->active_cell.col >= drawing_range.col0 &&
3421 sheet->active_cell.col <= drawing_range.coli)
3422 gtk_sheet_show_active_cell(sheet);
3427 gtk_sheet_range_draw_selection(GtkSheet *sheet, GtkSheetRange range)
3433 if(range.col0 > sheet->range.coli || range.coli < sheet->range.col0 ||
3434 range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0)
3437 if(!gtk_sheet_range_isvisible(sheet, range)) return;
3438 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3442 range.col0=MAX(sheet->range.col0, range.col0);
3443 range.coli=MIN(sheet->range.coli, range.coli);
3444 range.row0=MAX(sheet->range.row0, range.row0);
3445 range.rowi=MIN(sheet->range.rowi, range.rowi);
3447 range.col0=MAX(range.col0, MIN_VISIBLE_COLUMN(sheet));
3448 range.coli=MIN(range.coli, MAX_VISIBLE_COLUMN(sheet));
3449 range.row0=MAX(range.row0, MIN_VISIBLE_ROW(sheet));
3450 range.rowi=MIN(range.rowi, MAX_VISIBLE_ROW(sheet));
3452 for(i=range.row0; i<=range.rowi; i++){
3453 for(j=range.col0; j<=range.coli; j++){
3455 if(gtk_sheet_cell_get_state(sheet, i, j)==GTK_STATE_SELECTED &&
3456 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
3459 row_button_set(sheet, i);
3460 column_button_set(sheet, j);
3463 area.x=COLUMN_LEFT_XPIXEL(sheet,j);
3464 area.y=ROW_TOP_YPIXEL(sheet,i);
3465 area.width= xxx_column_width(sheet, j);
3466 area.height=yyy_row_height(sheet, i);
3468 if(i==sheet->range.row0){
3470 area.height=area.height-2;
3472 if(i==sheet->range.rowi) area.height=area.height-3;
3473 if(j==sheet->range.col0){
3475 area.width=area.width-2;
3477 if(j==sheet->range.coli) area.width=area.width-3;
3479 if(i!=sheet->active_cell.row || j!=sheet->active_cell.col){
3480 gdk_draw_rectangle (sheet->sheet_window,
3484 area.width,area.height);
3491 gtk_sheet_draw_border(sheet, sheet->range);
3496 gtk_sheet_draw_backing_pixmap(GtkSheet *sheet, GtkSheetRange range)
3498 gint x,y,width,height;
3500 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3502 x = COLUMN_LEFT_XPIXEL(sheet,range.col0);
3503 y = ROW_TOP_YPIXEL(sheet, range.row0);
3504 width = COLUMN_LEFT_XPIXEL(sheet, range.coli) - x +
3505 xxx_column_width(sheet, range.coli);
3507 height=ROW_TOP_YPIXEL(sheet, range.rowi)-y+yyy_row_height(sheet, range.rowi);
3509 if(range.row0==sheet->range.row0){
3513 if(range.rowi==sheet->range.rowi) height=height+5;
3514 if(range.col0==sheet->range.col0){
3518 if(range.coli==sheet->range.coli) width=width+5;
3521 width=MIN(width, sheet->sheet_window_width-x);
3522 height=MIN(height, sheet->sheet_window_height-y);
3529 x = (sheet->row_titles_visible)
3530 ? MAX(x, sheet->row_title_area.width) : MAX(x, 0);
3531 y = (sheet->column_titles_visible)
3532 ? MAX(y, sheet->column_title_area.height) : MAX(y, 0);
3534 if(range.coli == xxx_column_count(sheet) - 1)
3535 width = sheet->sheet_window_width - x;
3536 if(range.rowi == yyy_row_count(sheet) - 1)
3537 height=sheet->sheet_window_height - y;
3539 gdk_draw_pixmap(sheet->sheet_window,
3540 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3552 gtk_sheet_set_cell_text(GtkSheet *sheet, gint row, gint col, const gchar *text)
3554 GtkSheetCellAttr attributes;
3556 g_return_if_fail (sheet != NULL);
3557 g_return_if_fail (GTK_IS_SHEET (sheet));
3558 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3559 if (col < 0 || row < 0) return;
3561 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3562 gtk_sheet_set_cell(sheet, row, col, attributes.justification, text);
3566 safe_strcmp(const gchar *s1, const gchar *s2)
3568 if ( !s1 && !s2) return 0;
3569 if ( !s1) return -1;
3570 if ( !s2) return +1;
3571 return strcmp(s1, s2);
3575 gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col,
3576 GtkJustification justification,
3579 GSheetModel *model ;
3583 GtkSheetRange range;
3585 GtkSheetCellAttr attributes;
3587 g_return_if_fail (sheet != NULL);
3588 g_return_if_fail (GTK_IS_SHEET (sheet));
3589 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3590 if (col < 0 || row < 0) return;
3592 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3594 attributes.justification = justification;
3596 model = gtk_sheet_get_model(sheet);
3598 old_text = g_sheet_model_get_string(model, row, col);
3602 if (0 != safe_strcmp(old_text, text))
3603 changed = g_sheet_model_set_string(model, text, row, col);
3605 if ( g_sheet_model_free_strings(model))
3609 if(changed && attributes.is_visible)
3611 gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
3613 if(s && strlen(s) > 0) {
3614 text_width = STRING_WIDTH(GTK_WIDGET(sheet),
3615 attributes.font_desc, text);
3617 dispose_string(sheet, s);
3621 range.col0 = sheet->view.col0;
3622 range.coli = sheet->view.coli;
3624 if(gtk_sheet_autoresize(sheet) &&
3625 text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
3626 gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width);
3627 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3630 if(!GTK_SHEET_IS_FROZEN(sheet))
3631 gtk_sheet_range_draw(sheet, &range);
3635 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
3641 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
3643 GtkSheetRange range;
3645 g_return_if_fail (sheet != NULL);
3646 g_return_if_fail (GTK_IS_SHEET (sheet));
3647 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3648 if (column < 0 || row < 0) return;
3652 range.col0 = sheet->view.col0;
3653 range.coli = sheet->view.coli;
3655 gtk_sheet_real_cell_clear(sheet, row, column, FALSE);
3657 if(!GTK_SHEET_IS_FROZEN(sheet)){
3658 gtk_sheet_range_draw(sheet, &range);
3663 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
3665 GtkSheetRange range;
3667 g_return_if_fail (sheet != NULL);
3668 g_return_if_fail (GTK_IS_SHEET (sheet));
3669 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3670 if (column < 0 || row < 0) return;
3674 range.col0 = sheet->view.col0;
3675 range.coli = sheet->view.coli;
3677 gtk_sheet_real_cell_clear(sheet, row, column, TRUE);
3679 if(!GTK_SHEET_IS_FROZEN(sheet)){
3680 gtk_sheet_range_draw(sheet, &range);
3685 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
3687 GSheetModel *model = gtk_sheet_get_model(sheet);
3689 gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column);
3691 if (old_text && strlen(old_text) > 0 )
3693 g_sheet_model_datum_clear(model, row, column);
3695 if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0)
3696 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL],
3700 dispose_string (sheet, old_text);
3704 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
3706 g_return_if_fail (sheet != NULL);
3707 g_return_if_fail (GTK_IS_SHEET (sheet));
3709 gtk_sheet_real_range_clear(sheet, range, FALSE);
3713 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range)
3715 g_return_if_fail (sheet != NULL);
3716 g_return_if_fail (GTK_IS_SHEET (sheet));
3718 gtk_sheet_real_range_clear(sheet, range, TRUE);
3723 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
3727 GtkSheetRange clear;
3731 clear.rowi = yyy_row_count(sheet) - 1;
3733 clear.coli = xxx_column_count(sheet) - 1;
3737 clear.row0=MAX(clear.row0, 0);
3738 clear.col0=MAX(clear.col0, 0);
3739 clear.rowi=MIN(clear.rowi, yyy_row_count(sheet) - 1 );
3740 clear.coli=MIN(clear.coli, xxx_column_count(sheet) - 1 );
3742 for(i=clear.row0; i<=clear.rowi; i++)
3743 for(j=clear.col0; j<=clear.coli; j++){
3744 gtk_sheet_real_cell_clear(sheet, i, j, delete);
3747 gtk_sheet_range_draw(sheet, NULL);
3752 gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col)
3755 char *text = gtk_sheet_cell_get_text(sheet, row, col);
3756 empty = (text == NULL );
3758 dispose_string(sheet, text);
3765 gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
3768 g_return_val_if_fail (sheet != NULL, NULL);
3769 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
3771 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet))
3773 if(col < 0 || row < 0) return NULL;
3775 model = gtk_sheet_get_model(sheet);
3780 return g_sheet_model_get_string(model, row, col);
3785 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
3788 GtkSheetRange *range;
3790 g_return_val_if_fail (sheet != NULL, 0);
3791 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3792 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return 0;
3793 if(col < 0 || row < 0) return 0;
3795 state = sheet->state;
3796 range = &sheet->range;
3800 case GTK_SHEET_NORMAL:
3801 return GTK_STATE_NORMAL;
3803 case GTK_SHEET_ROW_SELECTED:
3804 if(row>=range->row0 && row<=range->rowi)
3805 return GTK_STATE_SELECTED;
3807 case GTK_SHEET_COLUMN_SELECTED:
3808 if(col>=range->col0 && col<=range->coli)
3809 return GTK_STATE_SELECTED;
3811 case GTK_SHEET_RANGE_SELECTED:
3812 if(row >= range->row0 && row <= range->rowi && \
3813 col >= range->col0 && col <= range->coli)
3814 return GTK_STATE_SELECTED;
3817 return GTK_STATE_NORMAL;
3821 gtk_sheet_get_pixel_info (GtkSheet * sheet,
3829 g_return_val_if_fail (sheet != NULL, 0);
3830 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3832 /* bounds checking, return false if the user clicked
3833 * on a blank area */
3834 trow = ROW_FROM_YPIXEL (sheet, y);
3835 if (trow >= yyy_row_count(sheet))
3840 tcol = COLUMN_FROM_XPIXEL (sheet, x);
3841 if (tcol >= xxx_column_count(sheet))
3850 gtk_sheet_get_cell_area (GtkSheet * sheet,
3855 g_return_val_if_fail (sheet != NULL, 0);
3856 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3858 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3861 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) -
3862 (sheet->row_titles_visible
3863 ? sheet->row_title_area.width
3865 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL(sheet, row) -
3866 (sheet->column_titles_visible
3867 ? sheet->column_title_area.height
3869 area->width= (column == -1) ? sheet->row_title_area.width
3870 : xxx_column_width(sheet, column);
3872 area->height= (row == -1) ? sheet->column_title_area.height
3873 : yyy_row_height(sheet, row);
3876 if(row < 0 || column < 0) return FALSE;
3878 area->x = COLUMN_LEFT_XPIXEL(sheet, column);
3879 area->y = ROW_TOP_YPIXEL(sheet, row);
3880 if(sheet->row_titles_visible)
3881 area->x -= sheet->row_title_area.width;
3882 if(sheet->column_titles_visible)
3883 area->y -= sheet->column_title_area.height;
3885 area->width=sheet->column[column].width;
3886 area->height=yyy_row_height(sheet, row);
3892 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
3894 g_return_val_if_fail (sheet != NULL, 0);
3895 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3897 if(row < -1 || column < -1) return FALSE;
3898 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3901 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
3903 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
3906 sheet->active_cell.row = row;
3907 sheet->active_cell.col = column;
3909 if ( row == -1 || column == -1)
3911 gtk_sheet_hide_active_cell(sheet);
3915 if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE;
3917 if(gtk_sheet_autoscroll(sheet))
3918 gtk_sheet_move_query(sheet, row, column);
3924 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column)
3926 g_return_if_fail (sheet != NULL);
3927 g_return_if_fail (GTK_IS_SHEET (sheet));
3929 *row = sheet->active_cell.row;
3930 *column = sheet->active_cell.col;
3934 gtk_sheet_entry_changed(GtkWidget *widget, gpointer data)
3939 GtkJustification justification;
3940 GtkSheetCellAttr attributes;
3942 g_return_if_fail (data != NULL);
3943 g_return_if_fail (GTK_IS_SHEET (data));
3945 sheet=GTK_SHEET(data);
3947 if(!GTK_WIDGET_VISIBLE(widget)) return;
3948 if(sheet->state != GTK_STATE_NORMAL) return;
3950 row=sheet->active_cell.row;
3951 col=sheet->active_cell.col;
3953 if(row<0 || col<0) return;
3955 sheet->active_cell.row=-1;
3956 sheet->active_cell.col=-1;
3958 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3960 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3962 if(text && strlen(text) > 0){
3963 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3964 justification=attributes.justification;
3965 gtk_sheet_set_cell(sheet, row, col, justification, text);
3968 if(sheet->freeze_count == 0)
3969 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3971 sheet->active_cell.row=row;;
3972 sheet->active_cell.col=col;
3977 gtk_sheet_deactivate_cell(GtkSheet *sheet)
3979 gboolean veto = TRUE;
3981 g_return_val_if_fail (sheet != NULL, FALSE);
3982 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
3984 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return FALSE;
3985 if(sheet->state != GTK_SHEET_NORMAL) return FALSE;
3987 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[DEACTIVATE],
3988 sheet->active_cell.row,
3989 sheet->active_cell.col, &veto);
3991 if(!veto) return FALSE;
3993 if ( sheet->active_cell.row == -1 || sheet->active_cell.col == -1 )
3996 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
3997 (GtkSignalFunc) gtk_sheet_entry_changed,
3998 GTK_OBJECT(GTK_WIDGET(sheet)));
4000 gtk_sheet_hide_active_cell(sheet);
4001 sheet->active_cell.row = -1;
4002 sheet->active_cell.col = -1;
4004 if(GTK_SHEET_REDRAW_PENDING(sheet)){
4005 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
4006 gtk_sheet_range_draw(sheet, NULL);
4013 gtk_sheet_hide_active_cell(GtkSheet *sheet)
4017 GtkJustification justification;
4018 GtkSheetCellAttr attributes;
4020 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4022 row=sheet->active_cell.row;
4023 col=sheet->active_cell.col;
4025 if(row < 0 || col < 0) return;
4027 if(sheet->freeze_count == 0)
4028 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
4030 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
4032 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4033 justification=attributes.justification;
4035 if(text && strlen(text)!=0){
4036 gtk_sheet_set_cell(sheet, row, col, justification, text);
4037 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col);
4038 gtk_entry_set_text(GTK_ENTRY(sheet->sheet_entry), "");
4042 gtk_sheet_cell_clear(sheet, row, col);
4045 row=sheet->active_cell.row;
4046 col=sheet->active_cell.col;
4049 column_button_release(sheet, col);
4050 row_button_release(sheet, row);
4053 gtk_widget_hide(sheet->sheet_entry);
4054 gtk_widget_unmap(sheet->sheet_entry);
4056 if(row != -1 && col != -1)
4057 gdk_draw_pixmap(sheet->sheet_window,
4058 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4060 COLUMN_LEFT_XPIXEL(sheet,col)-1,
4061 ROW_TOP_YPIXEL(sheet,row)-1,
4062 COLUMN_LEFT_XPIXEL(sheet,col)-1,
4063 ROW_TOP_YPIXEL(sheet,row)-1,
4064 xxx_column_width(sheet, col) + 4,
4065 yyy_row_height(sheet, row)+4);
4067 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4069 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4074 gtk_sheet_activate_cell(GtkSheet *sheet, gint row, gint col)
4076 gboolean veto = TRUE;
4078 g_return_val_if_fail (sheet != NULL, FALSE);
4079 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
4081 if(row < 0 || col < 0) return FALSE;
4082 if(row >= yyy_row_count(sheet) || col >= xxx_column_count(sheet))
4085 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4086 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
4089 if(!veto) return FALSE;
4090 if(sheet->state != GTK_SHEET_NORMAL){
4091 sheet->state=GTK_SHEET_NORMAL;
4092 gtk_sheet_real_unselect_range(sheet, NULL);
4095 sheet->range.row0=row;
4096 sheet->range.col0=col;
4097 sheet->range.rowi=row;
4098 sheet->range.coli=col;
4099 sheet->active_cell.row=row;
4100 sheet->active_cell.col=col;
4101 sheet->selection_cell.row=row;
4102 sheet->selection_cell.col=col;
4104 row_button_set(sheet, row);
4105 column_button_set(sheet, col);
4108 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4109 gtk_sheet_show_active_cell(sheet);
4111 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
4113 G_CALLBACK(gtk_sheet_entry_changed),
4116 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4122 gtk_sheet_show_active_cell(GtkSheet *sheet)
4124 GtkEntry *sheet_entry;
4125 GtkSheetCellAttr attributes;
4127 const gchar *old_text;
4128 GtkJustification justification;
4131 g_return_if_fail (sheet != NULL);
4132 g_return_if_fail (GTK_IS_SHEET (sheet));
4134 row = sheet->active_cell.row;
4135 col = sheet->active_cell.col;
4137 /* Don't show the active cell, if there is no active cell: */
4138 if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */
4141 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4142 if(sheet->state != GTK_SHEET_NORMAL) return;
4143 if(GTK_SHEET_IN_SELECTION(sheet)) return;
4145 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4147 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
4149 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4151 justification = GTK_JUSTIFY_LEFT;
4153 if(gtk_sheet_justify_entry(sheet))
4154 justification = attributes.justification;
4156 text = gtk_sheet_cell_get_text(sheet, row, col);
4158 text = g_strdup("");
4160 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible);
4162 if(gtk_sheet_locked(sheet) || !attributes.is_editable)
4163 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
4165 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
4167 /*** Added by John Gotts. Mar 25, 2005 *********/
4168 old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
4169 if (strcmp(old_text, text) != 0)
4171 if(!GTK_IS_ITEM_ENTRY(sheet_entry))
4172 gtk_entry_set_text(GTK_ENTRY(sheet_entry), text);
4174 gtk_item_entry_set_text(GTK_ITEM_ENTRY(sheet_entry), text, justification);
4177 gtk_sheet_entry_set_max_size(sheet);
4178 gtk_sheet_size_allocate_entry(sheet);
4180 gtk_widget_map(sheet->sheet_entry);
4181 gtk_sheet_draw_active_cell(sheet);
4183 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
4185 dispose_string(sheet, text);
4189 gtk_sheet_draw_active_cell(GtkSheet *sheet)
4193 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
4194 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4196 row = sheet->active_cell.row;
4197 col = sheet->active_cell.col;
4199 if(row < 0 || col < 0) return;
4201 if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
4203 row_button_set(sheet, row);
4204 column_button_set(sheet, col);
4206 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4207 gtk_sheet_draw_border(sheet, sheet->range);
4212 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
4214 gint pixmap_width, pixmap_height;
4216 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4218 if(width == 0 && height == 0){
4219 width=sheet->sheet_window_width+80;
4220 height=sheet->sheet_window_height+80;
4226 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4229 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4233 /* reallocate if sizes don't match */
4234 gdk_window_get_size (sheet->pixmap,
4235 &pixmap_width, &pixmap_height);
4236 if ((pixmap_width != width) || (pixmap_height != height))
4238 g_object_unref(sheet->pixmap);
4239 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4242 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4248 gtk_sheet_new_selection(GtkSheet *sheet, GtkSheetRange *range)
4250 gint i,j, mask1, mask2;
4251 gint state, selected;
4252 gint x,y,width,height;
4253 GtkSheetRange new_range, aux_range;
4255 g_return_if_fail (sheet != NULL);
4257 if(range==NULL) range=&sheet->range;
4261 range->row0=MIN(range->row0, sheet->range.row0);
4262 range->rowi=MAX(range->rowi, sheet->range.rowi);
4263 range->col0=MIN(range->col0, sheet->range.col0);
4264 range->coli=MAX(range->coli, sheet->range.coli);
4266 range->row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
4267 range->rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
4268 range->col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
4269 range->coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
4271 aux_range.row0=MAX(new_range.row0, MIN_VISIBLE_ROW(sheet));
4272 aux_range.rowi=MIN(new_range.rowi, MAX_VISIBLE_ROW(sheet));
4273 aux_range.col0=MAX(new_range.col0, MIN_VISIBLE_COLUMN(sheet));
4274 aux_range.coli=MIN(new_range.coli, MAX_VISIBLE_COLUMN(sheet));
4276 for(i=range->row0; i<=range->rowi; i++){
4277 for(j=range->col0; j<=range->coli; j++){
4279 state=gtk_sheet_cell_get_state(sheet, i, j);
4280 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4281 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4283 if(state==GTK_STATE_SELECTED && selected &&
4284 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4285 (i==sheet->range.row0 || i==sheet->range.rowi ||
4286 j==sheet->range.col0 || j==sheet->range.coli ||
4287 i==new_range.row0 || i==new_range.rowi ||
4288 j==new_range.col0 || j==new_range.coli)){
4290 mask1 = i==sheet->range.row0 ? 1 : 0;
4291 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4292 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4293 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4295 mask2 = i==new_range.row0 ? 1 : 0;
4296 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4297 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4298 mask2 = j==new_range.coli ? mask2+8 : mask2;
4301 x=COLUMN_LEFT_XPIXEL(sheet,j);
4302 y=ROW_TOP_YPIXEL(sheet, i);
4303 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4304 xxx_column_width(sheet, j);
4305 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4307 if(i==sheet->range.row0){
4311 if(i==sheet->range.rowi) height=height+3;
4312 if(j==sheet->range.col0){
4316 if(j==sheet->range.coli) width=width+3;
4318 gdk_draw_pixmap(sheet->sheet_window,
4319 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4328 if(i != sheet->active_cell.row || j != sheet->active_cell.col){
4329 x=COLUMN_LEFT_XPIXEL(sheet,j);
4330 y=ROW_TOP_YPIXEL(sheet, i);
4331 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4332 xxx_column_width(sheet, j);
4334 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4336 if(i==new_range.row0){
4340 if(i==new_range.rowi) height=height-3;
4341 if(j==new_range.col0){
4345 if(j==new_range.coli) width=width-3;
4347 gdk_draw_rectangle (sheet->sheet_window,
4358 for(i=range->row0; i<=range->rowi; i++){
4359 for(j=range->col0; j<=range->coli; j++){
4361 state=gtk_sheet_cell_get_state(sheet, i, j);
4362 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4363 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4365 if(state==GTK_STATE_SELECTED && !selected &&
4366 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4368 x=COLUMN_LEFT_XPIXEL(sheet,j);
4369 y=ROW_TOP_YPIXEL(sheet, i);
4370 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4371 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4373 if(i==sheet->range.row0){
4377 if(i==sheet->range.rowi) height=height+3;
4378 if(j==sheet->range.col0){
4382 if(j==sheet->range.coli) width=width+3;
4384 gdk_draw_pixmap(sheet->sheet_window,
4385 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4397 for(i=range->row0; i<=range->rowi; i++){
4398 for(j=range->col0; j<=range->coli; j++){
4400 state=gtk_sheet_cell_get_state(sheet, i, j);
4401 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4402 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4404 if(state!=GTK_STATE_SELECTED && selected &&
4405 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4406 (i != sheet->active_cell.row || j != sheet->active_cell.col)){
4408 x=COLUMN_LEFT_XPIXEL(sheet,j);
4409 y=ROW_TOP_YPIXEL(sheet, i);
4410 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4411 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4413 if(i==new_range.row0){
4417 if(i==new_range.rowi) height=height-3;
4418 if(j==new_range.col0){
4422 if(j==new_range.coli) width=width-3;
4424 gdk_draw_rectangle (sheet->sheet_window,
4435 for(i=aux_range.row0; i<=aux_range.rowi; i++){
4436 for(j=aux_range.col0; j<=aux_range.coli; j++){
4438 if(xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4440 state=gtk_sheet_cell_get_state(sheet, i, j);
4442 mask1 = i==sheet->range.row0 ? 1 : 0;
4443 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4444 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4445 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4447 mask2 = i==new_range.row0 ? 1 : 0;
4448 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4449 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4450 mask2 = j==new_range.coli ? mask2+8 : mask2;
4451 if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){
4452 x=COLUMN_LEFT_XPIXEL(sheet,j);
4453 y=ROW_TOP_YPIXEL(sheet, i);
4454 width=xxx_column_width(sheet, j);
4455 height=yyy_row_height(sheet, i);
4457 gdk_draw_rectangle (sheet->sheet_window,
4465 gdk_draw_rectangle (sheet->sheet_window,
4472 gdk_draw_rectangle (sheet->sheet_window,
4480 gdk_draw_rectangle (sheet->sheet_window,
4497 gtk_sheet_draw_corners(sheet, new_range);
4502 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
4507 gint x,y,width,height;
4509 widget = GTK_WIDGET(sheet);
4511 x=COLUMN_LEFT_XPIXEL(sheet,new_range.col0);
4512 y=ROW_TOP_YPIXEL(sheet,new_range.row0);
4513 width=COLUMN_LEFT_XPIXEL(sheet,new_range.coli)-x+
4514 xxx_column_width(sheet, new_range.coli);
4516 height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+
4517 yyy_row_height(sheet, new_range.rowi);
4519 area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
4520 area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
4521 area.width=sheet->sheet_window_width;
4522 area.height=sheet->sheet_window_height;
4528 if(width>area.width) width=area.width+10;
4533 if(height>area.height) height=area.height+10;
4535 gdk_gc_set_clip_rectangle(sheet->xor_gc, &area);
4537 for(i=-1; i<=1; ++i)
4538 gdk_draw_rectangle (sheet->sheet_window,
4542 width-2*i,height-2*i);
4544 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
4546 gtk_sheet_draw_corners(sheet, new_range);
4551 gtk_sheet_draw_corners(GtkSheet *sheet, GtkSheetRange range)
4556 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.col0)){
4557 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4558 y=ROW_TOP_YPIXEL(sheet,range.row0);
4559 gdk_draw_pixmap(sheet->sheet_window,
4560 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4568 gdk_draw_rectangle (sheet->sheet_window,
4575 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) ||
4576 sheet->state == GTK_SHEET_COLUMN_SELECTED){
4577 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4578 xxx_column_width(sheet, range.coli);
4579 y=ROW_TOP_YPIXEL(sheet,range.row0);
4581 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
4583 y = ROW_TOP_YPIXEL(sheet, sheet->view.row0)+3;
4586 gdk_draw_pixmap(sheet->sheet_window,
4587 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4595 gdk_draw_rectangle (sheet->sheet_window,
4598 x-width+width/2,y-width+width/2,
4602 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.col0) ||
4603 sheet->state == GTK_SHEET_ROW_SELECTED){
4604 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4605 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4606 yyy_row_height(sheet, range.rowi);
4608 if(sheet->state == GTK_SHEET_ROW_SELECTED)
4610 x = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0)+3;
4613 gdk_draw_pixmap(sheet->sheet_window,
4614 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4622 gdk_draw_rectangle (sheet->sheet_window,
4625 x-width+width/2,y-width+width/2,
4629 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){
4630 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4631 xxx_column_width(sheet, range.coli);
4632 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4633 yyy_row_height(sheet, range.rowi);
4635 if(sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
4636 if(sheet->state == GTK_SHEET_NORMAL) width = 3;
4637 gdk_draw_pixmap(sheet->sheet_window,
4638 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4646 gdk_draw_rectangle (sheet->sheet_window,
4649 x-width+width/2,y-width+width/2,
4658 gtk_sheet_real_select_range (GtkSheet * sheet,
4659 GtkSheetRange * range)
4663 g_return_if_fail (sheet != NULL);
4665 if(range==NULL) range=&sheet->range;
4667 if(range->row0 < 0 || range->rowi < 0) return;
4668 if(range->col0 < 0 || range->coli < 0) return;
4673 if(state==GTK_SHEET_COLUMN_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4674 for(i=sheet->range.col0; i< range->col0; i++)
4675 column_button_release(sheet, i);
4676 for(i=range->coli+1; i<= sheet->range.coli; i++)
4677 column_button_release(sheet, i);
4678 for(i=range->col0; i<=range->coli; i++){
4679 column_button_set(sheet, i);
4683 if(state==GTK_SHEET_ROW_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4684 for(i=sheet->range.row0; i< range->row0; i++)
4685 row_button_release(sheet, i);
4686 for(i=range->rowi+1; i<= sheet->range.rowi; i++)
4687 row_button_release(sheet, i);
4688 for(i=range->row0; i<=range->rowi; i++){
4689 row_button_set(sheet, i);
4694 if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
4695 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
4698 gtk_sheet_new_selection(sheet, range);
4700 sheet->range.col0=range->col0;
4701 sheet->range.coli=range->coli;
4702 sheet->range.row0=range->row0;
4703 sheet->range.rowi=range->rowi;
4708 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4709 gtk_sheet_range_draw_selection(sheet, sheet->range);
4712 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[SELECT_RANGE], range);
4716 gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range)
4718 g_return_if_fail (sheet != NULL);
4720 if(range==NULL) range=&sheet->range;
4722 if(range->row0 < 0 || range->rowi < 0) return;
4723 if(range->col0 < 0 || range->coli < 0) return;
4726 if ( gtk_sheet_locked(sheet)) return ;
4728 if(sheet->state != GTK_SHEET_NORMAL)
4729 gtk_sheet_real_unselect_range(sheet, NULL);
4732 gboolean veto = TRUE;
4733 veto = gtk_sheet_deactivate_cell(sheet);
4737 sheet->range.row0=range->row0;
4738 sheet->range.rowi=range->rowi;
4739 sheet->range.col0=range->col0;
4740 sheet->range.coli=range->coli;
4741 sheet->active_cell.row=range->row0;
4742 sheet->active_cell.col=range->col0;
4743 sheet->selection_cell.row=range->rowi;
4744 sheet->selection_cell.col=range->coli;
4746 sheet->state = GTK_SHEET_RANGE_SELECTED;
4747 gtk_sheet_real_select_range(sheet, NULL);
4752 gtk_sheet_unselect_range (GtkSheet * sheet)
4754 gtk_sheet_real_unselect_range(sheet, NULL);
4755 sheet->state = GTK_STATE_NORMAL;
4756 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
4761 gtk_sheet_real_unselect_range (GtkSheet * sheet,
4762 const GtkSheetRange *range)
4764 g_return_if_fail (sheet != NULL);
4765 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)));
4768 range=&sheet->range;
4771 if(range->row0 < 0 || range->rowi < 0) return;
4772 if(range->col0 < 0 || range->coli < 0) return;
4774 if (gtk_sheet_range_isvisible (sheet, *range)){
4775 gtk_sheet_draw_backing_pixmap(sheet, *range);
4779 for(i=range->col0; i<=range->coli; i++){
4780 column_button_release(sheet, i);
4783 for(i=range->row0; i<=range->rowi; i++){
4784 row_button_release(sheet, i);
4788 gtk_sheet_position_children(sheet);
4793 gtk_sheet_expose (GtkWidget * widget,
4794 GdkEventExpose * event)
4797 GtkSheetRange range;
4799 g_return_val_if_fail (widget != NULL, FALSE);
4800 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4801 g_return_val_if_fail (event != NULL, FALSE);
4803 sheet = GTK_SHEET (widget);
4805 if (GTK_WIDGET_DRAWABLE (widget))
4807 range.row0=ROW_FROM_YPIXEL(sheet,event->area.y);
4808 range.col0=COLUMN_FROM_XPIXEL(sheet,event->area.x);
4809 range.rowi=ROW_FROM_YPIXEL(sheet,event->area.y+event->area.height);
4810 range.coli=COLUMN_FROM_XPIXEL(sheet,event->area.x+event->area.width);
4812 /* exposure events on the sheet */
4814 if(event->window == sheet->row_title_window && sheet->row_titles_visible){
4816 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
4817 gtk_sheet_button_draw(sheet,i,-1);
4820 if(event->window == sheet->column_title_window && sheet->column_titles_visible){
4822 for(i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
4823 gtk_sheet_button_draw(sheet,-1,i);
4826 if (event->window == sheet->sheet_window){
4827 gtk_sheet_draw_backing_pixmap(sheet, range);
4829 if(sheet->state != GTK_SHEET_NORMAL){
4830 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4831 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4832 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4833 gtk_sheet_draw_backing_pixmap(sheet, sheet->drag_range);
4835 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4836 gtk_sheet_range_draw_selection(sheet, sheet->range);
4837 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4838 draw_xor_rectangle(sheet, sheet->drag_range);
4841 if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet))){
4842 if(sheet->state == GTK_SHEET_NORMAL){
4843 gtk_sheet_draw_active_cell(sheet);
4844 if(!GTK_SHEET_IN_SELECTION(sheet))
4845 gtk_widget_queue_draw(sheet->sheet_entry);
4854 if(sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet))
4855 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4857 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
4864 gtk_sheet_button_press (GtkWidget * widget,
4865 GdkEventButton * event)
4868 GdkModifierType mods;
4869 gint x, y, row, column;
4872 g_return_val_if_fail (widget != NULL, FALSE);
4873 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4874 g_return_val_if_fail (event != NULL, FALSE);
4876 sheet = GTK_SHEET (widget);
4878 if ( event->type == GDK_2BUTTON_PRESS)
4880 gtk_widget_get_pointer (widget, &x, &y);
4881 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4883 if (event->window == sheet->column_title_window )
4885 gtk_signal_emit (GTK_OBJECT (sheet),
4886 sheet_signals[DOUBLE_CLICK_COLUMN], column);
4888 else if (event->window == sheet->row_title_window )
4890 gtk_signal_emit (GTK_OBJECT (sheet),
4891 sheet_signals[DOUBLE_CLICK_ROW], row);
4897 if(event->type != GDK_BUTTON_PRESS) return TRUE;
4899 gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
4901 if(!(mods & GDK_BUTTON1_MASK)) return TRUE;
4904 /* press on resize windows */
4905 if (event->window == sheet->column_title_window &&
4906 gtk_sheet_columns_resizable(sheet))
4908 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
4909 if(POSSIBLE_XDRAG(sheet, sheet->x_drag, &sheet->drag_cell.col)){
4911 if (event->type == GDK_2BUTTON_PRESS){
4912 gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
4913 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_XDRAG);
4916 gtk_sheet_column_size_request(sheet, sheet->drag_cell.col, &req);
4917 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4918 gdk_pointer_grab (sheet->column_title_window, FALSE,
4919 GDK_POINTER_MOTION_HINT_MASK |
4920 GDK_BUTTON1_MOTION_MASK |
4921 GDK_BUTTON_RELEASE_MASK,
4922 NULL, NULL, event->time);
4924 draw_xor_vline (sheet);
4929 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet))
4931 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
4933 if(POSSIBLE_YDRAG(sheet, sheet->y_drag, &sheet->drag_cell.row)){
4935 gtk_sheet_row_size_request(sheet, sheet->drag_cell.row, &req);
4936 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
4937 gdk_pointer_grab (sheet->row_title_window, FALSE,
4938 GDK_POINTER_MOTION_HINT_MASK |
4939 GDK_BUTTON1_MOTION_MASK |
4940 GDK_BUTTON_RELEASE_MASK,
4941 NULL, NULL, event->time);
4943 draw_xor_hline (sheet);
4948 /* the sheet itself does not handle other than single click events */
4949 if(event->type != GDK_BUTTON_PRESS) return FALSE;
4951 /* selections on the sheet */
4952 if(event->window == sheet->sheet_window){
4953 gtk_widget_get_pointer (widget, &x, &y);
4954 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4955 gdk_pointer_grab (sheet->sheet_window, FALSE,
4956 GDK_POINTER_MOTION_HINT_MASK |
4957 GDK_BUTTON1_MOTION_MASK |
4958 GDK_BUTTON_RELEASE_MASK,
4959 NULL, NULL, event->time);
4960 gtk_grab_add(GTK_WIDGET(sheet));
4961 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4962 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4964 if(sheet->selection_mode != GTK_SELECTION_SINGLE &&
4965 sheet->cursor_drag->type==GDK_SIZING &&
4966 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_RESIZE(sheet)){
4967 if(sheet->state==GTK_STATE_NORMAL) {
4968 row=sheet->active_cell.row;
4969 column=sheet->active_cell.col;
4970 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4971 sheet->active_cell.row=row;
4972 sheet->active_cell.col=column;
4973 sheet->drag_range=sheet->range;
4974 sheet->state=GTK_SHEET_RANGE_SELECTED;
4975 gtk_sheet_select_range(sheet, &sheet->drag_range);
4979 if(row > sheet->range.rowi) row--;
4980 if(column > sheet->range.coli) column--;
4981 sheet->drag_cell.row = row;
4982 sheet->drag_cell.col = column;
4983 sheet->drag_range=sheet->range;
4984 draw_xor_rectangle(sheet, sheet->drag_range);
4985 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
4987 else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW &&
4988 !GTK_SHEET_IN_SELECTION(sheet)
4989 && ! GTK_SHEET_IN_DRAG(sheet)
4990 && ! gtk_sheet_locked(sheet)
4991 && sheet->active_cell.row >= 0
4992 && sheet->active_cell.col >= 0
4995 if(sheet->state==GTK_STATE_NORMAL) {
4996 row=sheet->active_cell.row;
4997 column=sheet->active_cell.col;
4998 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4999 sheet->active_cell.row=row;
5000 sheet->active_cell.col=column;
5001 sheet->drag_range=sheet->range;
5002 sheet->state=GTK_SHEET_RANGE_SELECTED;
5003 gtk_sheet_select_range(sheet, &sheet->drag_range);
5007 if(row < sheet->range.row0) row++;
5008 if(row > sheet->range.rowi) row--;
5009 if(column < sheet->range.col0) column++;
5010 if(column > sheet->range.coli) column--;
5011 sheet->drag_cell.row=row;
5012 sheet->drag_cell.col=column;
5013 sheet->drag_range=sheet->range;
5014 draw_xor_rectangle(sheet, sheet->drag_range);
5015 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5019 gtk_sheet_click_cell(sheet, row, column, &veto);
5020 if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5024 if(event->window == sheet->column_title_window){
5025 gtk_widget_get_pointer (widget, &x, &y);
5026 column = COLUMN_FROM_XPIXEL(sheet, x);
5027 if(xxx_column_is_sensitive(sheet, column)){
5028 gtk_sheet_click_cell(sheet, -1, column, &veto);
5029 gtk_grab_add(GTK_WIDGET(sheet));
5030 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5031 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5032 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5036 if(event->window == sheet->row_title_window){
5037 gtk_widget_get_pointer (widget, &x, &y);
5038 row = ROW_FROM_YPIXEL(sheet, y);
5039 if(yyy_row_is_sensitive(sheet, row)){
5040 gtk_sheet_click_cell(sheet, row, -1, &veto);
5041 gtk_grab_add(GTK_WIDGET(sheet));
5042 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5043 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5044 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5052 gtk_sheet_scroll(gpointer data)
5055 gint x,y,row,column;
5058 sheet=GTK_SHEET(data);
5060 GDK_THREADS_ENTER();
5062 gtk_widget_get_pointer (GTK_WIDGET(sheet), &x, &y);
5063 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5067 if(GTK_SHEET_IN_SELECTION(sheet))
5068 gtk_sheet_extend_selection(sheet, row, column);
5070 if(GTK_SHEET_IN_DRAG(sheet) || GTK_SHEET_IN_RESIZE(sheet)){
5071 move=gtk_sheet_move_query(sheet, row, column);
5072 if(move) draw_xor_rectangle(sheet, sheet->drag_range);
5075 GDK_THREADS_LEAVE();
5082 gtk_sheet_click_cell(GtkSheet *sheet, gint row, gint column, gboolean *veto)
5086 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)){
5091 if(column >= 0 && row >= 0)
5092 if(! xxx_column_is_visible(sheet, column) || !yyy_row_is_visible(sheet, row))
5098 _gtkextra_signal_emit(GTK_OBJECT(sheet), sheet_signals[TRAVERSE],
5099 sheet->active_cell.row, sheet->active_cell.col,
5100 &row, &column, veto);
5103 if(sheet->state == GTK_STATE_NORMAL) return;
5105 row = sheet->active_cell.row;
5106 column = sheet->active_cell.col;
5108 gtk_sheet_activate_cell(sheet, row, column);
5112 if(row == -1 && column >= 0){
5113 if(gtk_sheet_autoscroll(sheet))
5114 gtk_sheet_move_query(sheet, row, column);
5115 gtk_sheet_select_column(sheet, column);
5118 if(column == -1 && row >= 0){
5119 if(gtk_sheet_autoscroll(sheet))
5120 gtk_sheet_move_query(sheet, row, column);
5121 gtk_sheet_select_row(sheet, row);
5125 if(row==-1 && column ==-1){
5126 sheet->range.row0=0;
5127 sheet->range.col0=0;
5128 sheet->range.rowi = yyy_row_count(sheet) - 1;
5129 sheet->range.coli = xxx_column_count(sheet) - 1;
5130 sheet->active_cell.row=0;
5131 sheet->active_cell.col=0;
5132 gtk_sheet_select_range(sheet, NULL);
5136 if(row!=-1 && column !=-1){
5137 if(sheet->state != GTK_SHEET_NORMAL){
5138 sheet->state = GTK_SHEET_NORMAL;
5139 gtk_sheet_real_unselect_range(sheet, NULL);
5143 if(!gtk_sheet_deactivate_cell(sheet)){
5149 if(gtk_sheet_autoscroll(sheet))
5150 gtk_sheet_move_query(sheet, row, column);
5151 sheet->active_cell.row=row;
5152 sheet->active_cell.col=column;
5153 sheet->selection_cell.row=row;
5154 sheet->selection_cell.col=column;
5155 sheet->range.row0=row;
5156 sheet->range.col0=column;
5157 sheet->range.rowi=row;
5158 sheet->range.coli=column;
5159 sheet->state=GTK_SHEET_NORMAL;
5160 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5161 gtk_sheet_draw_active_cell(sheet);
5165 g_assert_not_reached();
5166 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5167 sheet->active_cell.col);
5171 gtk_sheet_button_release (GtkWidget * widget,
5172 GdkEventButton * event)
5177 sheet=GTK_SHEET(widget);
5179 /* release on resize windows */
5180 if (GTK_SHEET_IN_XDRAG (sheet)){
5181 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
5182 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5183 gtk_widget_get_pointer (widget, &x, NULL);
5184 gdk_pointer_ungrab (event->time);
5185 draw_xor_vline (sheet);
5187 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col, new_column_width (sheet, sheet->drag_cell.col, &x));
5188 sheet->old_hadjustment = -1.;
5189 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed");
5193 if (GTK_SHEET_IN_YDRAG (sheet)){
5194 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5195 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5196 gtk_widget_get_pointer (widget, NULL, &y);
5197 gdk_pointer_ungrab (event->time);
5198 draw_xor_hline (sheet);
5200 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
5201 sheet->old_vadjustment = -1.;
5202 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed");
5207 if (GTK_SHEET_IN_DRAG(sheet)){
5208 GtkSheetRange old_range;
5209 draw_xor_rectangle(sheet, sheet->drag_range);
5210 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5211 gdk_pointer_ungrab (event->time);
5213 gtk_sheet_real_unselect_range(sheet, NULL);
5215 sheet->active_cell.row = sheet->active_cell.row +
5216 (sheet->drag_range.row0 - sheet->range.row0);
5217 sheet->active_cell.col = sheet->active_cell.col +
5218 (sheet->drag_range.col0 - sheet->range.col0);
5219 sheet->selection_cell.row = sheet->selection_cell.row +
5220 (sheet->drag_range.row0 - sheet->range.row0);
5221 sheet->selection_cell.col = sheet->selection_cell.col +
5222 (sheet->drag_range.col0 - sheet->range.col0);
5223 old_range=sheet->range;
5224 sheet->range=sheet->drag_range;
5225 sheet->drag_range=old_range;
5226 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[MOVE_RANGE],
5227 &sheet->drag_range, &sheet->range);
5228 gtk_sheet_select_range(sheet, &sheet->range);
5231 if (GTK_SHEET_IN_RESIZE(sheet)){
5232 GtkSheetRange old_range;
5233 draw_xor_rectangle(sheet, sheet->drag_range);
5234 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5235 gdk_pointer_ungrab (event->time);
5237 gtk_sheet_real_unselect_range(sheet, NULL);
5239 sheet->active_cell.row = sheet->active_cell.row +
5240 (sheet->drag_range.row0 - sheet->range.row0);
5241 sheet->active_cell.col = sheet->active_cell.col +
5242 (sheet->drag_range.col0 - sheet->range.col0);
5243 if(sheet->drag_range.row0 < sheet->range.row0)
5244 sheet->selection_cell.row = sheet->drag_range.row0;
5245 if(sheet->drag_range.rowi >= sheet->range.rowi)
5246 sheet->selection_cell.row = sheet->drag_range.rowi;
5247 if(sheet->drag_range.col0 < sheet->range.col0)
5248 sheet->selection_cell.col = sheet->drag_range.col0;
5249 if(sheet->drag_range.coli >= sheet->range.coli)
5250 sheet->selection_cell.col = sheet->drag_range.coli;
5251 old_range = sheet->range;
5252 sheet->range = sheet->drag_range;
5253 sheet->drag_range = old_range;
5255 if(sheet->state==GTK_STATE_NORMAL) sheet->state=GTK_SHEET_RANGE_SELECTED;
5256 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[RESIZE_RANGE],
5257 &sheet->drag_range, &sheet->range);
5258 gtk_sheet_select_range(sheet, &sheet->range);
5261 if(sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)){
5262 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5263 gdk_pointer_ungrab (event->time);
5264 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5265 sheet->active_cell.col);
5268 if(GTK_SHEET_IN_SELECTION)
5269 gdk_pointer_ungrab (event->time);
5271 gtk_timeout_remove(sheet->timer);
5272 gtk_grab_remove(GTK_WIDGET(sheet));
5274 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5280 gtk_sheet_motion (GtkWidget * widget,
5281 GdkEventMotion * event)
5284 GdkModifierType mods;
5285 GdkCursorType new_cursor;
5286 gint x, y, row, column;
5288 g_return_val_if_fail (widget != NULL, FALSE);
5289 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
5290 g_return_val_if_fail (event != NULL, FALSE);
5293 sheet = GTK_SHEET (widget);
5295 /* selections on the sheet */
5299 if(event->window == sheet->column_title_window && gtk_sheet_columns_resizable(sheet)){
5300 gtk_widget_get_pointer(widget, &x, &y);
5301 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_XDRAG(sheet, x, &column)){
5302 new_cursor=GDK_SB_H_DOUBLE_ARROW;
5303 if(new_cursor != sheet->cursor_drag->type){
5304 gdk_cursor_destroy(sheet->cursor_drag);
5305 sheet->cursor_drag=gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
5306 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5309 new_cursor=GDK_TOP_LEFT_ARROW;
5310 if(!GTK_SHEET_IN_XDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5311 gdk_cursor_destroy(sheet->cursor_drag);
5312 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5313 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5318 if(event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet)){
5319 gtk_widget_get_pointer(widget, &x, &y);
5320 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_YDRAG(sheet,y, &column)){
5321 new_cursor=GDK_SB_V_DOUBLE_ARROW;
5322 if(new_cursor != sheet->cursor_drag->type){
5323 gdk_cursor_destroy(sheet->cursor_drag);
5324 sheet->cursor_drag=gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
5325 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5328 new_cursor=GDK_TOP_LEFT_ARROW;
5329 if(!GTK_SHEET_IN_YDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5330 gdk_cursor_destroy(sheet->cursor_drag);
5331 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5332 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5337 new_cursor=GDK_PLUS;
5338 if(!POSSIBLE_DRAG(sheet,x,y,&row,&column) && !GTK_SHEET_IN_DRAG(sheet) &&
5339 !POSSIBLE_RESIZE(sheet,x,y,&row,&column) && !GTK_SHEET_IN_RESIZE(sheet) &&
5340 event->window == sheet->sheet_window &&
5341 new_cursor != sheet->cursor_drag->type){
5342 gdk_cursor_destroy(sheet->cursor_drag);
5343 sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
5344 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5347 new_cursor=GDK_TOP_LEFT_ARROW;
5348 if(!(POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5349 (POSSIBLE_DRAG(sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG(sheet)) &&
5350 event->window == sheet->sheet_window &&
5351 new_cursor != sheet->cursor_drag->type){
5352 gdk_cursor_destroy(sheet->cursor_drag);
5353 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5354 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5357 new_cursor=GDK_SIZING;
5358 if(!GTK_SHEET_IN_DRAG(sheet) &&
5359 (POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5360 event->window == sheet->sheet_window &&
5361 new_cursor != sheet->cursor_drag->type){
5362 gdk_cursor_destroy(sheet->cursor_drag);
5363 sheet->cursor_drag=gdk_cursor_new(GDK_SIZING);
5364 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5367 gdk_window_get_pointer (widget->window, &x, &y, &mods);
5368 if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
5370 if (GTK_SHEET_IN_XDRAG (sheet)){
5371 if (event->is_hint || event->window != widget->window)
5372 gtk_widget_get_pointer (widget, &x, NULL);
5376 new_column_width (sheet, sheet->drag_cell.col, &x);
5377 if (x != sheet->x_drag)
5379 draw_xor_vline (sheet);
5381 draw_xor_vline (sheet);
5386 if (GTK_SHEET_IN_YDRAG (sheet)){
5387 if (event->is_hint || event->window != widget->window)
5388 gtk_widget_get_pointer (widget, NULL, &y);
5392 new_row_height (sheet, sheet->drag_cell.row, &y);
5393 if (y != sheet->y_drag)
5395 draw_xor_hline (sheet);
5397 draw_xor_hline (sheet);
5402 if (GTK_SHEET_IN_DRAG(sheet)){
5404 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col;
5405 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row;
5406 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5407 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5411 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5412 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5413 aux=sheet->drag_range;
5414 sheet->drag_range.row0=sheet->range.row0+row;
5415 sheet->drag_range.col0=sheet->range.col0+column;
5416 sheet->drag_range.rowi=sheet->range.rowi+row;
5417 sheet->drag_range.coli=sheet->range.coli+column;
5418 if(aux.row0 != sheet->drag_range.row0 ||
5419 aux.col0 != sheet->drag_range.col0){
5420 draw_xor_rectangle (sheet, aux);
5421 draw_xor_rectangle (sheet, sheet->drag_range);
5427 if (GTK_SHEET_IN_RESIZE(sheet)){
5429 gint v_h, current_col, current_row, col_threshold, row_threshold;
5432 if(abs(x-COLUMN_LEFT_XPIXEL(sheet,sheet->drag_cell.col)) >
5433 abs(y-ROW_TOP_YPIXEL(sheet,sheet->drag_cell.row))) v_h=2;
5435 current_col = COLUMN_FROM_XPIXEL(sheet,x);
5436 current_row = ROW_FROM_YPIXEL(sheet,y);
5437 column = current_col-sheet->drag_cell.col;
5438 row = current_row-sheet->drag_cell.row;
5440 /*use half of column width resp. row height as threshold to expand selection*/
5441 col_threshold = COLUMN_LEFT_XPIXEL(sheet,current_col)+xxx_column_width (sheet,current_col)/2;
5443 if (x < col_threshold)
5446 else if (column < 0){
5447 if (x > col_threshold)
5450 row_threshold = ROW_TOP_YPIXEL(sheet,current_row)+yyy_row_height (sheet, current_row)/2;
5452 if(y < row_threshold)
5456 if(y > row_threshold)
5460 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5461 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5471 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5472 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5474 aux=sheet->drag_range;
5475 sheet->drag_range=sheet->range;
5477 if(row<0) sheet->drag_range.row0=sheet->range.row0+row;
5478 if(row>0) sheet->drag_range.rowi=sheet->range.rowi+row;
5479 if(column<0) sheet->drag_range.col0=sheet->range.col0+column;
5480 if(column>0) sheet->drag_range.coli=sheet->range.coli+column;
5482 if(aux.row0 != sheet->drag_range.row0 ||
5483 aux.rowi != sheet->drag_range.rowi ||
5484 aux.col0 != sheet->drag_range.col0 ||
5485 aux.coli != sheet->drag_range.coli){
5486 draw_xor_rectangle (sheet, aux);
5487 draw_xor_rectangle (sheet, sheet->drag_range);
5495 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5497 if(sheet->state==GTK_SHEET_NORMAL && row==sheet->active_cell.row &&
5498 column==sheet->active_cell.col) return TRUE;
5500 if(GTK_SHEET_IN_SELECTION(sheet) && mods&GDK_BUTTON1_MASK)
5501 gtk_sheet_extend_selection(sheet, row, column);
5507 gtk_sheet_move_query(GtkSheet *sheet, gint row, gint column)
5509 gint row_move, column_move;
5510 gfloat row_align, col_align;
5511 guint height, width;
5513 gint new_col = column;
5520 height = sheet->sheet_window_height;
5521 width = sheet->sheet_window_width;
5523 if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5525 new_row = MIN(yyy_row_count(sheet), row + 1);
5527 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet) - 1 &&
5528 ROW_TOP_YPIXEL(sheet, yyy_row_count(sheet)-1) +
5529 yyy_row_height(sheet, yyy_row_count(sheet)-1) < height){
5534 if(row<MIN_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5538 if(column>=MAX_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5540 new_col = MIN(xxx_column_count(sheet) - 1, column + 1);
5542 if(MAX_VISIBLE_COLUMN(sheet) == (xxx_column_count(sheet) - 1) &&
5543 COLUMN_LEFT_XPIXEL(sheet, xxx_column_count(sheet) - 1) +
5544 xxx_column_width(sheet, xxx_column_count(sheet) - 1) < width)
5546 column_move = FALSE;
5550 if(column<MIN_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5555 if(row_move || column_move){
5556 gtk_sheet_moveto(sheet, new_row, new_col, row_align, col_align);
5559 return(row_move || column_move);
5563 gtk_sheet_extend_selection(GtkSheet *sheet, gint row, gint column)
5565 GtkSheetRange range;
5569 if(row == sheet->selection_cell.row && column == sheet->selection_cell.col)
5572 if(sheet->selection_mode == GTK_SELECTION_SINGLE) return;
5574 gtk_sheet_move_query(sheet, row, column);
5575 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5577 if(GTK_SHEET_IN_DRAG(sheet)) return;
5581 switch(sheet->state){
5582 case GTK_SHEET_ROW_SELECTED:
5583 column = xxx_column_count(sheet) - 1;
5585 case GTK_SHEET_COLUMN_SELECTED:
5586 row = yyy_row_count(sheet) - 1;
5588 case GTK_SHEET_NORMAL:
5589 sheet->state=GTK_SHEET_RANGE_SELECTED;
5590 r=sheet->active_cell.row;
5591 c=sheet->active_cell.col;
5592 sheet->range.col0=c;
5593 sheet->range.row0=r;
5594 sheet->range.coli=c;
5595 sheet->range.rowi=r;
5596 gdk_draw_pixmap(sheet->sheet_window,
5597 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
5599 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5600 ROW_TOP_YPIXEL(sheet,r)-1,
5601 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5602 ROW_TOP_YPIXEL(sheet,r)-1,
5603 xxx_column_width(sheet, c)+4,
5604 yyy_row_height(sheet, r)+4);
5605 gtk_sheet_range_draw_selection(sheet, sheet->range);
5606 case GTK_SHEET_RANGE_SELECTED:
5607 sheet->state=GTK_SHEET_RANGE_SELECTED;
5610 sheet->selection_cell.row = row;
5611 sheet->selection_cell.col = column;
5613 range.col0=MIN(column,sheet->active_cell.col);
5614 range.coli=MAX(column,sheet->active_cell.col);
5615 range.row0=MIN(row,sheet->active_cell.row);
5616 range.rowi=MAX(row,sheet->active_cell.row);
5618 if(range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi ||
5619 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli ||
5620 state==GTK_SHEET_NORMAL)
5621 gtk_sheet_real_select_range(sheet, &range);
5626 gtk_sheet_entry_key_press(GtkWidget *widget,
5630 gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", key, &focus);
5635 gtk_sheet_key_press(GtkWidget *widget,
5641 gboolean extend_selection = FALSE;
5642 gboolean force_move = FALSE;
5643 gboolean in_selection = FALSE;
5644 gboolean veto = TRUE;
5647 sheet = GTK_SHEET(widget);
5649 if(key->state & GDK_CONTROL_MASK || key->keyval==GDK_Control_L ||
5650 key->keyval==GDK_Control_R) return FALSE;
5654 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL)
5655 gtk_sheet_clip_range(sheet, sheet->range);
5656 if(key->keyval=='x' || key->keyval == 'X')
5657 gtk_sheet_unclip_range(sheet);
5662 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval==GDK_Shift_L
5663 || key->keyval==GDK_Shift_R;
5666 in_selection = GTK_SHEET_IN_SELECTION(sheet);
5667 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5669 switch(key->keyval){
5670 case GDK_Return: case GDK_KP_Enter:
5671 if(sheet->state == GTK_SHEET_NORMAL &&
5672 !GTK_SHEET_IN_SELECTION(sheet))
5673 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
5675 row = sheet->active_cell.row;
5676 col = sheet->active_cell.col;
5677 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5678 row = MIN_VISIBLE_ROW(sheet)-1;
5679 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5680 col = MIN_VISIBLE_COLUMN(sheet);
5681 if(row < yyy_row_count(sheet) - 1){
5683 while(!yyy_row_is_visible(sheet, row) && row<yyy_row_count(sheet)-1)
5686 gtk_sheet_click_cell(sheet, row, col, &veto);
5687 extend_selection = FALSE;
5689 case GDK_ISO_Left_Tab:
5690 row = sheet->active_cell.row;
5691 col = sheet->active_cell.col;
5692 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5693 col = MIN_VISIBLE_COLUMN(sheet)-1;
5694 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5695 row = MIN_VISIBLE_ROW(sheet);
5698 while(! xxx_column_is_visible(sheet, col) && col>0) col--;
5701 gtk_sheet_click_cell(sheet, row, col, &veto);
5702 extend_selection = FALSE;
5705 row = sheet->active_cell.row;
5706 col = sheet->active_cell.col;
5707 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5708 col = MIN_VISIBLE_COLUMN(sheet)-1;
5709 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5710 row = MIN_VISIBLE_ROW(sheet);
5711 if(col < xxx_column_count(sheet) - 1)
5714 while(! xxx_column_is_visible(sheet, col) &&
5715 col < xxx_column_count(sheet) - 1)
5718 gtk_sheet_click_cell(sheet, row, col, &veto);
5719 extend_selection = FALSE;
5721 /* case GDK_BackSpace:
5722 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){
5723 if(sheet->active_cell.col > 0){
5724 col = sheet->active_cell.col - scroll;
5725 row = sheet->active_cell.row;
5726 while(!sheet->column[col].is_visible && col > 0) col--;
5729 gtk_sheet_click_cell(sheet, row, col, &veto);
5730 extend_selection = FALSE;
5734 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5736 if(extend_selection){
5737 if(state==GTK_STATE_NORMAL){
5738 row=sheet->active_cell.row;
5739 col=sheet->active_cell.col;
5740 gtk_sheet_click_cell(sheet, row, col, &veto);
5743 if(sheet->selection_cell.row > 0){
5744 row = sheet->selection_cell.row - scroll;
5745 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5747 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5751 col = sheet->active_cell.col;
5752 row = sheet->active_cell.row;
5753 if(state==GTK_SHEET_COLUMN_SELECTED)
5754 row = MIN_VISIBLE_ROW(sheet);
5755 if(state==GTK_SHEET_ROW_SELECTED)
5756 col = MIN_VISIBLE_COLUMN(sheet);
5758 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5760 gtk_sheet_click_cell(sheet, row, col, &veto);
5761 extend_selection = FALSE;
5764 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5766 if(extend_selection){
5767 if(state==GTK_STATE_NORMAL){
5768 row=sheet->active_cell.row;
5769 col=sheet->active_cell.col;
5770 gtk_sheet_click_cell(sheet, row, col, &veto);
5773 if(sheet->selection_cell.row < yyy_row_count(sheet)-1){
5774 row = sheet->selection_cell.row + scroll;
5775 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5776 row = MIN(yyy_row_count(sheet)-1, row);
5777 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5781 col = sheet->active_cell.col;
5782 row = sheet->active_cell.row;
5783 if(sheet->active_cell.row < yyy_row_count(sheet)-1){
5784 if(state==GTK_SHEET_COLUMN_SELECTED)
5785 row = MIN_VISIBLE_ROW(sheet)-1;
5786 if(state==GTK_SHEET_ROW_SELECTED)
5787 col = MIN_VISIBLE_COLUMN(sheet);
5789 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5790 row = MIN(yyy_row_count(sheet)-1, row);
5792 gtk_sheet_click_cell(sheet, row, col, &veto);
5793 extend_selection = FALSE;
5796 if(extend_selection){
5797 if(state==GTK_STATE_NORMAL){
5798 row=sheet->active_cell.row;
5799 col=sheet->active_cell.col;
5800 gtk_sheet_click_cell(sheet, row, col, &veto);
5803 if(sheet->selection_cell.col < xxx_column_count(sheet) - 1)
5805 col = sheet->selection_cell.col + 1;
5806 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1)
5808 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5812 col = sheet->active_cell.col;
5813 row = sheet->active_cell.row;
5814 if(sheet->active_cell.col < xxx_column_count(sheet) - 1){
5816 if(state==GTK_SHEET_ROW_SELECTED)
5817 col = MIN_VISIBLE_COLUMN(sheet)-1;
5818 if(state==GTK_SHEET_COLUMN_SELECTED)
5819 row = MIN_VISIBLE_ROW(sheet);
5820 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1) col++;
5821 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5823 gtk_sheet_click_cell(sheet, row, col, &veto);
5828 extend_selection = FALSE;
5831 if(extend_selection){
5832 if(state==GTK_STATE_NORMAL){
5833 row=sheet->active_cell.row;
5834 col=sheet->active_cell.col;
5835 gtk_sheet_click_cell(sheet, row, col, &veto);
5838 if(sheet->selection_cell.col > 0){
5839 col = sheet->selection_cell.col - 1;
5840 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5841 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5845 col = sheet->active_cell.col - 1;
5846 row = sheet->active_cell.row;
5847 if(state==GTK_SHEET_ROW_SELECTED)
5848 col = MIN_VISIBLE_COLUMN(sheet)-1;
5849 if(state==GTK_SHEET_COLUMN_SELECTED)
5850 row = MIN_VISIBLE_ROW(sheet);
5851 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5854 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5856 gtk_sheet_click_cell(sheet, row, col, &veto);
5860 extend_selection = FALSE;
5864 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5865 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5866 extend_selection = FALSE;
5869 row=yyy_row_count(sheet)-1;
5870 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5871 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5872 extend_selection = FALSE;
5876 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5877 if(extend_selection) return TRUE;
5879 if(state == GTK_SHEET_ROW_SELECTED)
5880 sheet->active_cell.col=MIN_VISIBLE_COLUMN(sheet);
5881 if(state == GTK_SHEET_COLUMN_SELECTED)
5882 sheet->active_cell.row=MIN_VISIBLE_ROW(sheet);
5886 if(extend_selection) return TRUE;
5888 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5889 sheet->active_cell.col);
5895 gtk_sheet_size_request (GtkWidget * widget,
5896 GtkRequisition * requisition)
5900 GtkSheetChild *child;
5901 GtkRequisition child_requisition;
5903 g_return_if_fail (widget != NULL);
5904 g_return_if_fail (GTK_IS_SHEET (widget));
5905 g_return_if_fail (requisition != NULL);
5907 sheet = GTK_SHEET (widget);
5909 requisition->width = 3*DEFAULT_COLUMN_WIDTH;
5910 requisition->height = 3*DEFAULT_ROW_HEIGHT(widget);
5912 /* compute the size of the column title area */
5913 if(sheet->column_titles_visible)
5914 requisition->height += sheet->column_title_area.height;
5916 /* compute the size of the row title area */
5917 if(sheet->row_titles_visible)
5918 requisition->width += sheet->row_title_area.width;
5920 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5921 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5922 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5923 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5925 if(!sheet->column_titles_visible)
5926 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5928 if(!sheet->row_titles_visible)
5929 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5931 children = sheet->children;
5934 child = children->data;
5935 children = children->next;
5937 gtk_widget_size_request(child->widget, &child_requisition);
5943 gtk_sheet_size_allocate (GtkWidget * widget,
5944 GtkAllocation * allocation)
5947 GtkAllocation sheet_allocation;
5950 g_return_if_fail (widget != NULL);
5951 g_return_if_fail (GTK_IS_SHEET (widget));
5952 g_return_if_fail (allocation != NULL);
5954 sheet = GTK_SHEET (widget);
5955 widget->allocation = *allocation;
5956 border_width = GTK_CONTAINER(widget)->border_width;
5958 if (GTK_WIDGET_REALIZED (widget))
5959 gdk_window_move_resize (widget->window,
5960 allocation->x + border_width,
5961 allocation->y + border_width,
5962 allocation->width - 2*border_width,
5963 allocation->height - 2*border_width);
5965 /* use internal allocation structure for all the math
5966 * because it's easier than always subtracting the container
5968 sheet->internal_allocation.x = 0;
5969 sheet->internal_allocation.y = 0;
5970 sheet->internal_allocation.width = allocation->width - 2*border_width;
5971 sheet->internal_allocation.height = allocation->height - 2*border_width;
5973 sheet_allocation.x = 0;
5974 sheet_allocation.y = 0;
5975 sheet_allocation.width = allocation->width - 2*border_width;
5976 sheet_allocation.height = allocation->height - 2*border_width;
5978 sheet->sheet_window_width = sheet_allocation.width;
5979 sheet->sheet_window_height = sheet_allocation.height;
5981 if (GTK_WIDGET_REALIZED (widget))
5982 gdk_window_move_resize (sheet->sheet_window,
5985 sheet_allocation.width,
5986 sheet_allocation.height);
5988 /* position the window which holds the column title buttons */
5989 sheet->column_title_area.x = 0;
5990 sheet->column_title_area.y = 0;
5991 if(sheet->row_titles_visible)
5992 sheet->column_title_area.x = sheet->row_title_area.width;
5993 sheet->column_title_area.width = sheet_allocation.width -
5994 sheet->column_title_area.x;
5995 if(GTK_WIDGET_REALIZED(widget) && sheet->column_titles_visible)
5996 gdk_window_move_resize (sheet->column_title_window,
5997 sheet->column_title_area.x,
5998 sheet->column_title_area.y,
5999 sheet->column_title_area.width,
6000 sheet->column_title_area.height);
6002 sheet->sheet_window_width = sheet_allocation.width;
6003 sheet->sheet_window_height = sheet_allocation.height;
6005 /* column button allocation */
6006 size_allocate_column_title_buttons (sheet);
6008 /* position the window which holds the row title buttons */
6009 sheet->row_title_area.x = 0;
6010 sheet->row_title_area.y = 0;
6011 if(sheet->column_titles_visible)
6012 sheet->row_title_area.y = sheet->column_title_area.height;
6013 sheet->row_title_area.height = sheet_allocation.height -
6014 sheet->row_title_area.y;
6016 if(GTK_WIDGET_REALIZED(widget) && sheet->row_titles_visible)
6017 gdk_window_move_resize (sheet->row_title_window,
6018 sheet->row_title_area.x,
6019 sheet->row_title_area.y,
6020 sheet->row_title_area.width,
6021 sheet->row_title_area.height);
6024 /* row button allocation */
6025 size_allocate_row_title_buttons (sheet);
6027 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6028 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6029 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6030 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6032 if(!sheet->column_titles_visible)
6033 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6035 if(!sheet->row_titles_visible)
6036 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6038 size_allocate_column_title_buttons(sheet);
6039 size_allocate_row_title_buttons(sheet);
6041 /* re-scale backing pixmap */
6042 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
6043 gtk_sheet_position_children(sheet);
6045 /* set the scrollbars adjustments */
6046 adjust_scrollbars (sheet);
6050 size_allocate_column_title_buttons (GtkSheet * sheet)
6055 if (!sheet->column_titles_visible) return;
6056 if (!GTK_WIDGET_REALIZED (sheet))
6059 width = sheet->sheet_window_width;
6062 if(sheet->row_titles_visible)
6064 width -= sheet->row_title_area.width;
6065 x = sheet->row_title_area.width;
6068 if(sheet->column_title_area.width != width || sheet->column_title_area.x != x)
6070 sheet->column_title_area.width = width;
6071 sheet->column_title_area.x = x;
6072 gdk_window_move_resize (sheet->column_title_window,
6073 sheet->column_title_area.x,
6074 sheet->column_title_area.y,
6075 sheet->column_title_area.width,
6076 sheet->column_title_area.height);
6080 if(MAX_VISIBLE_COLUMN(sheet) == xxx_column_count(sheet) - 1)
6081 gdk_window_clear_area (sheet->column_title_window,
6083 sheet->column_title_area.width,
6084 sheet->column_title_area.height);
6086 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6088 for (i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
6089 gtk_sheet_button_draw(sheet,-1,i);
6093 size_allocate_row_title_buttons (GtkSheet * sheet)
6098 if (!sheet->row_titles_visible) return;
6099 if (!GTK_WIDGET_REALIZED (sheet))
6102 height = sheet->sheet_window_height;
6105 if(sheet->column_titles_visible)
6107 height -= sheet->column_title_area.height;
6108 y = sheet->column_title_area.height;
6111 if(sheet->row_title_area.height != height || sheet->row_title_area.y != y)
6113 sheet->row_title_area.y = y;
6114 sheet->row_title_area.height = height;
6115 gdk_window_move_resize (sheet->row_title_window,
6116 sheet->row_title_area.x,
6117 sheet->row_title_area.y,
6118 sheet->row_title_area.width,
6119 sheet->row_title_area.height);
6121 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet)-1)
6122 gdk_window_clear_area (sheet->row_title_window,
6124 sheet->row_title_area.width,
6125 sheet->row_title_area.height);
6127 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6129 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
6130 gtk_sheet_button_draw(sheet,i,-1);
6135 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
6137 GtkAllocation shentry_allocation;
6138 GtkSheetCellAttr attributes;
6139 GtkEntry *sheet_entry;
6140 GtkStyle *style = NULL, *previous_style = NULL;
6142 gint size, max_size, text_size, column_width;
6145 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6146 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
6148 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
6150 gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes);
6152 if(GTK_WIDGET_REALIZED(sheet->sheet_entry)){
6154 if(!GTK_WIDGET(sheet_entry)->style)
6155 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry));
6157 previous_style = GTK_WIDGET(sheet_entry)->style;
6159 style = gtk_style_copy(previous_style);
6160 style->bg[GTK_STATE_NORMAL] = attributes.background;
6161 style->fg[GTK_STATE_NORMAL] = attributes.foreground;
6162 style->text[GTK_STATE_NORMAL] = attributes.foreground;
6163 style->bg[GTK_STATE_ACTIVE] = attributes.background;
6164 style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
6165 style->text[GTK_STATE_ACTIVE] = attributes.foreground;
6167 pango_font_description_free(style->font_desc);
6168 style->font_desc = pango_font_description_copy(attributes.font_desc);
6170 GTK_WIDGET(sheet_entry)->style = style;
6171 gtk_widget_size_request(sheet->sheet_entry, NULL);
6172 GTK_WIDGET(sheet_entry)->style = previous_style;
6174 if(style != previous_style){
6175 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6176 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
6177 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
6178 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
6179 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
6181 gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
6185 if(GTK_IS_ITEM_ENTRY(sheet_entry))
6186 max_size = GTK_ITEM_ENTRY(sheet_entry)->text_max_size;
6191 text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
6192 if(text && strlen(text) > 0){
6193 text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
6196 column_width=xxx_column_width(sheet, sheet->active_cell.col);
6198 size=MIN(text_size, max_size);
6199 size=MAX(size,column_width-2*CELLOFFSET);
6201 row=sheet->active_cell.row;
6202 col=sheet->active_cell.col;
6204 shentry_allocation.x = COLUMN_LEFT_XPIXEL(sheet,sheet->active_cell.col);
6205 shentry_allocation.y = ROW_TOP_YPIXEL(sheet,sheet->active_cell.row);
6206 shentry_allocation.width = column_width;
6207 shentry_allocation.height = yyy_row_height(sheet, sheet->active_cell.row);
6209 if(GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6211 shentry_allocation.height -= 2*CELLOFFSET;
6212 shentry_allocation.y += CELLOFFSET;
6213 if(gtk_sheet_clip_text(sheet))
6214 shentry_allocation.width = column_width - 2*CELLOFFSET;
6216 shentry_allocation.width = size;
6218 switch(GTK_ITEM_ENTRY(sheet_entry)->justification){
6219 case GTK_JUSTIFY_CENTER:
6220 shentry_allocation.x += (column_width)/2 - size/2;
6222 case GTK_JUSTIFY_RIGHT:
6223 shentry_allocation.x += column_width - size - CELLOFFSET;
6225 case GTK_JUSTIFY_LEFT:
6226 case GTK_JUSTIFY_FILL:
6227 shentry_allocation.x += CELLOFFSET;
6233 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6234 shentry_allocation.x += 2;
6235 shentry_allocation.y += 2;
6236 shentry_allocation.width -= MIN(shentry_allocation.width, 3);
6237 shentry_allocation.height -= MIN(shentry_allocation.height, 3);
6240 gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation);
6242 if(previous_style == style) gtk_style_unref(previous_style);
6246 gtk_sheet_entry_set_max_size(GtkSheet *sheet)
6250 gint sizel=0, sizer=0;
6252 GtkJustification justification;
6255 row=sheet->active_cell.row;
6256 col=sheet->active_cell.col;
6258 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry) || gtk_sheet_clip_text(sheet)) return;
6260 justification = GTK_ITEM_ENTRY(sheet->sheet_entry)->justification;
6262 switch(justification){
6263 case GTK_JUSTIFY_FILL:
6264 case GTK_JUSTIFY_LEFT:
6265 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6266 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6271 size+=xxx_column_width(sheet, i);
6273 size = MIN(size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL(sheet, col));
6275 case GTK_JUSTIFY_RIGHT:
6276 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--)
6278 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6283 size+=xxx_column_width(sheet, i);
6286 case GTK_JUSTIFY_CENTER:
6287 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6288 /* if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6294 sizer+=xxx_column_width(sheet, i);
6296 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--)
6298 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6303 sizel+=xxx_column_width(sheet, i);
6305 size=2*MIN(sizel, sizer);
6310 size += xxx_column_width(sheet, col);
6311 GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size = size;
6315 create_sheet_entry(GtkSheet *sheet)
6320 gint found_entry = FALSE;
6322 widget = GTK_WIDGET(sheet);
6324 if(sheet->sheet_entry){
6325 /* avoids warnings */
6326 gtk_widget_ref(sheet->sheet_entry);
6327 gtk_widget_unparent(sheet->sheet_entry);
6328 gtk_widget_destroy(sheet->sheet_entry);
6331 if(sheet->entry_type){
6333 if(!g_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY)){
6335 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6337 sheet->sheet_entry = parent;
6339 entry = gtk_sheet_get_entry (sheet);
6340 if(GTK_IS_ENTRY(entry)) found_entry = TRUE;
6344 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6352 g_warning ("Entry type must be GtkEntry subclass, using default");
6353 entry = gtk_item_entry_new();
6354 sheet->sheet_entry = entry;
6358 sheet->sheet_entry = parent;
6365 entry = gtk_item_entry_new();
6366 sheet->sheet_entry = entry;
6370 gtk_widget_size_request(sheet->sheet_entry, NULL);
6372 if(GTK_WIDGET_REALIZED(sheet))
6374 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
6375 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
6376 gtk_widget_realize(sheet->sheet_entry);
6379 gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event",
6380 (GtkSignalFunc) gtk_sheet_entry_key_press,
6383 gtk_widget_show (sheet->sheet_entry);
6387 /* Finds the last child widget that happens to be of type GtkEntry */
6389 find_entry(GtkWidget *w, gpointer user_data)
6391 GtkWidget **entry = user_data;
6392 if ( GTK_IS_ENTRY(w))
6399 gtk_sheet_get_entry(GtkSheet *sheet)
6402 GtkWidget *entry = NULL;
6403 GtkTableChild *table_child;
6404 GtkBoxChild *box_child;
6405 GList *children = NULL;
6407 g_return_val_if_fail (sheet != NULL, NULL);
6408 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6409 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6411 if(GTK_IS_ENTRY(sheet->sheet_entry)) return (sheet->sheet_entry);
6413 parent = GTK_WIDGET(sheet->sheet_entry);
6415 if(GTK_IS_TABLE(parent)) children = GTK_TABLE(parent)->children;
6416 if(GTK_IS_BOX(parent)) children = GTK_BOX(parent)->children;
6418 if(GTK_IS_CONTAINER(parent))
6420 gtk_container_forall(GTK_CONTAINER(parent), find_entry, &entry);
6422 if(GTK_IS_ENTRY(entry))
6426 if(!children) return NULL;
6429 if(GTK_IS_TABLE(parent)) {
6430 table_child = children->data;
6431 entry = table_child->widget;
6433 if(GTK_IS_BOX(parent)){
6434 box_child = children->data;
6435 entry = box_child->widget;
6438 if(GTK_IS_ENTRY(entry))
6440 children = children->next;
6444 if(!GTK_IS_ENTRY(entry)) return NULL;
6451 gtk_sheet_get_entry_widget(GtkSheet *sheet)
6453 g_return_val_if_fail (sheet != NULL, NULL);
6454 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6455 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6457 return (sheet->sheet_entry);
6463 row_button_set (GtkSheet *sheet, gint row)
6465 if(sheet->row[row].button.state == GTK_STATE_ACTIVE) return;
6467 sheet->row[row].button.state = GTK_STATE_ACTIVE;
6468 gtk_sheet_button_draw(sheet, row, -1);
6473 row_button_release (GtkSheet *sheet, gint row)
6475 if(sheet->row[row].button.state == GTK_STATE_NORMAL) return;
6477 sheet->row[row].button.state = GTK_STATE_NORMAL;
6478 gtk_sheet_button_draw(sheet, row, -1);
6483 gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
6485 GdkWindow *window = NULL;
6486 GtkShadowType shadow_type;
6487 guint width = 0, height = 0;
6490 gint text_width = 0, text_height = 0;
6491 GtkSheetButton *button = NULL;
6492 GtkSheetChild *child = NULL;
6493 GdkRectangle allocation;
6494 gboolean is_sensitive = FALSE;
6499 PangoAlignment align = PANGO_ALIGN_LEFT;
6502 rtl = gtk_widget_get_direction(GTK_WIDGET(sheet)) == GTK_TEXT_DIR_RTL;
6504 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6506 if(row >= 0 && !yyy_row_is_visible(sheet, row)) return;
6507 if(column >= 0 && ! xxx_column_is_visible(sheet, column)) return;
6508 if(row >= 0 && !sheet->row_titles_visible) return;
6509 if(column >= 0 && !sheet->column_titles_visible) return;
6510 if(column>=0 && column < MIN_VISIBLE_COLUMN(sheet)) return;
6511 if(column>=0 && column > MAX_VISIBLE_COLUMN(sheet)) return;
6512 if(row>=0 && row < MIN_VISIBLE_ROW(sheet)) return;
6513 if(row>=0 && row > MAX_VISIBLE_ROW(sheet)) return;
6514 if( (row == -1) && (column == -1) ) return;
6517 window=sheet->column_title_window;
6518 button= xxx_column_button(sheet, column);
6520 x = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING;
6521 if(sheet->row_titles_visible) x -= sheet->row_title_area.width;
6523 width = xxx_column_width(sheet, column);
6524 height = sheet->column_title_area.height;
6525 is_sensitive=xxx_column_is_sensitive(sheet, column);
6528 window=sheet->row_title_window;
6529 button = yyy_row_button(sheet, row);
6532 y = ROW_TOP_YPIXEL(sheet, row)+CELL_SPACING;
6533 if(sheet->column_titles_visible) y-=sheet->column_title_area.height;
6534 width = sheet->row_title_area.width;
6535 height = yyy_row_height(sheet, row);
6536 is_sensitive=yyy_row_is_sensitive(sheet, row);
6541 allocation.width = width;
6542 allocation.height = height;
6544 gdk_window_clear_area (window,
6548 gtk_paint_box (sheet->button->style, window,
6549 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
6550 &allocation, GTK_WIDGET(sheet->button),
6551 "buttondefault", x, y, width, height);
6553 state = button->state;
6554 if(!is_sensitive) state=GTK_STATE_INSENSITIVE;
6556 if (state == GTK_STATE_ACTIVE)
6557 shadow_type = GTK_SHADOW_IN;
6559 shadow_type = GTK_SHADOW_OUT;
6561 if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
6562 gtk_paint_box (sheet->button->style, window,
6563 button->state, shadow_type,
6564 &allocation, GTK_WIDGET(sheet->button),
6565 "button", x, y, width, height);
6567 if(button->label_visible){
6569 text_height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))-2*CELLOFFSET;
6571 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6573 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation);
6575 y += 2*sheet->button->style->ythickness;
6578 if(button->label && strlen(button->label)>0){
6580 PangoLayout *layout = NULL;
6581 gint real_x = x, real_y = y;
6583 words=button->label;
6584 line = g_new(gchar, 1);
6587 while(words && *words != '\0'){
6590 line=g_realloc(line, len+2);
6594 if(*words == '\n' || *(words+1) == '\0'){
6595 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, line);
6597 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), line);
6598 switch(button->justification){
6599 case GTK_JUSTIFY_LEFT:
6600 real_x = x + CELLOFFSET;
6601 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6603 case GTK_JUSTIFY_RIGHT:
6604 real_x = x + width - text_width - CELLOFFSET;
6605 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6607 case GTK_JUSTIFY_CENTER:
6609 real_x = x + (width - text_width)/2;
6610 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6611 pango_layout_set_justify (layout, TRUE);
6613 pango_layout_set_alignment (layout, align);
6614 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6623 g_object_unref(G_OBJECT(layout));
6625 real_y += text_height + 2;
6628 line = g_new(gchar, 1);
6636 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6638 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, NULL);
6642 if((child = button->child) && (child->widget)){
6643 child->x = allocation.x;
6644 child->y = allocation.y;
6646 child->x += (width - child->widget->requisition.width) / 2;
6647 child->y += (height - child->widget->requisition.height) / 2;
6648 allocation.x = child->x;
6649 allocation.y = child->y;
6650 allocation.width = child->widget->requisition.width;
6651 allocation.height = child->widget->requisition.height;
6656 gtk_widget_set_state(child->widget, button->state);
6658 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
6659 GTK_WIDGET_MAPPED(child->widget))
6661 gtk_widget_size_allocate(child->widget,
6663 gtk_widget_queue_draw(child->widget);
6667 gtk_sheet_button_free(button);
6676 * vadjustment_changed
6677 * hadjustment_changed
6678 * vadjustment_value_changed
6679 * hadjustment_value_changed */
6682 adjust_scrollbars (GtkSheet * sheet)
6685 if(sheet->vadjustment){
6686 sheet->vadjustment->page_size = sheet->sheet_window_height;
6687 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
6688 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
6689 sheet->vadjustment->lower = 0;
6690 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
6692 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet))
6694 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) -
6695 sheet->sheet_window_height);
6696 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
6700 gtk_signal_emit_by_name (GTK_OBJECT(sheet->vadjustment), "changed");
6704 if(sheet->hadjustment){
6705 sheet->hadjustment->page_size = sheet->sheet_window_width;
6706 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
6707 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
6708 sheet->hadjustment->lower = 0;
6709 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
6711 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet))
6713 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) -
6714 sheet->sheet_window_width);
6715 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment),
6719 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), "changed");
6723 if(GTK_WIDGET_REALIZED(sheet))
6725 if(sheet->row_titles_visible){
6726 size_allocate_row_title_buttons(sheet);
6727 gdk_window_show(sheet->row_title_window);
6730 if(sheet->column_titles_visible){
6731 size_allocate_column_title_buttons(sheet);
6732 gdk_window_show(sheet->column_title_window);
6735 gtk_sheet_range_draw(sheet, NULL);
6742 vadjustment_changed (GtkAdjustment * adjustment,
6747 g_return_if_fail (adjustment != NULL);
6748 g_return_if_fail (data != NULL);
6750 sheet = GTK_SHEET (data);
6755 hadjustment_changed (GtkAdjustment * adjustment,
6760 g_return_if_fail (adjustment != NULL);
6761 g_return_if_fail (data != NULL);
6763 sheet = GTK_SHEET (data);
6768 vadjustment_value_changed (GtkAdjustment * adjustment,
6772 gint diff, value, old_value;
6776 g_return_if_fail (adjustment != NULL);
6777 g_return_if_fail (data != NULL);
6778 g_return_if_fail (GTK_IS_SHEET (data));
6780 sheet = GTK_SHEET (data);
6782 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6784 row=ROW_FROM_YPIXEL(sheet,sheet->column_title_area.height + CELL_SPACING);
6785 if(!sheet->column_titles_visible)
6786 row=ROW_FROM_YPIXEL(sheet,CELL_SPACING);
6788 old_value = -sheet->voffset;
6790 new_row = g_sheet_row_pixel_to_row(sheet->row_geometry,
6791 adjustment->value,sheet);
6793 y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
6795 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
6796 yyy_row_height(sheet, row) > sheet->vadjustment->step_increment){
6797 /* This avoids embarrassing twitching */
6798 if(row == new_row && row != yyy_row_count(sheet) - 1 &&
6799 adjustment->value - sheet->old_vadjustment >=
6800 sheet->vadjustment->step_increment &&
6801 new_row + 1 != MIN_VISIBLE_ROW(sheet)){
6803 y=y+yyy_row_height(sheet, row);
6807 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6808 if(sheet->old_vadjustment >= 0. && row == new_row){
6809 sheet->old_vadjustment = sheet->vadjustment->value;
6813 sheet->old_vadjustment = sheet->vadjustment->value;
6814 adjustment->value=y;
6818 sheet->vadjustment->step_increment= yyy_row_height(sheet, 0);
6820 sheet->vadjustment->step_increment=
6821 MIN(yyy_row_height(sheet, new_row), yyy_row_height(sheet, new_row-1));
6824 sheet->vadjustment->value=adjustment->value;
6826 value = adjustment->value;
6828 if (value >= -sheet->voffset)
6831 diff = value + sheet->voffset;
6836 diff = -sheet->voffset - value;
6839 sheet->voffset = -value;
6841 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6842 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6843 if(!sheet->column_titles_visible)
6844 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6846 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6847 sheet->state == GTK_SHEET_NORMAL &&
6848 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6849 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6850 sheet->active_cell.col))
6854 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6856 if(!text || strlen(text)==0)
6857 gtk_sheet_cell_clear(sheet,
6858 sheet->active_cell.row,
6859 sheet->active_cell.col);
6860 gtk_widget_unmap(sheet->sheet_entry);
6863 gtk_sheet_position_children(sheet);
6865 gtk_sheet_range_draw(sheet, NULL);
6866 size_allocate_row_title_buttons(sheet);
6867 size_allocate_global_button(sheet);
6871 hadjustment_value_changed (GtkAdjustment * adjustment,
6875 gint i, diff, value, old_value;
6876 gint column, new_column;
6879 g_return_if_fail (adjustment != NULL);
6880 g_return_if_fail (data != NULL);
6881 g_return_if_fail (GTK_IS_SHEET (data));
6883 sheet = GTK_SHEET (data);
6885 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6887 column=COLUMN_FROM_XPIXEL(sheet,sheet->row_title_area.width + CELL_SPACING);
6888 if(!sheet->row_titles_visible)
6889 column=COLUMN_FROM_XPIXEL(sheet, CELL_SPACING);
6891 old_value = -sheet->hoffset;
6893 for(i=0; i < xxx_column_count(sheet); i++)
6895 if(xxx_column_is_visible(sheet, i)) x += xxx_column_width(sheet, i);
6896 if(x > adjustment->value) break;
6898 x-=xxx_column_width(sheet, i);
6901 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
6902 xxx_column_width(sheet, i) > sheet->hadjustment->step_increment){
6903 /* This avoids embarrassing twitching */
6904 if(column == new_column && column != xxx_column_count(sheet) - 1 &&
6905 adjustment->value - sheet->old_hadjustment >=
6906 sheet->hadjustment->step_increment &&
6907 new_column + 1 != MIN_VISIBLE_COLUMN(sheet)){
6909 x=x+xxx_column_width(sheet, column);
6913 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6914 if(sheet->old_hadjustment >= 0. && new_column == column){
6915 sheet->old_hadjustment = sheet->hadjustment->value;
6919 sheet->old_hadjustment = sheet->hadjustment->value;
6920 adjustment->value=x;
6922 if(new_column == 0){
6923 sheet->hadjustment->step_increment=
6924 xxx_column_width(sheet, 0);
6926 sheet->hadjustment->step_increment=
6927 MIN(xxx_column_width(sheet, new_column), xxx_column_width(sheet, new_column-1));
6931 sheet->hadjustment->value=adjustment->value;
6933 value = adjustment->value;
6935 if (value >= -sheet->hoffset)
6938 diff = value + sheet->hoffset;
6943 diff = -sheet->hoffset - value;
6946 sheet->hoffset = -value;
6948 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6949 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6950 if(!sheet->row_titles_visible)
6951 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6953 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6954 sheet->state == GTK_SHEET_NORMAL &&
6955 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6956 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6957 sheet->active_cell.col))
6961 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6962 if(!text || strlen(text)==0)
6963 gtk_sheet_cell_clear(sheet,
6964 sheet->active_cell.row,
6965 sheet->active_cell.col);
6967 gtk_widget_unmap(sheet->sheet_entry);
6970 gtk_sheet_position_children(sheet);
6972 gtk_sheet_range_draw(sheet, NULL);
6973 size_allocate_column_title_buttons(sheet);
6977 /* COLUMN RESIZING */
6979 draw_xor_vline (GtkSheet * sheet)
6983 g_return_if_fail (sheet != NULL);
6985 widget = GTK_WIDGET (sheet);
6987 gdk_draw_line (widget->window, sheet->xor_gc,
6989 sheet->column_title_area.height,
6991 sheet->sheet_window_height + 1);
6996 draw_xor_hline (GtkSheet * sheet)
7000 g_return_if_fail (sheet != NULL);
7002 widget = GTK_WIDGET (sheet);
7004 gdk_draw_line (widget->window, sheet->xor_gc,
7005 sheet->row_title_area.width,
7008 sheet->sheet_window_width + 1,
7012 /* SELECTED RANGE */
7014 draw_xor_rectangle(GtkSheet *sheet, GtkSheetRange range)
7017 GdkRectangle clip_area, area;
7020 area.x=COLUMN_LEFT_XPIXEL(sheet, range.col0);
7021 area.y=ROW_TOP_YPIXEL(sheet, range.row0);
7022 area.width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-area.x+
7023 xxx_column_width(sheet, range.coli);
7024 area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+
7025 yyy_row_height(sheet, range.rowi);
7027 clip_area.x=sheet->row_title_area.width;
7028 clip_area.y=sheet->column_title_area.height;
7029 clip_area.width=sheet->sheet_window_width;
7030 clip_area.height=sheet->sheet_window_height;
7032 if(!sheet->row_titles_visible) clip_area.x = 0;
7033 if(!sheet->column_titles_visible) clip_area.y = 0;
7036 area.width=area.width+area.x;
7039 if(area.width>clip_area.width) area.width=clip_area.width+10;
7041 area.height=area.height+area.y;
7044 if(area.height>clip_area.height) area.height=clip_area.height+10;
7049 clip_area.height+=3;
7051 gdk_gc_get_values(sheet->xor_gc, &values);
7053 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
7056 gdk_draw_rectangle(sheet->sheet_window,
7060 area.width-2*i, area.height-2*i);
7063 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
7065 gdk_gc_set_foreground(sheet->xor_gc, &values.foreground);
7070 /* this function returns the new width of the column being resized given
7071 * the column and x position of the cursor; the x cursor position is passed
7072 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7074 new_column_width (GtkSheet * sheet,
7083 min_width = sheet->column_requisition;
7085 /* you can't shrink a column to less than its minimum width */
7086 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
7088 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
7091 /* don't grow past the end of the window */
7093 if (cx > sheet->sheet_window_width)
7095 *x = cx = sheet->sheet_window_width;
7098 /* calculate new column width making sure it doesn't end up
7099 * less than the minimum width */
7100 width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
7101 if (width < min_width)
7104 xxx_set_column_width(sheet, column, width);
7105 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7106 size_allocate_column_title_buttons (sheet);
7111 /* this function returns the new height of the row being resized given
7112 * the row and y position of the cursor; the y cursor position is passed
7113 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7115 new_row_height (GtkSheet * sheet,
7123 min_height = sheet->row_requisition;
7125 /* you can't shrink a row to less than its minimum height */
7126 if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
7129 *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
7132 /* don't grow past the end of the window */
7134 if (cy > sheet->sheet_window_height)
7136 *y = cy = sheet->sheet_window_height;
7139 /* calculate new row height making sure it doesn't end up
7140 * less than the minimum height */
7141 height = (cy - ROW_TOP_YPIXEL (sheet, row));
7142 if (height < min_height)
7143 height = min_height;
7145 yyy_set_row_height(sheet, row, height);
7146 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
7147 size_allocate_row_title_buttons (sheet);
7153 gtk_sheet_set_column_width (GtkSheet * sheet,
7159 g_return_if_fail (sheet != NULL);
7160 g_return_if_fail (GTK_IS_SHEET (sheet));
7162 if (column < 0 || column >= xxx_column_count(sheet))
7165 gtk_sheet_column_size_request(sheet, column, &min_width);
7166 if(width < min_width) return;
7168 xxx_set_column_width(sheet, column, width);
7170 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7171 size_allocate_column_title_buttons (sheet);
7172 adjust_scrollbars (sheet);
7173 gtk_sheet_size_allocate_entry(sheet);
7174 gtk_sheet_range_draw (sheet, NULL);
7177 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, column);
7178 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_COL_WIDTH], column, width);
7185 gtk_sheet_set_row_height (GtkSheet * sheet,
7191 g_return_if_fail (sheet != NULL);
7192 g_return_if_fail (GTK_IS_SHEET (sheet));
7194 if (row < 0 || row >= yyy_row_count(sheet))
7197 gtk_sheet_row_size_request(sheet, row, &min_height);
7198 if(height < min_height) return;
7200 yyy_set_row_height(sheet, row, height);
7202 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7203 size_allocate_row_title_buttons (sheet);
7204 adjust_scrollbars (sheet);
7205 gtk_sheet_size_allocate_entry(sheet);
7206 gtk_sheet_range_draw (sheet, NULL);
7209 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], row, -1);
7210 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_ROW_HEIGHT], row, height);
7216 gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr *attributes)
7218 const GdkColor *fg, *bg;
7219 const GtkJustification *j ;
7220 const PangoFontDescription *font_desc ;
7221 const GtkSheetCellBorder *border ;
7223 g_return_val_if_fail (sheet != NULL, FALSE);
7224 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
7226 if(row < 0 || col < 0) return FALSE;
7228 init_attributes(sheet, col, attributes);
7233 attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
7234 attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
7236 fg = g_sheet_model_get_foreground(sheet->model, row, col);
7238 attributes->foreground = *fg;
7240 bg = g_sheet_model_get_background(sheet->model, row, col);
7242 attributes->background = *bg;
7244 j = g_sheet_model_get_justification(sheet->model, row, col);
7245 if (j) attributes->justification = *j;
7247 font_desc = g_sheet_model_get_font_desc(sheet->model, row, col);
7248 if ( font_desc ) attributes->font_desc = font_desc;
7250 border = g_sheet_model_get_cell_border(sheet->model, row, col);
7252 if ( border ) attributes->border = *border;
7258 init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
7260 /* DEFAULT VALUES */
7261 attributes->foreground = GTK_WIDGET(sheet)->style->black;
7262 attributes->background = sheet->bg_color;
7263 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
7264 GdkColormap *colormap;
7265 colormap=gdk_colormap_get_system();
7266 gdk_color_black(colormap, &attributes->foreground);
7267 attributes->background = sheet->bg_color;
7269 attributes->justification = xxx_column_justification(sheet, col);
7270 attributes->border.width = 0;
7271 attributes->border.line_style = GDK_LINE_SOLID;
7272 attributes->border.cap_style = GDK_CAP_NOT_LAST;
7273 attributes->border.join_style = GDK_JOIN_MITER;
7274 attributes->border.mask = 0;
7275 attributes->border.color = GTK_WIDGET(sheet)->style->black;
7276 attributes->is_editable = TRUE;
7277 attributes->is_visible = TRUE;
7278 attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
7284 /********************************************************************
7285 * Container Functions:
7290 * gtk_sheet_move_child
7291 * gtk_sheet_position_child
7292 * gtk_sheet_position_children
7293 * gtk_sheet_realize_child
7294 * gtk_sheet_get_child_at
7295 ********************************************************************/
7298 gtk_sheet_put(GtkSheet *sheet, GtkWidget *child, gint x, gint y)
7300 GtkRequisition child_requisition;
7301 GtkSheetChild *child_info;
7303 g_return_val_if_fail(sheet != NULL, NULL);
7304 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7305 g_return_val_if_fail(child != NULL, NULL);
7306 g_return_val_if_fail(child->parent == NULL, NULL);
7308 child_info = g_new (GtkSheetChild, 1);
7309 child_info->widget = child;
7312 child_info->attached_to_cell = FALSE;
7313 child_info->floating = TRUE;
7314 child_info->xpadding = child_info->ypadding = 0;
7315 child_info->xexpand = child_info->yexpand = FALSE;
7316 child_info->xshrink = child_info->yshrink = FALSE;
7317 child_info->xfill = child_info->yfill = FALSE;
7319 sheet->children = g_list_append(sheet->children, child_info);
7321 gtk_widget_set_parent (child, GTK_WIDGET(sheet));
7323 gtk_widget_size_request(child, &child_requisition);
7325 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7327 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7328 (!GTK_WIDGET_REALIZED(child) || GTK_WIDGET_NO_WINDOW(child)))
7329 gtk_sheet_realize_child(sheet, child_info);
7331 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7332 !GTK_WIDGET_MAPPED(child))
7333 gtk_widget_map(child);
7336 gtk_sheet_position_child(sheet, child_info);
7338 /* This will avoid drawing on the titles */
7340 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7342 if(sheet->row_titles_visible)
7343 gdk_window_show(sheet->row_title_window);
7344 if(sheet->column_titles_visible)
7345 gdk_window_show(sheet->column_title_window);
7348 return (child_info);
7352 gtk_sheet_attach_floating (GtkSheet *sheet,
7357 GtkSheetChild *child;
7359 if(row < 0 || col < 0){
7360 gtk_sheet_button_attach(sheet, widget, row, col);
7364 gtk_sheet_get_cell_area(sheet, row, col, &area);
7365 child = gtk_sheet_put(sheet, widget, area.x, area.y);
7366 child->attached_to_cell = TRUE;
7372 gtk_sheet_attach_default (GtkSheet *sheet,
7376 if(row < 0 || col < 0){
7377 gtk_sheet_button_attach(sheet, widget, row, col);
7381 gtk_sheet_attach(sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
7385 gtk_sheet_attach (GtkSheet *sheet,
7394 GtkSheetChild *child = NULL;
7396 if(row < 0 || col < 0){
7397 gtk_sheet_button_attach(sheet, widget, row, col);
7401 child = g_new0(GtkSheetChild, 1);
7402 child->attached_to_cell = TRUE;
7403 child->floating = FALSE;
7404 child->widget = widget;
7407 child->xpadding = xpadding;
7408 child->ypadding = ypadding;
7409 child->xexpand = (xoptions & GTK_EXPAND) != 0;
7410 child->yexpand = (yoptions & GTK_EXPAND) != 0;
7411 child->xshrink = (xoptions & GTK_SHRINK) != 0;
7412 child->yshrink = (yoptions & GTK_SHRINK) != 0;
7413 child->xfill = (xoptions & GTK_FILL) != 0;
7414 child->yfill = (yoptions & GTK_FILL) != 0;
7416 sheet->children = g_list_append(sheet->children, child);
7418 gtk_sheet_get_cell_area(sheet, row, col, &area);
7420 child->x = area.x + child->xpadding;
7421 child->y = area.y + child->ypadding;
7423 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7425 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7426 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7427 gtk_sheet_realize_child(sheet, child);
7429 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7430 !GTK_WIDGET_MAPPED(widget))
7431 gtk_widget_map(widget);
7434 gtk_sheet_position_child(sheet, child);
7436 /* This will avoid drawing on the titles */
7438 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7440 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
7441 gdk_window_show(sheet->row_title_window);
7442 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
7443 gdk_window_show(sheet->column_title_window);
7449 gtk_sheet_button_attach (GtkSheet *sheet,
7453 GtkSheetButton *button = 0;
7454 GtkSheetChild *child;
7455 GtkRequisition button_requisition;
7457 if(row >= 0 && col >= 0) return;
7458 if(row < 0 && col < 0) return;
7460 child = g_new (GtkSheetChild, 1);
7461 child->widget = widget;
7464 child->attached_to_cell = TRUE;
7465 child->floating = FALSE;
7468 child->xpadding = child->ypadding = 0;
7469 child->xshrink = child->yshrink = FALSE;
7470 child->xfill = child->yfill = FALSE;
7473 sheet->children = g_list_append(sheet->children, child);
7475 gtk_sheet_button_size_request(sheet, button, &button_requisition);
7478 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7480 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7481 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7482 gtk_sheet_realize_child(sheet, child);
7484 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7485 !GTK_WIDGET_MAPPED(widget))
7486 gtk_widget_map(widget);
7489 if(row == -1) size_allocate_column_title_buttons(sheet);
7490 if(col == -1) size_allocate_row_title_buttons(sheet);
7495 label_size_request(GtkSheet *sheet, gchar *label, GtkRequisition *req)
7500 gint row_height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)) - 2*CELLOFFSET + 2;
7506 while(words && *words != '\0'){
7507 if(*words == '\n' || *(words+1) == '\0'){
7508 req->height += row_height;
7511 req->width = MAX(req->width, STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, word));
7519 if(n > 0) req->height -= 2;
7523 gtk_sheet_button_size_request (GtkSheet *sheet,
7524 const GtkSheetButton *button,
7525 GtkRequisition *button_requisition)
7527 GtkRequisition requisition;
7528 GtkRequisition label_requisition;
7530 if(gtk_sheet_autoresize(sheet) && button->label && strlen(button->label) > 0){
7531 label_size_request(sheet, button->label, &label_requisition);
7532 label_requisition.width += 2*CELLOFFSET;
7533 label_requisition.height += 2*CELLOFFSET;
7535 label_requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7536 label_requisition.width = COLUMN_MIN_WIDTH;
7541 gtk_widget_size_request(button->child->widget, &requisition);
7542 requisition.width += 2*button->child->xpadding;
7543 requisition.height += 2*button->child->ypadding;
7544 requisition.width += 2*sheet->button->style->xthickness;
7545 requisition.height += 2*sheet->button->style->ythickness;
7549 requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7550 requisition.width = COLUMN_MIN_WIDTH;
7553 *button_requisition = requisition;
7554 button_requisition->width = MAX(requisition.width, label_requisition.width);
7555 button_requisition->height = MAX(requisition.height, label_requisition.height);
7560 gtk_sheet_row_size_request (GtkSheet *sheet,
7564 GtkRequisition button_requisition;
7567 gtk_sheet_button_size_request(sheet,
7568 yyy_row_button(sheet, row),
7569 &button_requisition);
7571 *requisition = button_requisition.height;
7573 children = sheet->children;
7575 GtkSheetChild *child = (GtkSheetChild *)children->data;
7576 GtkRequisition child_requisition;
7578 if(child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink){
7579 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7581 if(child_requisition.height + 2 * child->ypadding > *requisition)
7582 *requisition = child_requisition.height + 2 * child->ypadding;
7584 children = children->next;
7587 sheet->row_requisition = * requisition;
7591 gtk_sheet_column_size_request (GtkSheet *sheet,
7595 GtkRequisition button_requisition;
7598 gtk_sheet_button_size_request(sheet,
7599 xxx_column_button(sheet, col),
7600 &button_requisition);
7602 *requisition = button_requisition.width;
7604 children = sheet->children;
7606 GtkSheetChild *child = (GtkSheetChild *)children->data;
7607 GtkRequisition child_requisition;
7609 if(child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink){
7610 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7612 if(child_requisition.width + 2 * child->xpadding > *requisition)
7613 *requisition = child_requisition.width + 2 * child->xpadding;
7615 children = children->next;
7618 sheet->column_requisition = *requisition;
7622 gtk_sheet_move_child(GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
7624 GtkSheetChild *child;
7627 g_return_if_fail(sheet != NULL);
7628 g_return_if_fail(GTK_IS_SHEET(sheet));
7630 children = sheet->children;
7633 child = children->data;
7635 if(child->widget == widget){
7638 child->row = ROW_FROM_YPIXEL(sheet, y);
7639 child->col = COLUMN_FROM_XPIXEL(sheet, x);
7640 gtk_sheet_position_child(sheet, child);
7644 children = children->next;
7647 g_warning("Widget must be a GtkSheet child");
7652 gtk_sheet_position_child(GtkSheet *sheet, GtkSheetChild *child)
7654 GtkRequisition child_requisition;
7655 GtkAllocation child_allocation;
7661 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7663 if(sheet->column_titles_visible)
7664 yoffset = sheet->column_title_area.height;
7666 if(sheet->row_titles_visible)
7667 xoffset = sheet->row_title_area.width;
7669 if(child->attached_to_cell){
7671 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col);
7672 child->y = ROW_TOP_YPIXEL(sheet, child->row);
7674 if(sheet->row_titles_visible)
7675 child->x-=sheet->row_title_area.width;
7676 if(sheet->column_titles_visible)
7677 child->y-=sheet->column_title_area.height;
7679 width = xxx_column_width(sheet, child->col);
7680 height = yyy_row_height(sheet, child->row);
7683 gtk_sheet_get_cell_area(sheet, child->row, child->col, &area);
7684 child->x = area.x + child->xpadding;
7685 child->y = area.y + child->ypadding;
7687 if(!child->floating){
7688 if(child_requisition.width + 2*child->xpadding <= xxx_column_width(sheet, child->col)){
7690 child_requisition.width = child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7693 child->x = area.x + xxx_column_width(sheet, child->col) / 2 -
7694 child_requisition.width / 2;
7696 child_allocation.width = child_requisition.width;
7699 if(!child->xshrink){
7700 gtk_sheet_set_column_width(sheet, child->col, child_requisition.width + 2 * child->xpadding);
7702 child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7705 if(child_requisition.height + 2*child->ypadding <= yyy_row_height(sheet, child->row)){
7707 child_requisition.height = child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7710 child->y = area.y + yyy_row_height(sheet, child->row) / 2 -
7711 child_requisition.height / 2;
7713 child_allocation.height = child_requisition.height;
7716 if(!child->yshrink){
7717 gtk_sheet_set_row_height(sheet, child->row, child_requisition.height + 2 * child->ypadding);
7719 child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7722 child_allocation.width = child_requisition.width;
7723 child_allocation.height = child_requisition.height;
7726 x = child_allocation.x = child->x + xoffset;
7727 y = child_allocation.y = child->y + yoffset;
7731 x = child_allocation.x = child->x + sheet->hoffset + xoffset;
7732 x = child_allocation.x = child->x + xoffset;
7733 y = child_allocation.y = child->y + sheet->voffset + yoffset;
7734 y = child_allocation.y = child->y + yoffset;
7735 child_allocation.width = child_requisition.width;
7736 child_allocation.height = child_requisition.height;
7739 gtk_widget_size_allocate(child->widget, &child_allocation);
7740 gtk_widget_queue_draw(child->widget);
7744 gtk_sheet_forall (GtkContainer *container,
7745 gboolean include_internals,
7746 GtkCallback callback,
7747 gpointer callback_data)
7750 GtkSheetChild *child;
7753 g_return_if_fail (GTK_IS_SHEET (container));
7754 g_return_if_fail (callback != NULL);
7756 sheet = GTK_SHEET (container);
7757 children = sheet->children;
7760 child = children->data;
7761 children = children->next;
7763 (* callback) (child->widget, callback_data);
7766 (* callback) (sheet->button, callback_data);
7767 if(sheet->sheet_entry)
7768 (* callback) (sheet->sheet_entry, callback_data);
7773 gtk_sheet_position_children(GtkSheet *sheet)
7776 GtkSheetChild *child;
7778 children = sheet->children;
7782 child = (GtkSheetChild *)children->data;
7784 if(child->col !=-1 && child->row != -1)
7785 gtk_sheet_position_child(sheet, child);
7787 if(child->row == -1){
7788 if(child->col < MIN_VISIBLE_COLUMN(sheet) ||
7789 child->col > MAX_VISIBLE_COLUMN(sheet))
7790 gtk_sheet_child_hide(child);
7792 gtk_sheet_child_show(child);
7794 if(child->col == -1){
7795 if(child->row < MIN_VISIBLE_ROW(sheet) ||
7796 child->row > MAX_VISIBLE_ROW(sheet))
7797 gtk_sheet_child_hide(child);
7799 gtk_sheet_child_show(child);
7802 children = children->next;
7808 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
7812 GtkSheetChild *child = 0;
7814 g_return_if_fail(container != NULL);
7815 g_return_if_fail(GTK_IS_SHEET(container));
7817 sheet = GTK_SHEET(container);
7819 children = sheet->children;
7823 child = (GtkSheetChild *)children->data;
7825 if(child->widget == widget) break;
7827 children = children->next;
7832 gtk_widget_unparent (widget);
7833 child->widget = NULL;
7835 sheet->children = g_list_remove_link (sheet->children, children);
7836 g_list_free_1 (children);
7843 gtk_sheet_realize_child(GtkSheet *sheet, GtkSheetChild *child)
7847 widget = GTK_WIDGET(sheet);
7849 if(GTK_WIDGET_REALIZED(widget)){
7850 if(child->row == -1)
7851 gtk_widget_set_parent_window(child->widget, sheet->column_title_window);
7852 else if(child->col == -1)
7853 gtk_widget_set_parent_window(child->widget, sheet->row_title_window);
7855 gtk_widget_set_parent_window(child->widget, sheet->sheet_window);
7858 gtk_widget_set_parent(child->widget, widget);
7864 gtk_sheet_get_child_at(GtkSheet *sheet, gint row, gint col)
7867 GtkSheetChild *child = 0;
7869 g_return_val_if_fail(sheet != NULL, NULL);
7870 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7872 children = sheet->children;
7876 child = (GtkSheetChild *)children->data;
7878 if(child->attached_to_cell)
7879 if(child->row == row && child->col == col) break;
7881 children = children->next;
7884 if(children) return child;
7890 gtk_sheet_child_hide(GtkSheetChild *child)
7892 g_return_if_fail(child != NULL);
7893 gtk_widget_hide(child->widget);
7897 gtk_sheet_child_show(GtkSheetChild *child)
7899 g_return_if_fail(child != NULL);
7901 gtk_widget_show(child->widget);
7905 gtk_sheet_get_model(const GtkSheet *sheet)
7907 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
7909 return sheet->model;
7914 gtk_sheet_button_new(void)
7916 GtkSheetButton *button = g_slice_new(GtkSheetButton);
7918 button->state = GTK_STATE_NORMAL;
7919 button->label = NULL;
7920 button->label_visible = TRUE;
7921 button->child = NULL;
7922 button->justification = GTK_JUSTIFY_FILL;
7929 gtk_sheet_button_free(GtkSheetButton *button)
7931 g_free(button->label);
7932 g_slice_free(GtkSheetButton, button);