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
27 * @short_description: spreadsheet widget for gtk2
29 * GtkSheet is a matrix widget for GTK+. It consists of an scrollable grid of
30 * cells where you can allocate text. Cell contents can be edited interactively
31 * through a specially designed entry, GtkItemEntry. It is also a container
32 * subclass, allowing you to display buttons, curves, pixmaps and any other
35 * You can also set many attributes as: border, foreground and background color,
36 * text justification, and more.
38 * The testgtksheet program shows how easy is to create a spreadsheet -like GUI
48 #include <gdk/gdkkeysyms.h>
49 #include <gtk/gtksignal.h>
50 #include <gtk/gtklabel.h>
51 #include <gtk/gtkbutton.h>
52 #include <gtk/gtkadjustment.h>
53 #include <gtk/gtktable.h>
54 #include <gtk/gtkbox.h>
55 #include <gtk/gtkmain.h>
56 #include <gtk/gtktypeutils.h>
57 #include <gtk/gtkentry.h>
58 #include <gtk/gtkcontainer.h>
59 #include <gtk/gtkpixmap.h>
60 #include <pango/pango.h>
61 #include "gtkitementry.h"
63 #include "gtkextra-marshal.h"
64 #include "gsheetmodel.h"
69 GTK_SHEET_IS_LOCKED = 1 << 0,
70 GTK_SHEET_IS_FROZEN = 1 << 1,
71 GTK_SHEET_IN_XDRAG = 1 << 2,
72 GTK_SHEET_IN_YDRAG = 1 << 3,
73 GTK_SHEET_IN_DRAG = 1 << 4,
74 GTK_SHEET_IN_SELECTION = 1 << 5,
75 GTK_SHEET_IN_RESIZE = 1 << 6,
76 GTK_SHEET_IN_CLIP = 1 << 7,
77 GTK_SHEET_REDRAW_PENDING = 1 << 8,
80 #define GTK_SHEET_FLAGS(sheet) (GTK_SHEET (sheet)->flags)
81 #define GTK_SHEET_SET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) |= (flag))
82 #define GTK_SHEET_UNSET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) &= ~ (flag))
84 #define GTK_SHEET_IS_LOCKED(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_LOCKED)
87 #define GTK_SHEET_IS_FROZEN(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN)
88 #define GTK_SHEET_IN_XDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG)
89 #define GTK_SHEET_IN_YDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG)
90 #define GTK_SHEET_IN_DRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_DRAG)
91 #define GTK_SHEET_IN_SELECTION(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_SELECTION)
92 #define GTK_SHEET_IN_RESIZE(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_RESIZE)
93 #define GTK_SHEET_IN_CLIP(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_CLIP)
94 #define GTK_SHEET_REDRAW_PENDING(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_REDRAW_PENDING)
96 #define CELL_SPACING 1
98 #define TIMEOUT_SCROLL 20
99 #define TIMEOUT_FLASH 200
100 #define TIME_INTERVAL 8
101 #define COLUMN_MIN_WIDTH 10
106 #define DEFAULT_COLUMN_WIDTH 80
109 static void gtk_sheet_column_title_button_draw (GtkSheet *sheet, gint column);
111 static void gtk_sheet_row_title_button_draw (GtkSheet *sheet, gint row);
114 static gboolean gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col);
117 void dispose_string (const GtkSheet *sheet, gchar *text)
119 GSheetModel *model = gtk_sheet_get_model (sheet);
124 if (g_sheet_model_free_strings (model))
129 guint DEFAULT_ROW_HEIGHT (GtkWidget *widget)
131 if (!widget->style->font_desc) return 24;
134 PangoContext *context = gtk_widget_get_pango_context (widget);
135 PangoFontMetrics *metrics =
136 pango_context_get_metrics (context,
137 widget->style->font_desc,
138 pango_context_get_language (context));
139 guint val = pango_font_metrics_get_descent (metrics) +
140 pango_font_metrics_get_ascent (metrics);
141 pango_font_metrics_unref (metrics);
142 return PANGO_PIXELS (val)+2 * CELLOFFSET;
147 guint DEFAULT_FONT_ASCENT (GtkWidget *widget)
149 if (!widget->style->font_desc) return 12;
152 PangoContext *context = gtk_widget_get_pango_context (widget);
153 PangoFontMetrics *metrics =
154 pango_context_get_metrics (context,
155 widget->style->font_desc,
156 pango_context_get_language (context));
157 guint val = pango_font_metrics_get_ascent (metrics);
158 pango_font_metrics_unref (metrics);
159 return PANGO_PIXELS (val);
164 guint STRING_WIDTH (GtkWidget *widget,
165 const PangoFontDescription *font, const gchar *text)
170 layout = gtk_widget_create_pango_layout (widget, text);
171 pango_layout_set_font_description (layout, font);
173 pango_layout_get_extents (layout, NULL, &rect);
175 g_object_unref (G_OBJECT (layout));
176 return PANGO_PIXELS (rect.width);
180 guint DEFAULT_FONT_DESCENT (GtkWidget *widget)
182 if (!widget->style->font_desc) return 12;
185 PangoContext *context = gtk_widget_get_pango_context (widget);
186 PangoFontMetrics *metrics =
187 pango_context_get_metrics (context,
188 widget->style->font_desc,
189 pango_context_get_language (context));
190 guint val = pango_font_metrics_get_descent (metrics);
191 pango_font_metrics_unref (metrics);
192 return PANGO_PIXELS (val);
198 yyy_row_is_visible (const GtkSheet *sheet, gint row)
200 GSheetRow *row_geo = sheet->row_geometry;
202 return g_sheet_row_get_visibility (row_geo, row, 0);
207 yyy_row_is_sensitive (const GtkSheet *sheet, gint row)
209 GSheetRow *row_geo = sheet->row_geometry;
211 return g_sheet_row_get_sensitivity (row_geo, row, 0);
217 yyy_row_count (const GtkSheet *sheet)
219 GSheetRow *row_geo = sheet->row_geometry;
221 return g_sheet_row_get_row_count (row_geo, 0);
225 yyy_row_height (const GtkSheet *sheet, gint row)
227 GSheetRow *row_geo = sheet->row_geometry;
229 return g_sheet_row_get_height (row_geo, row, 0);
233 yyy_row_top_ypixel (const GtkSheet *sheet, gint row)
235 GSheetRow *geo = sheet->row_geometry;
237 gint y = g_sheet_row_start_pixel (geo, row, 0);
239 if ( sheet->column_titles_visible )
240 y += sheet->column_title_area.height;
246 /* Return the row containing pixel Y */
248 yyy_row_ypixel_to_row (const GtkSheet *sheet, gint y)
250 GSheetRow *geo = sheet->row_geometry;
252 gint cy = sheet->voffset;
254 if (sheet->column_titles_visible)
255 cy += sheet->column_title_area.height;
257 if (y < cy) return 0;
259 return g_sheet_row_pixel_to_row (geo, y - cy, 0);
263 /* gives the top pixel of the given row in context of
264 * the sheet's voffset */
266 ROW_TOP_YPIXEL (const GtkSheet *sheet, gint row)
268 return (sheet->voffset + yyy_row_top_ypixel (sheet, row));
272 /* returns the row index from a y pixel location in the
273 * context of the sheet's voffset */
275 ROW_FROM_YPIXEL (const GtkSheet *sheet, gint y)
277 return (yyy_row_ypixel_to_row (sheet, y));
280 static inline GtkSheetButton *
281 xxx_column_button (const GtkSheet *sheet, gint col)
283 GSheetColumn *col_geo = sheet->column_geometry;
284 if ( col < 0 ) return NULL ;
286 return g_sheet_column_get_button (col_geo, col);
291 xxx_column_left_xpixel (const GtkSheet *sheet, gint col)
293 GSheetColumn *geo = sheet->column_geometry;
295 gint x = g_sheet_column_start_pixel (geo, col);
297 if ( sheet->row_titles_visible )
298 x += sheet->row_title_area.width;
304 xxx_column_width (const GtkSheet *sheet, gint col)
306 GSheetColumn *col_geo = sheet->column_geometry;
308 return g_sheet_column_get_width (col_geo, col);
313 xxx_set_column_width (GtkSheet *sheet, gint col, gint width)
315 if ( sheet->column_geometry )
316 g_sheet_column_set_width (sheet->column_geometry, col, width);
320 xxx_column_set_left_column (GtkSheet *sheet, gint col, gint i)
322 GSheetColumn *col_geo = sheet->column_geometry;
324 g_sheet_column_set_left_text_column (col_geo, col, i);
328 xxx_column_left_column (const GtkSheet *sheet, gint col)
330 GSheetColumn *col_geo = sheet->column_geometry;
332 return g_sheet_column_get_left_text_column (col_geo, col);
336 xxx_column_set_right_column (GtkSheet *sheet, gint col, gint i)
338 GSheetColumn *col_geo = sheet->column_geometry;
340 g_sheet_column_set_right_text_column (col_geo, col, i);
344 xxx_column_right_column (const GtkSheet *sheet, gint col)
346 GSheetColumn *col_geo = sheet->column_geometry;
348 return g_sheet_column_get_right_text_column (col_geo, col);
351 static inline GtkJustification
352 xxx_column_justification (const GtkSheet *sheet, gint col)
354 GSheetColumn *col_geo = sheet->column_geometry;
356 return g_sheet_column_get_justification (col_geo, col);
360 xxx_column_is_visible (const GtkSheet *sheet, gint col)
362 GSheetColumn *col_geo = sheet->column_geometry;
364 return g_sheet_column_get_visibility (col_geo, col);
369 xxx_column_is_sensitive (const GtkSheet *sheet, gint col)
371 GSheetColumn *col_geo = sheet->column_geometry;
373 return g_sheet_column_get_sensitivity (col_geo, col);
377 /* gives the left pixel of the given column in context of
378 * the sheet's hoffset */
380 COLUMN_LEFT_XPIXEL (const GtkSheet *sheet, gint ncol)
382 return (sheet->hoffset + xxx_column_left_xpixel (sheet, ncol));
386 xxx_column_count (const GtkSheet *sheet)
388 GSheetColumn *col_geo = sheet->column_geometry;
390 return g_sheet_column_get_column_count (col_geo);
393 /* returns the column index from a x pixel location in the
394 * context of the sheet's hoffset */
396 COLUMN_FROM_XPIXEL (const GtkSheet * sheet,
402 if ( sheet->row_titles_visible )
403 cx += sheet->row_title_area.width;
405 if (x < cx) return 0;
406 for (i = 0; i < xxx_column_count (sheet); i++)
408 if (x >= cx && x <= (cx + xxx_column_width (sheet, i)) &&
409 xxx_column_is_visible (sheet, i))
411 if ( xxx_column_is_visible (sheet, i))
412 cx += xxx_column_width (sheet, i);
416 return xxx_column_count (sheet) - 1;
419 /* returns the total height of the sheet */
420 static inline gint SHEET_HEIGHT (GtkSheet *sheet)
422 const gint n_rows = yyy_row_count (sheet);
424 return yyy_row_top_ypixel (sheet, n_rows - 1) +
425 yyy_row_height (sheet, n_rows - 1);
429 static inline GtkSheetButton *
430 yyy_row_button (GtkSheet *sheet, gint row)
432 GSheetRow *row_geo = sheet->row_geometry;
434 return g_sheet_row_get_button (row_geo, row, sheet);
441 yyy_set_row_height (GtkSheet *sheet, gint row, gint height)
443 if ( sheet->row_geometry )
444 g_sheet_row_set_height (sheet->row_geometry, row, height, sheet);
449 /* returns the total width of the sheet */
450 static inline gint SHEET_WIDTH (GtkSheet *sheet)
454 cx = ( sheet->row_titles_visible ? sheet->row_title_area.width : 0);
456 for (i = 0; i < xxx_column_count (sheet); i++)
457 if (xxx_column_is_visible (sheet, i))
458 cx += xxx_column_width (sheet, i);
463 #define MIN_VISIBLE_ROW(sheet) sheet->view.row0
464 #define MAX_VISIBLE_ROW(sheet) sheet->view.rowi
465 #define MIN_VISIBLE_COLUMN(sheet) sheet->view.col0
466 #define MAX_VISIBLE_COLUMN(sheet) sheet->view.coli
469 static inline gboolean
470 POSSIBLE_XDRAG (const GtkSheet *sheet, gint x, gint *drag_column)
474 column = COLUMN_FROM_XPIXEL (sheet, x);
475 *drag_column = column;
477 xdrag = COLUMN_LEFT_XPIXEL (sheet, column) + CELL_SPACING;
478 if (x <= xdrag + DRAG_WIDTH / 2 && column != 0)
480 while (! xxx_column_is_visible (sheet, column - 1) && column > 0) column--;
481 *drag_column = column - 1;
482 return xxx_column_is_sensitive (sheet, column - 1);
485 xdrag += xxx_column_width (sheet, column);
486 if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2)
487 return xxx_column_is_sensitive (sheet, column);
492 static inline gboolean
493 POSSIBLE_YDRAG (const GtkSheet *sheet, gint y, gint *drag_row)
496 row = ROW_FROM_YPIXEL (sheet, y);
499 ydrag = ROW_TOP_YPIXEL (sheet,row)+CELL_SPACING;
500 if (y <= ydrag + DRAG_WIDTH / 2 && row != 0)
502 while (!yyy_row_is_visible (sheet, row - 1) && row > 0) row--;
504 return yyy_row_is_sensitive (sheet, row - 1);
507 ydrag +=yyy_row_height (sheet, row);
509 if (y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2)
510 return yyy_row_is_sensitive (sheet, row);
516 static inline gboolean
517 POSSIBLE_DRAG (const GtkSheet *sheet, gint x, gint y,
518 gint *drag_row, gint *drag_column)
522 /* Can't drag if nothing is selected */
523 if ( sheet->range.row0 < 0 || sheet->range.rowi < 0 ||
524 sheet->range.col0 < 0 || sheet->range.coli < 0 )
527 *drag_column = COLUMN_FROM_XPIXEL (sheet, x);
528 *drag_row = ROW_FROM_YPIXEL (sheet, y);
530 if (x >= COLUMN_LEFT_XPIXEL (sheet, sheet->range.col0) - DRAG_WIDTH / 2 &&
531 x <= COLUMN_LEFT_XPIXEL (sheet, sheet->range.coli) +
532 xxx_column_width (sheet, sheet->range.coli) + DRAG_WIDTH / 2)
534 ydrag = ROW_TOP_YPIXEL (sheet,sheet->range.row0);
535 if (y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2)
537 *drag_row = sheet->range.row0;
540 ydrag = ROW_TOP_YPIXEL (sheet, sheet->range.rowi) +
541 yyy_row_height (sheet, sheet->range.rowi);
542 if (y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2)
544 *drag_row = sheet->range.rowi;
549 if (y >= ROW_TOP_YPIXEL (sheet, sheet->range.row0) - DRAG_WIDTH / 2 &&
550 y <= ROW_TOP_YPIXEL (sheet, sheet->range.rowi) +
551 yyy_row_height (sheet, sheet->range.rowi) + DRAG_WIDTH / 2)
553 xdrag = COLUMN_LEFT_XPIXEL (sheet, sheet->range.col0);
554 if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2)
556 *drag_column = sheet->range.col0;
559 xdrag = COLUMN_LEFT_XPIXEL (sheet, sheet->range.coli) +
560 xxx_column_width (sheet, sheet->range.coli);
561 if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2)
563 *drag_column = sheet->range.coli;
571 static inline gboolean
572 POSSIBLE_RESIZE (const GtkSheet *sheet, gint x, gint y,
573 gint *drag_row, gint *drag_column)
577 /* Can't drag if nothing is selected */
578 if ( sheet->range.row0 < 0 || sheet->range.rowi < 0 ||
579 sheet->range.col0 < 0 || sheet->range.coli < 0 )
582 xdrag = COLUMN_LEFT_XPIXEL (sheet,sheet->range.coli)+
583 xxx_column_width (sheet, sheet->range.coli);
585 ydrag = ROW_TOP_YPIXEL (sheet,sheet->range.rowi)+
586 yyy_row_height (sheet, sheet->range.rowi);
588 if (sheet->state == GTK_SHEET_COLUMN_SELECTED)
589 ydrag = ROW_TOP_YPIXEL (sheet, sheet->view.row0);
591 if (sheet->state == GTK_SHEET_ROW_SELECTED)
592 xdrag = COLUMN_LEFT_XPIXEL (sheet, sheet->view.col0);
594 *drag_column = COLUMN_FROM_XPIXEL (sheet,x);
595 *drag_row = ROW_FROM_YPIXEL (sheet,y);
597 if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2 &&
598 y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2) return TRUE;
603 static void gtk_sheet_class_init (GtkSheetClass * klass);
604 static void gtk_sheet_init (GtkSheet * sheet);
605 static void gtk_sheet_destroy (GtkObject * object);
606 static void gtk_sheet_finalize (GObject * object);
607 static void gtk_sheet_style_set (GtkWidget *widget,
608 GtkStyle *previous_style);
609 static void gtk_sheet_realize (GtkWidget * widget);
610 static void gtk_sheet_unrealize (GtkWidget * widget);
611 static void gtk_sheet_map (GtkWidget * widget);
612 static void gtk_sheet_unmap (GtkWidget * widget);
613 static gint gtk_sheet_expose (GtkWidget * widget,
614 GdkEventExpose * event);
615 static void gtk_sheet_forall (GtkContainer *container,
616 gboolean include_internals,
617 GtkCallback callback,
618 gpointer callback_data);
620 static void gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
621 GtkAdjustment *hadjustment,
622 GtkAdjustment *vadjustment);
624 static gint gtk_sheet_button_press (GtkWidget * widget,
625 GdkEventButton * event);
626 static gint gtk_sheet_button_release (GtkWidget * widget,
627 GdkEventButton * event);
628 static gint gtk_sheet_motion (GtkWidget * widget,
629 GdkEventMotion * event);
630 static gint gtk_sheet_entry_key_press (GtkWidget *widget,
632 static gint gtk_sheet_key_press (GtkWidget *widget,
634 static void gtk_sheet_size_request (GtkWidget * widget,
635 GtkRequisition * requisition);
636 static void gtk_sheet_size_allocate (GtkWidget * widget,
637 GtkAllocation * allocation);
641 static gint gtk_sheet_range_isvisible (GtkSheet * sheet,
642 GtkSheetRange range);
643 static gint gtk_sheet_cell_isvisible (GtkSheet * sheet,
644 gint row, gint column);
647 static gint gtk_sheet_scroll (gpointer data);
648 static gint gtk_sheet_flash (gpointer data);
650 /* Drawing Routines */
652 /* draw cell background and frame */
653 static void gtk_sheet_cell_draw_default (GtkSheet *sheet,
654 gint row, gint column);
656 /* draw cell border */
657 static void gtk_sheet_cell_draw_border (GtkSheet *sheet,
658 gint row, gint column,
661 /* draw cell contents */
662 static void gtk_sheet_cell_draw_label (GtkSheet *sheet,
663 gint row, gint column);
665 /* draw visible part of range. If range == NULL then draw the whole screen */
666 static void gtk_sheet_range_draw (GtkSheet *sheet,
667 const GtkSheetRange *range);
669 /* highlight the visible part of the selected range */
670 static void gtk_sheet_range_draw_selection (GtkSheet *sheet,
671 GtkSheetRange range);
675 static gint gtk_sheet_move_query (GtkSheet *sheet,
676 gint row, gint column);
677 static void gtk_sheet_real_select_range (GtkSheet * sheet,
678 const GtkSheetRange * range);
679 static void gtk_sheet_real_unselect_range (GtkSheet * sheet,
680 const GtkSheetRange * range);
681 static void gtk_sheet_extend_selection (GtkSheet *sheet,
682 gint row, gint column);
683 static void gtk_sheet_new_selection (GtkSheet *sheet,
684 GtkSheetRange *range);
685 static void gtk_sheet_draw_border (GtkSheet *sheet,
686 GtkSheetRange range);
687 static void gtk_sheet_draw_corners (GtkSheet *sheet,
688 GtkSheetRange range);
691 /* Active Cell handling */
693 static void gtk_sheet_entry_changed (GtkWidget *widget,
695 static gboolean gtk_sheet_deactivate_cell (GtkSheet *sheet);
696 static void gtk_sheet_hide_active_cell (GtkSheet *sheet);
697 static gboolean gtk_sheet_activate_cell (GtkSheet *sheet,
699 static void gtk_sheet_draw_active_cell (GtkSheet *sheet);
700 static void gtk_sheet_show_active_cell (GtkSheet *sheet);
701 static void gtk_sheet_click_cell (GtkSheet *sheet,
708 static void gtk_sheet_make_backing_pixmap (GtkSheet *sheet,
709 guint width, guint height);
710 static void gtk_sheet_draw_backing_pixmap (GtkSheet *sheet,
711 GtkSheetRange range);
714 static void adjust_scrollbars (GtkSheet * sheet);
715 static void vadjustment_changed (GtkAdjustment * adjustment,
717 static void hadjustment_changed (GtkAdjustment * adjustment,
719 static void vadjustment_value_changed (GtkAdjustment * adjustment,
721 static void hadjustment_value_changed (GtkAdjustment * adjustment,
725 static void draw_xor_vline (GtkSheet * sheet);
726 static void draw_xor_hline (GtkSheet * sheet);
727 static void draw_xor_rectangle (GtkSheet *sheet,
728 GtkSheetRange range);
729 static void gtk_sheet_draw_flashing_range (GtkSheet *sheet,
730 GtkSheetRange range);
731 static guint new_column_width (GtkSheet * sheet,
734 static guint new_row_height (GtkSheet * sheet,
739 static void create_global_button (GtkSheet *sheet);
740 static void global_button_clicked (GtkWidget *widget,
744 static void create_sheet_entry (GtkSheet *sheet);
745 static void gtk_sheet_size_allocate_entry (GtkSheet *sheet);
746 static void gtk_sheet_entry_set_max_size (GtkSheet *sheet);
748 /* Sheet button gadgets */
750 static void size_allocate_column_title_buttons (GtkSheet * sheet);
751 static void size_allocate_row_title_buttons (GtkSheet * sheet);
754 static void size_allocate_global_button (GtkSheet *sheet);
755 static void gtk_sheet_button_size_request (GtkSheet *sheet,
756 const GtkSheetButton *button,
757 GtkRequisition *requisition);
759 /* Attributes routines */
760 static void init_attributes (const GtkSheet *sheet, gint col,
761 GtkSheetCellAttr *attributes);
764 /* Memory allocation routines */
765 static void gtk_sheet_real_range_clear (GtkSheet *sheet,
766 const GtkSheetRange *range,
768 static void gtk_sheet_real_cell_clear (GtkSheet *sheet,
774 /* Container Functions */
775 static void gtk_sheet_remove (GtkContainer *container,
777 static void gtk_sheet_realize_child (GtkSheet *sheet,
778 GtkSheetChild *child);
779 static void gtk_sheet_position_child (GtkSheet *sheet,
780 GtkSheetChild *child);
781 static void gtk_sheet_position_children (GtkSheet *sheet);
782 static void gtk_sheet_child_show (GtkSheetChild *child);
783 static void gtk_sheet_child_hide (GtkSheetChild *child);
784 static void gtk_sheet_column_size_request (GtkSheet *sheet,
787 static void gtk_sheet_row_size_request (GtkSheet *sheet,
795 _gtkextra_signal_emit (GtkObject *object, guint signal_id, ...);
818 static GtkContainerClass *parent_class = NULL;
819 static guint sheet_signals[LAST_SIGNAL] = { 0 };
823 gtk_sheet_get_type ()
825 static GType sheet_type = 0;
829 static const GTypeInfo sheet_info =
831 sizeof (GtkSheetClass),
834 (GClassInitFunc) gtk_sheet_class_init,
839 (GInstanceInitFunc) gtk_sheet_init,
843 g_type_register_static (GTK_TYPE_CONTAINER, "GtkSheet",
849 static GtkSheetRange*
850 gtk_sheet_range_copy (const GtkSheetRange *range)
852 GtkSheetRange *new_range;
854 g_return_val_if_fail (range != NULL, NULL);
856 new_range = g_new (GtkSheetRange, 1);
864 gtk_sheet_range_free (GtkSheetRange *range)
866 g_return_if_fail (range != NULL);
872 gtk_sheet_range_get_type (void)
874 static GType sheet_range_type = 0;
876 if (!sheet_range_type)
879 g_boxed_type_register_static ("GtkSheetRange",
880 (GBoxedCopyFunc) gtk_sheet_range_copy,
881 (GBoxedFreeFunc)gtk_sheet_range_free);
884 return sheet_range_type;
888 gtk_sheet_class_init (GtkSheetClass * klass)
890 GtkObjectClass *object_class;
891 GtkWidgetClass *widget_class;
892 GtkContainerClass *container_class;
893 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
895 object_class = (GtkObjectClass *) klass;
896 widget_class = (GtkWidgetClass *) klass;
897 container_class = (GtkContainerClass *) klass;
899 parent_class = g_type_class_peek_parent (klass);
902 * GtkSheet::select-row
903 * @sheet: the sheet widget that emitted the signal
904 * @row: the newly selected row index
906 * A row has been selected.
908 sheet_signals[SELECT_ROW] =
909 gtk_signal_new ("select-row",
911 GTK_CLASS_TYPE (object_class),
912 GTK_SIGNAL_OFFSET (GtkSheetClass, select_row),
914 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
917 * GtkSheet::select - column
918 * @sheet: the sheet widget that emitted the signal
919 * @column: the newly selected column index
921 * A column has been selected.
923 sheet_signals[SELECT_COLUMN] =
924 gtk_signal_new ("select-column",
926 GTK_CLASS_TYPE (object_class),
927 GTK_SIGNAL_OFFSET (GtkSheetClass, select_column),
929 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
933 * GtkSheet::double - click - row
934 * @sheet: the sheet widget that emitted the signal
935 * @row: the row that was double clicked.
937 * A row's title button has been double clicked
939 sheet_signals[DOUBLE_CLICK_ROW] =
940 gtk_signal_new ("double-click-row",
942 GTK_CLASS_TYPE (object_class),
945 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
949 * GtkSheet::double - click - column
950 * @sheet: the sheet widget that emitted the signal
951 * @column: the column that was double clicked.
953 * A column's title button has been double clicked
955 sheet_signals[DOUBLE_CLICK_COLUMN] =
956 gtk_signal_new ("double-click-column",
958 GTK_CLASS_TYPE (object_class),
961 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
963 sheet_signals[SELECT_RANGE] =
964 gtk_signal_new ("select-range",
966 GTK_CLASS_TYPE (object_class),
967 GTK_SIGNAL_OFFSET (GtkSheetClass, select_range),
968 gtkextra_VOID__BOXED,
969 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
971 sheet_signals[CLIP_RANGE] =
972 gtk_signal_new ("clip-range",
974 GTK_CLASS_TYPE (object_class),
975 GTK_SIGNAL_OFFSET (GtkSheetClass, clip_range),
976 gtkextra_VOID__BOXED,
977 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
979 sheet_signals[RESIZE_RANGE] =
980 gtk_signal_new ("resize-range",
982 GTK_CLASS_TYPE (object_class),
983 GTK_SIGNAL_OFFSET (GtkSheetClass, resize_range),
984 gtkextra_VOID__BOXED_BOXED,
985 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
986 sheet_signals[MOVE_RANGE] =
987 gtk_signal_new ("move-range",
989 GTK_CLASS_TYPE (object_class),
990 GTK_SIGNAL_OFFSET (GtkSheetClass, move_range),
991 gtkextra_VOID__BOXED_BOXED,
992 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
993 sheet_signals[TRAVERSE] =
994 gtk_signal_new ("traverse",
996 GTK_CLASS_TYPE (object_class),
997 GTK_SIGNAL_OFFSET (GtkSheetClass, traverse),
998 gtkextra_BOOLEAN__INT_INT_POINTER_POINTER,
999 GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT,
1000 GTK_TYPE_POINTER, GTK_TYPE_POINTER);
1002 sheet_signals[DEACTIVATE] =
1003 gtk_signal_new ("deactivate",
1005 GTK_CLASS_TYPE (object_class),
1006 GTK_SIGNAL_OFFSET (GtkSheetClass, deactivate),
1007 gtkextra_BOOLEAN__INT_INT,
1008 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1010 sheet_signals[ACTIVATE] =
1011 gtk_signal_new ("activate",
1013 GTK_CLASS_TYPE (object_class),
1014 GTK_SIGNAL_OFFSET (GtkSheetClass, activate),
1015 gtkextra_BOOLEAN__INT_INT,
1016 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1018 sheet_signals[SET_CELL] =
1019 gtk_signal_new ("set-cell",
1021 GTK_CLASS_TYPE (object_class),
1022 GTK_SIGNAL_OFFSET (GtkSheetClass, set_cell),
1023 gtkextra_VOID__INT_INT,
1024 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1026 sheet_signals[CLEAR_CELL] =
1027 gtk_signal_new ("clear-cell",
1029 GTK_CLASS_TYPE (object_class),
1030 GTK_SIGNAL_OFFSET (GtkSheetClass, clear_cell),
1031 gtkextra_VOID__INT_INT,
1032 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1034 sheet_signals[CHANGED] =
1035 gtk_signal_new ("changed",
1037 GTK_CLASS_TYPE (object_class),
1038 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1039 gtkextra_VOID__INT_INT,
1040 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1042 sheet_signals[NEW_COL_WIDTH] =
1043 gtk_signal_new ("new-column-width",
1045 GTK_CLASS_TYPE (object_class),
1046 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1047 gtkextra_VOID__INT_INT,
1048 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1050 sheet_signals[NEW_ROW_HEIGHT] =
1051 gtk_signal_new ("new-row-height",
1053 GTK_CLASS_TYPE (object_class),
1054 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1055 gtkextra_VOID__INT_INT,
1056 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1058 widget_class->set_scroll_adjustments_signal =
1059 gtk_signal_new ("set-scroll-adjustments",
1061 GTK_CLASS_TYPE (object_class),
1062 GTK_SIGNAL_OFFSET (GtkSheetClass, set_scroll_adjustments),
1063 gtkextra_VOID__OBJECT_OBJECT,
1064 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1067 container_class->add = NULL;
1068 container_class->remove = gtk_sheet_remove;
1069 container_class->forall = gtk_sheet_forall;
1071 object_class->destroy = gtk_sheet_destroy;
1072 gobject_class->finalize = gtk_sheet_finalize;
1074 widget_class->realize = gtk_sheet_realize;
1075 widget_class->unrealize = gtk_sheet_unrealize;
1076 widget_class->map = gtk_sheet_map;
1077 widget_class->unmap = gtk_sheet_unmap;
1078 widget_class->style_set = gtk_sheet_style_set;
1079 widget_class->button_press_event = gtk_sheet_button_press;
1080 widget_class->button_release_event = gtk_sheet_button_release;
1081 widget_class->motion_notify_event = gtk_sheet_motion;
1082 widget_class->key_press_event = gtk_sheet_key_press;
1083 widget_class->expose_event = gtk_sheet_expose;
1084 widget_class->size_request = gtk_sheet_size_request;
1085 widget_class->size_allocate = gtk_sheet_size_allocate;
1086 widget_class->focus_in_event = NULL;
1087 widget_class->focus_out_event = NULL;
1089 klass->set_scroll_adjustments = gtk_sheet_set_scroll_adjustments;
1090 klass->select_row = NULL;
1091 klass->select_column = NULL;
1092 klass->select_range = NULL;
1093 klass->clip_range = NULL;
1094 klass->resize_range = NULL;
1095 klass->move_range = NULL;
1096 klass->traverse = NULL;
1097 klass->deactivate = NULL;
1098 klass->activate = NULL;
1099 klass->set_cell = NULL;
1100 klass->clear_cell = NULL;
1101 klass->changed = NULL;
1105 gtk_sheet_init (GtkSheet *sheet)
1107 sheet->column_geometry = NULL;
1108 sheet->row_geometry = NULL;
1110 sheet->children = NULL;
1113 sheet->selection_mode = GTK_SELECTION_BROWSE;
1114 sheet->freeze_count = 0;
1115 sheet->state = GTK_SHEET_NORMAL;
1117 GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW);
1118 GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS);
1120 sheet->view.row0 = 0;
1121 sheet->view.col0 = 0;
1122 sheet->view.rowi = 0;
1123 sheet->view.coli = 0;
1125 sheet->column_title_window = NULL;
1126 sheet->column_title_area.x = 0;
1127 sheet->column_title_area.y = 0;
1128 sheet->column_title_area.width = 0;
1129 sheet->column_title_area.height = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet));
1131 sheet->row_title_window = NULL;
1132 sheet->row_title_area.x = 0;
1133 sheet->row_title_area.y = 0;
1134 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1135 sheet->row_title_area.height = 0;
1138 sheet->active_cell.row = 0;
1139 sheet->active_cell.col = 0;
1140 sheet->selection_cell.row = 0;
1141 sheet->selection_cell.col = 0;
1143 sheet->sheet_entry = NULL;
1144 sheet->pixmap = NULL;
1146 sheet->range.row0 = 0;
1147 sheet->range.rowi = 0;
1148 sheet->range.col0 = 0;
1149 sheet->range.coli = 0;
1151 sheet->state = GTK_SHEET_NORMAL;
1153 sheet->sheet_window = NULL;
1154 sheet->sheet_window_width = 0;
1155 sheet->sheet_window_height = 0;
1156 sheet->sheet_entry = NULL;
1157 sheet->button = NULL;
1162 sheet->hadjustment = NULL;
1163 sheet->vadjustment = NULL;
1165 sheet->cursor_drag = gdk_cursor_new (GDK_PLUS);
1166 sheet->xor_gc = NULL;
1167 sheet->fg_gc = NULL;
1168 sheet->bg_gc = NULL;
1172 gdk_color_parse ("white", &sheet->bg_color);
1173 gdk_color_alloc (gdk_colormap_get_system (), &sheet->bg_color);
1174 gdk_color_parse ("gray", &sheet->grid_color);
1175 gdk_color_alloc (gdk_colormap_get_system (), &sheet->grid_color);
1176 sheet->show_grid = TRUE;
1180 /* Callback which occurs whenever columns are inserted / deleted in the model */
1182 columns_inserted_deleted_callback (GSheetModel *model, gint first_column,
1187 GtkSheet *sheet = GTK_SHEET (data);
1189 GtkSheetRange range;
1190 gint model_columns = g_sheet_model_get_column_count (model);
1193 /* Need to update all the columns starting from the first column and onwards.
1194 * Previous column are unchanged, so don't need to be updated.
1196 range.col0 = first_column;
1198 range.coli = xxx_column_count (sheet) - 1;
1199 range.rowi = yyy_row_count (sheet) - 1;
1202 COLUMN_FROM_XPIXEL (sheet, sheet->row_title_area.width + 1);
1205 COLUMN_FROM_XPIXEL (sheet, sheet->sheet_window_width);
1207 if ( sheet->view.coli > range.coli)
1208 sheet->view.coli = range.coli;
1210 adjust_scrollbars (sheet);
1212 if (sheet->active_cell.col >= model_columns)
1213 gtk_sheet_activate_cell (sheet, sheet->active_cell.row, model_columns - 1);
1215 for (i = first_column; i <= MAX_VISIBLE_COLUMN (sheet); i++)
1216 gtk_sheet_column_title_button_draw (sheet, i);
1218 gtk_sheet_range_draw (sheet, &range);
1222 /* Callback which occurs whenever rows are inserted / deleted in the model */
1224 rows_inserted_deleted_callback (GSheetModel *model, gint first_row,
1225 gint n_rows, gpointer data)
1228 GtkSheet *sheet = GTK_SHEET (data);
1230 GtkSheetRange range;
1232 gint model_rows = g_sheet_model_get_row_count (model);
1234 /* Need to update all the rows starting from the first row and onwards.
1235 * Previous rows are unchanged, so don't need to be updated.
1237 range.row0 = first_row;
1239 range.rowi = yyy_row_count (sheet) - 1;
1240 range.coli = xxx_column_count (sheet) - 1;
1243 ROW_FROM_YPIXEL (sheet, sheet->column_title_area.height + 1);
1245 ROW_FROM_YPIXEL (sheet, sheet->sheet_window_height - 1);
1247 if ( sheet->view.rowi > range.rowi)
1248 sheet->view.rowi = range.rowi;
1250 adjust_scrollbars (sheet);
1252 if (sheet->active_cell.row >= model_rows)
1253 gtk_sheet_activate_cell (sheet, model_rows - 1, sheet->active_cell.col);
1255 for (i = first_row; i <= MAX_VISIBLE_ROW (sheet); i++)
1256 gtk_sheet_row_title_button_draw (sheet, i);
1258 gtk_sheet_range_draw (sheet, &range);
1262 If row0 or rowi are negative, then all rows will be updated.
1263 If col0 or coli are negative, then all columns will be updated.
1266 range_update_callback (GSheetModel *m, gint row0, gint col0,
1267 gint rowi, gint coli, gpointer data)
1269 GtkSheet *sheet = GTK_SHEET (data);
1271 GtkSheetRange range;
1278 if ( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
1280 gtk_sheet_range_draw (sheet, NULL);
1283 else if ( row0 < 0 || rowi < 0 )
1285 range.row0 = MIN_VISIBLE_ROW (sheet);
1286 range.rowi = MAX_VISIBLE_ROW (sheet);
1288 else if ( col0 < 0 || coli < 0 )
1290 range.col0 = MIN_VISIBLE_COLUMN (sheet);
1291 range.coli = MAX_VISIBLE_COLUMN (sheet);
1294 gtk_sheet_range_draw (sheet, &range);
1298 static void gtk_sheet_construct (GtkSheet *sheet,
1301 const gchar *title);
1306 * @rows: initial number of rows
1307 * @columns: initial number of columns
1308 * @title: sheet title
1309 * @model: the model to use for the sheet data
1311 * Creates a new sheet widget with the given number of rows and columns.
1313 * Returns: the new sheet widget
1316 gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, const gchar *title,
1321 widget = gtk_type_new (gtk_sheet_get_type ());
1323 gtk_sheet_construct (GTK_SHEET (widget), vgeo, hgeo, title);
1326 gtk_sheet_set_model (GTK_SHEET (widget), model);
1334 * gtk_sheet_set_model
1335 * @sheet: the sheet to set the model for
1336 * @model: the model to use for the sheet data
1338 * Sets the model for a GtkSheet
1342 gtk_sheet_set_model (GtkSheet *sheet, GSheetModel *model)
1344 g_return_if_fail (GTK_IS_SHEET (sheet));
1345 g_return_if_fail (G_IS_SHEET_MODEL (model));
1347 sheet->model = model;
1349 g_signal_connect (model, "range_changed",
1350 G_CALLBACK (range_update_callback), sheet);
1352 g_signal_connect (model, "rows_inserted",
1353 G_CALLBACK (rows_inserted_deleted_callback), sheet);
1355 g_signal_connect (model, "rows_deleted",
1356 G_CALLBACK (rows_inserted_deleted_callback), sheet);
1358 g_signal_connect (model, "columns_inserted",
1359 G_CALLBACK (columns_inserted_deleted_callback), sheet);
1361 g_signal_connect (model, "columns_deleted",
1362 G_CALLBACK (columns_inserted_deleted_callback), sheet);
1367 /* Call back for when the column titles have changed.
1368 FIRST is the first column changed.
1369 N_COLUMNS is the number of columns which have changed, or - 1, which
1370 indicates that the column has changed to its right - most extremity
1373 column_titles_changed (GtkWidget *w, gint first, gint n_columns, gpointer data)
1375 GtkSheet *sheet = GTK_SHEET (data);
1376 gboolean extremity = FALSE;
1378 if ( n_columns == -1 )
1381 n_columns = xxx_column_count (sheet) - 1 ;
1384 if (!GTK_SHEET_IS_FROZEN (sheet))
1387 for ( i = first ; i <= first + n_columns ; ++i )
1389 gtk_sheet_column_title_button_draw (sheet, i);
1390 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[CHANGED], -1, i);
1395 gtk_sheet_column_title_button_draw (sheet, -1);
1400 gtk_sheet_construct (GtkSheet *sheet,
1405 g_return_if_fail (G_IS_SHEET_COLUMN (hgeo));
1406 g_return_if_fail (G_IS_SHEET_ROW (vgeo));
1408 sheet->column_geometry = hgeo;
1409 sheet->row_geometry = vgeo;
1412 sheet->columns_resizable = TRUE;
1413 sheet->rows_resizable = TRUE;
1415 sheet->row_titles_visible = TRUE;
1416 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1418 sheet->column_titles_visible = TRUE;
1419 sheet->autoscroll = TRUE;
1420 sheet->justify_entry = TRUE;
1423 /* create sheet entry */
1424 sheet->entry_type = 0;
1425 create_sheet_entry (sheet);
1427 /* create global selection button */
1428 create_global_button (sheet);
1431 sheet->name = g_strdup (title);
1433 g_signal_connect (sheet->column_geometry, "columns_changed",
1434 G_CALLBACK (column_titles_changed), sheet);
1440 gtk_sheet_new_with_custom_entry (GSheetRow *rows, GSheetColumn *columns,
1441 const gchar *title, GtkType entry_type)
1445 widget = gtk_type_new (gtk_sheet_get_type ());
1447 gtk_sheet_construct_with_custom_entry (GTK_SHEET (widget),
1448 rows, columns, title, entry_type);
1454 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet,
1460 gtk_sheet_construct (sheet, vgeo, hgeo, title);
1462 sheet->entry_type = entry_type;
1463 create_sheet_entry (sheet);
1469 gtk_sheet_change_entry (GtkSheet *sheet, GtkType entry_type)
1473 g_return_if_fail (sheet != NULL);
1474 g_return_if_fail (GTK_IS_SHEET (sheet));
1476 state = sheet->state;
1478 if (sheet->state == GTK_SHEET_NORMAL)
1479 gtk_sheet_hide_active_cell (sheet);
1481 sheet->entry_type = entry_type;
1483 create_sheet_entry (sheet);
1485 if (state == GTK_SHEET_NORMAL)
1487 gtk_sheet_show_active_cell (sheet);
1488 g_signal_connect (G_OBJECT (gtk_sheet_get_entry (sheet)),
1490 G_CALLBACK (gtk_sheet_entry_changed),
1496 gtk_sheet_show_grid (GtkSheet *sheet, gboolean show)
1498 g_return_if_fail (sheet != NULL);
1499 g_return_if_fail (GTK_IS_SHEET (sheet));
1501 if (show == sheet->show_grid) return;
1503 sheet->show_grid = show;
1505 if (!GTK_SHEET_IS_FROZEN (sheet))
1506 gtk_sheet_range_draw (sheet, NULL);
1510 gtk_sheet_grid_visible (GtkSheet *sheet)
1512 g_return_val_if_fail (sheet != NULL, 0);
1513 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1515 return sheet->show_grid;
1519 gtk_sheet_set_background (GtkSheet *sheet, GdkColor *color)
1521 g_return_if_fail (sheet != NULL);
1522 g_return_if_fail (GTK_IS_SHEET (sheet));
1526 gdk_color_parse ("white", &sheet->bg_color);
1527 gdk_color_alloc (gdk_colormap_get_system (), &sheet->bg_color);
1530 sheet->bg_color = *color;
1532 if (!GTK_SHEET_IS_FROZEN (sheet))
1533 gtk_sheet_range_draw (sheet, NULL);
1537 gtk_sheet_set_grid (GtkSheet *sheet, GdkColor *color)
1539 g_return_if_fail (sheet != NULL);
1540 g_return_if_fail (GTK_IS_SHEET (sheet));
1544 gdk_color_parse ("black", &sheet->grid_color);
1545 gdk_color_alloc (gdk_colormap_get_system (), &sheet->grid_color);
1548 sheet->grid_color = *color;
1550 if (!GTK_SHEET_IS_FROZEN (sheet))
1551 gtk_sheet_range_draw (sheet, NULL);
1555 gtk_sheet_get_columns_count (GtkSheet *sheet)
1557 g_return_val_if_fail (sheet != NULL, 0);
1558 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1560 return xxx_column_count (sheet);
1564 gtk_sheet_get_rows_count (GtkSheet *sheet)
1566 g_return_val_if_fail (sheet != NULL, 0);
1567 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1569 return yyy_row_count (sheet);
1573 gtk_sheet_get_state (GtkSheet *sheet)
1575 g_return_val_if_fail (sheet != NULL, 0);
1576 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1578 return (sheet->state);
1582 gtk_sheet_set_selection_mode (GtkSheet *sheet, gint mode)
1584 g_return_if_fail (sheet != NULL);
1585 g_return_if_fail (GTK_IS_SHEET (sheet));
1587 if (GTK_WIDGET_REALIZED (sheet))
1588 gtk_sheet_real_unselect_range (sheet, NULL);
1590 sheet->selection_mode = mode;
1594 gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize)
1596 g_return_if_fail (sheet != NULL);
1597 g_return_if_fail (GTK_IS_SHEET (sheet));
1599 sheet->autoresize = autoresize;
1603 gtk_sheet_autoresize (GtkSheet *sheet)
1605 g_return_val_if_fail (sheet != NULL, FALSE);
1606 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1608 return sheet->autoresize;
1612 gtk_sheet_set_column_width (GtkSheet * sheet,
1618 gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
1620 gint text_width = 0;
1623 g_return_if_fail (sheet != NULL);
1624 g_return_if_fail (GTK_IS_SHEET (sheet));
1625 if (column >= xxx_column_count (sheet) || column < 0) return;
1627 for (row = 0; row < yyy_row_count (sheet); row++)
1629 gchar *text = gtk_sheet_cell_get_text (sheet, row, column);
1630 if (text && strlen (text) > 0)
1632 GtkSheetCellAttr attributes;
1634 gtk_sheet_get_attributes (sheet, row, column, &attributes);
1635 if (attributes.is_visible)
1637 gint width = STRING_WIDTH (GTK_WIDGET (sheet),
1638 attributes.font_desc,
1640 + 2 * CELLOFFSET + attributes.border.width;
1641 text_width = MAX (text_width, width);
1644 dispose_string (sheet, text);
1647 if (text_width > xxx_column_width (sheet, column) )
1649 gtk_sheet_set_column_width (sheet, column, text_width);
1650 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_REDRAW_PENDING);
1656 gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll)
1658 g_return_if_fail (sheet != NULL);
1659 g_return_if_fail (GTK_IS_SHEET (sheet));
1661 sheet->autoscroll = autoscroll;
1665 gtk_sheet_autoscroll (GtkSheet *sheet)
1667 g_return_val_if_fail (sheet != NULL, FALSE);
1668 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1670 return sheet->autoscroll;
1674 gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text)
1676 g_return_if_fail (sheet != NULL);
1677 g_return_if_fail (GTK_IS_SHEET (sheet));
1679 sheet->clip_text = clip_text;
1683 gtk_sheet_clip_text (GtkSheet *sheet)
1685 g_return_val_if_fail (sheet != NULL, FALSE);
1686 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1688 return sheet->clip_text;
1692 gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify)
1694 g_return_if_fail (sheet != NULL);
1695 g_return_if_fail (GTK_IS_SHEET (sheet));
1697 sheet->justify_entry = justify;
1701 gtk_sheet_justify_entry (GtkSheet *sheet)
1703 g_return_val_if_fail (sheet != NULL, FALSE);
1704 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1706 return sheet->justify_entry;
1710 gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked)
1712 g_return_if_fail (sheet != NULL);
1713 g_return_if_fail (GTK_IS_SHEET (sheet));
1717 GTK_SHEET_SET_FLAGS (sheet,GTK_SHEET_IS_LOCKED);
1718 gtk_widget_hide (sheet->sheet_entry);
1719 gtk_widget_unmap (sheet->sheet_entry);
1723 GTK_SHEET_UNSET_FLAGS (sheet,GTK_SHEET_IS_LOCKED);
1724 if (GTK_WIDGET_MAPPED (GTK_WIDGET (sheet)))
1726 gtk_widget_show (sheet->sheet_entry);
1727 gtk_widget_map (sheet->sheet_entry);
1731 gtk_entry_set_editable (GTK_ENTRY (sheet->sheet_entry), locked);
1736 gtk_sheet_locked (const GtkSheet *sheet)
1738 g_return_val_if_fail (sheet != NULL, FALSE);
1739 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1741 return GTK_SHEET_IS_LOCKED (sheet);
1744 /* This routine has problems with gtk+- 1.2 related with the
1745 label / button drawing - I think it's a bug in gtk+- 1.2 */
1747 gtk_sheet_set_title (GtkSheet *sheet, const gchar *title)
1751 g_return_if_fail (sheet != NULL);
1752 g_return_if_fail (title != NULL);
1753 g_return_if_fail (GTK_IS_SHEET (sheet));
1756 g_free (sheet->name);
1758 sheet->name = g_strdup (title);
1760 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) || !title) return;
1762 if (GTK_BIN (sheet->button)->child)
1763 label = GTK_BIN (sheet->button)->child;
1765 size_allocate_global_button (sheet);
1769 gtk_sheet_freeze (GtkSheet *sheet)
1771 g_return_if_fail (sheet != NULL);
1772 g_return_if_fail (GTK_IS_SHEET (sheet));
1774 sheet->freeze_count++;
1775 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IS_FROZEN);
1779 gtk_sheet_thaw (GtkSheet *sheet)
1781 g_return_if_fail (sheet != NULL);
1782 g_return_if_fail (GTK_IS_SHEET (sheet));
1784 if (sheet->freeze_count == 0) return;
1786 sheet->freeze_count--;
1787 if (sheet->freeze_count > 0) return;
1789 adjust_scrollbars (sheet);
1791 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IS_FROZEN);
1793 sheet->old_vadjustment = -1.;
1794 sheet->old_hadjustment = -1.;
1796 if (sheet->hadjustment)
1797 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1799 if (sheet->vadjustment)
1800 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1803 if (sheet->state == GTK_STATE_NORMAL)
1804 if (sheet->sheet_entry && GTK_WIDGET_MAPPED (sheet->sheet_entry))
1806 gtk_sheet_activate_cell (sheet, sheet->active_cell.row, sheet->active_cell.col);
1812 gtk_sheet_set_row_titles_width (GtkSheet *sheet, guint width)
1814 if (width < COLUMN_MIN_WIDTH) return;
1816 sheet->row_title_area.width = width;
1817 sheet->view.col0 = COLUMN_FROM_XPIXEL (sheet, sheet->row_title_area.width + 1);
1818 sheet->view.coli = COLUMN_FROM_XPIXEL (sheet, sheet->sheet_window_width);
1821 adjust_scrollbars (sheet);
1823 sheet->old_hadjustment = -1.;
1824 if (sheet->hadjustment)
1825 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1827 size_allocate_global_button (sheet);
1831 gtk_sheet_set_column_titles_height (GtkSheet *sheet, guint height)
1833 if (height < DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet))) return;
1835 sheet->column_title_area.height = height;
1836 sheet->view.row0 = ROW_FROM_YPIXEL (sheet, sheet->column_title_area.height + 1);
1837 sheet->view.rowi = ROW_FROM_YPIXEL (sheet, sheet->sheet_window_height - 1);
1839 adjust_scrollbars (sheet);
1841 sheet->old_vadjustment = -1.;
1842 if (sheet->vadjustment)
1843 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1845 size_allocate_global_button (sheet);
1849 gtk_sheet_show_column_titles (GtkSheet *sheet)
1853 if (sheet->column_titles_visible) return;
1855 sheet->column_titles_visible = TRUE;
1858 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
1860 gdk_window_show (sheet->column_title_window);
1861 gdk_window_move_resize (sheet->column_title_window,
1862 sheet->column_title_area.x,
1863 sheet->column_title_area.y,
1864 sheet->column_title_area.width,
1865 sheet->column_title_area.height);
1867 for (col = MIN_VISIBLE_COLUMN (sheet);
1868 col <= MAX_VISIBLE_COLUMN (sheet);
1871 GtkSheetButton *button = xxx_column_button (sheet, col);
1872 GtkSheetChild *child = button->child;
1874 gtk_sheet_child_show (child);
1875 gtk_sheet_button_free (button);
1877 adjust_scrollbars (sheet);
1880 sheet->old_vadjustment = -1.;
1881 if (sheet->vadjustment)
1882 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1884 size_allocate_global_button (sheet);
1889 gtk_sheet_show_row_titles (GtkSheet *sheet)
1893 if (sheet->row_titles_visible) return;
1895 sheet->row_titles_visible = TRUE;
1898 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
1900 gdk_window_show (sheet->row_title_window);
1901 gdk_window_move_resize (sheet->row_title_window,
1902 sheet->row_title_area.x,
1903 sheet->row_title_area.y,
1904 sheet->row_title_area.width,
1905 sheet->row_title_area.height);
1907 for (row = MIN_VISIBLE_ROW (sheet);
1908 row <= MAX_VISIBLE_ROW (sheet);
1911 const GtkSheetButton *button = yyy_row_button (sheet, row);
1912 GtkSheetChild *child = button->child;
1916 gtk_sheet_child_show (child);
1919 adjust_scrollbars (sheet);
1922 sheet->old_hadjustment = -1.;
1923 if (sheet->hadjustment)
1924 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1926 size_allocate_global_button (sheet);
1930 gtk_sheet_hide_column_titles (GtkSheet *sheet)
1934 if (!sheet->column_titles_visible) return;
1936 sheet->column_titles_visible = FALSE;
1938 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
1940 if (sheet->column_title_window)
1941 gdk_window_hide (sheet->column_title_window);
1942 if (GTK_WIDGET_VISIBLE (sheet->button))
1943 gtk_widget_hide (sheet->button);
1945 for (col = MIN_VISIBLE_COLUMN (sheet);
1946 col <= MAX_VISIBLE_COLUMN (sheet);
1949 GtkSheetButton *button = xxx_column_button (sheet, col);
1950 GtkSheetChild *child = button->child;
1952 gtk_sheet_child_hide (child);
1953 gtk_sheet_button_free (button);
1955 adjust_scrollbars (sheet);
1958 sheet->old_vadjustment = -1.;
1959 if (sheet->vadjustment)
1960 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1965 gtk_sheet_hide_row_titles (GtkSheet *sheet)
1969 if (!sheet->row_titles_visible) return;
1971 sheet->row_titles_visible = FALSE;
1974 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
1976 if (sheet->row_title_window)
1977 gdk_window_hide (sheet->row_title_window);
1978 if (GTK_WIDGET_VISIBLE (sheet->button))
1979 gtk_widget_hide (sheet->button);
1980 for (row = MIN_VISIBLE_ROW (sheet);
1981 row <= MAX_VISIBLE_ROW (sheet);
1984 const GtkSheetButton *button = yyy_row_button (sheet, row);
1985 GtkSheetChild *child = button->child;
1988 gtk_sheet_child_hide (child);
1990 adjust_scrollbars (sheet);
1993 sheet->old_hadjustment = -1.;
1994 if (sheet->hadjustment)
1995 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
2000 gtk_sheet_column_titles_visible (GtkSheet *sheet)
2002 g_return_val_if_fail (sheet != NULL, FALSE);
2003 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2004 return sheet->column_titles_visible;
2008 gtk_sheet_row_titles_visible (GtkSheet *sheet)
2010 g_return_val_if_fail (sheet != NULL, FALSE);
2011 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2012 return sheet->row_titles_visible;
2018 gtk_sheet_moveto (GtkSheet * sheet,
2025 guint width, height;
2027 gint min_row, min_col;
2029 g_return_if_fail (sheet != NULL);
2030 g_return_if_fail (GTK_IS_SHEET (sheet));
2031 g_return_if_fail (sheet->hadjustment != NULL);
2032 g_return_if_fail (sheet->vadjustment != NULL);
2034 if (row < 0 || row >= yyy_row_count (sheet))
2036 if (column < 0 || column >= xxx_column_count (sheet))
2039 height = sheet->sheet_window_height;
2040 width = sheet->sheet_window_width;
2042 /* adjust vertical scrollbar */
2044 if (row >= 0 && row_align >= 0.)
2046 y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
2047 - (gint) ( row_align*height + (1. - row_align) * yyy_row_height (sheet, row));
2049 /* This forces the sheet to scroll when you don't see the entire cell */
2052 if (row_align == 1.)
2054 while (min_row >= 0 && min_row > MIN_VISIBLE_ROW (sheet))
2056 if (yyy_row_is_visible (sheet, min_row))
2057 adjust += yyy_row_height (sheet, min_row);
2058 if (adjust >= height)
2064 min_row = MAX (min_row, 0);
2065 y = ROW_TOP_YPIXEL (sheet, min_row) - sheet->voffset +
2066 yyy_row_height (sheet, min_row) - 1;
2070 sheet->vadjustment->value = 0.0;
2072 sheet->vadjustment->value = y;
2074 sheet->old_vadjustment = -1.;
2075 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
2080 /* adjust horizontal scrollbar */
2081 if (column >= 0 && col_align >= 0.)
2083 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
2084 - (gint) ( col_align*width + (1.- col_align)*
2085 xxx_column_width (sheet, column));
2088 /* This forces the sheet to scroll when you don't see the entire cell */
2091 if (col_align == 1.)
2093 while (min_col >= 0 && min_col > MIN_VISIBLE_COLUMN (sheet))
2095 if (xxx_column_is_visible (sheet, min_col))
2096 adjust += xxx_column_width (sheet, min_col);
2098 if (adjust >= width)
2104 min_col = MAX (min_col, 0);
2105 x = COLUMN_LEFT_XPIXEL (sheet, min_col) - sheet->hoffset +
2106 xxx_column_width (sheet, min_col) - 1;
2110 sheet->hadjustment->value = 0.0;
2112 sheet->hadjustment->value = x;
2114 sheet->old_vadjustment = -1.;
2115 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
2123 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
2125 g_return_if_fail (sheet != NULL);
2126 g_return_if_fail (GTK_IS_SHEET (sheet));
2128 sheet->columns_resizable = resizable;
2132 gtk_sheet_columns_resizable (GtkSheet *sheet)
2134 g_return_val_if_fail (sheet != NULL, FALSE);
2135 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2137 return sheet->columns_resizable;
2142 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
2144 g_return_if_fail (sheet != NULL);
2145 g_return_if_fail (GTK_IS_SHEET (sheet));
2147 sheet->rows_resizable = resizable;
2151 gtk_sheet_rows_resizable (GtkSheet *sheet)
2153 g_return_val_if_fail (sheet != NULL, FALSE);
2154 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2156 return sheet->rows_resizable;
2161 gtk_sheet_select_row (GtkSheet * sheet,
2164 g_return_if_fail (sheet != NULL);
2165 g_return_if_fail (GTK_IS_SHEET (sheet));
2167 if (row < 0 || row >= yyy_row_count (sheet))
2170 if (sheet->state != GTK_SHEET_NORMAL)
2171 gtk_sheet_real_unselect_range (sheet, NULL);
2174 gboolean veto = TRUE;
2175 veto = gtk_sheet_deactivate_cell (sheet);
2179 sheet->state = GTK_SHEET_ROW_SELECTED;
2180 sheet->range.row0 = row;
2181 sheet->range.col0 = 0;
2182 sheet->range.rowi = row;
2183 sheet->range.coli = xxx_column_count (sheet) - 1;
2184 sheet->active_cell.row = row;
2185 sheet->active_cell.col = 0;
2187 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_ROW], row);
2188 gtk_sheet_real_select_range (sheet, NULL);
2193 gtk_sheet_select_column (GtkSheet * sheet, gint column)
2195 g_return_if_fail (sheet != NULL);
2196 g_return_if_fail (GTK_IS_SHEET (sheet));
2198 if (column < 0 || column >= xxx_column_count (sheet))
2201 if (sheet->state != GTK_SHEET_NORMAL)
2202 gtk_sheet_real_unselect_range (sheet, NULL);
2205 gboolean veto = TRUE;
2206 veto = gtk_sheet_deactivate_cell (sheet);
2210 sheet->state = GTK_SHEET_COLUMN_SELECTED;
2211 sheet->range.row0 = 0;
2212 sheet->range.col0 = column;
2213 sheet->range.rowi = yyy_row_count (sheet) - 1;
2214 sheet->range.coli = column;
2215 sheet->active_cell.row = 0;
2216 sheet->active_cell.col = column;
2218 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_COLUMN], column);
2219 gtk_sheet_real_select_range (sheet, NULL);
2223 gtk_sheet_clip_range (GtkSheet *sheet, const GtkSheetRange *range)
2226 g_return_if_fail (sheet != NULL);
2227 g_return_if_fail (GTK_IS_SHEET (sheet));
2229 if (GTK_SHEET_IN_CLIP (sheet)) return;
2231 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_CLIP);
2234 sheet->clip_range = sheet->range;
2236 sheet->clip_range=*range;
2238 sheet->interval = 0;
2239 sheet->clip_timer = gtk_timeout_add (TIMEOUT_FLASH, gtk_sheet_flash, sheet);
2241 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[CLIP_RANGE],
2242 &sheet->clip_range);
2247 gtk_sheet_unclip_range (GtkSheet *sheet)
2250 g_return_if_fail (sheet != NULL);
2251 g_return_if_fail (GTK_IS_SHEET (sheet));
2253 if (!GTK_SHEET_IN_CLIP (sheet)) return;
2255 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_CLIP);
2256 gtk_timeout_remove (sheet->clip_timer);
2257 gtk_sheet_range_draw (sheet, &sheet->clip_range);
2259 if (gtk_sheet_range_isvisible (sheet, sheet->range))
2260 gtk_sheet_range_draw (sheet, &sheet->range);
2264 gtk_sheet_in_clip (GtkSheet *sheet)
2266 g_return_val_if_fail (sheet != NULL, FALSE);
2267 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2269 return GTK_SHEET_IN_CLIP (sheet);
2273 gtk_sheet_flash (gpointer data)
2276 gint x,y,width,height;
2277 GdkRectangle clip_area;
2279 sheet = GTK_SHEET (data);
2281 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return TRUE;
2282 if (!GTK_WIDGET_DRAWABLE (GTK_WIDGET (sheet))) return TRUE;
2283 if (!gtk_sheet_range_isvisible (sheet, sheet->clip_range)) return TRUE;
2284 if (GTK_SHEET_IN_XDRAG (sheet)) return TRUE;
2285 if (GTK_SHEET_IN_YDRAG (sheet)) return TRUE;
2287 GDK_THREADS_ENTER ();
2289 x = COLUMN_LEFT_XPIXEL (sheet,sheet->clip_range.col0)+1;
2290 y = ROW_TOP_YPIXEL (sheet,sheet->clip_range.row0)+1;
2291 width = COLUMN_LEFT_XPIXEL (sheet,sheet->clip_range.coli)- x+
2292 xxx_column_width (sheet, sheet->clip_range.coli) - 1;
2293 height = ROW_TOP_YPIXEL (sheet,sheet->clip_range.rowi)- y+
2294 yyy_row_height (sheet, sheet->clip_range.rowi)- 1;
2296 clip_area.x = COLUMN_LEFT_XPIXEL (sheet, MIN_VISIBLE_COLUMN (sheet));
2297 clip_area.y = ROW_TOP_YPIXEL (sheet, MIN_VISIBLE_ROW (sheet));
2298 clip_area.width = sheet->sheet_window_width;
2299 clip_area.height = sheet->sheet_window_height;
2306 if (width > clip_area.width) width = clip_area.width + 10;
2312 if (height > clip_area.height) height = clip_area.height + 10;
2314 gdk_draw_pixmap (sheet->sheet_window,
2315 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
2321 gdk_draw_pixmap (sheet->sheet_window,
2322 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
2328 gdk_draw_pixmap (sheet->sheet_window,
2329 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
2335 gdk_draw_pixmap (sheet->sheet_window,
2336 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
2343 sheet->interval = sheet->interval + 1;
2344 if (sheet->interval == TIME_INTERVAL) sheet->interval = 0;
2346 gdk_gc_set_dashes (sheet->xor_gc, sheet->interval, (gint8*)"\4\4", 2);
2347 gtk_sheet_draw_flashing_range (sheet,sheet->clip_range);
2348 gdk_gc_set_dashes (sheet->xor_gc, 0, (gint8*)"\4\4", 2);
2350 GDK_THREADS_LEAVE ();
2357 gtk_sheet_draw_flashing_range (GtkSheet *sheet, GtkSheetRange range)
2359 GdkRectangle clip_area;
2360 gint x,y,width,height;
2362 if (!gtk_sheet_range_isvisible (sheet, sheet->clip_range)) return;
2364 clip_area.x = COLUMN_LEFT_XPIXEL (sheet, MIN_VISIBLE_COLUMN (sheet));
2365 clip_area.y = ROW_TOP_YPIXEL (sheet, MIN_VISIBLE_ROW (sheet));
2366 clip_area.width = sheet->sheet_window_width;
2367 clip_area.height = sheet->sheet_window_height;
2369 gdk_gc_set_clip_rectangle (sheet->xor_gc, &clip_area);
2371 x = COLUMN_LEFT_XPIXEL (sheet,sheet->clip_range.col0)+1;
2372 y = ROW_TOP_YPIXEL (sheet,sheet->clip_range.row0)+1;
2373 width = COLUMN_LEFT_XPIXEL (sheet,sheet->clip_range.coli)- x+
2374 xxx_column_width (sheet, sheet->clip_range.coli) - 1;
2375 height = ROW_TOP_YPIXEL (sheet,sheet->clip_range.rowi)- y+
2376 yyy_row_height (sheet, sheet->clip_range.rowi)- 1;
2383 if (width > clip_area.width) width = clip_area.width + 10;
2389 if (height > clip_area.height) height = clip_area.height + 10;
2391 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 1, 0, 0 );
2393 gdk_draw_rectangle (sheet->sheet_window, sheet->xor_gc, FALSE,
2397 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 0, 0, 0);
2399 gdk_gc_set_clip_rectangle (sheet->xor_gc, NULL);
2403 gtk_sheet_range_isvisible (GtkSheet * sheet,
2404 GtkSheetRange range)
2406 g_return_val_if_fail (sheet != NULL, FALSE);
2408 if (range.row0 < 0 || range.row0 >= yyy_row_count (sheet))
2411 if (range.rowi < 0 || range.rowi >= yyy_row_count (sheet))
2414 if (range.col0 < 0 || range.col0 >= xxx_column_count (sheet))
2417 if (range.coli < 0 || range.coli >= xxx_column_count (sheet))
2420 if (range.rowi < MIN_VISIBLE_ROW (sheet))
2423 if (range.row0 > MAX_VISIBLE_ROW (sheet))
2426 if (range.coli < MIN_VISIBLE_COLUMN (sheet))
2429 if (range.col0 > MAX_VISIBLE_COLUMN (sheet))
2436 gtk_sheet_cell_isvisible (GtkSheet * sheet,
2437 gint row, gint column)
2439 GtkSheetRange range;
2442 range.col0 = column;
2444 range.coli = column;
2446 return gtk_sheet_range_isvisible (sheet, range);
2450 gtk_sheet_get_visible_range (GtkSheet *sheet, GtkSheetRange *range)
2453 g_return_if_fail (sheet != NULL);
2454 g_return_if_fail (GTK_IS_SHEET (sheet)) ;
2455 g_return_if_fail (range != NULL);
2457 range->row0 = MIN_VISIBLE_ROW (sheet);
2458 range->col0 = MIN_VISIBLE_COLUMN (sheet);
2459 range->rowi = MAX_VISIBLE_ROW (sheet);
2460 range->coli = MAX_VISIBLE_COLUMN (sheet);
2465 gtk_sheet_get_vadjustment (GtkSheet * sheet)
2467 g_return_val_if_fail (sheet != NULL, NULL);
2468 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2470 return sheet->vadjustment;
2474 gtk_sheet_get_hadjustment (GtkSheet * sheet)
2476 g_return_val_if_fail (sheet != NULL, NULL);
2477 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2479 return sheet->hadjustment;
2483 gtk_sheet_set_vadjustment (GtkSheet *sheet,
2484 GtkAdjustment *adjustment)
2486 GtkAdjustment *old_adjustment;
2488 g_return_if_fail (sheet != NULL);
2489 g_return_if_fail (GTK_IS_SHEET (sheet));
2491 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2493 if (sheet->vadjustment == adjustment)
2496 old_adjustment = sheet->vadjustment;
2498 if (sheet->vadjustment)
2500 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2501 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2504 sheet->vadjustment = adjustment;
2506 if (sheet->vadjustment)
2508 gtk_object_ref (GTK_OBJECT (sheet->vadjustment));
2509 gtk_object_sink (GTK_OBJECT (sheet->vadjustment));
2511 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "changed",
2512 (GtkSignalFunc) vadjustment_changed,
2514 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "value_changed",
2515 (GtkSignalFunc) vadjustment_value_changed,
2519 if (!sheet->vadjustment || !old_adjustment)
2521 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2525 sheet->old_vadjustment = sheet->vadjustment->value;
2529 gtk_sheet_set_hadjustment (GtkSheet *sheet,
2530 GtkAdjustment *adjustment)
2532 GtkAdjustment *old_adjustment;
2534 g_return_if_fail (sheet != NULL);
2535 g_return_if_fail (GTK_IS_SHEET (sheet));
2537 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2539 if (sheet->hadjustment == adjustment)
2542 old_adjustment = sheet->hadjustment;
2544 if (sheet->hadjustment)
2546 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2547 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2550 sheet->hadjustment = adjustment;
2552 if (sheet->hadjustment)
2554 gtk_object_ref (GTK_OBJECT (sheet->hadjustment));
2555 gtk_object_sink (GTK_OBJECT (sheet->hadjustment));
2557 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "changed",
2558 (GtkSignalFunc) hadjustment_changed,
2560 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "value_changed",
2561 (GtkSignalFunc) hadjustment_value_changed,
2565 if (!sheet->hadjustment || !old_adjustment)
2567 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2571 sheet->old_hadjustment = sheet->hadjustment->value;
2575 gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
2576 GtkAdjustment *hadjustment,
2577 GtkAdjustment *vadjustment)
2579 if (sheet->hadjustment != hadjustment)
2580 gtk_sheet_set_hadjustment (sheet, hadjustment);
2582 if (sheet->vadjustment != vadjustment)
2583 gtk_sheet_set_vadjustment (sheet, vadjustment);
2587 gtk_sheet_finalize (GObject * object)
2591 g_return_if_fail (object != NULL);
2592 g_return_if_fail (GTK_IS_SHEET (object));
2594 sheet = GTK_SHEET (object);
2596 /* get rid of all the cells */
2597 gtk_sheet_range_clear (sheet, NULL);
2598 gtk_sheet_range_delete (sheet, NULL);
2602 g_free (sheet->name);
2606 if (G_OBJECT_CLASS (parent_class)->finalize)
2607 (*G_OBJECT_CLASS (parent_class)->finalize) (object);
2611 gtk_sheet_destroy (GtkObject * object)
2616 g_return_if_fail (object != NULL);
2617 g_return_if_fail (GTK_IS_SHEET (object));
2619 sheet = GTK_SHEET (object);
2621 /* destroy the entry */
2622 if (sheet->sheet_entry && GTK_IS_WIDGET (sheet->sheet_entry))
2624 gtk_widget_destroy (sheet->sheet_entry);
2625 sheet->sheet_entry = NULL;
2628 /* destroy the global selection button */
2629 if (sheet->button && GTK_IS_WIDGET (sheet->button))
2631 gtk_widget_destroy (sheet->button);
2632 sheet->button = NULL;
2637 gtk_timeout_remove (sheet->timer);
2641 if (sheet->clip_timer)
2643 gtk_timeout_remove (sheet->clip_timer);
2644 sheet->clip_timer = 0;
2647 /* unref adjustments */
2648 if (sheet->hadjustment)
2650 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2651 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2652 sheet->hadjustment = NULL;
2654 if (sheet->vadjustment)
2656 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2657 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2658 sheet->vadjustment = NULL;
2661 children = sheet->children;
2664 GtkSheetChild *child = (GtkSheetChild *)children->data;
2665 if (child && child->widget)
2666 gtk_sheet_remove (GTK_CONTAINER (sheet), child->widget);
2667 children = sheet->children;
2669 sheet->children = NULL;
2671 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2672 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2676 gtk_sheet_style_set (GtkWidget *widget,
2677 GtkStyle *previous_style)
2681 g_return_if_fail (widget != NULL);
2682 g_return_if_fail (GTK_IS_SHEET (widget));
2684 if (GTK_WIDGET_CLASS (parent_class)->style_set)
2685 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
2687 sheet = GTK_SHEET (widget);
2689 if (GTK_WIDGET_REALIZED (widget))
2691 gtk_style_set_background (widget->style, widget->window, widget->state);
2697 gtk_sheet_realize (GtkWidget * widget)
2700 GdkWindowAttr attributes;
2701 gint attributes_mask;
2702 GdkGCValues values, auxvalues;
2703 GdkColormap *colormap;
2705 GtkSheetChild *child;
2708 g_return_if_fail (widget != NULL);
2709 g_return_if_fail (GTK_IS_SHEET (widget));
2711 sheet = GTK_SHEET (widget);
2713 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2715 attributes.window_type = GDK_WINDOW_CHILD;
2716 attributes.x = widget->allocation.x;
2717 attributes.y = widget->allocation.y;
2718 attributes.width = widget->allocation.width;
2719 attributes.height = widget->allocation.height;
2720 attributes.wclass = GDK_INPUT_OUTPUT;
2722 attributes.visual = gtk_widget_get_visual (widget);
2723 attributes.colormap = gtk_widget_get_colormap (widget);
2725 attributes.event_mask = gtk_widget_get_events (widget);
2726 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2727 GDK_BUTTON_PRESS_MASK |
2728 GDK_BUTTON_RELEASE_MASK |
2729 GDK_KEY_PRESS_MASK |
2730 GDK_POINTER_MOTION_MASK |
2731 GDK_POINTER_MOTION_HINT_MASK);
2732 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
2735 attributes.cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
2738 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2740 gdk_window_set_user_data (widget->window, sheet);
2742 widget->style = gtk_style_attach (widget->style, widget->window);
2744 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2747 if (sheet->row_titles_visible)
2748 attributes.x = sheet->row_title_area.width;
2750 attributes.width = sheet->column_title_area.width;
2751 attributes.height = sheet->column_title_area.height;
2753 /* column - title window */
2754 sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2755 gdk_window_set_user_data (sheet->column_title_window, sheet);
2756 gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL);
2760 if (sheet->column_titles_visible)
2761 attributes.y = sheet->column_title_area.height;
2762 attributes.width = sheet->row_title_area.width;
2763 attributes.height = sheet->row_title_area.height;
2765 /* row - title window */
2766 sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2767 gdk_window_set_user_data (sheet->row_title_window, sheet);
2768 gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL);
2770 /* sheet - window */
2771 attributes.cursor = gdk_cursor_new (GDK_PLUS);
2775 attributes.width = sheet->sheet_window_width,
2776 attributes.height = sheet->sheet_window_height;
2778 sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2779 gdk_window_set_user_data (sheet->sheet_window, sheet);
2781 gdk_cursor_unref (attributes.cursor);
2783 gdk_window_set_background (sheet->sheet_window, &widget->style->white);
2784 gdk_window_show (sheet->sheet_window);
2786 /* backing_pixmap */
2787 gtk_sheet_make_backing_pixmap (sheet, 0, 0);
2791 gdk_gc_unref (sheet->fg_gc);
2793 gdk_gc_unref (sheet->bg_gc);
2794 sheet->fg_gc = gdk_gc_new (widget->window);
2795 sheet->bg_gc = gdk_gc_new (widget->window);
2797 colormap = gtk_widget_get_colormap (widget);
2799 gdk_color_white (colormap, &widget->style->white);
2800 gdk_color_black (colormap, &widget->style->black);
2802 gdk_gc_get_values (sheet->fg_gc, &auxvalues);
2804 values.foreground = widget->style->white;
2805 values.function = GDK_INVERT;
2806 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2808 gdk_gc_unref (sheet->xor_gc);
2809 sheet->xor_gc = gdk_gc_new_with_values (widget->window,
2815 if (sheet->sheet_entry->parent)
2817 gtk_widget_ref (sheet->sheet_entry);
2818 gtk_widget_unparent (sheet->sheet_entry);
2820 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
2821 gtk_widget_set_parent (sheet->sheet_entry, GTK_WIDGET (sheet));
2823 if (sheet->button && sheet->button->parent)
2825 gtk_widget_ref (sheet->button);
2826 gtk_widget_unparent (sheet->button);
2828 gtk_widget_set_parent_window (sheet->button, sheet->sheet_window);
2829 gtk_widget_set_parent (sheet->button, GTK_WIDGET (sheet));
2831 if (!sheet->cursor_drag)
2832 sheet->cursor_drag = gdk_cursor_new (GDK_PLUS);
2834 if (sheet->column_titles_visible)
2835 gdk_window_show (sheet->column_title_window);
2836 if (sheet->row_titles_visible)
2837 gdk_window_show (sheet->row_title_window);
2839 size_allocate_row_title_buttons (sheet);
2840 size_allocate_column_title_buttons (sheet);
2842 name = g_strdup (sheet->name);
2843 gtk_sheet_set_title (sheet, name);
2847 children = sheet->children;
2850 child = children->data;
2851 children = children->next;
2853 gtk_sheet_realize_child (sheet, child);
2858 create_global_button (GtkSheet *sheet)
2860 sheet->button = gtk_button_new_with_label (" ");
2862 gtk_signal_connect (GTK_OBJECT (sheet->button),
2864 (GtkSignalFunc) global_button_clicked,
2869 size_allocate_global_button (GtkSheet *sheet)
2871 GtkAllocation allocation;
2873 if (!sheet->column_titles_visible) return;
2874 if (!sheet->row_titles_visible) return;
2876 gtk_widget_size_request (sheet->button, NULL);
2880 allocation.width = sheet->row_title_area.width;
2881 allocation.height = sheet->column_title_area.height;
2883 gtk_widget_size_allocate (sheet->button, &allocation);
2884 gtk_widget_show (sheet->button);
2888 global_button_clicked (GtkWidget *widget, gpointer data)
2892 gtk_sheet_click_cell (GTK_SHEET (data), - 1, - 1, &veto);
2893 gtk_widget_grab_focus (GTK_WIDGET (data));
2898 gtk_sheet_unrealize (GtkWidget * widget)
2902 g_return_if_fail (widget != NULL);
2903 g_return_if_fail (GTK_IS_SHEET (widget));
2905 sheet = GTK_SHEET (widget);
2907 gdk_cursor_destroy (sheet->cursor_drag);
2909 gdk_gc_destroy (sheet->xor_gc);
2910 gdk_gc_destroy (sheet->fg_gc);
2911 gdk_gc_destroy (sheet->bg_gc);
2913 gdk_window_destroy (sheet->sheet_window);
2914 gdk_window_destroy (sheet->column_title_window);
2915 gdk_window_destroy (sheet->row_title_window);
2919 g_object_unref (sheet->pixmap);
2920 sheet->pixmap = NULL;
2923 sheet->column_title_window = NULL;
2924 sheet->sheet_window = NULL;
2925 sheet->cursor_drag = NULL;
2926 sheet->xor_gc = NULL;
2927 sheet->fg_gc = NULL;
2928 sheet->bg_gc = NULL;
2930 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2931 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2935 gtk_sheet_map (GtkWidget * widget)
2938 GtkSheetChild *child;
2941 g_return_if_fail (widget != NULL);
2942 g_return_if_fail (GTK_IS_SHEET (widget));
2944 sheet = GTK_SHEET (widget);
2946 if (!GTK_WIDGET_MAPPED (widget))
2948 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2950 if (!sheet->cursor_drag) sheet->cursor_drag = gdk_cursor_new (GDK_PLUS);
2952 gdk_window_show (widget->window);
2954 gdk_window_show (sheet->sheet_window);
2956 if (sheet->column_titles_visible)
2958 size_allocate_column_title_buttons (sheet);
2959 gdk_window_show (sheet->column_title_window);
2961 if (sheet->row_titles_visible)
2963 size_allocate_row_title_buttons (sheet);
2964 gdk_window_show (sheet->row_title_window);
2967 if (!GTK_WIDGET_MAPPED (sheet->sheet_entry)
2968 && ! gtk_sheet_locked (sheet)
2969 && sheet->active_cell.row >= 0
2970 && sheet->active_cell.col >= 0 )
2972 gtk_widget_show (sheet->sheet_entry);
2973 gtk_widget_map (sheet->sheet_entry);
2976 if (GTK_WIDGET_VISIBLE (sheet->button) &&
2977 !GTK_WIDGET_MAPPED (sheet->button))
2979 gtk_widget_show (sheet->button);
2980 gtk_widget_map (sheet->button);
2983 if (GTK_BIN (sheet->button)->child)
2984 if (GTK_WIDGET_VISIBLE (GTK_BIN (sheet->button)->child) &&
2985 !GTK_WIDGET_MAPPED (GTK_BIN (sheet->button)->child))
2986 gtk_widget_map (GTK_BIN (sheet->button)->child);
2988 gtk_sheet_range_draw (sheet, NULL);
2989 gtk_sheet_activate_cell (sheet,
2990 sheet->active_cell.row,
2991 sheet->active_cell.col);
2993 children = sheet->children;
2996 child = children->data;
2997 children = children->next;
2999 if (GTK_WIDGET_VISIBLE (child->widget) &&
3000 !GTK_WIDGET_MAPPED (child->widget))
3002 gtk_widget_map (child->widget);
3003 gtk_sheet_position_child (sheet, child);
3011 gtk_sheet_unmap (GtkWidget * widget)
3014 GtkSheetChild *child;
3017 g_return_if_fail (widget != NULL);
3018 g_return_if_fail (GTK_IS_SHEET (widget));
3020 sheet = GTK_SHEET (widget);
3022 if (GTK_WIDGET_MAPPED (widget))
3024 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3026 gdk_window_hide (sheet->sheet_window);
3027 if (sheet->column_titles_visible)
3028 gdk_window_hide (sheet->column_title_window);
3029 if (sheet->row_titles_visible)
3030 gdk_window_hide (sheet->row_title_window);
3031 gdk_window_hide (widget->window);
3033 if (GTK_WIDGET_MAPPED (sheet->sheet_entry))
3034 gtk_widget_unmap (sheet->sheet_entry);
3036 if (GTK_WIDGET_MAPPED (sheet->button))
3037 gtk_widget_unmap (sheet->button);
3039 children = sheet->children;
3042 child = children->data;
3043 children = children->next;
3045 if (GTK_WIDGET_VISIBLE (child->widget) &&
3046 GTK_WIDGET_MAPPED (child->widget))
3048 gtk_widget_unmap (child->widget);
3057 gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
3060 GdkGC *fg_gc, *bg_gc;
3061 GtkSheetCellAttr attributes;
3064 g_return_if_fail (sheet != NULL);
3066 /* bail now if we arn't drawable yet */
3067 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
3069 if (row < 0 || row >= yyy_row_count (sheet)) return;
3070 if (col < 0 || col >= xxx_column_count (sheet)) return;
3071 if (! xxx_column_is_visible (sheet, col)) return;
3072 if (! yyy_row_is_visible (sheet, row)) return;
3074 widget = GTK_WIDGET (sheet);
3076 gtk_sheet_get_attributes (sheet, row, col, &attributes);
3078 /* select GC for background rectangle */
3079 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3080 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3082 fg_gc = sheet->fg_gc;
3083 bg_gc = sheet->bg_gc;
3085 area.x = COLUMN_LEFT_XPIXEL (sheet,col);
3086 area.y = ROW_TOP_YPIXEL (sheet,row);
3087 area.width= xxx_column_width (sheet, col);
3088 area.height = yyy_row_height (sheet, row);
3090 gdk_draw_rectangle (sheet->pixmap,
3098 gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0);
3100 if (sheet->show_grid)
3102 gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color);
3104 gdk_draw_rectangle (sheet->pixmap,
3108 area.width, area.height);
3113 gtk_sheet_cell_draw_border (GtkSheet *sheet, gint row, gint col, gint mask)
3116 GdkGC *fg_gc, *bg_gc;
3117 GtkSheetCellAttr attributes;
3121 g_return_if_fail (sheet != NULL);
3123 /* bail now if we arn't drawable yet */
3124 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
3126 if (row < 0 || row >= yyy_row_count (sheet)) return;
3127 if (col < 0 || col >= xxx_column_count (sheet)) return;
3128 if (!xxx_column_is_visible (sheet, col)) return;
3129 if (!yyy_row_is_visible (sheet, row)) return;
3131 widget = GTK_WIDGET (sheet);
3133 gtk_sheet_get_attributes (sheet, row, col, &attributes);
3135 /* select GC for background rectangle */
3136 gdk_gc_set_foreground (sheet->fg_gc, &attributes.border.color);
3137 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3139 fg_gc = sheet->fg_gc;
3140 bg_gc = sheet->bg_gc;
3142 area.x = COLUMN_LEFT_XPIXEL (sheet,col);
3143 area.y = ROW_TOP_YPIXEL (sheet,row);
3144 area.width = xxx_column_width (sheet, col);
3145 area.height = yyy_row_height (sheet, row);
3147 width = attributes.border.width;
3148 gdk_gc_set_line_attributes (sheet->fg_gc, attributes.border.width,
3149 attributes.border.line_style,
3150 attributes.border.cap_style,
3151 attributes.border.join_style);
3155 if (attributes.border.mask & GTK_SHEET_LEFT_BORDER & mask)
3156 gdk_draw_line (sheet->pixmap, sheet->fg_gc,
3157 area.x, area.y - width / 2,
3158 area.x, area.y + area.height + width / 2+1);
3160 if (attributes.border.mask & GTK_SHEET_RIGHT_BORDER & mask)
3161 gdk_draw_line (sheet->pixmap, sheet->fg_gc,
3162 area.x + area.width, area.y - width / 2,
3163 area.x + area.width,
3164 area.y + area.height + width / 2+1);
3166 if (attributes.border.mask & GTK_SHEET_TOP_BORDER & mask)
3167 gdk_draw_line (sheet->pixmap, sheet->fg_gc,
3168 area.x - width / 2,area.y,
3169 area.x + area.width + width / 2+1,
3172 if (attributes.border.mask & GTK_SHEET_BOTTOM_BORDER & mask)
3173 gdk_draw_line (sheet->pixmap, sheet->fg_gc,
3174 area.x - width / 2, area.y + area.height,
3175 area.x + area.width + width / 2+1,
3176 area.y + area.height);
3183 gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
3186 GdkRectangle area, clip_area;
3188 gint text_width, text_height, y;
3190 gint size, sizel, sizer;
3191 GdkGC *fg_gc, *bg_gc;
3192 GtkSheetCellAttr attributes;
3193 PangoLayout *layout;
3194 PangoRectangle rect;
3195 PangoRectangle logical_rect;
3196 PangoLayoutLine *line;
3197 PangoFontMetrics *metrics;
3198 PangoContext *context = gtk_widget_get_pango_context (GTK_WIDGET (sheet));
3199 gint ascent, descent, y_pos;
3203 g_return_if_fail (sheet != NULL);
3205 /* bail now if we aren't drawable yet */
3206 if (!GTK_WIDGET_DRAWABLE (sheet))
3209 label = gtk_sheet_cell_get_text (sheet, row, col);
3213 if (row < 0 || row >= yyy_row_count (sheet)) return;
3214 if (col < 0 || col >= xxx_column_count (sheet)) return;
3215 if (! xxx_column_is_visible (sheet, col)) return;
3216 if (!yyy_row_is_visible (sheet, row)) return;
3219 widget = GTK_WIDGET (sheet);
3221 gtk_sheet_get_attributes (sheet, row, col, &attributes);
3223 /* select GC for background rectangle */
3224 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3225 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3227 fg_gc = sheet->fg_gc;
3228 bg_gc = sheet->bg_gc;
3230 area.x = COLUMN_LEFT_XPIXEL (sheet,col);
3231 area.y = ROW_TOP_YPIXEL (sheet,row);
3232 area.width = xxx_column_width (sheet, col);
3233 area.height = yyy_row_height (sheet, row);
3237 layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), label);
3238 dispose_string (sheet, label);
3239 pango_layout_set_font_description (layout, attributes.font_desc);
3241 pango_layout_get_pixel_extents (layout, NULL, &rect);
3243 line = pango_layout_get_lines (layout)->data;
3244 pango_layout_line_get_extents (line, NULL, &logical_rect);
3246 metrics = pango_context_get_metrics (context,
3247 attributes.font_desc,
3248 pango_context_get_language (context));
3250 ascent = pango_font_metrics_get_ascent (metrics) / PANGO_SCALE;
3251 descent = pango_font_metrics_get_descent (metrics) / PANGO_SCALE;
3253 pango_font_metrics_unref (metrics);
3255 /* Align primarily for locale's ascent / descent */
3257 logical_rect.height /= PANGO_SCALE;
3258 logical_rect.y /= PANGO_SCALE;
3259 y_pos = area.height - logical_rect.height;
3261 if (logical_rect.height > area.height)
3262 y_pos = (logical_rect.height - area.height - 2 * CELLOFFSET) / 2;
3265 else if (y_pos + logical_rect.height > area.height)
3266 y_pos = area.height - logical_rect.height;
3268 text_width = rect.width;
3269 text_height = rect.height;
3270 y = area.y + y_pos - CELLOFFSET;
3272 switch (attributes.justification)
3274 case GTK_JUSTIFY_RIGHT:
3276 area.x +=area.width;
3277 if (!gtk_sheet_clip_text (sheet))
3279 for (i = col - 1; i >= MIN_VISIBLE_COLUMN (sheet); i--)
3281 if ( !gtk_sheet_cell_empty (sheet, row, i)) break;
3282 if (size >= text_width + CELLOFFSET) break;
3283 size +=xxx_column_width (sheet, i);
3284 xxx_column_set_right_column (sheet, i,
3286 xxx_column_right_column (sheet, i)));
3291 xoffset += area.width - text_width - 2 * CELLOFFSET -
3292 attributes.border.width / 2;
3294 case GTK_JUSTIFY_CENTER:
3295 sizel = area.width / 2;
3296 sizer = area.width / 2;
3297 area.x += area.width / 2;
3298 if (!gtk_sheet_clip_text (sheet))
3300 for (i = col + 1; i <= MAX_VISIBLE_COLUMN (sheet); i++)
3302 if ( ! gtk_sheet_cell_empty (sheet, row, i)) break;
3303 if (sizer >= text_width / 2) break;
3304 sizer += xxx_column_width (sheet, i);
3305 xxx_column_set_left_column (sheet, i,
3308 xxx_column_left_column (sheet, i)));
3310 for (i = col - 1; i >= MIN_VISIBLE_COLUMN (sheet); i--)
3312 if ( ! gtk_sheet_cell_empty (sheet, row, i)) break;
3313 if (sizel >= text_width / 2) break;
3314 sizel +=xxx_column_width (sheet, i);
3315 xxx_column_set_right_column (sheet, i,
3317 xxx_column_right_column (sheet, i)));
3319 size = MIN (sizel, sizer);
3322 xoffset += sizel - text_width / 2 - CELLOFFSET;
3323 area.width = sizel + sizer;
3325 case GTK_JUSTIFY_LEFT:
3328 if (!gtk_sheet_clip_text (sheet))
3330 for (i = col + 1; i <= MAX_VISIBLE_COLUMN (sheet); i++)
3332 if (! gtk_sheet_cell_empty (sheet, row, i)) break;
3333 if (size >= text_width + CELLOFFSET) break;
3334 size +=xxx_column_width (sheet, i);
3335 xxx_column_set_left_column (sheet, i,
3338 xxx_column_left_column (sheet, i)));
3343 xoffset += attributes.border.width / 2;
3347 if (!gtk_sheet_clip_text (sheet)) clip_area = area;
3348 gdk_gc_set_clip_rectangle (fg_gc, &clip_area);
3351 gdk_draw_layout (sheet->pixmap, fg_gc,
3352 area.x + xoffset + CELLOFFSET,
3356 gdk_gc_set_clip_rectangle (fg_gc, NULL);
3357 g_object_unref (G_OBJECT (layout));
3359 gdk_draw_pixmap (sheet->sheet_window,
3360 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
3374 gtk_sheet_range_draw (GtkSheet *sheet, const GtkSheetRange *range)
3377 GtkSheetRange drawing_range;
3380 g_return_if_fail (sheet != NULL);
3381 g_return_if_fail (GTK_SHEET (sheet));
3383 if (!GTK_WIDGET_DRAWABLE (GTK_WIDGET (sheet))) return;
3384 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
3385 if (!GTK_WIDGET_MAPPED (GTK_WIDGET (sheet))) return;
3389 drawing_range.row0 = MIN_VISIBLE_ROW (sheet);
3390 drawing_range.col0 = MIN_VISIBLE_COLUMN (sheet);
3391 drawing_range.rowi = MIN (MAX_VISIBLE_ROW (sheet), yyy_row_count (sheet) - 1);
3392 drawing_range.coli = MAX_VISIBLE_COLUMN (sheet);
3395 gdk_draw_rectangle (sheet->pixmap,
3396 GTK_WIDGET (sheet)->style->white_gc,
3399 sheet->sheet_window_width,sheet->sheet_window_height);
3404 drawing_range.row0 = MAX (range->row0, MIN_VISIBLE_ROW (sheet));
3405 drawing_range.col0 = MAX (range->col0, MIN_VISIBLE_COLUMN (sheet));
3406 drawing_range.rowi = MIN (range->rowi, MAX_VISIBLE_ROW (sheet));
3407 drawing_range.coli = MIN (range->coli, MAX_VISIBLE_COLUMN (sheet));
3411 if (drawing_range.coli == xxx_column_count (sheet) - 1)
3413 area.x = COLUMN_LEFT_XPIXEL (sheet,
3414 xxx_column_count (sheet) - 1) +
3415 xxx_column_width (sheet, xxx_column_count (sheet) - 1) + 1;
3419 gdk_gc_set_foreground (sheet->fg_gc, &sheet->bg_color);
3421 gdk_draw_rectangle (sheet->pixmap,
3425 sheet->sheet_window_width - area.x,
3426 sheet->sheet_window_height);
3428 gdk_draw_pixmap (sheet->sheet_window,
3429 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
3435 sheet->sheet_window_width - area.x,
3436 sheet->sheet_window_height);
3439 if (drawing_range.rowi == yyy_row_count (sheet) - 1)
3442 area.y = ROW_TOP_YPIXEL (sheet,
3443 yyy_row_count (sheet) - 1) +
3444 yyy_row_height (sheet, yyy_row_count (sheet) - 1) + 1;
3446 gdk_gc_set_foreground (sheet->fg_gc, &sheet->bg_color);
3448 gdk_draw_rectangle (sheet->pixmap,
3452 sheet->sheet_window_width,
3453 sheet->sheet_window_height - area.y);
3455 gdk_draw_pixmap (sheet->sheet_window,
3456 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
3462 sheet->sheet_window_width,
3463 sheet->sheet_window_height - area.y);
3466 for (i = drawing_range.row0; i <= drawing_range.rowi; i++)
3467 for (j = drawing_range.col0; j <= drawing_range.coli; j++)
3469 gtk_sheet_cell_draw_default (sheet, i, j);
3472 for (i = drawing_range.row0; i <= drawing_range.rowi; i++)
3473 for (j = drawing_range.col0; j <= drawing_range.coli; j++)
3475 gtk_sheet_cell_draw_border (sheet, i - 1, j, GTK_SHEET_BOTTOM_BORDER);
3476 gtk_sheet_cell_draw_border (sheet, i + 1, j, GTK_SHEET_TOP_BORDER);
3477 gtk_sheet_cell_draw_border (sheet, i, j - 1, GTK_SHEET_RIGHT_BORDER);
3478 gtk_sheet_cell_draw_border (sheet, i, j + 1, GTK_SHEET_LEFT_BORDER);
3479 gtk_sheet_cell_draw_border (sheet, i, j, 15);
3482 for (i = drawing_range.row0; i <= drawing_range.rowi; i++)
3483 for (j = drawing_range.col0; j <= drawing_range.coli; j++)
3484 gtk_sheet_cell_draw_label (sheet, i, j);
3486 for (i = drawing_range.row0; i <= drawing_range.rowi; i++)
3487 for (j= xxx_column_left_column (sheet, drawing_range.col0);
3488 j < drawing_range.col0; j++)
3489 gtk_sheet_cell_draw_label (sheet, i, j);
3491 for (i = drawing_range.row0; i <= drawing_range.rowi; i++)
3492 for (j = drawing_range.coli + 1;
3493 j <= xxx_column_right_column (sheet, drawing_range.coli);
3495 gtk_sheet_cell_draw_label (sheet, i, j);
3497 gtk_sheet_draw_backing_pixmap (sheet, drawing_range);
3499 if (sheet->state != GTK_SHEET_NORMAL &&
3500 gtk_sheet_range_isvisible (sheet, sheet->range))
3501 gtk_sheet_range_draw_selection (sheet, drawing_range);
3503 if (sheet->state == GTK_STATE_NORMAL &&
3504 sheet->active_cell.row >= drawing_range.row0 &&
3505 sheet->active_cell.row <= drawing_range.rowi &&
3506 sheet->active_cell.col >= drawing_range.col0 &&
3507 sheet->active_cell.col <= drawing_range.coli)
3508 gtk_sheet_show_active_cell (sheet);
3513 gtk_sheet_range_draw_selection (GtkSheet *sheet, GtkSheetRange range)
3519 if (range.col0 > sheet->range.coli || range.coli < sheet->range.col0 ||
3520 range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0)
3523 if (!gtk_sheet_range_isvisible (sheet, range)) return;
3524 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
3528 range.col0 = MAX (sheet->range.col0, range.col0);
3529 range.coli = MIN (sheet->range.coli, range.coli);
3530 range.row0 = MAX (sheet->range.row0, range.row0);
3531 range.rowi = MIN (sheet->range.rowi, range.rowi);
3533 range.col0 = MAX (range.col0, MIN_VISIBLE_COLUMN (sheet));
3534 range.coli = MIN (range.coli, MAX_VISIBLE_COLUMN (sheet));
3535 range.row0 = MAX (range.row0, MIN_VISIBLE_ROW (sheet));
3536 range.rowi = MIN (range.rowi, MAX_VISIBLE_ROW (sheet));
3538 for (i = range.row0; i <= range.rowi; i++)
3540 for (j = range.col0; j <= range.coli; j++)
3543 if (gtk_sheet_cell_get_state (sheet, i, j) == GTK_STATE_SELECTED &&
3544 xxx_column_is_visible (sheet, j) && yyy_row_is_visible (sheet, i))
3547 area.x = COLUMN_LEFT_XPIXEL (sheet,j);
3548 area.y = ROW_TOP_YPIXEL (sheet,i);
3549 area.width= xxx_column_width (sheet, j);
3550 area.height = yyy_row_height (sheet, i);
3552 if (i == sheet->range.row0)
3554 area.y = area.y + 2;
3555 area.height = area.height - 2;
3557 if (i == sheet->range.rowi) area.height = area.height - 3;
3558 if (j == sheet->range.col0)
3560 area.x = area.x + 2;
3561 area.width = area.width - 2;
3563 if (j == sheet->range.coli) area.width = area.width - 3;
3565 if (i!=sheet->active_cell.row || j!=sheet->active_cell.col)
3567 gdk_draw_rectangle (sheet->sheet_window,
3570 area.x + 1,area.y + 1,
3571 area.width,area.height);
3578 gtk_sheet_draw_border (sheet, sheet->range);
3582 gtk_sheet_draw_backing_pixmap (GtkSheet *sheet, GtkSheetRange range)
3584 gint x,y,width,height;
3586 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
3588 x = COLUMN_LEFT_XPIXEL (sheet,range.col0);
3589 y = ROW_TOP_YPIXEL (sheet, range.row0);
3590 width = COLUMN_LEFT_XPIXEL (sheet, range.coli) - x +
3591 xxx_column_width (sheet, range.coli);
3593 height = ROW_TOP_YPIXEL (sheet, range.rowi)- y + yyy_row_height (sheet, range.rowi);
3595 if (range.row0 == sheet->range.row0)
3598 height = height + 5;
3600 if (range.rowi == sheet->range.rowi) height = height + 5;
3601 if (range.col0 == sheet->range.col0)
3606 if (range.coli == sheet->range.coli) width = width + 5;
3608 width = MIN (width, sheet->sheet_window_width - x);
3609 height = MIN (height, sheet->sheet_window_height - y);
3616 x = (sheet->row_titles_visible)
3617 ? MAX (x, sheet->row_title_area.width) : MAX (x, 0);
3618 y = (sheet->column_titles_visible)
3619 ? MAX (y, sheet->column_title_area.height) : MAX (y, 0);
3621 if (range.coli == xxx_column_count (sheet) - 1)
3622 width = sheet->sheet_window_width - x;
3623 if (range.rowi == yyy_row_count (sheet) - 1)
3624 height = sheet->sheet_window_height - y;
3626 gdk_draw_pixmap (sheet->sheet_window,
3627 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
3639 gtk_sheet_set_cell_text (GtkSheet *sheet, gint row, gint col, const gchar *text)
3641 GtkSheetCellAttr attributes;
3643 g_return_if_fail (sheet != NULL);
3644 g_return_if_fail (GTK_IS_SHEET (sheet));
3645 if (col >= xxx_column_count (sheet) || row >= yyy_row_count (sheet)) return;
3646 if (col < 0 || row < 0) return;
3648 gtk_sheet_get_attributes (sheet, row, col, &attributes);
3649 gtk_sheet_set_cell (sheet, row, col, attributes.justification, text);
3653 safe_strcmp (const gchar *s1, const gchar *s2)
3655 if ( !s1 && !s2) return 0;
3656 if ( !s1) return - 1;
3657 if ( !s2) return +1;
3658 return strcmp (s1, s2);
3662 gtk_sheet_set_cell (GtkSheet *sheet, gint row, gint col,
3663 GtkJustification justification,
3666 GSheetModel *model ;
3670 GtkSheetRange range;
3672 GtkSheetCellAttr attributes;
3674 g_return_if_fail (sheet != NULL);
3675 g_return_if_fail (GTK_IS_SHEET (sheet));
3676 if (col >= xxx_column_count (sheet) || row >= yyy_row_count (sheet)) return;
3677 if (col < 0 || row < 0) return;
3679 gtk_sheet_get_attributes (sheet, row, col, &attributes);
3681 attributes.justification = justification;
3683 model = gtk_sheet_get_model (sheet);
3685 old_text = g_sheet_model_get_string (model, row, col);
3689 if (0 != safe_strcmp (old_text, text))
3690 changed = g_sheet_model_set_string (model, text, row, col);
3692 if ( g_sheet_model_free_strings (model))
3696 if (changed && attributes.is_visible)
3698 gchar *s = gtk_sheet_cell_get_text (sheet, row, col);
3700 if (s && strlen (s) > 0)
3702 text_width = STRING_WIDTH (GTK_WIDGET (sheet),
3703 attributes.font_desc, text);
3705 dispose_string (sheet, s);
3709 range.col0 = sheet->view.col0;
3710 range.coli = sheet->view.coli;
3712 if (gtk_sheet_autoresize (sheet) &&
3713 text_width > xxx_column_width (sheet, col) -
3714 2 * CELLOFFSET- attributes.border.width)
3716 gtk_sheet_set_column_width (sheet, col, text_width + 2 * CELLOFFSET
3717 + attributes.border.width);
3718 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_REDRAW_PENDING);
3721 if (!GTK_SHEET_IS_FROZEN (sheet))
3722 gtk_sheet_range_draw (sheet, &range);
3726 gtk_signal_emit (GTK_OBJECT (sheet),sheet_signals[CHANGED], row, col);
3732 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
3734 GtkSheetRange range;
3736 g_return_if_fail (sheet != NULL);
3737 g_return_if_fail (GTK_IS_SHEET (sheet));
3738 if (column >= xxx_column_count (sheet) ||
3739 row >= yyy_row_count (sheet)) return;
3741 if (column < 0 || row < 0) return;
3745 range.col0 = sheet->view.col0;
3746 range.coli = sheet->view.coli;
3748 gtk_sheet_real_cell_clear (sheet, row, column, FALSE);
3750 if (!GTK_SHEET_IS_FROZEN (sheet))
3752 gtk_sheet_range_draw (sheet, &range);
3757 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
3759 GtkSheetRange range;
3761 g_return_if_fail (sheet != NULL);
3762 g_return_if_fail (GTK_IS_SHEET (sheet));
3763 if (column >= xxx_column_count (sheet) || row >= yyy_row_count (sheet)) return;
3764 if (column < 0 || row < 0) return;
3768 range.col0 = sheet->view.col0;
3769 range.coli = sheet->view.coli;
3771 gtk_sheet_real_cell_clear (sheet, row, column, TRUE);
3773 if (!GTK_SHEET_IS_FROZEN (sheet))
3775 gtk_sheet_range_draw (sheet, &range);
3780 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
3782 GSheetModel *model = gtk_sheet_get_model (sheet);
3784 gchar *old_text = gtk_sheet_cell_get_text (sheet, row, column);
3786 if (old_text && strlen (old_text) > 0 )
3788 g_sheet_model_datum_clear (model, row, column);
3790 if (GTK_IS_OBJECT (sheet) && G_OBJECT (sheet)->ref_count > 0)
3791 gtk_signal_emit (GTK_OBJECT (sheet),sheet_signals[CLEAR_CELL],
3795 dispose_string (sheet, old_text);
3799 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
3801 g_return_if_fail (sheet != NULL);
3802 g_return_if_fail (GTK_IS_SHEET (sheet));
3804 gtk_sheet_real_range_clear (sheet, range, FALSE);
3808 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range)
3810 g_return_if_fail (sheet != NULL);
3811 g_return_if_fail (GTK_IS_SHEET (sheet));
3813 gtk_sheet_real_range_clear (sheet, range, TRUE);
3818 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
3822 GtkSheetRange clear;
3827 clear.rowi = yyy_row_count (sheet) - 1;
3829 clear.coli = xxx_column_count (sheet) - 1;
3834 clear.row0 = MAX (clear.row0, 0);
3835 clear.col0 = MAX (clear.col0, 0);
3836 clear.rowi = MIN (clear.rowi, yyy_row_count (sheet) - 1 );
3837 clear.coli = MIN (clear.coli, xxx_column_count (sheet) - 1 );
3839 for (i = clear.row0; i <= clear.rowi; i++)
3840 for (j = clear.col0; j <= clear.coli; j++)
3842 gtk_sheet_real_cell_clear (sheet, i, j, delete);
3845 gtk_sheet_range_draw (sheet, NULL);
3850 gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col)
3853 char *text = gtk_sheet_cell_get_text (sheet, row, col);
3854 empty = (text == NULL );
3856 dispose_string (sheet, text);
3863 gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
3866 g_return_val_if_fail (sheet != NULL, NULL);
3867 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
3869 if (col >= xxx_column_count (sheet) || row >= yyy_row_count (sheet))
3871 if (col < 0 || row < 0) return NULL;
3873 model = gtk_sheet_get_model (sheet);
3878 return g_sheet_model_get_string (model, row, col);
3883 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
3886 GtkSheetRange *range;
3888 g_return_val_if_fail (sheet != NULL, 0);
3889 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3890 if (col >= xxx_column_count (sheet) || row >= yyy_row_count (sheet)) return 0;
3891 if (col < 0 || row < 0) return 0;
3893 state = sheet->state;
3894 range = &sheet->range;
3898 case GTK_SHEET_NORMAL:
3899 return GTK_STATE_NORMAL;
3901 case GTK_SHEET_ROW_SELECTED:
3902 if (row >= range->row0 && row <= range->rowi)
3903 return GTK_STATE_SELECTED;
3905 case GTK_SHEET_COLUMN_SELECTED:
3906 if (col >= range->col0 && col <= range->coli)
3907 return GTK_STATE_SELECTED;
3909 case GTK_SHEET_RANGE_SELECTED:
3910 if (row >= range->row0 && row <= range->rowi && \
3911 col >= range->col0 && col <= range->coli)
3912 return GTK_STATE_SELECTED;
3915 return GTK_STATE_NORMAL;
3919 gtk_sheet_get_pixel_info (GtkSheet * sheet,
3927 g_return_val_if_fail (sheet != NULL, 0);
3928 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3930 /* bounds checking, return false if the user clicked
3932 trow = ROW_FROM_YPIXEL (sheet, y);
3933 if (trow >= yyy_row_count (sheet))
3938 tcol = COLUMN_FROM_XPIXEL (sheet, x);
3939 if (tcol >= xxx_column_count (sheet))
3948 gtk_sheet_get_cell_area (GtkSheet * sheet,
3953 g_return_val_if_fail (sheet != NULL, 0);
3954 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3956 if (row >= yyy_row_count (sheet) || column >= xxx_column_count (sheet))
3959 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL (sheet, column) -
3960 (sheet->row_titles_visible
3961 ? sheet->row_title_area.width
3963 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL (sheet, row) -
3964 (sheet->column_titles_visible
3965 ? sheet->column_title_area.height
3967 area->width= (column == -1) ? sheet->row_title_area.width
3968 : xxx_column_width (sheet, column);
3970 area->height= (row == -1) ? sheet->column_title_area.height
3971 : yyy_row_height (sheet, row);
3977 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
3979 g_return_val_if_fail (sheet != NULL, 0);
3980 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3982 if (row < - 1 || column < - 1) return FALSE;
3983 if (row >= yyy_row_count (sheet) || column >= xxx_column_count (sheet))
3986 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
3988 if (!gtk_sheet_deactivate_cell (sheet)) return FALSE;
3991 sheet->active_cell.row = row;
3992 sheet->active_cell.col = column;
3994 if ( row == -1 || column == -1)
3996 gtk_sheet_hide_active_cell (sheet);
4000 if (!gtk_sheet_activate_cell (sheet, row, column)) return FALSE;
4002 if (gtk_sheet_autoscroll (sheet))
4003 gtk_sheet_move_query (sheet, row, column);
4009 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column)
4011 g_return_if_fail (sheet != NULL);
4012 g_return_if_fail (GTK_IS_SHEET (sheet));
4014 *row = sheet->active_cell.row;
4015 *column = sheet->active_cell.col;
4019 gtk_sheet_entry_changed (GtkWidget *widget, gpointer data)
4024 GtkJustification justification;
4025 GtkSheetCellAttr attributes;
4027 g_return_if_fail (data != NULL);
4028 g_return_if_fail (GTK_IS_SHEET (data));
4030 sheet = GTK_SHEET (data);
4032 if (!GTK_WIDGET_VISIBLE (widget)) return;
4033 if (sheet->state != GTK_STATE_NORMAL) return;
4035 row = sheet->active_cell.row;
4036 col = sheet->active_cell.col;
4038 if (row < 0 || col < 0) return;
4040 sheet->active_cell.row =- 1;
4041 sheet->active_cell.col =- 1;
4043 text = gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)));
4045 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IS_FROZEN);
4047 if (text && strlen (text) > 0)
4049 gtk_sheet_get_attributes (sheet, row, col, &attributes);
4050 justification = attributes.justification;
4051 gtk_sheet_set_cell (sheet, row, col, justification, text);
4054 if (sheet->freeze_count == 0)
4055 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IS_FROZEN);
4057 sheet->active_cell.row = row;;
4058 sheet->active_cell.col = col;
4063 gtk_sheet_deactivate_cell (GtkSheet *sheet)
4065 gboolean veto = TRUE;
4067 g_return_val_if_fail (sheet != NULL, FALSE);
4068 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
4070 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return FALSE;
4071 if (sheet->state != GTK_SHEET_NORMAL) return FALSE;
4073 _gtkextra_signal_emit (GTK_OBJECT (sheet),sheet_signals[DEACTIVATE],
4074 sheet->active_cell.row,
4075 sheet->active_cell.col, &veto);
4077 if (!veto) return FALSE;
4079 if ( sheet->active_cell.row == -1 || sheet->active_cell.col == -1 )
4082 gtk_signal_disconnect_by_func (GTK_OBJECT (gtk_sheet_get_entry (sheet)),
4083 (GtkSignalFunc) gtk_sheet_entry_changed,
4084 GTK_OBJECT (GTK_WIDGET (sheet)));
4086 gtk_sheet_hide_active_cell (sheet);
4087 sheet->active_cell.row = -1;
4088 sheet->active_cell.col = -1;
4090 if (GTK_SHEET_REDRAW_PENDING (sheet))
4092 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_REDRAW_PENDING);
4093 gtk_sheet_range_draw (sheet, NULL);
4100 gtk_sheet_hide_active_cell (GtkSheet *sheet)
4104 GtkJustification justification;
4105 GtkSheetCellAttr attributes;
4107 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
4109 row = sheet->active_cell.row;
4110 col = sheet->active_cell.col;
4112 if (row < 0 || col < 0) return;
4114 if (sheet->freeze_count == 0)
4115 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IS_FROZEN);
4117 text = gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)));
4119 gtk_sheet_get_attributes (sheet, row, col, &attributes);
4120 justification = attributes.justification;
4122 if (text && strlen (text) != 0)
4124 gtk_sheet_set_cell (sheet, row, col, justification, text);
4125 gtk_signal_emit (GTK_OBJECT (sheet),sheet_signals[SET_CELL], row, col);
4129 gtk_sheet_cell_clear (sheet, row, col);
4132 row = sheet->active_cell.row;
4133 col = sheet->active_cell.col;
4135 gtk_widget_hide (sheet->sheet_entry);
4136 gtk_widget_unmap (sheet->sheet_entry);
4138 if (row != -1 && col != -1)
4139 gdk_draw_pixmap (sheet->sheet_window,
4140 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
4142 COLUMN_LEFT_XPIXEL (sheet,col)- 1,
4143 ROW_TOP_YPIXEL (sheet,row)- 1,
4144 COLUMN_LEFT_XPIXEL (sheet,col)- 1,
4145 ROW_TOP_YPIXEL (sheet,row)- 1,
4146 xxx_column_width (sheet, col) + 4,
4147 yyy_row_height (sheet, row)+4);
4149 gtk_widget_grab_focus (GTK_WIDGET (sheet));
4151 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (sheet->sheet_entry), GTK_VISIBLE);
4156 gtk_sheet_activate_cell (GtkSheet *sheet, gint row, gint col)
4158 gboolean veto = TRUE;
4160 g_return_val_if_fail (sheet != NULL, FALSE);
4161 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
4163 if (row < 0 || col < 0) return FALSE;
4164 if (row >= yyy_row_count (sheet) || col >= xxx_column_count (sheet))
4167 /* _gtkextra_signal_emit (GTK_OBJECT (sheet),sheet_signals[ACTIVATE], row, col, &veto);
4168 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return veto;
4171 if (!veto) return FALSE;
4172 if (sheet->state != GTK_SHEET_NORMAL)
4174 sheet->state = GTK_SHEET_NORMAL;
4175 gtk_sheet_real_unselect_range (sheet, NULL);
4178 sheet->range.row0 = row;
4179 sheet->range.col0 = col;
4180 sheet->range.rowi = row;
4181 sheet->range.coli = col;
4182 sheet->active_cell.row = row;
4183 sheet->active_cell.col = col;
4184 sheet->selection_cell.row = row;
4185 sheet->selection_cell.col = col;
4187 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
4188 gtk_sheet_show_active_cell (sheet);
4190 g_signal_connect (G_OBJECT (gtk_sheet_get_entry (sheet)),
4192 G_CALLBACK (gtk_sheet_entry_changed),
4195 _gtkextra_signal_emit (GTK_OBJECT (sheet),sheet_signals[ACTIVATE], row, col, &veto);
4201 gtk_sheet_show_active_cell (GtkSheet *sheet)
4203 GtkEntry *sheet_entry;
4204 GtkSheetCellAttr attributes;
4206 const gchar *old_text;
4207 GtkJustification justification;
4210 g_return_if_fail (sheet != NULL);
4211 g_return_if_fail (GTK_IS_SHEET (sheet));
4213 row = sheet->active_cell.row;
4214 col = sheet->active_cell.col;
4216 /* Don't show the active cell, if there is no active cell: */
4217 if (! (row >= 0 && col >= 0)) /* e.g row or coll == -1. */
4220 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
4221 if (sheet->state != GTK_SHEET_NORMAL) return;
4222 if (GTK_SHEET_IN_SELECTION (sheet)) return;
4224 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (sheet->sheet_entry), GTK_VISIBLE);
4226 sheet_entry = GTK_ENTRY (gtk_sheet_get_entry (sheet));
4228 gtk_sheet_get_attributes (sheet, row, col, &attributes);
4230 justification = GTK_JUSTIFY_LEFT;
4232 if (gtk_sheet_justify_entry (sheet))
4233 justification = attributes.justification;
4235 text = gtk_sheet_cell_get_text (sheet, row, col);
4237 text = g_strdup ("");
4239 gtk_entry_set_visibility (GTK_ENTRY (sheet_entry), attributes.is_visible);
4241 if (gtk_sheet_locked (sheet) || !attributes.is_editable)
4242 gtk_entry_set_editable (GTK_ENTRY (sheet_entry), FALSE);
4244 gtk_entry_set_editable (GTK_ENTRY (sheet_entry), TRUE);
4246 /*** Added by John Gotts. Mar 25, 2005 *********/
4247 old_text = gtk_entry_get_text (GTK_ENTRY (sheet_entry));
4248 if (strcmp (old_text, text) != 0)
4250 if (!GTK_IS_ITEM_ENTRY (sheet_entry))
4251 gtk_entry_set_text (GTK_ENTRY (sheet_entry), text);
4253 gtk_item_entry_set_text (GTK_ITEM_ENTRY (sheet_entry), text, justification);
4256 gtk_sheet_entry_set_max_size (sheet);
4257 gtk_sheet_size_allocate_entry (sheet);
4259 gtk_widget_map (sheet->sheet_entry);
4260 gtk_sheet_draw_active_cell (sheet);
4262 gtk_widget_grab_focus (GTK_WIDGET (sheet_entry));
4264 dispose_string (sheet, text);
4268 gtk_sheet_draw_active_cell (GtkSheet *sheet)
4272 if (!GTK_WIDGET_DRAWABLE (GTK_WIDGET (sheet))) return;
4273 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
4275 row = sheet->active_cell.row;
4276 col = sheet->active_cell.col;
4278 if (row < 0 || col < 0) return;
4280 if (!gtk_sheet_cell_isvisible (sheet, row, col)) return;
4282 gtk_sheet_draw_border (sheet, sheet->range);
4287 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
4289 gint pixmap_width, pixmap_height;
4291 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
4293 if (width == 0 && height == 0)
4295 width = sheet->sheet_window_width + 80;
4296 height = sheet->sheet_window_height + 80;
4302 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4305 if (!GTK_SHEET_IS_FROZEN (sheet)) gtk_sheet_range_draw (sheet, NULL);
4309 /* reallocate if sizes don't match */
4310 gdk_window_get_size (sheet->pixmap,
4311 &pixmap_width, &pixmap_height);
4312 if ( (pixmap_width != width) || (pixmap_height != height))
4314 g_object_unref (sheet->pixmap);
4315 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4318 if (!GTK_SHEET_IS_FROZEN (sheet)) gtk_sheet_range_draw (sheet, NULL);
4324 gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
4326 gint i,j, mask1, mask2;
4327 gint state, selected;
4328 gint x,y,width,height;
4329 GtkSheetRange new_range, aux_range;
4331 g_return_if_fail (sheet != NULL);
4333 if (range == NULL) range=&sheet->range;
4337 range->row0 = MIN (range->row0, sheet->range.row0);
4338 range->rowi = MAX (range->rowi, sheet->range.rowi);
4339 range->col0 = MIN (range->col0, sheet->range.col0);
4340 range->coli = MAX (range->coli, sheet->range.coli);
4342 range->row0 = MAX (range->row0, MIN_VISIBLE_ROW (sheet));
4343 range->rowi = MIN (range->rowi, MAX_VISIBLE_ROW (sheet));
4344 range->col0 = MAX (range->col0, MIN_VISIBLE_COLUMN (sheet));
4345 range->coli = MIN (range->coli, MAX_VISIBLE_COLUMN (sheet));
4347 aux_range.row0 = MAX (new_range.row0, MIN_VISIBLE_ROW (sheet));
4348 aux_range.rowi = MIN (new_range.rowi, MAX_VISIBLE_ROW (sheet));
4349 aux_range.col0 = MAX (new_range.col0, MIN_VISIBLE_COLUMN (sheet));
4350 aux_range.coli = MIN (new_range.coli, MAX_VISIBLE_COLUMN (sheet));
4352 for (i = range->row0; i <= range->rowi; i++)
4354 for (j = range->col0; j <= range->coli; j++)
4357 state = gtk_sheet_cell_get_state (sheet, i, j);
4358 selected= (i <= new_range.rowi && i >= new_range.row0 &&
4359 j <= new_range.coli && j >= new_range.col0) ? TRUE : FALSE;
4361 if (state == GTK_STATE_SELECTED && selected &&
4362 xxx_column_is_visible (sheet, j) && yyy_row_is_visible (sheet, i) &&
4363 (i == sheet->range.row0 || i == sheet->range.rowi ||
4364 j == sheet->range.col0 || j == sheet->range.coli ||
4365 i == new_range.row0 || i == new_range.rowi ||
4366 j == new_range.col0 || j == new_range.coli))
4369 mask1 = i == sheet->range.row0 ? 1 : 0;
4370 mask1 = i == sheet->range.rowi ? mask1 + 2 : mask1;
4371 mask1 = j == sheet->range.col0 ? mask1 + 4 : mask1;
4372 mask1 = j == sheet->range.coli ? mask1 + 8 : mask1;
4374 mask2 = i == new_range.row0 ? 1 : 0;
4375 mask2 = i == new_range.rowi ? mask2 + 2 : mask2;
4376 mask2 = j == new_range.col0 ? mask2 + 4 : mask2;
4377 mask2 = j == new_range.coli ? mask2 + 8 : mask2;
4381 x = COLUMN_LEFT_XPIXEL (sheet,j);
4382 y = ROW_TOP_YPIXEL (sheet, i);
4383 width = COLUMN_LEFT_XPIXEL (sheet, j)- x+
4384 xxx_column_width (sheet, j);
4385 height = ROW_TOP_YPIXEL (sheet, i)- y + yyy_row_height (sheet, i);
4387 if (i == sheet->range.row0)
4390 height = height + 3;
4392 if (i == sheet->range.rowi) height = height + 3;
4393 if (j == sheet->range.col0)
4398 if (j == sheet->range.coli) width = width + 3;
4400 gdk_draw_pixmap (sheet->sheet_window,
4401 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
4410 if (i != sheet->active_cell.row || j != sheet->active_cell.col)
4412 x = COLUMN_LEFT_XPIXEL (sheet,j);
4413 y = ROW_TOP_YPIXEL (sheet, i);
4414 width = COLUMN_LEFT_XPIXEL (sheet, j)- x+
4415 xxx_column_width (sheet, j);
4417 height = ROW_TOP_YPIXEL (sheet, i)- y + yyy_row_height (sheet, i);
4419 if (i == new_range.row0)
4422 height = height - 2;
4424 if (i == new_range.rowi) height = height - 3;
4425 if (j == new_range.col0)
4430 if (j == new_range.coli) width = width - 3;
4432 gdk_draw_rectangle (sheet->sheet_window,
4443 for (i = range->row0; i <= range->rowi; i++)
4445 for (j = range->col0; j <= range->coli; j++)
4448 state = gtk_sheet_cell_get_state (sheet, i, j);
4449 selected= (i <= new_range.rowi && i >= new_range.row0 &&
4450 j <= new_range.coli && j >= new_range.col0) ? TRUE : FALSE;
4452 if (state == GTK_STATE_SELECTED && !selected &&
4453 xxx_column_is_visible (sheet, j) && yyy_row_is_visible (sheet, i))
4456 x = COLUMN_LEFT_XPIXEL (sheet,j);
4457 y = ROW_TOP_YPIXEL (sheet, i);
4458 width = COLUMN_LEFT_XPIXEL (sheet, j)- x+ xxx_column_width (sheet, j);
4459 height = ROW_TOP_YPIXEL (sheet, i)- y + yyy_row_height (sheet, i);
4461 if (i == sheet->range.row0)
4464 height = height + 3;
4466 if (i == sheet->range.rowi) height = height + 3;
4467 if (j == sheet->range.col0)
4472 if (j == sheet->range.coli) width = width + 3;
4474 gdk_draw_pixmap (sheet->sheet_window,
4475 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
4487 for (i = range->row0; i <= range->rowi; i++)
4489 for (j = range->col0; j <= range->coli; j++)
4492 state = gtk_sheet_cell_get_state (sheet, i, j);
4493 selected= (i <= new_range.rowi && i >= new_range.row0 &&
4494 j <= new_range.coli && j >= new_range.col0) ? TRUE : FALSE;
4496 if (state!=GTK_STATE_SELECTED && selected &&
4497 xxx_column_is_visible (sheet, j) && yyy_row_is_visible (sheet, i) &&
4498 (i != sheet->active_cell.row || j != sheet->active_cell.col))
4501 x = COLUMN_LEFT_XPIXEL (sheet,j);
4502 y = ROW_TOP_YPIXEL (sheet, i);
4503 width = COLUMN_LEFT_XPIXEL (sheet, j)- x+ xxx_column_width (sheet, j);
4504 height = ROW_TOP_YPIXEL (sheet, i)- y + yyy_row_height (sheet, i);
4506 if (i == new_range.row0)
4509 height = height - 2;
4511 if (i == new_range.rowi) height = height - 3;
4512 if (j == new_range.col0)
4517 if (j == new_range.coli) width = width - 3;
4519 gdk_draw_rectangle (sheet->sheet_window,
4530 for (i = aux_range.row0; i <= aux_range.rowi; i++)
4532 for (j = aux_range.col0; j <= aux_range.coli; j++)
4535 if (xxx_column_is_visible (sheet, j) && yyy_row_is_visible (sheet, i))
4538 state = gtk_sheet_cell_get_state (sheet, i, j);
4540 mask1 = i == sheet->range.row0 ? 1 : 0;
4541 mask1 = i == sheet->range.rowi ? mask1 + 2 : mask1;
4542 mask1 = j == sheet->range.col0 ? mask1 + 4 : mask1;
4543 mask1 = j == sheet->range.coli ? mask1 + 8 : mask1;
4545 mask2 = i == new_range.row0 ? 1 : 0;
4546 mask2 = i == new_range.rowi ? mask2 + 2 : mask2;
4547 mask2 = j == new_range.col0 ? mask2 + 4 : mask2;
4548 mask2 = j == new_range.coli ? mask2 + 8 : mask2;
4549 if (mask2!=mask1 || (mask2 == mask1 && state!=GTK_STATE_SELECTED))
4551 x = COLUMN_LEFT_XPIXEL (sheet,j);
4552 y = ROW_TOP_YPIXEL (sheet, i);
4553 width = xxx_column_width (sheet, j);
4554 height = yyy_row_height (sheet, i);
4556 gdk_draw_rectangle (sheet->sheet_window,
4564 gdk_draw_rectangle (sheet->sheet_window,
4567 x + 1,y + height - 1,
4571 gdk_draw_rectangle (sheet->sheet_window,
4579 gdk_draw_rectangle (sheet->sheet_window,
4582 x + width - 1,y + 1,
4596 gtk_sheet_draw_corners (sheet, new_range);
4601 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
4606 gint x,y,width,height;
4608 widget = GTK_WIDGET (sheet);
4610 x = COLUMN_LEFT_XPIXEL (sheet,new_range.col0);
4611 y = ROW_TOP_YPIXEL (sheet,new_range.row0);
4612 width = COLUMN_LEFT_XPIXEL (sheet,new_range.coli)- x+
4613 xxx_column_width (sheet, new_range.coli);
4615 height = ROW_TOP_YPIXEL (sheet,new_range.rowi)- y+
4616 yyy_row_height (sheet, new_range.rowi);
4618 area.x = COLUMN_LEFT_XPIXEL (sheet, MIN_VISIBLE_COLUMN (sheet));
4619 area.y = ROW_TOP_YPIXEL (sheet, MIN_VISIBLE_ROW (sheet));
4620 area.width = sheet->sheet_window_width;
4621 area.height = sheet->sheet_window_height;
4628 if (width > area.width) width = area.width + 10;
4631 height = height + y;
4634 if (height > area.height) height = area.height + 10;
4636 gdk_gc_set_clip_rectangle (sheet->xor_gc, &area);
4638 for (i =- 1; i <= 1; ++i)
4639 gdk_draw_rectangle (sheet->sheet_window,
4643 width - 2 * i,height - 2 * i);
4645 gdk_gc_set_clip_rectangle (sheet->xor_gc, NULL);
4647 gtk_sheet_draw_corners (sheet, new_range);
4652 gtk_sheet_draw_corners (GtkSheet *sheet, GtkSheetRange range)
4657 if (gtk_sheet_cell_isvisible (sheet, range.row0, range.col0))
4659 x = COLUMN_LEFT_XPIXEL (sheet,range.col0);
4660 y = ROW_TOP_YPIXEL (sheet,range.row0);
4661 gdk_draw_pixmap (sheet->sheet_window,
4662 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
4670 gdk_draw_rectangle (sheet->sheet_window,
4677 if (gtk_sheet_cell_isvisible (sheet, range.row0, range.coli) ||
4678 sheet->state == GTK_SHEET_COLUMN_SELECTED)
4680 x = COLUMN_LEFT_XPIXEL (sheet,range.coli)+
4681 xxx_column_width (sheet, range.coli);
4682 y = ROW_TOP_YPIXEL (sheet,range.row0);
4684 if (sheet->state == GTK_SHEET_COLUMN_SELECTED)
4686 y = ROW_TOP_YPIXEL (sheet, sheet->view.row0)+3;
4689 gdk_draw_pixmap (sheet->sheet_window,
4690 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
4698 gdk_draw_rectangle (sheet->sheet_window,
4701 x - width + width / 2,y - width + width / 2,
4702 2 + width,2 + width);
4705 if (gtk_sheet_cell_isvisible (sheet, range.rowi, range.col0) ||
4706 sheet->state == GTK_SHEET_ROW_SELECTED)
4708 x = COLUMN_LEFT_XPIXEL (sheet,range.col0);
4709 y = ROW_TOP_YPIXEL (sheet,range.rowi)+
4710 yyy_row_height (sheet, range.rowi);
4712 if (sheet->state == GTK_SHEET_ROW_SELECTED)
4714 x = COLUMN_LEFT_XPIXEL (sheet, sheet->view.col0)+3;
4717 gdk_draw_pixmap (sheet->sheet_window,
4718 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
4726 gdk_draw_rectangle (sheet->sheet_window,
4729 x - width + width / 2,y - width + width / 2,
4730 2 + width,2 + width);
4733 if (gtk_sheet_cell_isvisible (sheet, range.rowi, range.coli))
4735 x = COLUMN_LEFT_XPIXEL (sheet,range.coli)+
4736 xxx_column_width (sheet, range.coli);
4737 y = ROW_TOP_YPIXEL (sheet,range.rowi)+
4738 yyy_row_height (sheet, range.rowi);
4740 if (sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
4741 if (sheet->state == GTK_SHEET_NORMAL) width = 3;
4742 gdk_draw_pixmap (sheet->sheet_window,
4743 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
4751 gdk_draw_rectangle (sheet->sheet_window,
4754 x - width + width / 2,y - width + width / 2,
4755 2 + width,2 + width);
4763 gtk_sheet_real_select_range (GtkSheet * sheet,
4764 const GtkSheetRange * range)
4768 g_return_if_fail (sheet != NULL);
4770 if (range == NULL) range = &sheet->range;
4772 memcpy (&sheet->range, range, sizeof (*range));
4774 if (range->row0 < 0 || range->rowi < 0) return;
4775 if (range->col0 < 0 || range->coli < 0) return;
4777 state = sheet->state;
4779 if (range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
4780 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
4782 gtk_sheet_new_selection (sheet, &sheet->range);
4786 gtk_sheet_draw_backing_pixmap (sheet, sheet->range);
4787 gtk_sheet_range_draw_selection (sheet, sheet->range);
4790 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_RANGE], &sheet->range);
4794 gtk_sheet_select_range (GtkSheet * sheet, const GtkSheetRange *range)
4796 g_return_if_fail (sheet != NULL);
4798 if (range == NULL) range=&sheet->range;
4800 if (range->row0 < 0 || range->rowi < 0) return;
4801 if (range->col0 < 0 || range->coli < 0) return;
4804 if ( gtk_sheet_locked (sheet)) return ;
4806 if (sheet->state != GTK_SHEET_NORMAL)
4807 gtk_sheet_real_unselect_range (sheet, NULL);
4810 gboolean veto = TRUE;
4811 veto = gtk_sheet_deactivate_cell (sheet);
4815 sheet->range.row0 = range->row0;
4816 sheet->range.rowi = range->rowi;
4817 sheet->range.col0 = range->col0;
4818 sheet->range.coli = range->coli;
4819 sheet->active_cell.row = range->row0;
4820 sheet->active_cell.col = range->col0;
4821 sheet->selection_cell.row = range->rowi;
4822 sheet->selection_cell.col = range->coli;
4824 sheet->state = GTK_SHEET_RANGE_SELECTED;
4825 gtk_sheet_real_select_range (sheet, NULL);
4830 gtk_sheet_unselect_range (GtkSheet * sheet)
4832 gtk_sheet_real_unselect_range (sheet, NULL);
4833 sheet->state = GTK_STATE_NORMAL;
4834 gtk_sheet_activate_cell (sheet,
4835 sheet->active_cell.row, sheet->active_cell.col);
4840 gtk_sheet_real_unselect_range (GtkSheet * sheet,
4841 const GtkSheetRange *range)
4843 g_return_if_fail (sheet != NULL);
4844 g_return_if_fail (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)));
4847 range = &sheet->range;
4849 if (range->row0 < 0 || range->rowi < 0) return;
4850 if (range->col0 < 0 || range->coli < 0) return;
4852 if (gtk_sheet_range_isvisible (sheet, *range))
4853 gtk_sheet_draw_backing_pixmap (sheet, *range);
4855 sheet->range.row0 = -1;
4856 sheet->range.rowi = -1;
4857 sheet->range.col0 = -1;
4858 sheet->range.coli = -1;
4860 gtk_sheet_position_children (sheet);
4865 gtk_sheet_expose (GtkWidget * widget,
4866 GdkEventExpose * event)
4869 GtkSheetRange range;
4871 g_return_val_if_fail (widget != NULL, FALSE);
4872 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4873 g_return_val_if_fail (event != NULL, FALSE);
4875 sheet = GTK_SHEET (widget);
4877 if (GTK_WIDGET_DRAWABLE (widget))
4879 range.row0 = ROW_FROM_YPIXEL (sheet, event->area.y);
4880 range.col0 = COLUMN_FROM_XPIXEL (sheet, event->area.x);
4881 range.rowi = ROW_FROM_YPIXEL (sheet, event->area.y + event->area.height);
4882 range.coli = COLUMN_FROM_XPIXEL (sheet, event->area.x + event->area.width);
4884 /* exposure events on the sheet */
4885 if (event->window == sheet->row_title_window &&
4886 sheet->row_titles_visible)
4889 for (i = MIN_VISIBLE_ROW (sheet); i <= MAX_VISIBLE_ROW (sheet); i++)
4890 gtk_sheet_row_title_button_draw (sheet, i);
4893 if (event->window == sheet->column_title_window &&
4894 sheet->column_titles_visible)
4897 for (i = MIN_VISIBLE_COLUMN (sheet); i <= MAX_VISIBLE_COLUMN (sheet); i++)
4898 gtk_sheet_column_title_button_draw (sheet, i);
4901 if (event->window == sheet->sheet_window)
4903 gtk_sheet_draw_backing_pixmap (sheet, range);
4905 if (sheet->state != GTK_SHEET_NORMAL)
4907 if (gtk_sheet_range_isvisible (sheet, sheet->range))
4908 gtk_sheet_draw_backing_pixmap (sheet, sheet->range);
4909 if (GTK_SHEET_IN_RESIZE (sheet) || GTK_SHEET_IN_DRAG (sheet))
4910 gtk_sheet_draw_backing_pixmap (sheet, sheet->drag_range);
4912 if (gtk_sheet_range_isvisible (sheet, sheet->range))
4913 gtk_sheet_range_draw_selection (sheet, sheet->range);
4914 if (GTK_SHEET_IN_RESIZE (sheet) || GTK_SHEET_IN_DRAG (sheet))
4915 draw_xor_rectangle (sheet, sheet->drag_range);
4918 if ((!GTK_SHEET_IN_XDRAG (sheet)) && (!GTK_SHEET_IN_YDRAG (sheet)))
4920 if (sheet->state == GTK_SHEET_NORMAL)
4922 gtk_sheet_draw_active_cell (sheet);
4923 if (!GTK_SHEET_IN_SELECTION (sheet))
4924 gtk_widget_queue_draw (sheet->sheet_entry);
4930 if (sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION (sheet))
4931 gtk_widget_grab_focus (GTK_WIDGET (sheet));
4933 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
4940 gtk_sheet_button_press (GtkWidget * widget,
4941 GdkEventButton * event)
4944 GdkModifierType mods;
4945 gint x, y, row, column;
4948 g_return_val_if_fail (widget != NULL, FALSE);
4949 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4950 g_return_val_if_fail (event != NULL, FALSE);
4952 sheet = GTK_SHEET (widget);
4954 if ( event->type == GDK_2BUTTON_PRESS)
4956 gtk_widget_get_pointer (widget, &x, &y);
4957 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4959 if (event->window == sheet->column_title_window)
4961 gtk_signal_emit (GTK_OBJECT (sheet),
4962 sheet_signals[DOUBLE_CLICK_COLUMN], column);
4964 else if (event->window == sheet->row_title_window)
4966 gtk_signal_emit (GTK_OBJECT (sheet),
4967 sheet_signals[DOUBLE_CLICK_ROW], row);
4972 gdk_window_get_pointer (widget->window, NULL, NULL, &mods);
4974 if (! (mods & GDK_BUTTON1_MASK)) return TRUE;
4977 /* press on resize windows */
4978 if (event->window == sheet->column_title_window &&
4979 gtk_sheet_columns_resizable (sheet))
4981 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
4982 if (POSSIBLE_XDRAG (sheet, sheet->x_drag, &sheet->drag_cell.col))
4985 if (event->type == GDK_2BUTTON_PRESS)
4987 gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
4988 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4991 gtk_sheet_column_size_request (sheet, sheet->drag_cell.col, &req);
4992 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4993 gdk_pointer_grab (sheet->column_title_window, FALSE,
4994 GDK_POINTER_MOTION_HINT_MASK |
4995 GDK_BUTTON1_MOTION_MASK |
4996 GDK_BUTTON_RELEASE_MASK,
4997 NULL, NULL, event->time);
4999 draw_xor_vline (sheet);
5004 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable (sheet))
5006 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
5008 if (POSSIBLE_YDRAG (sheet, sheet->y_drag, &sheet->drag_cell.row))
5011 gtk_sheet_row_size_request (sheet, sheet->drag_cell.row, &req);
5012 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5013 gdk_pointer_grab (sheet->row_title_window, FALSE,
5014 GDK_POINTER_MOTION_HINT_MASK |
5015 GDK_BUTTON1_MOTION_MASK |
5016 GDK_BUTTON_RELEASE_MASK,
5017 NULL, NULL, event->time);
5019 draw_xor_hline (sheet);
5024 /* the sheet itself does not handle other than single click events */
5025 if (event->type != GDK_BUTTON_PRESS) return FALSE;
5027 /* selections on the sheet */
5028 if (event->window == sheet->sheet_window)
5030 gtk_widget_get_pointer (widget, &x, &y);
5031 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5032 gdk_pointer_grab (sheet->sheet_window, FALSE,
5033 GDK_POINTER_MOTION_HINT_MASK |
5034 GDK_BUTTON1_MOTION_MASK |
5035 GDK_BUTTON_RELEASE_MASK,
5036 NULL, NULL, event->time);
5037 gtk_grab_add (GTK_WIDGET (sheet));
5038 sheet->timer = gtk_timeout_add (TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5039 gtk_widget_grab_focus (GTK_WIDGET (sheet));
5041 if (sheet->selection_mode != GTK_SELECTION_SINGLE &&
5042 sheet->cursor_drag->type == GDK_SIZING &&
5043 !GTK_SHEET_IN_SELECTION (sheet) && !GTK_SHEET_IN_RESIZE (sheet))
5045 if (sheet->state == GTK_STATE_NORMAL)
5047 row = sheet->active_cell.row;
5048 column = sheet->active_cell.col;
5049 if (!gtk_sheet_deactivate_cell (sheet)) return FALSE;
5050 sheet->active_cell.row = row;
5051 sheet->active_cell.col = column;
5052 sheet->drag_range = sheet->range;
5053 sheet->state = GTK_SHEET_RANGE_SELECTED;
5054 gtk_sheet_select_range (sheet, &sheet->drag_range);
5058 if (row > sheet->range.rowi) row--;
5059 if (column > sheet->range.coli) column--;
5060 sheet->drag_cell.row = row;
5061 sheet->drag_cell.col = column;
5062 sheet->drag_range = sheet->range;
5063 draw_xor_rectangle (sheet, sheet->drag_range);
5064 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_RESIZE);
5066 else if (sheet->cursor_drag->type == GDK_TOP_LEFT_ARROW &&
5067 !GTK_SHEET_IN_SELECTION (sheet)
5068 && ! GTK_SHEET_IN_DRAG (sheet)
5069 && ! gtk_sheet_locked (sheet)
5070 && sheet->active_cell.row >= 0
5071 && sheet->active_cell.col >= 0
5074 if (sheet->state == GTK_STATE_NORMAL)
5076 row = sheet->active_cell.row;
5077 column = sheet->active_cell.col;
5078 if (!gtk_sheet_deactivate_cell (sheet)) return FALSE;
5079 sheet->active_cell.row = row;
5080 sheet->active_cell.col = column;
5081 sheet->drag_range = sheet->range;
5082 sheet->state = GTK_SHEET_RANGE_SELECTED;
5083 gtk_sheet_select_range (sheet, &sheet->drag_range);
5087 if (row < sheet->range.row0) row++;
5088 if (row > sheet->range.rowi) row--;
5089 if (column < sheet->range.col0) column++;
5090 if (column > sheet->range.coli) column--;
5091 sheet->drag_cell.row = row;
5092 sheet->drag_cell.col = column;
5093 sheet->drag_range = sheet->range;
5094 draw_xor_rectangle (sheet, sheet->drag_range);
5095 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_DRAG);
5099 gtk_sheet_click_cell (sheet, row, column, &veto);
5100 if (veto) GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5104 if (event->window == sheet->column_title_window)
5106 gtk_widget_get_pointer (widget, &x, &y);
5107 column = COLUMN_FROM_XPIXEL (sheet, x);
5108 if (xxx_column_is_sensitive (sheet, column))
5110 gtk_sheet_click_cell (sheet, - 1, column, &veto);
5111 gtk_grab_add (GTK_WIDGET (sheet));
5112 sheet->timer = gtk_timeout_add (TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5113 gtk_widget_grab_focus (GTK_WIDGET (sheet));
5114 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5118 if (event->window == sheet->row_title_window)
5120 gtk_widget_get_pointer (widget, &x, &y);
5121 row = ROW_FROM_YPIXEL (sheet, y);
5122 if (yyy_row_is_sensitive (sheet, row))
5124 gtk_sheet_click_cell (sheet, row, - 1, &veto);
5125 gtk_grab_add (GTK_WIDGET (sheet));
5126 sheet->timer = gtk_timeout_add (TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5127 gtk_widget_grab_focus (GTK_WIDGET (sheet));
5128 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5136 gtk_sheet_scroll (gpointer data)
5139 gint x,y,row,column;
5142 sheet = GTK_SHEET (data);
5144 GDK_THREADS_ENTER ();
5146 gtk_widget_get_pointer (GTK_WIDGET (sheet), &x, &y);
5147 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5151 if (GTK_SHEET_IN_SELECTION (sheet))
5152 gtk_sheet_extend_selection (sheet, row, column);
5154 if (GTK_SHEET_IN_DRAG (sheet) || GTK_SHEET_IN_RESIZE (sheet))
5156 move = gtk_sheet_move_query (sheet, row, column);
5157 if (move) draw_xor_rectangle (sheet, sheet->drag_range);
5160 GDK_THREADS_LEAVE ();
5167 gtk_sheet_click_cell (GtkSheet *sheet, gint row, gint column, gboolean *veto)
5171 if (row >= yyy_row_count (sheet) || column >= xxx_column_count (sheet))
5177 if (column >= 0 && row >= 0)
5178 if (! xxx_column_is_visible (sheet, column) || !yyy_row_is_visible (sheet, row))
5184 _gtkextra_signal_emit (GTK_OBJECT (sheet), sheet_signals[TRAVERSE],
5185 sheet->active_cell.row, sheet->active_cell.col,
5186 &row, &column, veto);
5190 if (sheet->state == GTK_STATE_NORMAL) return;
5192 row = sheet->active_cell.row;
5193 column = sheet->active_cell.col;
5195 gtk_sheet_activate_cell (sheet, row, column);
5199 if (row == -1 && column >= 0)
5201 if (gtk_sheet_autoscroll (sheet))
5202 gtk_sheet_move_query (sheet, row, column);
5203 gtk_sheet_select_column (sheet, column);
5206 if (column == -1 && row >= 0)
5208 if (gtk_sheet_autoscroll (sheet))
5209 gtk_sheet_move_query (sheet, row, column);
5210 gtk_sheet_select_row (sheet, row);
5214 if (row == - 1 && column == - 1)
5216 sheet->range.row0 = 0;
5217 sheet->range.col0 = 0;
5218 sheet->range.rowi = yyy_row_count (sheet) - 1;
5219 sheet->range.coli = xxx_column_count (sheet) - 1;
5220 sheet->active_cell.row = 0;
5221 sheet->active_cell.col = 0;
5222 gtk_sheet_select_range (sheet, NULL);
5226 if (row != -1 && column != -1)
5228 if (sheet->state != GTK_SHEET_NORMAL)
5230 sheet->state = GTK_SHEET_NORMAL;
5231 gtk_sheet_real_unselect_range (sheet, NULL);
5235 if (!gtk_sheet_deactivate_cell (sheet))
5242 if (gtk_sheet_autoscroll (sheet))
5243 gtk_sheet_move_query (sheet, row, column);
5244 sheet->active_cell.row = row;
5245 sheet->active_cell.col = column;
5246 sheet->selection_cell.row = row;
5247 sheet->selection_cell.col = column;
5248 sheet->range.row0 = row;
5249 sheet->range.col0 = column;
5250 sheet->range.rowi = row;
5251 sheet->range.coli = column;
5252 sheet->state = GTK_SHEET_NORMAL;
5253 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5254 gtk_sheet_draw_active_cell (sheet);
5258 g_assert_not_reached ();
5259 gtk_sheet_activate_cell (sheet, sheet->active_cell.row,
5260 sheet->active_cell.col);
5264 gtk_sheet_button_release (GtkWidget * widget,
5265 GdkEventButton * event)
5270 sheet = GTK_SHEET (widget);
5272 /* release on resize windows */
5273 if (GTK_SHEET_IN_XDRAG (sheet))
5275 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
5276 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5277 gtk_widget_get_pointer (widget, &x, NULL);
5278 gdk_pointer_ungrab (event->time);
5279 draw_xor_vline (sheet);
5281 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col,
5282 new_column_width (sheet, sheet->drag_cell.col, &x));
5283 sheet->old_hadjustment = -1.;
5284 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed");
5288 if (GTK_SHEET_IN_YDRAG (sheet))
5290 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5291 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5292 gtk_widget_get_pointer (widget, NULL, &y);
5293 gdk_pointer_ungrab (event->time);
5294 draw_xor_hline (sheet);
5296 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
5297 sheet->old_vadjustment = -1.;
5298 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed");
5303 if (GTK_SHEET_IN_DRAG (sheet))
5305 GtkSheetRange old_range;
5306 draw_xor_rectangle (sheet, sheet->drag_range);
5307 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_DRAG);
5308 gdk_pointer_ungrab (event->time);
5310 gtk_sheet_real_unselect_range (sheet, NULL);
5312 sheet->active_cell.row = sheet->active_cell.row +
5313 (sheet->drag_range.row0 - sheet->range.row0);
5314 sheet->active_cell.col = sheet->active_cell.col +
5315 (sheet->drag_range.col0 - sheet->range.col0);
5316 sheet->selection_cell.row = sheet->selection_cell.row +
5317 (sheet->drag_range.row0 - sheet->range.row0);
5318 sheet->selection_cell.col = sheet->selection_cell.col +
5319 (sheet->drag_range.col0 - sheet->range.col0);
5320 old_range = sheet->range;
5321 sheet->range = sheet->drag_range;
5322 sheet->drag_range = old_range;
5323 gtk_signal_emit (GTK_OBJECT (sheet),sheet_signals[MOVE_RANGE],
5324 &sheet->drag_range, &sheet->range);
5325 gtk_sheet_select_range (sheet, &sheet->range);
5328 if (GTK_SHEET_IN_RESIZE (sheet))
5330 GtkSheetRange old_range;
5331 draw_xor_rectangle (sheet, sheet->drag_range);
5332 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_RESIZE);
5333 gdk_pointer_ungrab (event->time);
5335 gtk_sheet_real_unselect_range (sheet, NULL);
5337 sheet->active_cell.row = sheet->active_cell.row +
5338 (sheet->drag_range.row0 - sheet->range.row0);
5339 sheet->active_cell.col = sheet->active_cell.col +
5340 (sheet->drag_range.col0 - sheet->range.col0);
5341 if (sheet->drag_range.row0 < sheet->range.row0)
5342 sheet->selection_cell.row = sheet->drag_range.row0;
5343 if (sheet->drag_range.rowi >= sheet->range.rowi)
5344 sheet->selection_cell.row = sheet->drag_range.rowi;
5345 if (sheet->drag_range.col0 < sheet->range.col0)
5346 sheet->selection_cell.col = sheet->drag_range.col0;
5347 if (sheet->drag_range.coli >= sheet->range.coli)
5348 sheet->selection_cell.col = sheet->drag_range.coli;
5349 old_range = sheet->range;
5350 sheet->range = sheet->drag_range;
5351 sheet->drag_range = old_range;
5353 if (sheet->state == GTK_STATE_NORMAL) sheet->state = GTK_SHEET_RANGE_SELECTED;
5354 gtk_signal_emit (GTK_OBJECT (sheet),sheet_signals[RESIZE_RANGE],
5355 &sheet->drag_range, &sheet->range);
5356 gtk_sheet_select_range (sheet, &sheet->range);
5359 if (sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION (sheet))
5361 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5362 gdk_pointer_ungrab (event->time);
5363 gtk_sheet_activate_cell (sheet, sheet->active_cell.row,
5364 sheet->active_cell.col);
5367 if (GTK_SHEET_IN_SELECTION)
5368 gdk_pointer_ungrab (event->time);
5370 gtk_timeout_remove (sheet->timer);
5371 gtk_grab_remove (GTK_WIDGET (sheet));
5373 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5379 gtk_sheet_motion (GtkWidget * widget,
5380 GdkEventMotion * event)
5383 GdkModifierType mods;
5384 GdkCursorType new_cursor;
5388 g_return_val_if_fail (widget != NULL, FALSE);
5389 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
5390 g_return_val_if_fail (event != NULL, FALSE);
5392 sheet = GTK_SHEET (widget);
5394 /* selections on the sheet */
5398 if (event->window == sheet->column_title_window &&
5399 gtk_sheet_columns_resizable (sheet))
5401 gtk_widget_get_pointer (widget, &x, &y);
5402 if (!GTK_SHEET_IN_SELECTION (sheet) &&
5403 POSSIBLE_XDRAG (sheet, x, &column))
5405 new_cursor = GDK_SB_H_DOUBLE_ARROW;
5406 if (new_cursor != sheet->cursor_drag->type)
5408 gdk_cursor_destroy (sheet->cursor_drag);
5409 sheet->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
5410 gdk_window_set_cursor (sheet->column_title_window,
5411 sheet->cursor_drag);
5416 new_cursor = GDK_TOP_LEFT_ARROW;
5417 if (!GTK_SHEET_IN_XDRAG (sheet) &&
5418 new_cursor != sheet->cursor_drag->type)
5420 gdk_cursor_destroy (sheet->cursor_drag);
5421 sheet->cursor_drag = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
5422 gdk_window_set_cursor (sheet->column_title_window,
5423 sheet->cursor_drag);
5428 if (event->window == sheet->row_title_window &&
5429 gtk_sheet_rows_resizable (sheet))
5431 gtk_widget_get_pointer (widget, &x, &y);
5432 if (!GTK_SHEET_IN_SELECTION (sheet) && POSSIBLE_YDRAG (sheet,y, &column))
5434 new_cursor = GDK_SB_V_DOUBLE_ARROW;
5435 if (new_cursor != sheet->cursor_drag->type)
5437 gdk_cursor_destroy (sheet->cursor_drag);
5438 sheet->cursor_drag = gdk_cursor_new (GDK_SB_V_DOUBLE_ARROW);
5439 gdk_window_set_cursor (sheet->row_title_window, sheet->cursor_drag);
5444 new_cursor = GDK_TOP_LEFT_ARROW;
5445 if (!GTK_SHEET_IN_YDRAG (sheet) &&
5446 new_cursor != sheet->cursor_drag->type)
5448 gdk_cursor_destroy (sheet->cursor_drag);
5449 sheet->cursor_drag = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
5450 gdk_window_set_cursor (sheet->row_title_window, sheet->cursor_drag);
5455 new_cursor = GDK_PLUS;
5456 if ( event->window == sheet->sheet_window &&
5457 !POSSIBLE_DRAG (sheet, x, y, &row, &column) &&
5458 !GTK_SHEET_IN_DRAG (sheet) &&
5459 !POSSIBLE_RESIZE (sheet, x, y, &row, &column) &&
5460 !GTK_SHEET_IN_RESIZE (sheet) &&
5461 new_cursor != sheet->cursor_drag->type)
5463 gdk_cursor_destroy (sheet->cursor_drag);
5464 sheet->cursor_drag = gdk_cursor_new (GDK_PLUS);
5465 gdk_window_set_cursor (sheet->sheet_window, sheet->cursor_drag);
5468 new_cursor = GDK_TOP_LEFT_ARROW;
5469 if ( event->window == sheet->sheet_window &&
5470 ! (POSSIBLE_RESIZE (sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE (sheet)) && (POSSIBLE_DRAG (sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG (sheet)) &&
5472 new_cursor != sheet->cursor_drag->type)
5474 gdk_cursor_destroy (sheet->cursor_drag);
5475 sheet->cursor_drag = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
5476 gdk_window_set_cursor (sheet->sheet_window,sheet->cursor_drag);
5479 new_cursor = GDK_SIZING;
5480 if ( event->window == sheet->sheet_window &&
5481 !GTK_SHEET_IN_DRAG (sheet) &&
5482 (POSSIBLE_RESIZE (sheet, x, y, &row, &column) ||
5483 GTK_SHEET_IN_RESIZE (sheet)) &&
5484 new_cursor != sheet->cursor_drag->type)
5486 gdk_cursor_destroy (sheet->cursor_drag);
5487 sheet->cursor_drag = gdk_cursor_new (GDK_SIZING);
5488 gdk_window_set_cursor (sheet->sheet_window,sheet->cursor_drag);
5491 gdk_window_get_pointer (widget->window, &x, &y, &mods);
5492 if (! (mods & GDK_BUTTON1_MASK)) return FALSE;
5494 if (GTK_SHEET_IN_XDRAG (sheet))
5496 if (event->is_hint || event->window != widget->window)
5497 gtk_widget_get_pointer (widget, &x, NULL);
5501 new_column_width (sheet, sheet->drag_cell.col, &x);
5502 if (x != sheet->x_drag)
5504 draw_xor_vline (sheet);
5506 draw_xor_vline (sheet);
5511 if (GTK_SHEET_IN_YDRAG (sheet))
5513 if (event->is_hint || event->window != widget->window)
5514 gtk_widget_get_pointer (widget, NULL, &y);
5518 new_row_height (sheet, sheet->drag_cell.row, &y);
5519 if (y != sheet->y_drag)
5521 draw_xor_hline (sheet);
5523 draw_xor_hline (sheet);
5528 if (GTK_SHEET_IN_DRAG (sheet))
5531 column = COLUMN_FROM_XPIXEL (sheet,x)- sheet->drag_cell.col;
5532 row = ROW_FROM_YPIXEL (sheet,y)- sheet->drag_cell.row;
5533 if (sheet->state == GTK_SHEET_COLUMN_SELECTED) row = 0;
5534 if (sheet->state == GTK_SHEET_ROW_SELECTED) column = 0;
5538 if (aux.row0 + row >= 0 && aux.rowi + row < yyy_row_count (sheet) &&
5539 aux.col0 + column >= 0 && aux.coli + column < xxx_column_count (sheet))
5541 aux = sheet->drag_range;
5542 sheet->drag_range.row0 = sheet->range.row0 + row;
5543 sheet->drag_range.col0 = sheet->range.col0 + column;
5544 sheet->drag_range.rowi = sheet->range.rowi + row;
5545 sheet->drag_range.coli = sheet->range.coli + column;
5546 if (aux.row0 != sheet->drag_range.row0 ||
5547 aux.col0 != sheet->drag_range.col0)
5549 draw_xor_rectangle (sheet, aux);
5550 draw_xor_rectangle (sheet, sheet->drag_range);
5556 if (GTK_SHEET_IN_RESIZE (sheet))
5559 gint v_h, current_col, current_row, col_threshold, row_threshold;
5562 if (abs (x - COLUMN_LEFT_XPIXEL (sheet,sheet->drag_cell.col)) >
5563 abs (y - ROW_TOP_YPIXEL (sheet,sheet->drag_cell.row))) v_h = 2;
5565 current_col = COLUMN_FROM_XPIXEL (sheet,x);
5566 current_row = ROW_FROM_YPIXEL (sheet,y);
5567 column = current_col - sheet->drag_cell.col;
5568 row = current_row - sheet->drag_cell.row;
5570 /*use half of column width resp. row height as threshold to
5572 col_threshold = COLUMN_LEFT_XPIXEL (sheet,current_col)+xxx_column_width (sheet,current_col)/2;
5575 if (x < col_threshold)
5578 else if (column < 0)
5580 if (x > col_threshold)
5583 row_threshold = ROW_TOP_YPIXEL (sheet,current_row) +
5584 yyy_row_height (sheet, current_row)/2;
5587 if (y < row_threshold)
5592 if (y > row_threshold)
5596 if (sheet->state == GTK_SHEET_COLUMN_SELECTED) row = 0;
5597 if (sheet->state == GTK_SHEET_ROW_SELECTED) column = 0;
5607 if (aux.row0 + row >= 0 && aux.rowi + row < yyy_row_count (sheet) &&
5608 aux.col0 + column >= 0 && aux.coli + column < xxx_column_count (sheet))
5611 aux = sheet->drag_range;
5612 sheet->drag_range = sheet->range;
5614 if (row < 0) sheet->drag_range.row0 = sheet->range.row0 + row;
5615 if (row > 0) sheet->drag_range.rowi = sheet->range.rowi + row;
5616 if (column < 0) sheet->drag_range.col0 = sheet->range.col0 + column;
5617 if (column > 0) sheet->drag_range.coli = sheet->range.coli + column;
5619 if (aux.row0 != sheet->drag_range.row0 ||
5620 aux.rowi != sheet->drag_range.rowi ||
5621 aux.col0 != sheet->drag_range.col0 ||
5622 aux.coli != sheet->drag_range.coli)
5624 draw_xor_rectangle (sheet, aux);
5625 draw_xor_rectangle (sheet, sheet->drag_range);
5633 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5635 if (sheet->state == GTK_SHEET_NORMAL && row == sheet->active_cell.row &&
5636 column == sheet->active_cell.col) return TRUE;
5638 if (GTK_SHEET_IN_SELECTION (sheet) && mods&GDK_BUTTON1_MASK)
5639 gtk_sheet_extend_selection (sheet, row, column);
5645 gtk_sheet_move_query (GtkSheet *sheet, gint row, gint column)
5647 gint row_move, column_move;
5648 gfloat row_align, col_align;
5649 guint height, width;
5651 gint new_col = column;
5654 column_move = FALSE;
5658 height = sheet->sheet_window_height;
5659 width = sheet->sheet_window_width;
5661 if (row >= MAX_VISIBLE_ROW (sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED)
5664 new_row = MIN (yyy_row_count (sheet), row + 1);
5666 if (MAX_VISIBLE_ROW (sheet) == yyy_row_count (sheet) - 1 &&
5667 ROW_TOP_YPIXEL (sheet, yyy_row_count (sheet)- 1) +
5668 yyy_row_height (sheet, yyy_row_count (sheet)- 1) < height)
5674 if (row < MIN_VISIBLE_ROW (sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED)
5679 if (column >= MAX_VISIBLE_COLUMN (sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED)
5682 new_col = MIN (xxx_column_count (sheet) - 1, column + 1);
5684 if (MAX_VISIBLE_COLUMN (sheet) == (xxx_column_count (sheet) - 1) &&
5685 COLUMN_LEFT_XPIXEL (sheet, xxx_column_count (sheet) - 1) +
5686 xxx_column_width (sheet, xxx_column_count (sheet) - 1) < width)
5688 column_move = FALSE;
5692 if (column < MIN_VISIBLE_COLUMN (sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED)
5698 if (row_move || column_move)
5700 gtk_sheet_moveto (sheet, new_row, new_col, row_align, col_align);
5703 return (row_move || column_move);
5707 gtk_sheet_extend_selection (GtkSheet *sheet, gint row, gint column)
5709 GtkSheetRange range;
5713 if (row == sheet->selection_cell.row && column == sheet->selection_cell.col)
5716 if (sheet->selection_mode == GTK_SELECTION_SINGLE) return;
5718 gtk_sheet_move_query (sheet, row, column);
5719 gtk_widget_grab_focus (GTK_WIDGET (sheet));
5721 if (GTK_SHEET_IN_DRAG (sheet)) return;
5723 state = sheet->state;
5725 switch (sheet->state)
5727 case GTK_SHEET_ROW_SELECTED:
5728 column = xxx_column_count (sheet) - 1;
5730 case GTK_SHEET_COLUMN_SELECTED:
5731 row = yyy_row_count (sheet) - 1;
5733 case GTK_SHEET_NORMAL:
5734 sheet->state = GTK_SHEET_RANGE_SELECTED;
5735 r = sheet->active_cell.row;
5736 c = sheet->active_cell.col;
5737 sheet->range.col0 = c;
5738 sheet->range.row0 = r;
5739 sheet->range.coli = c;
5740 sheet->range.rowi = r;
5741 gdk_draw_pixmap (sheet->sheet_window,
5742 GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
5744 COLUMN_LEFT_XPIXEL (sheet,c)- 1,
5745 ROW_TOP_YPIXEL (sheet,r)- 1,
5746 COLUMN_LEFT_XPIXEL (sheet,c)- 1,
5747 ROW_TOP_YPIXEL (sheet,r)- 1,
5748 xxx_column_width (sheet, c)+4,
5749 yyy_row_height (sheet, r)+4);
5750 gtk_sheet_range_draw_selection (sheet, sheet->range);
5751 case GTK_SHEET_RANGE_SELECTED:
5752 sheet->state = GTK_SHEET_RANGE_SELECTED;
5755 sheet->selection_cell.row = row;
5756 sheet->selection_cell.col = column;
5758 range.col0 = MIN (column,sheet->active_cell.col);
5759 range.coli = MAX (column,sheet->active_cell.col);
5760 range.row0 = MIN (row,sheet->active_cell.row);
5761 range.rowi = MAX (row,sheet->active_cell.row);
5763 if (range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi ||
5764 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli ||
5765 state == GTK_SHEET_NORMAL)
5766 gtk_sheet_real_select_range (sheet, &range);
5771 gtk_sheet_entry_key_press (GtkWidget *widget,
5775 gtk_signal_emit_by_name (GTK_OBJECT (widget), "key_press_event", key, &focus);
5780 gtk_sheet_key_press (GtkWidget *widget,
5786 gboolean extend_selection = FALSE;
5787 gboolean force_move = FALSE;
5788 gboolean in_selection = FALSE;
5789 gboolean veto = TRUE;
5792 sheet = GTK_SHEET (widget);
5794 if (key->state & GDK_CONTROL_MASK || key->keyval == GDK_Control_L ||
5795 key->keyval == GDK_Control_R) return FALSE;
5797 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval == GDK_Shift_L
5798 || key->keyval == GDK_Shift_R;
5800 state = sheet->state;
5801 in_selection = GTK_SHEET_IN_SELECTION (sheet);
5802 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5804 switch (key->keyval)
5806 case GDK_Return: case GDK_KP_Enter:
5807 if (sheet->state == GTK_SHEET_NORMAL &&
5808 !GTK_SHEET_IN_SELECTION (sheet))
5809 gtk_signal_emit_stop_by_name (GTK_OBJECT (gtk_sheet_get_entry (sheet)),
5811 row = sheet->active_cell.row;
5812 col = sheet->active_cell.col;
5813 if (sheet->state == GTK_SHEET_COLUMN_SELECTED)
5814 row = MIN_VISIBLE_ROW (sheet)- 1;
5815 if (sheet->state == GTK_SHEET_ROW_SELECTED)
5816 col = MIN_VISIBLE_COLUMN (sheet);
5817 if (row < yyy_row_count (sheet) - 1)
5820 while (!yyy_row_is_visible (sheet, row) && row < yyy_row_count (sheet)- 1)
5823 gtk_sheet_click_cell (sheet, row, col, &veto);
5824 extend_selection = FALSE;
5826 case GDK_ISO_Left_Tab:
5827 row = sheet->active_cell.row;
5828 col = sheet->active_cell.col;
5829 if (sheet->state == GTK_SHEET_ROW_SELECTED)
5830 col = MIN_VISIBLE_COLUMN (sheet)- 1;
5831 if (sheet->state == GTK_SHEET_COLUMN_SELECTED)
5832 row = MIN_VISIBLE_ROW (sheet);
5836 while (! xxx_column_is_visible (sheet, col) && col > 0) col--;
5839 gtk_sheet_click_cell (sheet, row, col, &veto);
5840 extend_selection = FALSE;
5843 row = sheet->active_cell.row;
5844 col = sheet->active_cell.col;
5845 if (sheet->state == GTK_SHEET_ROW_SELECTED)
5846 col = MIN_VISIBLE_COLUMN (sheet)- 1;
5847 if (sheet->state == GTK_SHEET_COLUMN_SELECTED)
5848 row = MIN_VISIBLE_ROW (sheet);
5849 if (col < xxx_column_count (sheet) - 1)
5852 while (! xxx_column_is_visible (sheet, col) &&
5853 col < xxx_column_count (sheet) - 1)
5856 gtk_sheet_click_cell (sheet, row, col, &veto);
5857 extend_selection = FALSE;
5860 scroll = MAX_VISIBLE_ROW (sheet)- MIN_VISIBLE_ROW (sheet)+1;
5862 if (extend_selection)
5864 if (state == GTK_STATE_NORMAL)
5866 row = sheet->active_cell.row;
5867 col = sheet->active_cell.col;
5868 gtk_sheet_click_cell (sheet, row, col, &veto);
5871 if (sheet->selection_cell.row > 0)
5873 row = sheet->selection_cell.row - scroll;
5874 while (!yyy_row_is_visible (sheet, row) && row > 0) row--;
5876 gtk_sheet_extend_selection (sheet, row, sheet->selection_cell.col);
5880 col = sheet->active_cell.col;
5881 row = sheet->active_cell.row;
5882 if (state == GTK_SHEET_COLUMN_SELECTED)
5883 row = MIN_VISIBLE_ROW (sheet);
5884 if (state == GTK_SHEET_ROW_SELECTED)
5885 col = MIN_VISIBLE_COLUMN (sheet);
5887 while (!yyy_row_is_visible (sheet, row) && row > 0) row--;
5889 gtk_sheet_click_cell (sheet, row, col, &veto);
5890 extend_selection = FALSE;
5893 scroll = MAX_VISIBLE_ROW (sheet)- MIN_VISIBLE_ROW (sheet)+1;
5895 if (extend_selection)
5897 if (state == GTK_STATE_NORMAL)
5899 row = sheet->active_cell.row;
5900 col = sheet->active_cell.col;
5901 gtk_sheet_click_cell (sheet, row, col, &veto);
5904 if (sheet->selection_cell.row < yyy_row_count (sheet)- 1)
5906 row = sheet->selection_cell.row + scroll;
5907 while (!yyy_row_is_visible (sheet, row) && row < yyy_row_count (sheet)- 1) row++;
5908 row = MIN (yyy_row_count (sheet)- 1, row);
5909 gtk_sheet_extend_selection (sheet, row, sheet->selection_cell.col);
5913 col = sheet->active_cell.col;
5914 row = sheet->active_cell.row;
5915 if (sheet->active_cell.row < yyy_row_count (sheet)- 1)
5917 if (state == GTK_SHEET_COLUMN_SELECTED)
5918 row = MIN_VISIBLE_ROW (sheet)- 1;
5919 if (state == GTK_SHEET_ROW_SELECTED)
5920 col = MIN_VISIBLE_COLUMN (sheet);
5922 while (!yyy_row_is_visible (sheet, row) && row < yyy_row_count (sheet)- 1) row++;
5923 row = MIN (yyy_row_count (sheet)- 1, row);
5925 gtk_sheet_click_cell (sheet, row, col, &veto);
5926 extend_selection = FALSE;
5929 if (extend_selection)
5931 if (state == GTK_STATE_NORMAL)
5933 row = sheet->active_cell.row;
5934 col = sheet->active_cell.col;
5935 gtk_sheet_click_cell (sheet, row, col, &veto);
5938 if (sheet->selection_cell.col < xxx_column_count (sheet) - 1)
5940 col = sheet->selection_cell.col + 1;
5941 while (! xxx_column_is_visible (sheet, col) && col < xxx_column_count (sheet) - 1)
5943 gtk_sheet_extend_selection (sheet, sheet->selection_cell.row, col);
5947 col = sheet->active_cell.col;
5948 row = sheet->active_cell.row;
5949 if (sheet->active_cell.col < xxx_column_count (sheet) - 1)
5952 if (state == GTK_SHEET_ROW_SELECTED)
5953 col = MIN_VISIBLE_COLUMN (sheet)- 1;
5954 if (state == GTK_SHEET_COLUMN_SELECTED)
5955 row = MIN_VISIBLE_ROW (sheet);
5956 while (! xxx_column_is_visible (sheet, col) && col < xxx_column_count (sheet) - 1) col++;
5957 if (strlen (gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)))) == 0
5960 gtk_sheet_click_cell (sheet, row, col, &veto);
5965 extend_selection = FALSE;
5968 if (extend_selection)
5970 if (state == GTK_STATE_NORMAL)
5972 row = sheet->active_cell.row;
5973 col = sheet->active_cell.col;
5974 gtk_sheet_click_cell (sheet, row, col, &veto);
5977 if (sheet->selection_cell.col > 0)
5979 col = sheet->selection_cell.col - 1;
5980 while (! xxx_column_is_visible (sheet, col) && col > 0) col--;
5981 gtk_sheet_extend_selection (sheet, sheet->selection_cell.row, col);
5985 col = sheet->active_cell.col - 1;
5986 row = sheet->active_cell.row;
5987 if (state == GTK_SHEET_ROW_SELECTED)
5988 col = MIN_VISIBLE_COLUMN (sheet)- 1;
5989 if (state == GTK_SHEET_COLUMN_SELECTED)
5990 row = MIN_VISIBLE_ROW (sheet);
5991 while (! xxx_column_is_visible (sheet, col) && col > 0) col--;
5994 if (strlen (gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)))) == 0
5997 gtk_sheet_click_cell (sheet, row, col, &veto);
6001 extend_selection = FALSE;
6005 while (!yyy_row_is_visible (sheet, row) && row < yyy_row_count (sheet)- 1) row++;
6006 gtk_sheet_click_cell (sheet, row, sheet->active_cell.col, &veto);
6007 extend_selection = FALSE;
6010 row = yyy_row_count (sheet)- 1;
6011 while (!yyy_row_is_visible (sheet, row) && row > 0) row--;
6012 gtk_sheet_click_cell (sheet, row, sheet->active_cell.col, &veto);
6013 extend_selection = FALSE;
6018 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
6019 if (extend_selection) return TRUE;
6021 if (state == GTK_SHEET_ROW_SELECTED)
6022 sheet->active_cell.col = MIN_VISIBLE_COLUMN (sheet);
6023 if (state == GTK_SHEET_COLUMN_SELECTED)
6024 sheet->active_cell.row = MIN_VISIBLE_ROW (sheet);
6028 if (extend_selection) return TRUE;
6030 gtk_sheet_activate_cell (sheet, sheet->active_cell.row,
6031 sheet->active_cell.col);
6037 gtk_sheet_size_request (GtkWidget * widget,
6038 GtkRequisition * requisition)
6042 GtkSheetChild *child;
6043 GtkRequisition child_requisition;
6045 g_return_if_fail (widget != NULL);
6046 g_return_if_fail (GTK_IS_SHEET (widget));
6047 g_return_if_fail (requisition != NULL);
6049 sheet = GTK_SHEET (widget);
6051 requisition->width = 3*DEFAULT_COLUMN_WIDTH;
6052 requisition->height = 3*DEFAULT_ROW_HEIGHT (widget);
6054 /* compute the size of the column title area */
6055 if (sheet->column_titles_visible)
6056 requisition->height += sheet->column_title_area.height;
6058 /* compute the size of the row title area */
6059 if (sheet->row_titles_visible)
6060 requisition->width += sheet->row_title_area.width;
6062 sheet->view.row0 = ROW_FROM_YPIXEL (sheet, sheet->column_title_area.height + 1);
6063 sheet->view.rowi = ROW_FROM_YPIXEL (sheet, sheet->sheet_window_height - 1);
6064 sheet->view.col0 = COLUMN_FROM_XPIXEL (sheet, sheet->row_title_area.width + 1);
6065 sheet->view.coli = COLUMN_FROM_XPIXEL (sheet, sheet->sheet_window_width);
6067 if (!sheet->column_titles_visible)
6068 sheet->view.row0 = ROW_FROM_YPIXEL (sheet, 1);
6070 if (!sheet->row_titles_visible)
6071 sheet->view.col0 = COLUMN_FROM_XPIXEL (sheet, 1);
6073 children = sheet->children;
6076 child = children->data;
6077 children = children->next;
6079 gtk_widget_size_request (child->widget, &child_requisition);
6085 gtk_sheet_size_allocate (GtkWidget * widget,
6086 GtkAllocation * allocation)
6089 GtkAllocation sheet_allocation;
6092 g_return_if_fail (widget != NULL);
6093 g_return_if_fail (GTK_IS_SHEET (widget));
6094 g_return_if_fail (allocation != NULL);
6096 sheet = GTK_SHEET (widget);
6097 widget->allocation = *allocation;
6098 border_width = GTK_CONTAINER (widget)->border_width;
6100 if (GTK_WIDGET_REALIZED (widget))
6101 gdk_window_move_resize (widget->window,
6102 allocation->x + border_width,
6103 allocation->y + border_width,
6104 allocation->width - 2 * border_width,
6105 allocation->height - 2 * border_width);
6107 /* use internal allocation structure for all the math
6108 * because it's easier than always subtracting the container
6110 sheet->internal_allocation.x = 0;
6111 sheet->internal_allocation.y = 0;
6112 sheet->internal_allocation.width = allocation->width - 2 * border_width;
6113 sheet->internal_allocation.height = allocation->height - 2 * border_width;
6115 sheet_allocation.x = 0;
6116 sheet_allocation.y = 0;
6117 sheet_allocation.width = allocation->width - 2 * border_width;
6118 sheet_allocation.height = allocation->height - 2 * border_width;
6120 sheet->sheet_window_width = sheet_allocation.width;
6121 sheet->sheet_window_height = sheet_allocation.height;
6123 if (GTK_WIDGET_REALIZED (widget))
6124 gdk_window_move_resize (sheet->sheet_window,
6127 sheet_allocation.width,
6128 sheet_allocation.height);
6130 /* position the window which holds the column title buttons */
6131 sheet->column_title_area.x = 0;
6132 sheet->column_title_area.y = 0;
6133 if (sheet->row_titles_visible)
6134 sheet->column_title_area.x = sheet->row_title_area.width;
6135 sheet->column_title_area.width = sheet_allocation.width -
6136 sheet->column_title_area.x;
6137 if (GTK_WIDGET_REALIZED (widget) && sheet->column_titles_visible)
6138 gdk_window_move_resize (sheet->column_title_window,
6139 sheet->column_title_area.x,
6140 sheet->column_title_area.y,
6141 sheet->column_title_area.width,
6142 sheet->column_title_area.height);
6144 sheet->sheet_window_width = sheet_allocation.width;
6145 sheet->sheet_window_height = sheet_allocation.height;
6147 /* column button allocation */
6148 size_allocate_column_title_buttons (sheet);
6150 /* position the window which holds the row title buttons */
6151 sheet->row_title_area.x = 0;
6152 sheet->row_title_area.y = 0;
6153 if (sheet->column_titles_visible)
6154 sheet->row_title_area.y = sheet->column_title_area.height;
6155 sheet->row_title_area.height = sheet_allocation.height -
6156 sheet->row_title_area.y;
6158 if (GTK_WIDGET_REALIZED (widget) && sheet->row_titles_visible)
6159 gdk_window_move_resize (sheet->row_title_window,
6160 sheet->row_title_area.x,
6161 sheet->row_title_area.y,
6162 sheet->row_title_area.width,
6163 sheet->row_title_area.height);
6166 /* row button allocation */
6167 size_allocate_row_title_buttons (sheet);
6169 sheet->view.row0 = ROW_FROM_YPIXEL (sheet, sheet->column_title_area.height + 1);
6170 sheet->view.rowi = ROW_FROM_YPIXEL (sheet, sheet->sheet_window_height - 1);
6171 sheet->view.col0 = COLUMN_FROM_XPIXEL (sheet, sheet->row_title_area.width + 1);
6172 sheet->view.coli = COLUMN_FROM_XPIXEL (sheet, sheet->sheet_window_width);
6174 if (!sheet->column_titles_visible)
6175 sheet->view.row0 = ROW_FROM_YPIXEL (sheet, 1);
6177 if (!sheet->row_titles_visible)
6178 sheet->view.col0 = COLUMN_FROM_XPIXEL (sheet, 1);
6180 size_allocate_column_title_buttons (sheet);
6181 size_allocate_row_title_buttons (sheet);
6183 /* re - scale backing pixmap */
6184 gtk_sheet_make_backing_pixmap (sheet, 0, 0);
6185 gtk_sheet_position_children (sheet);
6187 /* set the scrollbars adjustments */
6188 adjust_scrollbars (sheet);
6192 size_allocate_column_title_buttons (GtkSheet * sheet)
6197 if (!sheet->column_titles_visible) return;
6198 if (!GTK_WIDGET_REALIZED (sheet))
6201 width = sheet->sheet_window_width;
6204 if (sheet->row_titles_visible)
6206 width -= sheet->row_title_area.width;
6207 x = sheet->row_title_area.width;
6210 if (sheet->column_title_area.width != width || sheet->column_title_area.x != x)
6212 sheet->column_title_area.width = width;
6213 sheet->column_title_area.x = x;
6214 gdk_window_move_resize (sheet->column_title_window,
6215 sheet->column_title_area.x,
6216 sheet->column_title_area.y,
6217 sheet->column_title_area.width,
6218 sheet->column_title_area.height);
6222 if (MAX_VISIBLE_COLUMN (sheet) == xxx_column_count (sheet) - 1)
6223 gdk_window_clear_area (sheet->column_title_window,
6225 sheet->column_title_area.width,
6226 sheet->column_title_area.height);
6228 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
6230 for (i = MIN_VISIBLE_COLUMN (sheet); i <= MAX_VISIBLE_COLUMN (sheet); i++)
6231 gtk_sheet_column_title_button_draw (sheet, i);
6235 size_allocate_row_title_buttons (GtkSheet * sheet)
6240 if (!sheet->row_titles_visible) return;
6241 if (!GTK_WIDGET_REALIZED (sheet))
6244 height = sheet->sheet_window_height;
6247 if (sheet->column_titles_visible)
6249 height -= sheet->column_title_area.height;
6250 y = sheet->column_title_area.height;
6253 if (sheet->row_title_area.height != height || sheet->row_title_area.y != y)
6255 sheet->row_title_area.y = y;
6256 sheet->row_title_area.height = height;
6257 gdk_window_move_resize (sheet->row_title_window,
6258 sheet->row_title_area.x,
6259 sheet->row_title_area.y,
6260 sheet->row_title_area.width,
6261 sheet->row_title_area.height);
6263 if (MAX_VISIBLE_ROW (sheet) == yyy_row_count (sheet)- 1)
6264 gdk_window_clear_area (sheet->row_title_window,
6266 sheet->row_title_area.width,
6267 sheet->row_title_area.height);
6269 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
6271 for (i = MIN_VISIBLE_ROW (sheet); i <= MAX_VISIBLE_ROW (sheet); i++)
6273 if ( i >= yyy_row_count (sheet))
6275 gtk_sheet_row_title_button_draw (sheet, i);
6281 gtk_sheet_size_allocate_entry (GtkSheet *sheet)
6283 GtkAllocation shentry_allocation;
6284 GtkSheetCellAttr attributes = { 0 };
6285 GtkEntry *sheet_entry;
6286 GtkStyle *style = NULL, *previous_style = NULL;
6288 gint size, max_size, text_size, column_width;
6291 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
6292 if (!GTK_WIDGET_MAPPED (GTK_WIDGET (sheet))) return;
6294 sheet_entry = GTK_ENTRY (gtk_sheet_get_entry (sheet));
6296 if ( ! gtk_sheet_get_attributes (sheet, sheet->active_cell.row,
6297 sheet->active_cell.col,
6301 if ( GTK_WIDGET_REALIZED (sheet->sheet_entry) )
6303 if (!GTK_WIDGET (sheet_entry)->style)
6304 gtk_widget_ensure_style (GTK_WIDGET (sheet_entry));
6306 previous_style = GTK_WIDGET (sheet_entry)->style;
6308 style = gtk_style_copy (previous_style);
6309 style->bg[GTK_STATE_NORMAL] = attributes.background;
6310 style->fg[GTK_STATE_NORMAL] = attributes.foreground;
6311 style->text[GTK_STATE_NORMAL] = attributes.foreground;
6312 style->bg[GTK_STATE_ACTIVE] = attributes.background;
6313 style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
6314 style->text[GTK_STATE_ACTIVE] = attributes.foreground;
6316 pango_font_description_free (style->font_desc);
6317 g_assert (attributes.font_desc);
6318 style->font_desc = pango_font_description_copy (attributes.font_desc);
6320 GTK_WIDGET (sheet_entry)->style = style;
6321 gtk_widget_size_request (sheet->sheet_entry, NULL);
6322 GTK_WIDGET (sheet_entry)->style = previous_style;
6324 if (style != previous_style)
6326 if (!GTK_IS_ITEM_ENTRY (sheet->sheet_entry))
6328 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
6329 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
6330 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
6331 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
6333 gtk_widget_set_style (GTK_WIDGET (sheet_entry), style);
6337 if (GTK_IS_ITEM_ENTRY (sheet_entry))
6338 max_size = GTK_ITEM_ENTRY (sheet_entry)->text_max_size;
6343 text = gtk_entry_get_text (GTK_ENTRY (sheet_entry));
6344 if (text && strlen (text) > 0)
6345 text_size = STRING_WIDTH (GTK_WIDGET (sheet), attributes.font_desc, text);
6347 column_width = xxx_column_width (sheet, sheet->active_cell.col);
6349 size = MIN (text_size, max_size);
6350 size = MAX (size,column_width - 2 * CELLOFFSET);
6352 row = sheet->active_cell.row;
6353 col = sheet->active_cell.col;
6355 shentry_allocation.x = COLUMN_LEFT_XPIXEL (sheet,sheet->active_cell.col);
6356 shentry_allocation.y = ROW_TOP_YPIXEL (sheet,sheet->active_cell.row);
6357 shentry_allocation.width = column_width;
6358 shentry_allocation.height = yyy_row_height (sheet, sheet->active_cell.row);
6360 if (GTK_IS_ITEM_ENTRY (sheet->sheet_entry))
6362 shentry_allocation.height -= 2 * CELLOFFSET;
6363 shentry_allocation.y += CELLOFFSET;
6364 if (gtk_sheet_clip_text (sheet))
6365 shentry_allocation.width = column_width - 2 * CELLOFFSET;
6367 shentry_allocation.width = size;
6369 switch (GTK_ITEM_ENTRY (sheet_entry)->justification)
6371 case GTK_JUSTIFY_CENTER:
6372 shentry_allocation.x += column_width / 2 - size / 2;
6374 case GTK_JUSTIFY_RIGHT:
6375 shentry_allocation.x += column_width - size - CELLOFFSET;
6377 case GTK_JUSTIFY_LEFT:
6378 case GTK_JUSTIFY_FILL:
6379 shentry_allocation.x += CELLOFFSET;
6384 if (!GTK_IS_ITEM_ENTRY (sheet->sheet_entry))
6386 shentry_allocation.x += 2;
6387 shentry_allocation.y += 2;
6388 shentry_allocation.width -= MIN (shentry_allocation.width, 3);
6389 shentry_allocation.height -= MIN (shentry_allocation.height, 3);
6392 gtk_widget_size_allocate (sheet->sheet_entry, &shentry_allocation);
6394 if (previous_style == style) gtk_style_unref (previous_style);
6398 gtk_sheet_entry_set_max_size (GtkSheet *sheet)
6402 gint sizel = 0, sizer = 0;
6404 GtkJustification justification;
6407 row = sheet->active_cell.row;
6408 col = sheet->active_cell.col;
6410 if ( ! GTK_IS_ITEM_ENTRY (sheet->sheet_entry) || gtk_sheet_clip_text (sheet))
6413 justification = GTK_ITEM_ENTRY (sheet->sheet_entry)->justification;
6415 switch (justification)
6417 case GTK_JUSTIFY_FILL:
6418 case GTK_JUSTIFY_LEFT:
6419 for (i = col + 1; i <= MAX_VISIBLE_COLUMN (sheet); i++)
6421 if ((s = gtk_sheet_cell_get_text (sheet, row, i)))
6426 size +=xxx_column_width (sheet, i);
6428 size = MIN (size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL (sheet, col));
6430 case GTK_JUSTIFY_RIGHT:
6431 for (i = col - 1; i >= MIN_VISIBLE_COLUMN (sheet); i--)
6433 if ((s = gtk_sheet_cell_get_text (sheet, row, i)))
6438 size +=xxx_column_width (sheet, i);
6441 case GTK_JUSTIFY_CENTER:
6442 for (i = col + 1; i <= MAX_VISIBLE_COLUMN (sheet); i++)
6444 sizer += xxx_column_width (sheet, i);
6446 for (i = col - 1; i >= MIN_VISIBLE_COLUMN (sheet); i--)
6448 if ((s = gtk_sheet_cell_get_text (sheet, row, i)))
6453 sizel +=xxx_column_width (sheet, i);
6455 size = 2 * MIN (sizel, sizer);
6460 size += xxx_column_width (sheet, col);
6461 GTK_ITEM_ENTRY (sheet->sheet_entry)->text_max_size = size;
6465 create_sheet_entry (GtkSheet *sheet)
6470 gint found_entry = FALSE;
6472 widget = GTK_WIDGET (sheet);
6474 if (sheet->sheet_entry)
6476 /* avoids warnings */
6477 gtk_widget_ref (sheet->sheet_entry);
6478 gtk_widget_unparent (sheet->sheet_entry);
6479 gtk_widget_destroy (sheet->sheet_entry);
6482 if (sheet->entry_type)
6484 if (!g_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY))
6486 parent = GTK_WIDGET (gtk_type_new (sheet->entry_type));
6488 sheet->sheet_entry = parent;
6490 entry = gtk_sheet_get_entry (sheet);
6491 if (GTK_IS_ENTRY (entry))
6496 parent = GTK_WIDGET (gtk_type_new (sheet->entry_type));
6503 g_warning ("Entry type must be GtkEntry subclass, using default");
6504 entry = gtk_item_entry_new ();
6505 sheet->sheet_entry = entry;
6508 sheet->sheet_entry = parent;
6512 entry = gtk_item_entry_new ();
6513 sheet->sheet_entry = entry;
6516 gtk_widget_size_request (sheet->sheet_entry, NULL);
6518 if (GTK_WIDGET_REALIZED (sheet))
6520 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
6521 gtk_widget_set_parent (sheet->sheet_entry, GTK_WIDGET (sheet));
6522 gtk_widget_realize (sheet->sheet_entry);
6525 gtk_signal_connect_object (GTK_OBJECT (entry),"key_press_event",
6526 (GtkSignalFunc) gtk_sheet_entry_key_press,
6527 GTK_OBJECT (sheet));
6529 gtk_widget_show (sheet->sheet_entry);
6533 /* Finds the last child widget that happens to be of type GtkEntry */
6535 find_entry (GtkWidget *w, gpointer user_data)
6537 GtkWidget **entry = user_data;
6538 if ( GTK_IS_ENTRY (w))
6545 gtk_sheet_get_entry (GtkSheet *sheet)
6548 GtkWidget *entry = NULL;
6549 GtkTableChild *table_child;
6550 GtkBoxChild *box_child;
6551 GList *children = NULL;
6553 g_return_val_if_fail (sheet != NULL, NULL);
6554 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6555 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6557 if (GTK_IS_ENTRY (sheet->sheet_entry)) return (sheet->sheet_entry);
6559 parent = GTK_WIDGET (sheet->sheet_entry);
6561 if (GTK_IS_TABLE (parent)) children = GTK_TABLE (parent)->children;
6562 if (GTK_IS_BOX (parent)) children = GTK_BOX (parent)->children;
6564 if (GTK_IS_CONTAINER (parent))
6566 gtk_container_forall (GTK_CONTAINER (parent), find_entry, &entry);
6568 if (GTK_IS_ENTRY (entry))
6572 if (!children) return NULL;
6576 if (GTK_IS_TABLE (parent))
6578 table_child = children->data;
6579 entry = table_child->widget;
6581 if (GTK_IS_BOX (parent))
6583 box_child = children->data;
6584 entry = box_child->widget;
6587 if (GTK_IS_ENTRY (entry))
6589 children = children->next;
6593 if (!GTK_IS_ENTRY (entry)) return NULL;
6600 gtk_sheet_get_entry_widget (GtkSheet *sheet)
6602 g_return_val_if_fail (sheet != NULL, NULL);
6603 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6604 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6606 return (sheet->sheet_entry);
6611 gtk_sheet_button_draw (GtkSheet *sheet, GdkWindow *window,
6612 GtkSheetButton *button, gboolean is_sensitive,
6613 GdkRectangle allocation)
6615 GtkShadowType shadow_type;
6616 gint text_width = 0, text_height = 0;
6617 GtkSheetChild *child = NULL;
6618 PangoAlignment align = PANGO_ALIGN_LEFT;
6626 g_return_if_fail (sheet != NULL);
6627 g_return_if_fail (button != NULL);
6629 rtl = gtk_widget_get_direction (GTK_WIDGET (sheet)) == GTK_TEXT_DIR_RTL;
6631 gdk_window_clear_area (window,
6632 allocation.x, allocation.y,
6633 allocation.width, allocation.height);
6635 gtk_paint_box (sheet->button->style, window,
6636 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
6637 &allocation, GTK_WIDGET (sheet->button),
6639 allocation.x, allocation.y,
6640 allocation.width, allocation.height);
6642 state = button->state;
6643 if (!is_sensitive) state = GTK_STATE_INSENSITIVE;
6645 if (state == GTK_STATE_ACTIVE)
6646 shadow_type = GTK_SHADOW_IN;
6648 shadow_type = GTK_SHADOW_OUT;
6650 if (state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
6651 gtk_paint_box (sheet->button->style, window,
6652 button->state, shadow_type,
6653 &allocation, GTK_WIDGET (sheet->button),
6655 allocation.x, allocation.y,
6656 allocation.width, allocation.height);
6658 if (button->label_visible)
6661 text_height = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet))- 2 * CELLOFFSET;
6663 gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->fg_gc[button->state],
6665 gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->white_gc, &allocation);
6667 allocation.y += 2 * sheet->button->style->ythickness;
6670 if (button->label && strlen (button->label)>0)
6673 PangoLayout *layout = NULL;
6674 gint real_x = allocation.x, real_y = allocation.y;
6676 words = button->label;
6677 line = g_new (gchar, 1);
6680 while (words && *words != '\0')
6684 len = strlen (line);
6685 line = g_realloc (line, len + 2);
6689 if (*words == '\n' || * (words + 1) == '\0')
6691 text_width = STRING_WIDTH (GTK_WIDGET (sheet), GTK_WIDGET (sheet)->style->font_desc, line);
6693 layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), line);
6694 switch (button->justification)
6696 case GTK_JUSTIFY_LEFT:
6697 real_x = allocation.x + CELLOFFSET;
6698 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6700 case GTK_JUSTIFY_RIGHT:
6701 real_x = allocation.x + allocation.width - text_width - CELLOFFSET;
6702 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6704 case GTK_JUSTIFY_CENTER:
6706 real_x = allocation.x + (allocation.width - text_width)/2;
6707 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6708 pango_layout_set_justify (layout, TRUE);
6710 pango_layout_set_alignment (layout, align);
6711 gtk_paint_layout (GTK_WIDGET (sheet)->style,
6720 g_object_unref (G_OBJECT (layout));
6722 real_y += text_height + 2;
6725 line = g_new (gchar, 1);
6733 gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->fg_gc[button->state],
6735 gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->white_gc, NULL);
6739 if ((child = button->child) && (child->widget))
6741 child->x = allocation.x;
6742 child->y = allocation.y;
6744 child->x += (allocation.width - child->widget->requisition.width) / 2;
6745 child->y += (allocation.height - child->widget->requisition.height) / 2;
6746 allocation.x = child->x;
6747 allocation.y = child->y;
6748 allocation.width = child->widget->requisition.width;
6749 allocation.height = child->widget->requisition.height;
6751 allocation.x = child->x;
6752 allocation.y = child->y;
6754 gtk_widget_set_state (child->widget, button->state);
6756 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) &&
6757 GTK_WIDGET_MAPPED (child->widget))
6759 gtk_widget_size_allocate (child->widget,
6761 gtk_widget_queue_draw (child->widget);
6765 gtk_sheet_button_free (button);
6769 /* COLUMN value of - 1 indicates that the area to the right of the rightmost
6770 button should be redrawn */
6772 gtk_sheet_column_title_button_draw (GtkSheet *sheet, gint column)
6774 GdkWindow *window = NULL;
6775 GdkRectangle allocation;
6776 GtkSheetButton *button = NULL;
6777 gboolean is_sensitive = FALSE;
6779 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
6781 if (column >= 0 && ! xxx_column_is_visible (sheet, column)) return;
6782 if (column >= 0 && !sheet->column_titles_visible) return;
6783 if (column >= 0 && column < MIN_VISIBLE_COLUMN (sheet)) return;
6784 if (column >= 0 && column > MAX_VISIBLE_COLUMN (sheet)) return;
6786 window = sheet->column_title_window;
6788 allocation.height = sheet->column_title_area.height;
6792 const gint cols = xxx_column_count (sheet) ;
6793 allocation.x = COLUMN_LEFT_XPIXEL (sheet, cols - 1)
6795 allocation.width = sheet->column_title_area.width
6796 + sheet->column_title_area.x
6799 gdk_window_clear_area (window,
6800 allocation.x, allocation.y,
6801 allocation.width, allocation.height);
6805 button = xxx_column_button (sheet, column);
6806 allocation.x = COLUMN_LEFT_XPIXEL (sheet, column) + CELL_SPACING;
6807 if (sheet->row_titles_visible)
6808 allocation.x -= sheet->row_title_area.width;
6810 allocation.width = xxx_column_width (sheet, column);
6812 is_sensitive = xxx_column_is_sensitive (sheet, column);
6813 gtk_sheet_button_draw (sheet, window, button,
6814 is_sensitive, allocation);
6819 gtk_sheet_row_title_button_draw (GtkSheet *sheet, gint row)
6821 GdkWindow *window = NULL;
6822 GdkRectangle allocation;
6823 GtkSheetButton *button = NULL;
6824 gboolean is_sensitive = FALSE;
6827 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
6829 if (row >= 0 && !yyy_row_is_visible (sheet, row)) return;
6830 if (row >= 0 && !sheet->row_titles_visible) return;
6831 if (row >= 0 && row < MIN_VISIBLE_ROW (sheet)) return;
6832 if (row >= 0 && row > MAX_VISIBLE_ROW (sheet)) return;
6835 window = sheet->row_title_window;
6836 button = yyy_row_button (sheet, row);
6838 allocation.y = ROW_TOP_YPIXEL (sheet, row) + CELL_SPACING;
6839 if (sheet->column_titles_visible)
6840 allocation.y -= sheet->column_title_area.height;
6841 allocation.width = sheet->row_title_area.width;
6842 allocation.height = yyy_row_height (sheet, row);
6843 is_sensitive = yyy_row_is_sensitive (sheet, row);
6845 gtk_sheet_button_draw (sheet, window, button, is_sensitive, allocation);
6852 * vadjustment_changed
6853 * hadjustment_changed
6854 * vadjustment_value_changed
6855 * hadjustment_value_changed */
6858 adjust_scrollbars (GtkSheet * sheet)
6861 if (sheet->vadjustment)
6863 sheet->vadjustment->page_size = sheet->sheet_window_height;
6864 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
6865 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet));
6866 sheet->vadjustment->lower = 0;
6867 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
6868 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "changed");
6872 if (sheet->hadjustment)
6874 sheet->hadjustment->page_size = sheet->sheet_window_width;
6875 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
6876 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
6877 sheet->hadjustment->lower = 0;
6878 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
6879 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "changed");
6886 vadjustment_changed (GtkAdjustment * adjustment,
6891 g_return_if_fail (adjustment != NULL);
6892 g_return_if_fail (data != NULL);
6894 sheet = GTK_SHEET (data);
6899 hadjustment_changed (GtkAdjustment * adjustment,
6904 g_return_if_fail (adjustment != NULL);
6905 g_return_if_fail (data != NULL);
6907 sheet = GTK_SHEET (data);
6912 vadjustment_value_changed (GtkAdjustment * adjustment,
6916 gint diff, value, old_value;
6920 g_return_if_fail (adjustment != NULL);
6921 g_return_if_fail (data != NULL);
6922 g_return_if_fail (GTK_IS_SHEET (data));
6924 sheet = GTK_SHEET (data);
6926 if (GTK_SHEET_IS_FROZEN (sheet)) return;
6928 row = ROW_FROM_YPIXEL (sheet,sheet->column_title_area.height + CELL_SPACING);
6929 if (!sheet->column_titles_visible)
6930 row = ROW_FROM_YPIXEL (sheet, CELL_SPACING);
6932 old_value = - sheet->voffset;
6934 new_row = g_sheet_row_pixel_to_row (sheet->row_geometry,
6935 adjustment->value,sheet);
6937 y = g_sheet_row_start_pixel (sheet->row_geometry, new_row, sheet);
6939 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
6940 yyy_row_height (sheet, row) > sheet->vadjustment->step_increment)
6942 /* This avoids embarrassing twitching */
6943 if (row == new_row && row != yyy_row_count (sheet) - 1 &&
6944 adjustment->value - sheet->old_vadjustment >=
6945 sheet->vadjustment->step_increment &&
6946 new_row + 1 != MIN_VISIBLE_ROW (sheet))
6949 y = y+yyy_row_height (sheet, row);
6953 /* Negative old_adjustment enforces the redraw, otherwise avoid
6955 if (sheet->old_vadjustment >= 0. && row == new_row)
6957 sheet->old_vadjustment = sheet->vadjustment->value;
6961 sheet->old_vadjustment = sheet->vadjustment->value;
6962 adjustment->value = y;
6967 sheet->vadjustment->step_increment = yyy_row_height (sheet, 0);
6971 sheet->vadjustment->step_increment =
6972 MIN (yyy_row_height (sheet, new_row), yyy_row_height (sheet, new_row - 1));
6975 sheet->vadjustment->value = adjustment->value;
6977 value = adjustment->value;
6979 if (value >= - sheet->voffset)
6982 diff = value + sheet->voffset;
6987 diff = - sheet->voffset - value;
6990 sheet->voffset = - value;
6992 sheet->view.row0 = ROW_FROM_YPIXEL (sheet, sheet->column_title_area.height + 1);
6993 sheet->view.rowi = ROW_FROM_YPIXEL (sheet, sheet->sheet_window_height - 1);
6994 if (!sheet->column_titles_visible)
6995 sheet->view.row0 = ROW_FROM_YPIXEL (sheet, 1);
6997 if (GTK_WIDGET_REALIZED (sheet->sheet_entry) &&
6998 sheet->state == GTK_SHEET_NORMAL &&
6999 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
7000 !gtk_sheet_cell_isvisible (sheet, sheet->active_cell.row,
7001 sheet->active_cell.col))
7005 text = gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)));
7007 if (!text || strlen (text) == 0)
7008 gtk_sheet_cell_clear (sheet,
7009 sheet->active_cell.row,
7010 sheet->active_cell.col);
7011 gtk_widget_unmap (sheet->sheet_entry);
7014 gtk_sheet_position_children (sheet);
7016 gtk_sheet_range_draw (sheet, NULL);
7017 size_allocate_row_title_buttons (sheet);
7018 size_allocate_global_button (sheet);
7022 hadjustment_value_changed (GtkAdjustment * adjustment,
7026 gint i, diff, value, old_value;
7027 gint column, new_column;
7030 g_return_if_fail (adjustment != NULL);
7031 g_return_if_fail (data != NULL);
7032 g_return_if_fail (GTK_IS_SHEET (data));
7034 sheet = GTK_SHEET (data);
7036 if (GTK_SHEET_IS_FROZEN (sheet)) return;
7038 column = COLUMN_FROM_XPIXEL (sheet,sheet->row_title_area.width + CELL_SPACING);
7039 if (!sheet->row_titles_visible)
7040 column = COLUMN_FROM_XPIXEL (sheet, CELL_SPACING);
7042 old_value = - sheet->hoffset;
7044 for (i = 0; i < xxx_column_count (sheet); i++)
7046 if (xxx_column_is_visible (sheet, i)) x += xxx_column_width (sheet, i);
7047 if (x > adjustment->value) break;
7049 x -= xxx_column_width (sheet, i);
7052 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
7053 xxx_column_width (sheet, i) > sheet->hadjustment->step_increment)
7055 /* This avoids embarrassing twitching */
7056 if (column == new_column && column != xxx_column_count (sheet) - 1 &&
7057 adjustment->value - sheet->old_hadjustment >=
7058 sheet->hadjustment->step_increment &&
7059 new_column + 1 != MIN_VISIBLE_COLUMN (sheet))
7062 x += xxx_column_width (sheet, column);
7066 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
7067 if (sheet->old_hadjustment >= 0. && new_column == column)
7069 sheet->old_hadjustment = sheet->hadjustment->value;
7073 sheet->old_hadjustment = sheet->hadjustment->value;
7074 adjustment->value = x;
7076 if (new_column == 0)
7078 sheet->hadjustment->step_increment = xxx_column_width (sheet, 0);
7082 sheet->hadjustment->step_increment =
7083 MIN (xxx_column_width (sheet, new_column), xxx_column_width (sheet, new_column - 1));
7087 sheet->hadjustment->value = adjustment->value;
7089 value = adjustment->value;
7091 if (value >= - sheet->hoffset)
7094 diff = value + sheet->hoffset;
7099 diff = - sheet->hoffset - value;
7102 sheet->hoffset = - value;
7104 sheet->view.col0 = COLUMN_FROM_XPIXEL (sheet, sheet->row_title_area.width + 1);
7105 sheet->view.coli = COLUMN_FROM_XPIXEL (sheet, sheet->sheet_window_width);
7106 if (!sheet->row_titles_visible)
7107 sheet->view.col0 = COLUMN_FROM_XPIXEL (sheet, 1);
7109 if (GTK_WIDGET_REALIZED (sheet->sheet_entry) &&
7110 sheet->state == GTK_SHEET_NORMAL &&
7111 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
7112 !gtk_sheet_cell_isvisible (sheet, sheet->active_cell.row,
7113 sheet->active_cell.col))
7117 text = gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)));
7118 if (!text || strlen (text) == 0)
7119 gtk_sheet_cell_clear (sheet,
7120 sheet->active_cell.row,
7121 sheet->active_cell.col);
7123 gtk_widget_unmap (sheet->sheet_entry);
7126 gtk_sheet_position_children (sheet);
7128 gtk_sheet_range_draw (sheet, NULL);
7129 size_allocate_column_title_buttons (sheet);
7133 /* COLUMN RESIZING */
7135 draw_xor_vline (GtkSheet * sheet)
7139 g_return_if_fail (sheet != NULL);
7141 widget = GTK_WIDGET (sheet);
7143 gdk_draw_line (widget->window, sheet->xor_gc,
7145 sheet->column_title_area.height,
7147 sheet->sheet_window_height + 1);
7152 draw_xor_hline (GtkSheet * sheet)
7156 g_return_if_fail (sheet != NULL);
7158 widget = GTK_WIDGET (sheet);
7160 gdk_draw_line (widget->window, sheet->xor_gc,
7161 sheet->row_title_area.width,
7164 sheet->sheet_window_width + 1,
7168 /* SELECTED RANGE */
7170 draw_xor_rectangle (GtkSheet *sheet, GtkSheetRange range)
7173 GdkRectangle clip_area, area;
7176 area.x = COLUMN_LEFT_XPIXEL (sheet, range.col0);
7177 area.y = ROW_TOP_YPIXEL (sheet, range.row0);
7178 area.width = COLUMN_LEFT_XPIXEL (sheet, range.coli)- area.x+
7179 xxx_column_width (sheet, range.coli);
7180 area.height = ROW_TOP_YPIXEL (sheet, range.rowi)- area.y+
7181 yyy_row_height (sheet, range.rowi);
7183 clip_area.x = sheet->row_title_area.width;
7184 clip_area.y = sheet->column_title_area.height;
7185 clip_area.width = sheet->sheet_window_width;
7186 clip_area.height = sheet->sheet_window_height;
7188 if (!sheet->row_titles_visible) clip_area.x = 0;
7189 if (!sheet->column_titles_visible) clip_area.y = 0;
7193 area.width = area.width + area.x;
7196 if (area.width > clip_area.width) area.width = clip_area.width + 10;
7199 area.height = area.height + area.y;
7202 if (area.height > clip_area.height) area.height = clip_area.height + 10;
7206 clip_area.width += 3;
7207 clip_area.height += 3;
7209 gdk_gc_get_values (sheet->xor_gc, &values);
7211 gdk_gc_set_clip_rectangle (sheet->xor_gc, &clip_area);
7213 for (i =- 1; i <= 1; ++i)
7214 gdk_draw_rectangle (sheet->sheet_window,
7217 area.x + i, area.y + i,
7218 area.width - 2 * i, area.height - 2 * i);
7221 gdk_gc_set_clip_rectangle (sheet->xor_gc, NULL);
7223 gdk_gc_set_foreground (sheet->xor_gc, &values.foreground);
7228 /* this function returns the new width of the column being resized given
7229 * the column and x position of the cursor; the x cursor position is passed
7230 * in as a pointer and automaticaly corrected if it's beyond min / max limits */
7232 new_column_width (GtkSheet * sheet,
7241 min_width = sheet->column_requisition;
7243 /* you can't shrink a column to less than its minimum width */
7244 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
7246 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
7249 /* calculate new column width making sure it doesn't end up
7250 * less than the minimum width */
7251 width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
7252 if (width < min_width)
7255 xxx_set_column_width (sheet, column, width);
7256 sheet->view.coli = COLUMN_FROM_XPIXEL (sheet, sheet->sheet_window_width);
7257 size_allocate_column_title_buttons (sheet);
7262 /* this function returns the new height of the row being resized given
7263 * the row and y position of the cursor; the y cursor position is passed
7264 * in as a pointer and automaticaly corrected if it's beyond min / max limits */
7266 new_row_height (GtkSheet * sheet,
7274 min_height = sheet->row_requisition;
7276 /* you can't shrink a row to less than its minimum height */
7277 if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
7280 *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
7283 /* calculate new row height making sure it doesn't end up
7284 * less than the minimum height */
7285 height = (cy - ROW_TOP_YPIXEL (sheet, row));
7286 if (height < min_height)
7287 height = min_height;
7289 yyy_set_row_height (sheet, row, height);
7290 sheet->view.rowi = ROW_FROM_YPIXEL (sheet, sheet->sheet_window_height - 1);
7291 size_allocate_row_title_buttons (sheet);
7297 gtk_sheet_set_column_width (GtkSheet * sheet,
7303 g_return_if_fail (sheet != NULL);
7304 g_return_if_fail (GTK_IS_SHEET (sheet));
7306 if (column < 0 || column >= xxx_column_count (sheet))
7309 gtk_sheet_column_size_request (sheet, column, &min_width);
7310 if (width < min_width) return;
7312 xxx_set_column_width (sheet, column, width);
7314 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) && !GTK_SHEET_IS_FROZEN (sheet))
7316 size_allocate_column_title_buttons (sheet);
7317 adjust_scrollbars (sheet);
7318 gtk_sheet_size_allocate_entry (sheet);
7319 gtk_sheet_range_draw (sheet, NULL);
7322 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[CHANGED], - 1, column);
7323 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[NEW_COL_WIDTH],
7330 gtk_sheet_set_row_height (GtkSheet * sheet,
7336 g_return_if_fail (sheet != NULL);
7337 g_return_if_fail (GTK_IS_SHEET (sheet));
7339 if (row < 0 || row >= yyy_row_count (sheet))
7342 gtk_sheet_row_size_request (sheet, row, &min_height);
7343 if (height < min_height) return;
7345 yyy_set_row_height (sheet, row, height);
7347 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) && !GTK_SHEET_IS_FROZEN (sheet))
7349 size_allocate_row_title_buttons (sheet);
7350 adjust_scrollbars (sheet);
7351 gtk_sheet_size_allocate_entry (sheet);
7352 gtk_sheet_range_draw (sheet, NULL);
7355 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[CHANGED], row, - 1);
7356 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[NEW_ROW_HEIGHT], row, height);
7362 gtk_sheet_get_attributes (const GtkSheet *sheet, gint row, gint col,
7363 GtkSheetCellAttr *attributes)
7365 const GdkColor *fg, *bg;
7366 const GtkJustification *j ;
7367 const PangoFontDescription *font_desc ;
7368 const GtkSheetCellBorder *border ;
7370 g_return_val_if_fail (sheet != NULL, FALSE);
7371 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
7373 if (row < 0 || col < 0) return FALSE;
7375 init_attributes (sheet, col, attributes);
7380 attributes->is_editable = g_sheet_model_is_editable (sheet->model, row, col);
7381 attributes->is_visible = g_sheet_model_is_visible (sheet->model, row, col);
7383 fg = g_sheet_model_get_foreground (sheet->model, row, col);
7385 attributes->foreground = *fg;
7387 bg = g_sheet_model_get_background (sheet->model, row, col);
7389 attributes->background = *bg;
7391 j = g_sheet_model_get_justification (sheet->model, row, col);
7392 if (j) attributes->justification = *j;
7394 font_desc = g_sheet_model_get_font_desc (sheet->model, row, col);
7395 if ( font_desc ) attributes->font_desc = font_desc;
7397 border = g_sheet_model_get_cell_border (sheet->model, row, col);
7399 if ( border ) attributes->border = *border;
7405 init_attributes (const GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
7407 /* DEFAULT VALUES */
7408 attributes->foreground = GTK_WIDGET (sheet)->style->black;
7409 attributes->background = sheet->bg_color;
7410 if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
7412 GdkColormap *colormap;
7413 colormap = gdk_colormap_get_system ();
7414 gdk_color_black (colormap, &attributes->foreground);
7415 attributes->background = sheet->bg_color;
7417 attributes->justification = xxx_column_justification (sheet, col);
7418 attributes->border.width = 0;
7419 attributes->border.line_style = GDK_LINE_SOLID;
7420 attributes->border.cap_style = GDK_CAP_NOT_LAST;
7421 attributes->border.join_style = GDK_JOIN_MITER;
7422 attributes->border.mask = 0;
7423 attributes->border.color = GTK_WIDGET (sheet)->style->black;
7424 attributes->is_editable = TRUE;
7425 attributes->is_visible = TRUE;
7426 attributes->font_desc = GTK_WIDGET (sheet)->style->font_desc;
7430 /********************************************************************
7431 * Container Functions:
7436 * gtk_sheet_move_child
7437 * gtk_sheet_position_child
7438 * gtk_sheet_position_children
7439 * gtk_sheet_realize_child
7440 * gtk_sheet_get_child_at
7441 ********************************************************************/
7444 gtk_sheet_put (GtkSheet *sheet, GtkWidget *child, gint x, gint y)
7446 GtkRequisition child_requisition;
7447 GtkSheetChild *child_info;
7449 g_return_val_if_fail (sheet != NULL, NULL);
7450 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
7451 g_return_val_if_fail (child != NULL, NULL);
7452 g_return_val_if_fail (child->parent == NULL, NULL);
7454 child_info = g_new (GtkSheetChild, 1);
7455 child_info->widget = child;
7458 child_info->attached_to_cell = FALSE;
7459 child_info->floating = TRUE;
7460 child_info->xpadding = child_info->ypadding = 0;
7461 child_info->xexpand = child_info->yexpand = FALSE;
7462 child_info->xshrink = child_info->yshrink = FALSE;
7463 child_info->xfill = child_info->yfill = FALSE;
7465 sheet->children = g_list_append (sheet->children, child_info);
7467 gtk_widget_set_parent (child, GTK_WIDGET (sheet));
7469 gtk_widget_size_request (child, &child_requisition);
7471 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (sheet)))
7473 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) &&
7474 (!GTK_WIDGET_REALIZED (child) || GTK_WIDGET_NO_WINDOW (child)))
7475 gtk_sheet_realize_child (sheet, child_info);
7477 if (GTK_WIDGET_MAPPED (GTK_WIDGET (sheet)) &&
7478 !GTK_WIDGET_MAPPED (child))
7479 gtk_widget_map (child);
7482 gtk_sheet_position_child (sheet, child_info);
7484 /* This will avoid drawing on the titles */
7486 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
7488 if (sheet->row_titles_visible)
7489 gdk_window_show (sheet->row_title_window);
7490 if (sheet->column_titles_visible)
7491 gdk_window_show (sheet->column_title_window);
7494 return (child_info);
7498 gtk_sheet_attach_floating (GtkSheet *sheet,
7503 GtkSheetChild *child;
7505 if (row < 0 || col < 0)
7507 gtk_sheet_button_attach (sheet, widget, row, col);
7511 gtk_sheet_get_cell_area (sheet, row, col, &area);
7512 child = gtk_sheet_put (sheet, widget, area.x, area.y);
7513 child->attached_to_cell = TRUE;
7519 gtk_sheet_attach_default (GtkSheet *sheet,
7523 if (row < 0 || col < 0)
7525 gtk_sheet_button_attach (sheet, widget, row, col);
7529 gtk_sheet_attach (sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
7533 gtk_sheet_attach (GtkSheet *sheet,
7542 GtkSheetChild *child = NULL;
7544 if (row < 0 || col < 0)
7546 gtk_sheet_button_attach (sheet, widget, row, col);
7550 child = g_new0 (GtkSheetChild, 1);
7551 child->attached_to_cell = TRUE;
7552 child->floating = FALSE;
7553 child->widget = widget;
7556 child->xpadding = xpadding;
7557 child->ypadding = ypadding;
7558 child->xexpand = (xoptions & GTK_EXPAND) != 0;
7559 child->yexpand = (yoptions & GTK_EXPAND) != 0;
7560 child->xshrink = (xoptions & GTK_SHRINK) != 0;
7561 child->yshrink = (yoptions & GTK_SHRINK) != 0;
7562 child->xfill = (xoptions & GTK_FILL) != 0;
7563 child->yfill = (yoptions & GTK_FILL) != 0;
7565 sheet->children = g_list_append (sheet->children, child);
7567 gtk_sheet_get_cell_area (sheet, row, col, &area);
7569 child->x = area.x + child->xpadding;
7570 child->y = area.y + child->ypadding;
7572 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (sheet)))
7574 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) &&
7575 (!GTK_WIDGET_REALIZED (widget) || GTK_WIDGET_NO_WINDOW (widget)))
7576 gtk_sheet_realize_child (sheet, child);
7578 if (GTK_WIDGET_MAPPED (GTK_WIDGET (sheet)) &&
7579 !GTK_WIDGET_MAPPED (widget))
7580 gtk_widget_map (widget);
7583 gtk_sheet_position_child (sheet, child);
7585 /* This will avoid drawing on the titles */
7587 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
7589 if (GTK_SHEET_ROW_TITLES_VISIBLE (sheet))
7590 gdk_window_show (sheet->row_title_window);
7591 if (GTK_SHEET_COL_TITLES_VISIBLE (sheet))
7592 gdk_window_show (sheet->column_title_window);
7598 gtk_sheet_button_attach (GtkSheet *sheet,
7602 GtkSheetButton *button = 0;
7603 GtkSheetChild *child;
7604 GtkRequisition button_requisition;
7606 if (row >= 0 && col >= 0) return;
7607 if (row < 0 && col < 0) return;
7609 child = g_new (GtkSheetChild, 1);
7610 child->widget = widget;
7613 child->attached_to_cell = TRUE;
7614 child->floating = FALSE;
7617 child->xpadding = child->ypadding = 0;
7618 child->xshrink = child->yshrink = FALSE;
7619 child->xfill = child->yfill = FALSE;
7622 sheet->children = g_list_append (sheet->children, child);
7624 gtk_sheet_button_size_request (sheet, button, &button_requisition);
7627 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (sheet)))
7629 if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) &&
7630 (!GTK_WIDGET_REALIZED (widget) || GTK_WIDGET_NO_WINDOW (widget)))
7631 gtk_sheet_realize_child (sheet, child);
7633 if (GTK_WIDGET_MAPPED (GTK_WIDGET (sheet)) &&
7634 !GTK_WIDGET_MAPPED (widget))
7635 gtk_widget_map (widget);
7638 if (row == -1) size_allocate_column_title_buttons (sheet);
7639 if (col == -1) size_allocate_row_title_buttons (sheet);
7644 label_size_request (GtkSheet *sheet, gchar *label, GtkRequisition *req)
7649 gint row_height = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet)) - 2 * CELLOFFSET + 2;
7655 while (words && *words != '\0')
7657 if (*words == '\n' || * (words + 1) == '\0')
7659 req->height += row_height;
7662 req->width = MAX (req->width, STRING_WIDTH (GTK_WIDGET (sheet), GTK_WIDGET (sheet)->style->font_desc, word));
7672 if (n > 0) req->height -= 2;
7676 gtk_sheet_button_size_request (GtkSheet *sheet,
7677 const GtkSheetButton *button,
7678 GtkRequisition *button_requisition)
7680 GtkRequisition requisition;
7681 GtkRequisition label_requisition;
7683 if (gtk_sheet_autoresize (sheet) && button->label && strlen (button->label) > 0)
7685 label_size_request (sheet, button->label, &label_requisition);
7686 label_requisition.width += 2 * CELLOFFSET;
7687 label_requisition.height += 2 * CELLOFFSET;
7691 label_requisition.height = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet));
7692 label_requisition.width = COLUMN_MIN_WIDTH;
7697 gtk_widget_size_request (button->child->widget, &requisition);
7698 requisition.width += 2 * button->child->xpadding;
7699 requisition.height += 2 * button->child->ypadding;
7700 requisition.width += 2 * sheet->button->style->xthickness;
7701 requisition.height += 2 * sheet->button->style->ythickness;
7705 requisition.height = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet));
7706 requisition.width = COLUMN_MIN_WIDTH;
7709 *button_requisition = requisition;
7710 button_requisition->width = MAX (requisition.width, label_requisition.width);
7711 button_requisition->height = MAX (requisition.height, label_requisition.height);
7716 gtk_sheet_row_size_request (GtkSheet *sheet,
7720 GtkRequisition button_requisition;
7723 gtk_sheet_button_size_request (sheet,
7724 yyy_row_button (sheet, row),
7725 &button_requisition);
7727 *requisition = button_requisition.height;
7729 children = sheet->children;
7732 GtkSheetChild *child = (GtkSheetChild *)children->data;
7733 GtkRequisition child_requisition;
7735 if (child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink)
7737 gtk_widget_get_child_requisition (child->widget, &child_requisition);
7739 if (child_requisition.height + 2 * child->ypadding > *requisition)
7740 *requisition = child_requisition.height + 2 * child->ypadding;
7742 children = children->next;
7745 sheet->row_requisition = * requisition;
7749 gtk_sheet_column_size_request (GtkSheet *sheet,
7753 GtkRequisition button_requisition;
7756 gtk_sheet_button_size_request (sheet,
7757 xxx_column_button (sheet, col),
7758 &button_requisition);
7760 *requisition = button_requisition.width;
7762 children = sheet->children;
7765 GtkSheetChild *child = (GtkSheetChild *)children->data;
7766 GtkRequisition child_requisition;
7768 if (child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink)
7770 gtk_widget_get_child_requisition (child->widget, &child_requisition);
7772 if (child_requisition.width + 2 * child->xpadding > *requisition)
7773 *requisition = child_requisition.width + 2 * child->xpadding;
7775 children = children->next;
7778 sheet->column_requisition = *requisition;
7782 gtk_sheet_move_child (GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
7784 GtkSheetChild *child;
7787 g_return_if_fail (sheet != NULL);
7788 g_return_if_fail (GTK_IS_SHEET (sheet));
7790 children = sheet->children;
7793 child = children->data;
7795 if (child->widget == widget)
7799 child->row = ROW_FROM_YPIXEL (sheet, y);
7800 child->col = COLUMN_FROM_XPIXEL (sheet, x);
7801 gtk_sheet_position_child (sheet, child);
7805 children = children->next;
7808 g_warning ("Widget must be a GtkSheet child");
7813 gtk_sheet_position_child (GtkSheet *sheet, GtkSheetChild *child)
7815 GtkRequisition child_requisition;
7816 GtkAllocation child_allocation;
7822 gtk_widget_get_child_requisition (child->widget, &child_requisition);
7824 if (sheet->column_titles_visible)
7825 yoffset = sheet->column_title_area.height;
7827 if (sheet->row_titles_visible)
7828 xoffset = sheet->row_title_area.width;
7830 if (child->attached_to_cell)
7832 gtk_sheet_get_cell_area (sheet, child->row, child->col, &area);
7833 child->x = area.x + child->xpadding;
7834 child->y = area.y + child->ypadding;
7836 if (!child->floating)
7838 if (child_requisition.width + 2 * child->xpadding <= xxx_column_width (sheet, child->col))
7842 child_requisition.width = child_allocation.width = xxx_column_width (sheet, child->col) - 2 * child->xpadding;
7848 child->x = area.x + xxx_column_width (sheet, child->col) / 2 -
7849 child_requisition.width / 2;
7851 child_allocation.width = child_requisition.width;
7856 if (!child->xshrink)
7858 gtk_sheet_set_column_width (sheet, child->col, child_requisition.width + 2 * child->xpadding);
7860 child_allocation.width = xxx_column_width (sheet, child->col) - 2 * child->xpadding;
7863 if (child_requisition.height +
7864 2 * child->ypadding <= yyy_row_height (sheet, child->row))
7868 child_requisition.height = child_allocation.height =
7869 yyy_row_height (sheet, child->row) - 2 * child->ypadding;
7875 child->y = area.y + yyy_row_height (sheet, child->row) / 2
7876 - child_requisition.height / 2;
7878 child_allocation.height = child_requisition.height;
7883 if (!child->yshrink)
7885 gtk_sheet_set_row_height (sheet, child->row, child_requisition.height + 2 * child->ypadding);
7887 child_allocation.height = yyy_row_height (sheet, child->row) -
7888 2 * child->ypadding;
7893 child_allocation.width = child_requisition.width;
7894 child_allocation.height = child_requisition.height;
7897 x = child_allocation.x = child->x + xoffset;
7898 y = child_allocation.y = child->y + yoffset;
7902 x = child_allocation.x = child->x + sheet->hoffset + xoffset;
7903 x = child_allocation.x = child->x + xoffset;
7904 y = child_allocation.y = child->y + sheet->voffset + yoffset;
7905 y = child_allocation.y = child->y + yoffset;
7906 child_allocation.width = child_requisition.width;
7907 child_allocation.height = child_requisition.height;
7910 gtk_widget_size_allocate (child->widget, &child_allocation);
7911 gtk_widget_queue_draw (child->widget);
7915 gtk_sheet_forall (GtkContainer *container,
7916 gboolean include_internals,
7917 GtkCallback callback,
7918 gpointer callback_data)
7921 GtkSheetChild *child;
7924 g_return_if_fail (GTK_IS_SHEET (container));
7925 g_return_if_fail (callback != NULL);
7927 sheet = GTK_SHEET (container);
7928 children = sheet->children;
7931 child = children->data;
7932 children = children->next;
7934 (* callback) (child->widget, callback_data);
7937 (* callback) (sheet->button, callback_data);
7938 if (sheet->sheet_entry)
7939 (* callback) (sheet->sheet_entry, callback_data);
7944 gtk_sheet_position_children (GtkSheet *sheet)
7947 GtkSheetChild *child;
7949 children = sheet->children;
7953 child = (GtkSheetChild *)children->data;
7955 if (child->col != -1 && child->row != -1)
7956 gtk_sheet_position_child (sheet, child);
7958 if (child->row == -1)
7960 if (child->col < MIN_VISIBLE_COLUMN (sheet) ||
7961 child->col > MAX_VISIBLE_COLUMN (sheet))
7962 gtk_sheet_child_hide (child);
7964 gtk_sheet_child_show (child);
7966 if (child->col == -1)
7968 if (child->row < MIN_VISIBLE_ROW (sheet) ||
7969 child->row > MAX_VISIBLE_ROW (sheet))
7970 gtk_sheet_child_hide (child);
7972 gtk_sheet_child_show (child);
7975 children = children->next;
7980 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
7984 GtkSheetChild *child = 0;
7986 g_return_if_fail (container != NULL);
7987 g_return_if_fail (GTK_IS_SHEET (container));
7989 sheet = GTK_SHEET (container);
7991 children = sheet->children;
7995 child = (GtkSheetChild *)children->data;
7997 if (child->widget == widget) break;
7999 children = children->next;
8004 gtk_widget_unparent (widget);
8005 child->widget = NULL;
8007 sheet->children = g_list_remove_link (sheet->children, children);
8008 g_list_free_1 (children);
8015 gtk_sheet_realize_child (GtkSheet *sheet, GtkSheetChild *child)
8019 widget = GTK_WIDGET (sheet);
8021 if (GTK_WIDGET_REALIZED (widget))
8023 if (child->row == -1)
8024 gtk_widget_set_parent_window (child->widget, sheet->column_title_window);
8025 else if (child->col == -1)
8026 gtk_widget_set_parent_window (child->widget, sheet->row_title_window);
8028 gtk_widget_set_parent_window (child->widget, sheet->sheet_window);
8031 gtk_widget_set_parent (child->widget, widget);
8037 gtk_sheet_get_child_at (GtkSheet *sheet, gint row, gint col)
8040 GtkSheetChild *child = 0;
8042 g_return_val_if_fail (sheet != NULL, NULL);
8043 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
8045 children = sheet->children;
8049 child = (GtkSheetChild *)children->data;
8051 if (child->attached_to_cell)
8052 if (child->row == row && child->col == col) break;
8054 children = children->next;
8057 if (children) return child;
8063 gtk_sheet_child_hide (GtkSheetChild *child)
8065 g_return_if_fail (child != NULL);
8066 gtk_widget_hide (child->widget);
8070 gtk_sheet_child_show (GtkSheetChild *child)
8072 g_return_if_fail (child != NULL);
8074 gtk_widget_show (child->widget);
8078 gtk_sheet_get_model (const GtkSheet *sheet)
8080 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
8082 return sheet->model;
8087 gtk_sheet_button_new (void)
8089 GtkSheetButton *button = g_malloc (sizeof (GtkSheetButton));
8091 button->state = GTK_STATE_NORMAL;
8092 button->label = NULL;
8093 button->label_visible = TRUE;
8094 button->child = NULL;
8095 button->justification = GTK_JUSTIFY_FILL;
8102 gtk_sheet_button_free (GtkSheetButton *button)
8104 if (!button) return ;
8106 g_free (button->label);