1 /* This version of GtkSheet has been *heavily* modified, for the specific
2 requirements of PSPPIRE. */
4 /* GtkSheet widget for Gtk+.
5 * Copyright (C) 1999-2001 Adrian E. Feiguin <adrian@ifir.ifir.edu.ar>
7 * Based on GtkClist widget by Jay Painter, but major changes.
8 * Memory allocation routines inspired on SC (Spreadsheet Calculator)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 * @short_description: spreadsheet widget for gtk2
28 * GtkSheet is a matrix widget for GTK+. It consists of an scrollable grid of
29 * cells where you can allocate text. Cell contents can be edited interactively
30 * through a specially designed entry, GtkItemEntry. It is also a container
31 * subclass, allowing you to display buttons, curves, pixmaps and any other
34 * You can also set many attributes as: border, foreground and background color,
35 * text justification, and more.
37 * The testgtksheet program shows how easy is to create a spreadsheet-like GUI
45 #include <gdk/gdkkeysyms.h>
46 #include <gtk/gtksignal.h>
47 #include <gtk/gtklabel.h>
48 #include <gtk/gtkbutton.h>
49 #include <gtk/gtkadjustment.h>
50 #include <gtk/gtktable.h>
51 #include <gtk/gtkbox.h>
52 #include <gtk/gtkmain.h>
53 #include <gtk/gtktypeutils.h>
54 #include <gtk/gtkentry.h>
55 #include <gtk/gtkcontainer.h>
56 #include <gtk/gtkpixmap.h>
57 #include <pango/pango.h>
58 #include "gtkitementry.h"
60 #include "gtkextra-marshal.h"
61 #include "gsheetmodel.h"
67 GTK_SHEET_IS_LOCKED = 1 << 0,
68 GTK_SHEET_IS_FROZEN = 1 << 1,
69 GTK_SHEET_IN_XDRAG = 1 << 2,
70 GTK_SHEET_IN_YDRAG = 1 << 3,
71 GTK_SHEET_IN_DRAG = 1 << 4,
72 GTK_SHEET_IN_SELECTION = 1 << 5,
73 GTK_SHEET_IN_RESIZE = 1 << 6,
74 GTK_SHEET_IN_CLIP = 1 << 7,
75 GTK_SHEET_REDRAW_PENDING = 1 << 8,
78 #define GTK_SHEET_FLAGS(sheet) (GTK_SHEET (sheet)->flags)
79 #define GTK_SHEET_SET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) |= (flag))
80 #define GTK_SHEET_UNSET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) &= ~(flag))
82 #define GTK_SHEET_IS_LOCKED(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_LOCKED)
85 #define GTK_SHEET_IS_FROZEN(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN)
86 #define GTK_SHEET_IN_XDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG)
87 #define GTK_SHEET_IN_YDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG)
88 #define GTK_SHEET_IN_DRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_DRAG)
89 #define GTK_SHEET_IN_SELECTION(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_SELECTION)
90 #define GTK_SHEET_IN_RESIZE(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_RESIZE)
91 #define GTK_SHEET_IN_CLIP(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_CLIP)
92 #define GTK_SHEET_REDRAW_PENDING(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_REDRAW_PENDING)
94 #define CELL_SPACING 1
96 #define TIMEOUT_SCROLL 20
97 #define TIMEOUT_FLASH 200
98 #define TIME_INTERVAL 8
99 #define COLUMN_MIN_WIDTH 10
104 #define DEFAULT_COLUMN_WIDTH 80
107 static gboolean gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col);
110 void dispose_string (const GtkSheet *sheet, gchar *text)
112 GSheetModel *model = gtk_sheet_get_model(sheet);
117 if (g_sheet_model_free_strings(model))
122 guint DEFAULT_ROW_HEIGHT(GtkWidget *widget)
124 if(!widget->style->font_desc) return 24;
126 PangoContext *context = gtk_widget_get_pango_context(widget);
127 PangoFontMetrics *metrics = pango_context_get_metrics(context,
128 widget->style->font_desc,
129 pango_context_get_language(context));
130 guint val = pango_font_metrics_get_descent(metrics) +
131 pango_font_metrics_get_ascent(metrics);
132 pango_font_metrics_unref(metrics);
133 return PANGO_PIXELS(val)+2*CELLOFFSET;
136 static inline guint DEFAULT_FONT_ASCENT(GtkWidget *widget)
138 if(!widget->style->font_desc) return 12;
140 PangoContext *context = gtk_widget_get_pango_context(widget);
141 PangoFontMetrics *metrics = pango_context_get_metrics(context,
142 widget->style->font_desc,
143 pango_context_get_language(context));
144 guint val = pango_font_metrics_get_ascent(metrics);
145 pango_font_metrics_unref(metrics);
146 return PANGO_PIXELS(val);
149 static inline guint STRING_WIDTH(GtkWidget *widget,
150 const PangoFontDescription *font, const gchar *text)
155 layout = gtk_widget_create_pango_layout (widget, text);
156 pango_layout_set_font_description (layout, font);
158 pango_layout_get_extents (layout, NULL, &rect);
160 g_object_unref(G_OBJECT(layout));
161 return PANGO_PIXELS(rect.width);
164 static inline guint DEFAULT_FONT_DESCENT(GtkWidget *widget)
166 if(!widget->style->font_desc) return 12;
168 PangoContext *context = gtk_widget_get_pango_context(widget);
169 PangoFontMetrics *metrics = pango_context_get_metrics(context,
170 widget->style->font_desc,
171 pango_context_get_language(context));
172 guint val = pango_font_metrics_get_descent(metrics);
173 pango_font_metrics_unref(metrics);
174 return PANGO_PIXELS(val);
180 yyy_row_is_visible(GtkSheet *sheet, gint row)
182 GSheetRow *row_geo = sheet->row_geometry;
184 return g_sheet_row_get_visibility(row_geo, row, sheet);
189 yyy_row_is_sensitive(GtkSheet *sheet, gint row)
191 GSheetRow *row_geo = sheet->row_geometry;
193 return g_sheet_row_get_sensitivity(row_geo, row, sheet);
199 yyy_row_count(const GtkSheet *sheet)
201 GSheetRow *row_geo = sheet->row_geometry;
203 return g_sheet_row_get_row_count(row_geo, sheet);
207 yyy_row_height(const GtkSheet *sheet, gint row)
209 GSheetRow *row_geo = sheet->row_geometry;
211 return g_sheet_row_get_height(row_geo, row, sheet);
215 yyy_row_top_ypixel(GtkSheet *sheet, gint row)
217 GSheetRow *geo = sheet->row_geometry;
219 gint y = g_sheet_row_start_pixel(geo, row, sheet);
221 if ( sheet->column_titles_visible )
222 y += sheet->column_title_area.height;
228 /* Return the row containing pixel Y */
230 yyy_row_ypixel_to_row(GtkSheet *sheet, gint y)
232 GSheetRow *geo = sheet->row_geometry;
234 gint cy = sheet->voffset;
236 if(sheet->column_titles_visible)
237 cy += sheet->column_title_area.height;
242 return g_sheet_row_pixel_to_row(geo, y - cy, sheet);
246 /* gives the top pixel of the given row in context of
247 * the sheet's voffset */
249 ROW_TOP_YPIXEL(GtkSheet *sheet, gint row)
251 return (sheet->voffset + yyy_row_top_ypixel(sheet, row));
255 /* returns the row index from a y pixel location in the
256 * context of the sheet's voffset */
258 ROW_FROM_YPIXEL(GtkSheet *sheet, gint y)
260 return (yyy_row_ypixel_to_row(sheet, y));
263 static inline const GtkSheetButton *
264 xxx_column_button(GtkSheet *sheet, gint col)
266 GSheetColumn *col_geo = sheet->column_geometry;
268 return g_sheet_column_get_button(col_geo, col, sheet);
273 xxx_column_left_xpixel(GtkSheet *sheet, gint col)
275 GSheetColumn *geo = sheet->column_geometry;
277 gint x = g_sheet_column_start_pixel(geo, col, sheet);
279 if ( sheet->row_titles_visible )
280 x += sheet->row_title_area.width;
286 xxx_column_width(const GtkSheet *sheet, gint col)
288 GSheetColumn *col_geo = sheet->column_geometry;
290 return g_sheet_column_get_width(col_geo, col, sheet);
295 xxx_set_column_width(GtkSheet *sheet, gint col, gint width)
297 if ( sheet->column_geometry )
298 g_sheet_column_set_width(sheet->column_geometry, col, width, sheet);
302 xxx_column_set_left_column(GtkSheet *sheet, gint col, gint i)
304 GSheetColumn *col_geo = sheet->column_geometry;
306 g_sheet_column_set_left_text_column(col_geo, col, i, sheet);
310 xxx_column_left_column(const GtkSheet *sheet, gint col)
312 GSheetColumn *col_geo = sheet->column_geometry;
314 return g_sheet_column_get_left_text_column(col_geo, col, sheet);
318 xxx_column_set_right_column(GtkSheet *sheet, gint col, gint i)
320 GSheetColumn *col_geo = sheet->column_geometry;
322 g_sheet_column_set_right_text_column(col_geo, col, i, sheet);
326 xxx_column_right_column(const GtkSheet *sheet, gint col)
328 GSheetColumn *col_geo = sheet->column_geometry;
330 return g_sheet_column_get_right_text_column(col_geo, col, sheet);
333 static inline GtkJustification
334 xxx_column_justification(const GtkSheet *sheet, gint col)
336 GSheetColumn *col_geo = sheet->column_geometry;
338 return g_sheet_column_get_justification(col_geo, col, sheet);
342 xxx_column_is_visible(GtkSheet *sheet, gint col)
344 GSheetColumn *col_geo = sheet->column_geometry;
346 return g_sheet_column_get_visibility(col_geo, col, sheet);
351 xxx_column_is_sensitive(GtkSheet *sheet, gint col)
353 GSheetColumn *col_geo = sheet->column_geometry;
355 return g_sheet_column_get_sensitivity(col_geo, col, sheet);
359 /* gives the left pixel of the given column in context of
360 * the sheet's hoffset */
362 COLUMN_LEFT_XPIXEL(GtkSheet *sheet, gint ncol)
364 return (sheet->hoffset + xxx_column_left_xpixel(sheet, ncol));
368 xxx_column_count(const GtkSheet *sheet)
370 GSheetColumn *col_geo = sheet->column_geometry;
372 return g_sheet_column_get_column_count(col_geo, sheet);
375 /* returns the column index from a x pixel location in the
376 * context of the sheet's hoffset */
378 COLUMN_FROM_XPIXEL (GtkSheet * sheet,
384 if( sheet->row_titles_visible )
385 cx += sheet->row_title_area.width;
388 for (i = 0; i < xxx_column_count(sheet); i++)
390 if (x >= cx && x <= (cx + xxx_column_width(sheet, i)) &&
391 xxx_column_is_visible(sheet, i))
393 if( xxx_column_is_visible(sheet, i))
394 cx += xxx_column_width(sheet, i);
398 return xxx_column_count(sheet) - 1;
401 /* returns the total height of the sheet */
402 static inline gint SHEET_HEIGHT(GtkSheet *sheet)
404 const gint n_rows = yyy_row_count(sheet);
406 return yyy_row_top_ypixel(sheet, n_rows - 1) +
407 yyy_row_height(sheet, n_rows - 1);
411 static inline const GtkSheetButton *
412 yyy_row_button(GtkSheet *sheet, gint row)
414 GSheetRow *row_geo = sheet->row_geometry;
416 return g_sheet_row_get_button(row_geo, row, sheet);
423 yyy_set_row_height(GtkSheet *sheet, gint row, gint height)
425 if ( sheet->row_geometry )
426 g_sheet_row_set_height(sheet->row_geometry, row, height, sheet);
431 /* returns the total width of the sheet */
432 static inline gint SHEET_WIDTH(GtkSheet *sheet)
436 cx = ( sheet->row_titles_visible ? sheet->row_title_area.width : 0);
438 for (i=0; i < xxx_column_count(sheet); i++)
439 if(xxx_column_is_visible(sheet, i)) cx += xxx_column_width(sheet, i);
444 #define MIN_VISIBLE_ROW(sheet) sheet->view.row0
445 #define MAX_VISIBLE_ROW(sheet) sheet->view.rowi
446 #define MIN_VISIBLE_COLUMN(sheet) sheet->view.col0
447 #define MAX_VISIBLE_COLUMN(sheet) sheet->view.coli
451 POSSIBLE_XDRAG(GtkSheet *sheet, gint x, gint *drag_column)
455 column=COLUMN_FROM_XPIXEL(sheet, x);
458 xdrag=COLUMN_LEFT_XPIXEL(sheet,column)+CELL_SPACING;
459 if(x <= xdrag+DRAG_WIDTH/2 && column != 0){
460 while(! xxx_column_is_visible(sheet, column-1) && column>0) column--;
461 *drag_column=column-1;
462 return xxx_column_is_sensitive(sheet, column-1);
465 xdrag+= xxx_column_width(sheet, column);
466 if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag+DRAG_WIDTH/2)
467 return xxx_column_is_sensitive(sheet, column);
473 POSSIBLE_YDRAG(GtkSheet *sheet, gint y, gint *drag_row)
477 row=ROW_FROM_YPIXEL(sheet, y);
480 ydrag=ROW_TOP_YPIXEL(sheet,row)+CELL_SPACING;
481 if(y <= ydrag+DRAG_WIDTH/2 && row != 0){
482 while(!yyy_row_is_visible(sheet, row-1) && row>0) row--;
484 return yyy_row_is_sensitive(sheet, row-1);
487 ydrag+=yyy_row_height(sheet, row);
489 if(y >= ydrag-DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2)
490 return yyy_row_is_sensitive(sheet, row);
496 static inline gint POSSIBLE_DRAG(GtkSheet *sheet, gint x, gint y,
497 gint *drag_row, gint *drag_column)
501 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
502 *drag_row=ROW_FROM_YPIXEL(sheet,y);
504 if(x>=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0)-DRAG_WIDTH/2 &&
505 x<=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
506 xxx_column_width(sheet, sheet->range.coli) + DRAG_WIDTH/2){
507 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.row0);
508 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
509 *drag_row=sheet->range.row0;
512 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
513 yyy_row_height(sheet, sheet->range.rowi);
514 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
515 *drag_row=sheet->range.rowi;
520 if(y>=ROW_TOP_YPIXEL(sheet,sheet->range.row0)-DRAG_WIDTH/2 &&
521 y<=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
522 yyy_row_height(sheet, sheet->range.rowi)+DRAG_WIDTH/2){
523 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0);
524 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
525 *drag_column=sheet->range.col0;
528 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
529 xxx_column_width(sheet, sheet->range.coli);
530 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
531 *drag_column=sheet->range.coli;
538 static inline gint POSSIBLE_RESIZE(GtkSheet *sheet, gint x, gint y,
539 gint *drag_row, gint *drag_column)
543 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
544 xxx_column_width(sheet, sheet->range.coli);
546 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
547 yyy_row_height(sheet, sheet->range.rowi);
549 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
550 ydrag = ROW_TOP_YPIXEL(sheet, sheet->view.row0);
552 if(sheet->state == GTK_SHEET_ROW_SELECTED)
553 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0);
555 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
556 *drag_row=ROW_FROM_YPIXEL(sheet,y);
558 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2 &&
559 y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2) return TRUE;
564 static void gtk_sheet_class_init (GtkSheetClass * klass);
565 static void gtk_sheet_init (GtkSheet * sheet);
566 static void gtk_sheet_destroy (GtkObject * object);
567 static void gtk_sheet_finalize (GObject * object);
568 static void gtk_sheet_style_set (GtkWidget *widget,
569 GtkStyle *previous_style);
570 static void gtk_sheet_realize (GtkWidget * widget);
571 static void gtk_sheet_unrealize (GtkWidget * widget);
572 static void gtk_sheet_map (GtkWidget * widget);
573 static void gtk_sheet_unmap (GtkWidget * widget);
574 static gint gtk_sheet_expose (GtkWidget * widget,
575 GdkEventExpose * event);
576 static void gtk_sheet_forall (GtkContainer *container,
577 gboolean include_internals,
578 GtkCallback callback,
579 gpointer callback_data);
581 static void gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
582 GtkAdjustment *hadjustment,
583 GtkAdjustment *vadjustment);
585 static gint gtk_sheet_button_press (GtkWidget * widget,
586 GdkEventButton * event);
587 static gint gtk_sheet_button_release (GtkWidget * widget,
588 GdkEventButton * event);
589 static gint gtk_sheet_motion (GtkWidget * widget,
590 GdkEventMotion * event);
591 static gint gtk_sheet_entry_key_press (GtkWidget *widget,
593 static gint gtk_sheet_key_press (GtkWidget *widget,
595 static void gtk_sheet_size_request (GtkWidget * widget,
596 GtkRequisition * requisition);
597 static void gtk_sheet_size_allocate (GtkWidget * widget,
598 GtkAllocation * allocation);
602 static gint gtk_sheet_range_isvisible (GtkSheet * sheet,
603 GtkSheetRange range);
604 static gint gtk_sheet_cell_isvisible (GtkSheet * sheet,
605 gint row, gint column);
608 static gint gtk_sheet_scroll (gpointer data);
609 static gint gtk_sheet_flash (gpointer data);
611 /* Drawing Routines */
613 /* draw cell background and frame */
614 static void gtk_sheet_cell_draw_default (GtkSheet *sheet,
615 gint row, gint column);
617 /* draw cell border */
618 static void gtk_sheet_cell_draw_border (GtkSheet *sheet,
619 gint row, gint column,
622 /* draw cell contents */
623 static void gtk_sheet_cell_draw_label (GtkSheet *sheet,
624 gint row, gint column);
626 /* draw visible part of range. If range==NULL then draw the whole screen */
627 static void gtk_sheet_range_draw (GtkSheet *sheet,
628 const GtkSheetRange *range);
630 /* highlight the visible part of the selected range */
631 static void gtk_sheet_range_draw_selection (GtkSheet *sheet,
632 GtkSheetRange range);
636 static gint gtk_sheet_move_query (GtkSheet *sheet,
637 gint row, gint column);
638 static void gtk_sheet_real_select_range (GtkSheet * sheet,
639 GtkSheetRange * range);
640 static void gtk_sheet_real_unselect_range (GtkSheet * sheet,
641 const GtkSheetRange * range);
642 static void gtk_sheet_extend_selection (GtkSheet *sheet,
643 gint row, gint column);
644 static void gtk_sheet_new_selection (GtkSheet *sheet,
645 GtkSheetRange *range);
646 static void gtk_sheet_draw_border (GtkSheet *sheet,
647 GtkSheetRange range);
648 static void gtk_sheet_draw_corners (GtkSheet *sheet,
649 GtkSheetRange range);
652 /* Active Cell handling */
654 static void gtk_sheet_entry_changed (GtkWidget *widget,
656 static gboolean gtk_sheet_deactivate_cell (GtkSheet *sheet);
657 static void gtk_sheet_hide_active_cell (GtkSheet *sheet);
658 static gboolean gtk_sheet_activate_cell (GtkSheet *sheet,
660 static void gtk_sheet_draw_active_cell (GtkSheet *sheet);
661 static void gtk_sheet_show_active_cell (GtkSheet *sheet);
662 static void gtk_sheet_click_cell (GtkSheet *sheet,
669 static void gtk_sheet_make_backing_pixmap (GtkSheet *sheet,
670 guint width, guint height);
671 static void gtk_sheet_draw_backing_pixmap (GtkSheet *sheet,
672 GtkSheetRange range);
675 static void adjust_scrollbars (GtkSheet * sheet);
676 static void vadjustment_changed (GtkAdjustment * adjustment,
678 static void hadjustment_changed (GtkAdjustment * adjustment,
680 static void vadjustment_value_changed (GtkAdjustment * adjustment,
682 static void hadjustment_value_changed (GtkAdjustment * adjustment,
686 static void draw_xor_vline (GtkSheet * sheet);
687 static void draw_xor_hline (GtkSheet * sheet);
688 static void draw_xor_rectangle (GtkSheet *sheet,
689 GtkSheetRange range);
690 static void gtk_sheet_draw_flashing_range (GtkSheet *sheet,
691 GtkSheetRange range);
692 static guint new_column_width (GtkSheet * sheet,
695 static guint new_row_height (GtkSheet * sheet,
700 static void create_global_button (GtkSheet *sheet);
701 static void global_button_clicked (GtkWidget *widget,
705 static void create_sheet_entry (GtkSheet *sheet);
706 static void gtk_sheet_size_allocate_entry (GtkSheet *sheet);
707 static void gtk_sheet_entry_set_max_size (GtkSheet *sheet);
709 /* Sheet button gadgets */
711 static void size_allocate_column_title_buttons (GtkSheet * sheet);
712 static void size_allocate_row_title_buttons (GtkSheet * sheet);
715 static void gtk_sheet_button_draw (GtkSheet *sheet,
716 gint row, gint column);
717 static void size_allocate_global_button (GtkSheet *sheet);
718 static void gtk_sheet_button_size_request (GtkSheet *sheet,
719 const GtkSheetButton *button,
720 GtkRequisition *requisition);
722 /* Attributes routines */
723 static void init_attributes (GtkSheet *sheet, gint col,
724 GtkSheetCellAttr *attributes);
727 /* Memory allocation routines */
728 static void gtk_sheet_real_range_clear (GtkSheet *sheet,
729 const GtkSheetRange *range,
731 static void gtk_sheet_real_cell_clear (GtkSheet *sheet,
737 /* Container Functions */
738 static void gtk_sheet_remove (GtkContainer *container,
740 static void gtk_sheet_realize_child (GtkSheet *sheet,
741 GtkSheetChild *child);
742 static void gtk_sheet_position_child (GtkSheet *sheet,
743 GtkSheetChild *child);
744 static void gtk_sheet_position_children (GtkSheet *sheet);
745 static void gtk_sheet_child_show (GtkSheetChild *child);
746 static void gtk_sheet_child_hide (GtkSheetChild *child);
747 static void gtk_sheet_column_size_request (GtkSheet *sheet,
750 static void gtk_sheet_row_size_request (GtkSheet *sheet,
758 _gtkextra_signal_emit(GtkObject *object, guint signal_id, ...);
780 static GtkContainerClass *parent_class = NULL;
781 static guint sheet_signals[LAST_SIGNAL] = {0};
785 gtk_sheet_get_type ()
787 static GType sheet_type = 0;
791 static const GTypeInfo sheet_info =
793 sizeof (GtkSheetClass),
796 (GClassInitFunc) gtk_sheet_class_init,
801 (GInstanceInitFunc) gtk_sheet_init,
805 g_type_register_static (GTK_TYPE_CONTAINER, "GtkSheet",
811 static GtkSheetRange*
812 gtk_sheet_range_copy (const GtkSheetRange *range)
814 GtkSheetRange *new_range;
816 g_return_val_if_fail (range != NULL, NULL);
818 new_range = g_new (GtkSheetRange, 1);
826 gtk_sheet_range_free (GtkSheetRange *range)
828 g_return_if_fail (range != NULL);
834 gtk_sheet_range_get_type (void)
836 static GType sheet_range_type=0;
838 if(!sheet_range_type)
840 sheet_range_type = g_boxed_type_register_static("GtkSheetRange", (GBoxedCopyFunc)gtk_sheet_range_copy, (GBoxedFreeFunc)gtk_sheet_range_free);
842 return sheet_range_type;
847 gtk_sheet_class_init (GtkSheetClass * klass)
849 GtkObjectClass *object_class;
850 GtkWidgetClass *widget_class;
851 GtkContainerClass *container_class;
852 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
854 object_class = (GtkObjectClass *) klass;
855 widget_class = (GtkWidgetClass *) klass;
856 container_class = (GtkContainerClass *) klass;
858 parent_class = g_type_class_peek_parent (klass);
861 * GtkSheet::select-row
862 * @sheet: the sheet widget that emitted the signal
863 * @row: the newly selected row index
865 * A row has been selected.
867 sheet_signals[SELECT_ROW] =
868 gtk_signal_new ("select-row",
870 GTK_CLASS_TYPE(object_class),
871 GTK_SIGNAL_OFFSET (GtkSheetClass, select_row),
873 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
876 * GtkSheet::select-column
877 * @sheet: the sheet widget that emitted the signal
878 * @column: the newly selected column index
880 * A column has been selected.
882 sheet_signals[SELECT_COLUMN] =
883 gtk_signal_new ("select-column",
885 GTK_CLASS_TYPE(object_class),
886 GTK_SIGNAL_OFFSET (GtkSheetClass, select_column),
888 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
892 * GtkSheet::double-click-row
893 * @sheet: the sheet widget that emitted the signal
894 * @row: the row that was double clicked.
896 * A row's title button has been double clicked
898 sheet_signals[DOUBLE_CLICK_ROW] =
899 gtk_signal_new ("double-click-row",
901 GTK_CLASS_TYPE(object_class),
904 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
908 * GtkSheet::double-click-column
909 * @sheet: the sheet widget that emitted the signal
910 * @column: the column that was double clicked.
912 * A column's title button has been double clicked
914 sheet_signals[DOUBLE_CLICK_COLUMN] =
915 gtk_signal_new ("double-click-column",
917 GTK_CLASS_TYPE(object_class),
920 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
922 sheet_signals[SELECT_RANGE] =
923 gtk_signal_new ("select-range",
925 GTK_CLASS_TYPE(object_class),
926 GTK_SIGNAL_OFFSET (GtkSheetClass, select_range),
927 gtkextra_VOID__BOXED,
928 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
930 sheet_signals[CLIP_RANGE] =
931 gtk_signal_new ("clip-range",
933 GTK_CLASS_TYPE(object_class),
934 GTK_SIGNAL_OFFSET (GtkSheetClass, clip_range),
935 gtkextra_VOID__BOXED,
936 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
938 sheet_signals[RESIZE_RANGE] =
939 gtk_signal_new ("resize-range",
941 GTK_CLASS_TYPE(object_class),
942 GTK_SIGNAL_OFFSET (GtkSheetClass, resize_range),
943 gtkextra_VOID__BOXED_BOXED,
944 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
945 sheet_signals[MOVE_RANGE] =
946 gtk_signal_new ("move-range",
948 GTK_CLASS_TYPE(object_class),
949 GTK_SIGNAL_OFFSET (GtkSheetClass, move_range),
950 gtkextra_VOID__BOXED_BOXED,
951 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
952 sheet_signals[TRAVERSE] =
953 gtk_signal_new ("traverse",
955 GTK_CLASS_TYPE(object_class),
956 GTK_SIGNAL_OFFSET (GtkSheetClass, traverse),
957 gtkextra_BOOLEAN__INT_INT_POINTER_POINTER,
958 GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT,
959 GTK_TYPE_POINTER, GTK_TYPE_POINTER);
961 sheet_signals[DEACTIVATE] =
962 gtk_signal_new ("deactivate",
964 GTK_CLASS_TYPE(object_class),
965 GTK_SIGNAL_OFFSET (GtkSheetClass, deactivate),
966 gtkextra_BOOLEAN__INT_INT,
967 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
969 sheet_signals[ACTIVATE] =
970 gtk_signal_new ("activate",
972 GTK_CLASS_TYPE(object_class),
973 GTK_SIGNAL_OFFSET (GtkSheetClass, activate),
974 gtkextra_BOOLEAN__INT_INT,
975 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
977 sheet_signals[SET_CELL] =
978 gtk_signal_new ("set-cell",
980 GTK_CLASS_TYPE(object_class),
981 GTK_SIGNAL_OFFSET (GtkSheetClass, set_cell),
982 gtkextra_VOID__INT_INT,
983 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
985 sheet_signals[CLEAR_CELL] =
986 gtk_signal_new ("clear-cell",
988 GTK_CLASS_TYPE(object_class),
989 GTK_SIGNAL_OFFSET (GtkSheetClass, clear_cell),
990 gtkextra_VOID__INT_INT,
991 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
993 sheet_signals[CHANGED] =
994 gtk_signal_new ("changed",
996 GTK_CLASS_TYPE(object_class),
997 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
998 gtkextra_VOID__INT_INT,
999 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1001 sheet_signals[NEW_COL_WIDTH] =
1002 gtk_signal_new ("new-column-width",
1004 GTK_CLASS_TYPE(object_class),
1005 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1006 gtkextra_VOID__INT_INT,
1007 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1009 sheet_signals[NEW_ROW_HEIGHT] =
1010 gtk_signal_new ("new-row-height",
1012 GTK_CLASS_TYPE(object_class),
1013 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1014 gtkextra_VOID__INT_INT,
1015 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1017 widget_class->set_scroll_adjustments_signal =
1018 gtk_signal_new ("set-scroll-adjustments",
1020 GTK_CLASS_TYPE(object_class),
1021 GTK_SIGNAL_OFFSET (GtkSheetClass, set_scroll_adjustments),
1022 gtkextra_VOID__OBJECT_OBJECT,
1023 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1026 container_class->add = NULL;
1027 container_class->remove = gtk_sheet_remove;
1028 container_class->forall = gtk_sheet_forall;
1030 object_class->destroy = gtk_sheet_destroy;
1031 gobject_class->finalize = gtk_sheet_finalize;
1033 widget_class->realize = gtk_sheet_realize;
1034 widget_class->unrealize = gtk_sheet_unrealize;
1035 widget_class->map = gtk_sheet_map;
1036 widget_class->unmap = gtk_sheet_unmap;
1037 widget_class->style_set = gtk_sheet_style_set;
1038 widget_class->button_press_event = gtk_sheet_button_press;
1039 widget_class->button_release_event = gtk_sheet_button_release;
1040 widget_class->motion_notify_event = gtk_sheet_motion;
1041 widget_class->key_press_event = gtk_sheet_key_press;
1042 widget_class->expose_event = gtk_sheet_expose;
1043 widget_class->size_request = gtk_sheet_size_request;
1044 widget_class->size_allocate = gtk_sheet_size_allocate;
1045 widget_class->focus_in_event = NULL;
1046 widget_class->focus_out_event = NULL;
1048 klass->set_scroll_adjustments = gtk_sheet_set_scroll_adjustments;
1049 klass->select_row = NULL;
1050 klass->select_column = NULL;
1051 klass->select_range = NULL;
1052 klass->clip_range = NULL;
1053 klass->resize_range = NULL;
1054 klass->move_range = NULL;
1055 klass->traverse = NULL;
1056 klass->deactivate = NULL;
1057 klass->activate = NULL;
1058 klass->set_cell = NULL;
1059 klass->clear_cell = NULL;
1060 klass->changed = NULL;
1065 gtk_sheet_init (GtkSheet *sheet)
1067 sheet->column_geometry = NULL;
1068 sheet->row_geometry = NULL;
1070 sheet->children = NULL;
1073 sheet->selection_mode = GTK_SELECTION_BROWSE;
1074 sheet->freeze_count = 0;
1075 sheet->state = GTK_SHEET_NORMAL;
1077 GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW);
1078 GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS);
1080 sheet->view.row0 = 0;
1081 sheet->view.col0 = 0;
1082 sheet->view.rowi = 0;
1083 sheet->view.coli = 0;
1085 sheet->column_title_window=NULL;
1086 sheet->column_title_area.x=0;
1087 sheet->column_title_area.y=0;
1088 sheet->column_title_area.width=0;
1089 sheet->column_title_area.height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
1091 sheet->row_title_window=NULL;
1092 sheet->row_title_area.x=0;
1093 sheet->row_title_area.y=0;
1094 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1095 sheet->row_title_area.height=0;
1098 sheet->active_cell.row=0;
1099 sheet->active_cell.col=0;
1100 sheet->selection_cell.row=0;
1101 sheet->selection_cell.col=0;
1103 sheet->sheet_entry=NULL;
1106 sheet->range.row0=0;
1107 sheet->range.rowi=0;
1108 sheet->range.col0=0;
1109 sheet->range.coli=0;
1111 sheet->state=GTK_SHEET_NORMAL;
1113 sheet->sheet_window = NULL;
1114 sheet->sheet_window_width = 0;
1115 sheet->sheet_window_height = 0;
1116 sheet->sheet_entry = NULL;
1117 sheet->button = NULL;
1122 sheet->hadjustment = NULL;
1123 sheet->vadjustment = NULL;
1125 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
1126 sheet->xor_gc = NULL;
1127 sheet->fg_gc = NULL;
1128 sheet->bg_gc = NULL;
1132 gdk_color_parse("white", &sheet->bg_color);
1133 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1134 gdk_color_parse("gray", &sheet->grid_color);
1135 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1136 sheet->show_grid = TRUE;
1140 /* Callback which occurs whenever columns are inserted/deleted in the model */
1142 columns_inserted_deleted_callback (GSheetModel *model, gint first_column, gint n_columns,
1145 GtkSheet *sheet = GTK_SHEET(data);
1147 GtkSheetRange range;
1148 gint model_columns = g_sheet_model_get_column_count(model);
1151 /* Need to update all the columns starting from the first column and onwards.
1152 * Previous column are unchanged, so don't need to be updated.
1154 range.col0 = first_column;
1156 range.coli = xxx_column_count(sheet) - 1;
1157 range.rowi = yyy_row_count(sheet) - 1;
1159 if (sheet->active_cell.col >= model_columns)
1160 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, model_columns - 1);
1162 gtk_sheet_range_draw(sheet, &range);
1166 /* Callback which occurs whenever rows are inserted/deleted in the model */
1168 rows_inserted_deleted_callback (GSheetModel *m, gint first_row, gint n_rows,
1171 GtkSheet *sheet = GTK_SHEET(data);
1173 GtkSheetRange range;
1175 /* Need to update all the rows starting from the first row and onwards.
1176 * Previous rows are unchanged, so don't need to be updated.
1178 range.row0 = first_row;
1180 range.rowi = yyy_row_count(sheet) - 1;
1181 range.coli = xxx_column_count(sheet) - 1;
1183 gtk_sheet_range_draw(sheet, &range);
1188 If row0 or rowi are negative, then all rows will be updated.
1189 If col0 or coli are negative, then all columns will be updated.
1192 range_update_callback (GSheetModel *m, gint row0, gint col0,
1193 gint rowi, gint coli, gpointer data)
1195 GtkSheet *sheet = GTK_SHEET(data);
1197 GtkSheetRange range;
1204 if( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
1206 gtk_sheet_range_draw(sheet, NULL);
1209 else if ( row0 < 0 || rowi < 0 )
1211 range.row0=MIN_VISIBLE_ROW(sheet);
1212 range.rowi=MAX_VISIBLE_ROW(sheet);
1214 else if ( col0 < 0 || coli < 0 )
1216 range.col0=MIN_VISIBLE_COLUMN(sheet);
1217 range.coli=MAX_VISIBLE_COLUMN(sheet);
1220 gtk_sheet_range_draw(sheet, &range);
1224 static void gtk_sheet_construct (GtkSheet *sheet,
1227 const gchar *title);
1232 * @rows: initial number of rows
1233 * @columns: initial number of columns
1234 * @title: sheet title
1235 * @model: the model to use for the sheet data
1237 * Creates a new sheet widget with the given number of rows and columns.
1239 * Returns: the new sheet widget
1242 gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, const gchar *title,
1247 widget = gtk_type_new (gtk_sheet_get_type ());
1249 gtk_sheet_construct(GTK_SHEET(widget), vgeo, hgeo, title);
1252 gtk_sheet_set_model(GTK_SHEET(widget), model);
1260 * gtk_sheet_set_model
1261 * @sheet: the sheet to set the model for
1262 * @model: the model to use for the sheet data
1264 * Sets the model for a GtkSheet
1268 gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model)
1270 g_return_if_fail (GTK_IS_SHEET (sheet));
1271 g_return_if_fail (G_IS_SHEET_MODEL (model));
1273 sheet->model = model;
1275 g_signal_connect(model, "range_changed",
1276 G_CALLBACK(range_update_callback), sheet);
1278 g_signal_connect(model, "rows_inserted",
1279 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1281 g_signal_connect(model, "rows_deleted",
1282 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1284 g_signal_connect(model, "columns_inserted",
1285 G_CALLBACK(columns_inserted_deleted_callback), sheet);
1287 g_signal_connect(model, "columns_deleted",
1288 G_CALLBACK(columns_inserted_deleted_callback), sheet);
1295 column_titles_changed(GtkWidget *w, gint first, gint n_columns, gpointer data)
1297 GtkSheet *sheet = GTK_SHEET(data);
1300 if(!GTK_SHEET_IS_FROZEN(sheet)){
1302 for ( i = first ; i <= MAX_VISIBLE_COLUMN(sheet) ; ++i )
1304 gtk_sheet_button_draw(sheet, -1, i);
1305 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, i);
1311 gtk_sheet_construct (GtkSheet *sheet,
1316 g_return_if_fail(G_IS_SHEET_COLUMN(hgeo));
1317 g_return_if_fail(G_IS_SHEET_ROW(vgeo));
1319 sheet->column_geometry = hgeo;
1320 sheet->row_geometry = vgeo;
1323 sheet->columns_resizable = TRUE;
1324 sheet->rows_resizable = TRUE;
1326 sheet->row_titles_visible = TRUE;
1327 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1329 sheet->column_titles_visible = TRUE;
1330 sheet->autoscroll = TRUE;
1331 sheet->justify_entry = TRUE;
1334 /* create sheet entry */
1335 sheet->entry_type = 0;
1336 create_sheet_entry (sheet);
1338 /* create global selection button */
1339 create_global_button(sheet);
1342 sheet->name = g_strdup(title);
1344 g_signal_connect(sheet->column_geometry, "columns_changed",
1345 G_CALLBACK(column_titles_changed), sheet);
1351 gtk_sheet_new_with_custom_entry (GSheetRow *rows, GSheetColumn *columns, const gchar *title,
1356 widget = gtk_type_new (gtk_sheet_get_type ());
1358 gtk_sheet_construct_with_custom_entry(GTK_SHEET(widget),
1359 rows, columns, title, entry_type);
1365 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet,
1371 gtk_sheet_construct(sheet, vgeo, hgeo, title);
1373 sheet->entry_type = entry_type;
1374 create_sheet_entry(sheet);
1380 gtk_sheet_change_entry(GtkSheet *sheet, GtkType entry_type)
1384 g_return_if_fail (sheet != NULL);
1385 g_return_if_fail (GTK_IS_SHEET (sheet));
1387 state = sheet->state;
1389 if(sheet->state == GTK_SHEET_NORMAL)
1390 gtk_sheet_hide_active_cell(sheet);
1392 sheet->entry_type = entry_type;
1394 create_sheet_entry(sheet);
1396 if(state == GTK_SHEET_NORMAL)
1398 gtk_sheet_show_active_cell(sheet);
1399 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
1401 G_CALLBACK(gtk_sheet_entry_changed),
1410 gtk_sheet_show_grid(GtkSheet *sheet, gboolean show)
1412 g_return_if_fail (sheet != NULL);
1413 g_return_if_fail (GTK_IS_SHEET (sheet));
1415 if(show == sheet->show_grid) return;
1417 sheet->show_grid = show;
1419 if(!GTK_SHEET_IS_FROZEN(sheet))
1420 gtk_sheet_range_draw(sheet, NULL);
1424 gtk_sheet_grid_visible(GtkSheet *sheet)
1426 g_return_val_if_fail (sheet != NULL, 0);
1427 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1429 return sheet->show_grid;
1433 gtk_sheet_set_background(GtkSheet *sheet, GdkColor *color)
1435 g_return_if_fail (sheet != NULL);
1436 g_return_if_fail (GTK_IS_SHEET (sheet));
1439 gdk_color_parse("white", &sheet->bg_color);
1440 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1442 sheet->bg_color = *color;
1444 if(!GTK_SHEET_IS_FROZEN(sheet))
1445 gtk_sheet_range_draw(sheet, NULL);
1449 gtk_sheet_set_grid(GtkSheet *sheet, GdkColor *color)
1451 g_return_if_fail (sheet != NULL);
1452 g_return_if_fail (GTK_IS_SHEET (sheet));
1455 gdk_color_parse("black", &sheet->grid_color);
1456 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1458 sheet->grid_color = *color;
1460 if(!GTK_SHEET_IS_FROZEN(sheet))
1461 gtk_sheet_range_draw(sheet, NULL);
1465 gtk_sheet_get_columns_count(GtkSheet *sheet)
1467 g_return_val_if_fail (sheet != NULL, 0);
1468 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1470 return xxx_column_count(sheet);
1474 gtk_sheet_get_rows_count(GtkSheet *sheet)
1476 g_return_val_if_fail (sheet != NULL, 0);
1477 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1479 return yyy_row_count(sheet);
1483 gtk_sheet_get_state(GtkSheet *sheet)
1485 g_return_val_if_fail (sheet != NULL, 0);
1486 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1488 return (sheet->state);
1492 gtk_sheet_set_selection_mode(GtkSheet *sheet, gint mode)
1494 g_return_if_fail (sheet != NULL);
1495 g_return_if_fail (GTK_IS_SHEET (sheet));
1497 if(GTK_WIDGET_REALIZED(sheet))
1498 gtk_sheet_real_unselect_range(sheet, NULL);
1500 sheet->selection_mode = mode;
1504 gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize)
1506 g_return_if_fail (sheet != NULL);
1507 g_return_if_fail (GTK_IS_SHEET (sheet));
1509 sheet->autoresize = autoresize;
1513 gtk_sheet_autoresize (GtkSheet *sheet)
1515 g_return_val_if_fail (sheet != NULL, FALSE);
1516 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1518 return sheet->autoresize;
1522 gtk_sheet_set_column_width (GtkSheet * sheet,
1528 gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
1530 gint text_width = 0;
1533 g_return_if_fail (sheet != NULL);
1534 g_return_if_fail (GTK_IS_SHEET (sheet));
1535 if (column >= xxx_column_count(sheet) || column < 0) return;
1537 for (row = 0; row < yyy_row_count(sheet); row++)
1539 gchar *text = gtk_sheet_cell_get_text(sheet, row, column);
1540 if (text && strlen(text) > 0){
1541 GtkSheetCellAttr attributes;
1543 gtk_sheet_get_attributes(sheet, row, column, &attributes);
1544 if(attributes.is_visible){
1545 gint width = STRING_WIDTH(GTK_WIDGET(sheet),
1546 attributes.font_desc,
1548 + 2*CELLOFFSET + attributes.border.width;
1549 text_width = MAX (text_width, width);
1552 dispose_string(sheet, text);
1555 if(text_width > xxx_column_width(sheet, column) )
1557 gtk_sheet_set_column_width(sheet, column, text_width);
1558 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
1564 gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll)
1566 g_return_if_fail (sheet != NULL);
1567 g_return_if_fail (GTK_IS_SHEET (sheet));
1569 sheet->autoscroll = autoscroll;
1573 gtk_sheet_autoscroll (GtkSheet *sheet)
1575 g_return_val_if_fail (sheet != NULL, FALSE);
1576 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1578 return sheet->autoscroll;
1582 gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text)
1584 g_return_if_fail (sheet != NULL);
1585 g_return_if_fail (GTK_IS_SHEET (sheet));
1587 sheet->clip_text = clip_text;
1591 gtk_sheet_clip_text (GtkSheet *sheet)
1593 g_return_val_if_fail (sheet != NULL, FALSE);
1594 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1596 return sheet->clip_text;
1600 gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify)
1602 g_return_if_fail (sheet != NULL);
1603 g_return_if_fail (GTK_IS_SHEET (sheet));
1605 sheet->justify_entry = justify;
1609 gtk_sheet_justify_entry (GtkSheet *sheet)
1611 g_return_val_if_fail (sheet != NULL, FALSE);
1612 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1614 return sheet->justify_entry;
1618 gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked)
1620 g_return_if_fail (sheet != NULL);
1621 g_return_if_fail (GTK_IS_SHEET (sheet));
1625 GTK_SHEET_SET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
1626 gtk_widget_hide(sheet->sheet_entry);
1627 gtk_widget_unmap(sheet->sheet_entry);
1631 GTK_SHEET_UNSET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
1632 if (GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)))
1634 gtk_widget_show (sheet->sheet_entry);
1635 gtk_widget_map (sheet->sheet_entry);
1639 gtk_entry_set_editable(GTK_ENTRY(sheet->sheet_entry), locked);
1644 gtk_sheet_locked (const GtkSheet *sheet)
1646 g_return_val_if_fail (sheet != NULL, FALSE);
1647 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1649 return GTK_SHEET_IS_LOCKED(sheet);
1652 /* This routine has problems with gtk+-1.2 related with the
1653 * label/button drawing - I think it's a bug in gtk+-1.2 */
1656 gtk_sheet_set_title(GtkSheet *sheet, const gchar *title)
1658 /* GtkWidget *old_widget;
1659 */ GtkWidget *label;
1661 g_return_if_fail (sheet != NULL);
1662 g_return_if_fail (title != NULL);
1663 g_return_if_fail (GTK_IS_SHEET (sheet));
1666 g_free (sheet->name);
1668 sheet->name = g_strdup (title);
1670 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) || !title) return;
1672 if(GTK_BIN(sheet->button)->child)
1673 label = GTK_BIN(sheet->button)->child;
1675 gtk_label_set_text(GTK_LABEL(label), title);
1677 size_allocate_global_button(sheet);
1679 /* remove and destroy the old widget */
1681 old_widget = GTK_BIN (sheet->button)->child;
1684 gtk_container_remove (GTK_CONTAINER (sheet->button), old_widget);
1687 label = gtk_label_new (title);
1688 gtk_misc_set_alignment(GTK_MISC(label), 0.5 , 0.5 );
1690 gtk_container_add (GTK_CONTAINER (sheet->button), label);
1691 gtk_widget_show (label);
1693 size_allocate_global_button(sheet);
1695 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, -1);
1698 gtk_widget_destroy (old_widget);
1703 gtk_sheet_freeze (GtkSheet *sheet)
1705 g_return_if_fail (sheet != NULL);
1706 g_return_if_fail (GTK_IS_SHEET (sheet));
1708 sheet->freeze_count++;
1709 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1713 gtk_sheet_thaw(GtkSheet *sheet)
1715 g_return_if_fail (sheet != NULL);
1716 g_return_if_fail (GTK_IS_SHEET (sheet));
1718 if(sheet->freeze_count == 0) return;
1720 sheet->freeze_count--;
1721 if(sheet->freeze_count > 0) return;
1723 adjust_scrollbars(sheet);
1725 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1727 sheet->old_vadjustment = -1.;
1728 sheet->old_hadjustment = -1.;
1730 if(sheet->hadjustment)
1731 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1733 if(sheet->vadjustment)
1734 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1737 if(sheet->state == GTK_STATE_NORMAL)
1738 if(sheet->sheet_entry && GTK_WIDGET_MAPPED(sheet->sheet_entry)){
1739 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
1741 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
1743 (GtkSignalFunc)gtk_sheet_entry_changed,
1744 GTK_OBJECT(GTK_WIDGET(sheet)));
1745 gtk_sheet_show_active_cell(sheet);
1752 gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width)
1754 if(width < COLUMN_MIN_WIDTH) return;
1756 sheet->row_title_area.width = width;
1757 sheet->view.col0 = COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
1758 sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
1761 adjust_scrollbars(sheet);
1763 sheet->old_hadjustment = -1.;
1764 if(sheet->hadjustment)
1765 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1767 size_allocate_global_button(sheet);
1771 gtk_sheet_set_column_titles_height(GtkSheet *sheet, guint height)
1773 if(height < DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))) return;
1775 sheet->column_title_area.height = height;
1776 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
1777 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
1779 adjust_scrollbars(sheet);
1781 sheet->old_vadjustment = -1.;
1782 if(sheet->vadjustment)
1783 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1785 size_allocate_global_button(sheet);
1789 gtk_sheet_show_column_titles(GtkSheet *sheet)
1793 if(sheet->column_titles_visible) return;
1795 sheet->column_titles_visible = TRUE;
1798 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1799 gdk_window_show(sheet->column_title_window);
1800 gdk_window_move_resize (sheet->column_title_window,
1801 sheet->column_title_area.x,
1802 sheet->column_title_area.y,
1803 sheet->column_title_area.width,
1804 sheet->column_title_area.height);
1806 for(col = MIN_VISIBLE_COLUMN(sheet);
1807 col <= MAX_VISIBLE_COLUMN(sheet);
1810 const GtkSheetButton *button = xxx_column_button(sheet, col);
1811 GtkSheetChild *child = button->child;
1813 gtk_sheet_child_show(child);
1815 adjust_scrollbars(sheet);
1818 sheet->old_vadjustment = -1.;
1819 if(sheet->vadjustment)
1820 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1822 size_allocate_global_button(sheet);
1827 gtk_sheet_show_row_titles(GtkSheet *sheet)
1831 if(sheet->row_titles_visible) return;
1833 sheet->row_titles_visible = TRUE;
1836 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1837 gdk_window_show(sheet->row_title_window);
1838 gdk_window_move_resize (sheet->row_title_window,
1839 sheet->row_title_area.x,
1840 sheet->row_title_area.y,
1841 sheet->row_title_area.width,
1842 sheet->row_title_area.height);
1844 for(row = MIN_VISIBLE_ROW(sheet);
1845 row <= MAX_VISIBLE_ROW(sheet);
1848 const GtkSheetButton *button = yyy_row_button(sheet, row);
1849 GtkSheetChild *child = button->child;
1852 gtk_sheet_child_show(child);
1855 adjust_scrollbars(sheet);
1858 sheet->old_hadjustment = -1.;
1859 if(sheet->hadjustment)
1860 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1862 size_allocate_global_button(sheet);
1866 gtk_sheet_hide_column_titles(GtkSheet *sheet)
1870 if(!sheet->column_titles_visible) return;
1872 sheet->column_titles_visible = FALSE;
1874 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1875 if(sheet->column_title_window)
1876 gdk_window_hide(sheet->column_title_window);
1877 if(GTK_WIDGET_VISIBLE(sheet->button))
1878 gtk_widget_hide(sheet->button);
1880 for(col = MIN_VISIBLE_COLUMN(sheet);
1881 col <= MAX_VISIBLE_COLUMN(sheet);
1884 const GtkSheetButton *button = xxx_column_button(sheet, col);
1885 GtkSheetChild *child = button->child;
1887 gtk_sheet_child_hide(child);
1889 adjust_scrollbars(sheet);
1892 sheet->old_vadjustment = -1.;
1893 if(sheet->vadjustment)
1894 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1899 gtk_sheet_hide_row_titles(GtkSheet *sheet)
1903 if(!sheet->row_titles_visible) return;
1905 sheet->row_titles_visible = FALSE;
1908 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1909 if(sheet->row_title_window)
1910 gdk_window_hide(sheet->row_title_window);
1911 if(GTK_WIDGET_VISIBLE(sheet->button))
1912 gtk_widget_hide(sheet->button);
1913 for(row = MIN_VISIBLE_ROW(sheet);
1914 row <= MAX_VISIBLE_ROW(sheet);
1917 const GtkSheetButton *button = yyy_row_button(sheet, row);
1918 GtkSheetChild *child = button->child;
1921 gtk_sheet_child_hide(child);
1923 adjust_scrollbars(sheet);
1926 sheet->old_hadjustment = -1.;
1927 if(sheet->hadjustment)
1928 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1933 gtk_sheet_column_titles_visible(GtkSheet *sheet)
1935 g_return_val_if_fail (sheet != NULL, FALSE);
1936 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1937 return sheet->column_titles_visible;
1941 gtk_sheet_row_titles_visible(GtkSheet *sheet)
1943 g_return_val_if_fail (sheet != NULL, FALSE);
1944 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1945 return sheet->row_titles_visible;
1951 gtk_sheet_moveto (GtkSheet * sheet,
1958 guint width, height;
1960 gint min_row, min_col;
1962 g_return_if_fail (sheet != NULL);
1963 g_return_if_fail (GTK_IS_SHEET (sheet));
1964 g_return_if_fail (sheet->hadjustment != NULL);
1965 g_return_if_fail (sheet->vadjustment != NULL);
1967 if (row < 0 || row >= yyy_row_count(sheet))
1969 if (column < 0 || column >= xxx_column_count(sheet))
1972 height = sheet->sheet_window_height;
1973 width = sheet->sheet_window_width;
1975 /* adjust vertical scrollbar */
1977 if (row >= 0 && row_align >=0.)
1980 y = ROW_TOP_YPIXEL(sheet, row) - sheet->voffset -
1982 (1.-row_align)*yyy_row_height(sheet, row);
1984 y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
1985 - (gint) ( row_align*height + (1. - row_align) * yyy_row_height(sheet, row));
1987 /* This forces the sheet to scroll when you don't see the entire cell */
1990 if(row_align == 1.){
1991 while(min_row >= 0 && min_row > MIN_VISIBLE_ROW(sheet)){
1992 if(yyy_row_is_visible(sheet, min_row))
1993 adjust += yyy_row_height(sheet, min_row);
1994 if(adjust >= height){
1999 min_row = MAX(min_row, 0);
2000 y = ROW_TOP_YPIXEL(sheet, min_row) - sheet->voffset +
2001 yyy_row_height(sheet, min_row) - 1;
2005 sheet->vadjustment->value = 0.0;
2007 sheet->vadjustment->value = y;
2009 sheet->old_vadjustment = -1.;
2010 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
2015 /* adjust horizontal scrollbar */
2016 if (column >= 0 && col_align >= 0.)
2019 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset -
2021 (1.-col_align)*sheet->column[column].width;
2023 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
2024 - (gint) ( col_align*width + (1.-col_align)*
2025 xxx_column_width(sheet, column));
2028 /* This forces the sheet to scroll when you don't see the entire cell */
2031 if(col_align == 1.){
2032 while(min_col >= 0 && min_col > MIN_VISIBLE_COLUMN(sheet)){
2033 if(xxx_column_is_visible(sheet, min_col))
2034 adjust += xxx_column_width(sheet, min_col);
2036 if(adjust >= width){
2041 min_col = MAX(min_col, 0);
2042 x = COLUMN_LEFT_XPIXEL(sheet, min_col) - sheet->hoffset +
2043 xxx_column_width(sheet, min_col) - 1;
2047 sheet->hadjustment->value = 0.0;
2049 sheet->hadjustment->value = x;
2051 sheet->old_vadjustment = -1.;
2052 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
2060 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
2062 g_return_if_fail (sheet != NULL);
2063 g_return_if_fail (GTK_IS_SHEET (sheet));
2065 sheet->columns_resizable = resizable;
2069 gtk_sheet_columns_resizable (GtkSheet *sheet)
2071 g_return_val_if_fail (sheet != NULL, FALSE);
2072 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2074 return sheet->columns_resizable;
2079 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
2081 g_return_if_fail (sheet != NULL);
2082 g_return_if_fail (GTK_IS_SHEET (sheet));
2084 sheet->rows_resizable = resizable;
2088 gtk_sheet_rows_resizable (GtkSheet *sheet)
2090 g_return_val_if_fail (sheet != NULL, FALSE);
2091 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2093 return sheet->rows_resizable;
2098 gtk_sheet_select_row (GtkSheet * sheet,
2101 g_return_if_fail (sheet != NULL);
2102 g_return_if_fail (GTK_IS_SHEET (sheet));
2104 if (row < 0 || row >= yyy_row_count(sheet))
2107 if(sheet->state != GTK_SHEET_NORMAL)
2108 gtk_sheet_real_unselect_range(sheet, NULL);
2111 gboolean veto = TRUE;
2112 veto = gtk_sheet_deactivate_cell(sheet);
2116 sheet->state=GTK_SHEET_ROW_SELECTED;
2117 sheet->range.row0=row;
2118 sheet->range.col0=0;
2119 sheet->range.rowi=row;
2120 sheet->range.coli = xxx_column_count(sheet) - 1;
2121 sheet->active_cell.row=row;
2122 sheet->active_cell.col=0;
2124 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_ROW], row);
2125 gtk_sheet_real_select_range(sheet, NULL);
2131 gtk_sheet_select_column (GtkSheet * sheet,
2135 g_return_if_fail (sheet != NULL);
2136 g_return_if_fail (GTK_IS_SHEET (sheet));
2138 if (column < 0 || column >= xxx_column_count(sheet))
2141 if(sheet->state != GTK_SHEET_NORMAL)
2142 gtk_sheet_real_unselect_range(sheet, NULL);
2145 gboolean veto = TRUE;
2146 veto = gtk_sheet_deactivate_cell(sheet);
2150 sheet->state=GTK_SHEET_COLUMN_SELECTED;
2151 sheet->range.row0=0;
2152 sheet->range.col0=column;
2153 sheet->range.rowi= yyy_row_count(sheet) - 1;
2154 sheet->range.coli=column;
2155 sheet->active_cell.row=0;
2156 sheet->active_cell.col=column;
2158 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_COLUMN], column);
2159 gtk_sheet_real_select_range(sheet, NULL);
2164 gtk_sheet_clip_range (GtkSheet *sheet, const GtkSheetRange *range)
2167 g_return_if_fail (sheet != NULL);
2168 g_return_if_fail (GTK_IS_SHEET (sheet));
2170 if(GTK_SHEET_IN_CLIP(sheet)) return;
2172 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2175 sheet->clip_range = sheet->range;
2177 sheet->clip_range=*range;
2180 sheet->clip_timer=gtk_timeout_add(TIMEOUT_FLASH, gtk_sheet_flash, sheet);
2182 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CLIP_RANGE],
2183 &sheet->clip_range);
2188 gtk_sheet_unclip_range(GtkSheet *sheet)
2191 g_return_if_fail (sheet != NULL);
2192 g_return_if_fail (GTK_IS_SHEET (sheet));
2194 if(!GTK_SHEET_IN_CLIP(sheet)) return;
2196 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2197 gtk_timeout_remove(sheet->clip_timer);
2198 gtk_sheet_range_draw(sheet, &sheet->clip_range);
2200 if(gtk_sheet_range_isvisible(sheet, sheet->range))
2201 gtk_sheet_range_draw(sheet, &sheet->range);
2205 gtk_sheet_in_clip (GtkSheet *sheet)
2207 g_return_val_if_fail (sheet != NULL, FALSE);
2208 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2210 return GTK_SHEET_IN_CLIP(sheet);
2214 gtk_sheet_flash(gpointer data)
2217 gint x,y,width,height;
2218 GdkRectangle clip_area;
2220 sheet=GTK_SHEET(data);
2222 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return TRUE;
2223 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return TRUE;
2224 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return TRUE;
2225 if(GTK_SHEET_IN_XDRAG(sheet)) return TRUE;
2226 if(GTK_SHEET_IN_YDRAG(sheet)) return TRUE;
2228 GDK_THREADS_ENTER();
2230 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2231 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2232 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2233 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2234 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2235 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2237 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2238 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2239 clip_area.width=sheet->sheet_window_width;
2240 clip_area.height=sheet->sheet_window_height;
2246 if(width>clip_area.width) width=clip_area.width+10;
2251 if(height>clip_area.height) height=clip_area.height+10;
2253 gdk_draw_pixmap(sheet->sheet_window,
2254 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2260 gdk_draw_pixmap(sheet->sheet_window,
2261 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2267 gdk_draw_pixmap(sheet->sheet_window,
2268 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2274 gdk_draw_pixmap(sheet->sheet_window,
2275 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2282 sheet->interval=sheet->interval+1;
2283 if(sheet->interval==TIME_INTERVAL) sheet->interval=0;
2285 gdk_gc_set_dashes(sheet->xor_gc, sheet->interval, (gint8*)"\4\4", 2);
2286 gtk_sheet_draw_flashing_range(sheet,sheet->clip_range);
2287 gdk_gc_set_dashes(sheet->xor_gc, 0, (gint8*)"\4\4", 2);
2289 GDK_THREADS_LEAVE();
2296 gtk_sheet_draw_flashing_range(GtkSheet *sheet, GtkSheetRange range)
2298 GdkRectangle clip_area;
2299 gint x,y,width,height;
2301 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return;
2303 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2304 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2305 clip_area.width=sheet->sheet_window_width;
2306 clip_area.height=sheet->sheet_window_height;
2308 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
2310 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2311 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2312 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2313 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2314 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2315 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2321 if(width>clip_area.width) width=clip_area.width+10;
2326 if(height>clip_area.height) height=clip_area.height+10;
2328 gdk_gc_set_line_attributes(sheet->xor_gc, 1, 1, 0 ,0 );
2330 gdk_draw_rectangle(sheet->sheet_window, sheet->xor_gc, FALSE,
2334 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 0, 0, 0);
2336 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
2341 gtk_sheet_range_isvisible (GtkSheet * sheet,
2342 GtkSheetRange range)
2344 g_return_val_if_fail (sheet != NULL, FALSE);
2346 if (range.row0 < 0 || range.row0 >= yyy_row_count(sheet))
2349 if (range.rowi < 0 || range.rowi >= yyy_row_count(sheet))
2352 if (range.col0 < 0 || range.col0 >= xxx_column_count(sheet))
2355 if (range.coli < 0 || range.coli >= xxx_column_count(sheet))
2358 if (range.rowi < MIN_VISIBLE_ROW (sheet))
2361 if (range.row0 > MAX_VISIBLE_ROW (sheet))
2364 if (range.coli < MIN_VISIBLE_COLUMN (sheet))
2367 if (range.col0 > MAX_VISIBLE_COLUMN (sheet))
2374 gtk_sheet_cell_isvisible (GtkSheet * sheet,
2375 gint row, gint column)
2377 GtkSheetRange range;
2380 range.col0 = column;
2382 range.coli = column;
2384 return gtk_sheet_range_isvisible(sheet, range);
2388 gtk_sheet_get_visible_range(GtkSheet *sheet, GtkSheetRange *range)
2391 g_return_if_fail (sheet != NULL);
2392 g_return_if_fail (GTK_IS_SHEET (sheet)) ;
2393 g_return_if_fail (range != NULL);
2395 range->row0 = MIN_VISIBLE_ROW(sheet);
2396 range->col0 = MIN_VISIBLE_COLUMN(sheet);
2397 range->rowi = MAX_VISIBLE_ROW(sheet);
2398 range->coli = MAX_VISIBLE_COLUMN(sheet);
2403 gtk_sheet_get_vadjustment (GtkSheet * sheet)
2405 g_return_val_if_fail (sheet != NULL, NULL);
2406 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2408 return sheet->vadjustment;
2412 gtk_sheet_get_hadjustment (GtkSheet * sheet)
2414 g_return_val_if_fail (sheet != NULL, NULL);
2415 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2417 return sheet->hadjustment;
2421 gtk_sheet_set_vadjustment (GtkSheet *sheet,
2422 GtkAdjustment *adjustment)
2424 GtkAdjustment *old_adjustment;
2426 g_return_if_fail (sheet != NULL);
2427 g_return_if_fail (GTK_IS_SHEET (sheet));
2429 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2431 if (sheet->vadjustment == adjustment)
2434 old_adjustment = sheet->vadjustment;
2436 if (sheet->vadjustment)
2438 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2439 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2442 sheet->vadjustment = adjustment;
2444 if (sheet->vadjustment)
2446 gtk_object_ref (GTK_OBJECT (sheet->vadjustment));
2447 gtk_object_sink (GTK_OBJECT (sheet->vadjustment));
2449 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "changed",
2450 (GtkSignalFunc) vadjustment_changed,
2452 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "value_changed",
2453 (GtkSignalFunc) vadjustment_value_changed,
2457 if (!sheet->vadjustment || !old_adjustment)
2459 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2463 sheet->old_vadjustment = sheet->vadjustment->value;
2467 gtk_sheet_set_hadjustment (GtkSheet *sheet,
2468 GtkAdjustment *adjustment)
2470 GtkAdjustment *old_adjustment;
2472 g_return_if_fail (sheet != NULL);
2473 g_return_if_fail (GTK_IS_SHEET (sheet));
2475 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2477 if (sheet->hadjustment == adjustment)
2480 old_adjustment = sheet->hadjustment;
2482 if (sheet->hadjustment)
2484 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2485 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2488 sheet->hadjustment = adjustment;
2490 if (sheet->hadjustment)
2492 gtk_object_ref (GTK_OBJECT (sheet->hadjustment));
2493 gtk_object_sink (GTK_OBJECT (sheet->hadjustment));
2495 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "changed",
2496 (GtkSignalFunc) hadjustment_changed,
2498 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "value_changed",
2499 (GtkSignalFunc) hadjustment_value_changed,
2503 if (!sheet->hadjustment || !old_adjustment)
2505 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2509 sheet->old_hadjustment = sheet->hadjustment->value;
2513 gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
2514 GtkAdjustment *hadjustment,
2515 GtkAdjustment *vadjustment)
2517 if(sheet->hadjustment != hadjustment)
2518 gtk_sheet_set_hadjustment (sheet, hadjustment);
2519 if(sheet->vadjustment != vadjustment)
2520 gtk_sheet_set_vadjustment (sheet, vadjustment);
2524 gtk_sheet_finalize (GObject * object)
2528 g_return_if_fail (object != NULL);
2529 g_return_if_fail (GTK_IS_SHEET (object));
2531 sheet = GTK_SHEET (object);
2533 /* get rid of all the cells */
2534 gtk_sheet_range_clear (sheet, NULL);
2535 gtk_sheet_range_delete(sheet, NULL);
2538 g_free(sheet->name);
2542 if (G_OBJECT_CLASS (parent_class)->finalize)
2543 (*G_OBJECT_CLASS (parent_class)->finalize) (object);
2547 gtk_sheet_destroy (GtkObject * object)
2552 g_return_if_fail (object != NULL);
2553 g_return_if_fail (GTK_IS_SHEET (object));
2555 sheet = GTK_SHEET (object);
2557 /* destroy the entry */
2558 if(sheet->sheet_entry && GTK_IS_WIDGET(sheet->sheet_entry)){
2559 gtk_widget_destroy (sheet->sheet_entry);
2560 sheet->sheet_entry = NULL;
2563 /* destroy the global selection button */
2564 if(sheet->button && GTK_IS_WIDGET(sheet->button)){
2565 gtk_widget_destroy (sheet->button);
2566 sheet->button = NULL;
2570 gtk_timeout_remove(sheet->timer);
2574 if(sheet->clip_timer){
2575 gtk_timeout_remove(sheet->clip_timer);
2576 sheet->clip_timer = 0;
2579 /* unref adjustments */
2580 if (sheet->hadjustment)
2582 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2583 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2584 sheet->hadjustment = NULL;
2586 if (sheet->vadjustment)
2588 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2589 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2590 sheet->vadjustment = NULL;
2593 children = sheet->children;
2595 GtkSheetChild *child = (GtkSheetChild *)children->data;
2596 if(child && child->widget)
2597 gtk_sheet_remove(GTK_CONTAINER(sheet), child->widget);
2598 children = sheet->children;
2600 sheet->children = NULL;
2602 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2603 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2607 gtk_sheet_style_set (GtkWidget *widget,
2608 GtkStyle *previous_style)
2612 g_return_if_fail (widget != NULL);
2613 g_return_if_fail (GTK_IS_SHEET (widget));
2615 if (GTK_WIDGET_CLASS (parent_class)->style_set)
2616 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
2618 sheet = GTK_SHEET (widget);
2620 if(GTK_WIDGET_REALIZED(widget))
2622 gtk_style_set_background (widget->style, widget->window, widget->state);
2628 gtk_sheet_realize (GtkWidget * widget)
2631 GdkWindowAttr attributes;
2632 gint attributes_mask;
2633 GdkGCValues values, auxvalues;
2634 GdkColormap *colormap;
2636 GtkSheetChild *child;
2639 g_return_if_fail (widget != NULL);
2640 g_return_if_fail (GTK_IS_SHEET (widget));
2642 sheet = GTK_SHEET (widget);
2644 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2646 attributes.window_type = GDK_WINDOW_CHILD;
2647 attributes.x = widget->allocation.x;
2648 attributes.y = widget->allocation.y;
2649 attributes.width = widget->allocation.width;
2650 attributes.height = widget->allocation.height;
2651 attributes.wclass = GDK_INPUT_OUTPUT;
2653 attributes.visual = gtk_widget_get_visual (widget);
2654 attributes.colormap = gtk_widget_get_colormap (widget);
2656 attributes.event_mask = gtk_widget_get_events (widget);
2657 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2658 GDK_BUTTON_PRESS_MASK |
2659 GDK_BUTTON_RELEASE_MASK |
2660 GDK_KEY_PRESS_MASK |
2661 GDK_POINTER_MOTION_MASK |
2662 GDK_POINTER_MOTION_HINT_MASK);
2663 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
2666 attributes.cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
2669 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2671 gdk_window_set_user_data (widget->window, sheet);
2673 widget->style = gtk_style_attach (widget->style, widget->window);
2675 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2678 if(sheet->row_titles_visible)
2679 attributes.x = sheet->row_title_area.width;
2681 attributes.width = sheet->column_title_area.width;
2682 attributes.height = sheet->column_title_area.height;
2684 /* column-title window */
2685 sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2686 gdk_window_set_user_data (sheet->column_title_window, sheet);
2687 gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL);
2691 if(sheet->column_titles_visible)
2692 attributes.y = sheet->column_title_area.height;
2693 attributes.width = sheet->row_title_area.width;
2694 attributes.height = sheet->row_title_area.height;
2696 /* row-title window */
2697 sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2698 gdk_window_set_user_data (sheet->row_title_window, sheet);
2699 gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL);
2702 attributes.cursor = gdk_cursor_new(GDK_PLUS);
2706 attributes.width = sheet->sheet_window_width,
2707 attributes.height = sheet->sheet_window_height;
2709 sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2710 gdk_window_set_user_data (sheet->sheet_window, sheet);
2712 gdk_cursor_unref(attributes.cursor);
2714 gdk_window_set_background (sheet->sheet_window, &widget->style->white);
2715 gdk_window_show (sheet->sheet_window);
2717 /* backing_pixmap */
2718 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
2722 gdk_gc_unref(sheet->fg_gc);
2724 gdk_gc_unref(sheet->bg_gc);
2725 sheet->fg_gc = gdk_gc_new (widget->window);
2726 sheet->bg_gc = gdk_gc_new (widget->window);
2728 colormap = gtk_widget_get_colormap(widget);
2730 gdk_color_white(colormap, &widget->style->white);
2731 gdk_color_black(colormap, &widget->style->black);
2733 gdk_gc_get_values(sheet->fg_gc, &auxvalues);
2735 values.foreground = widget->style->white;
2736 values.function = GDK_INVERT;
2737 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2739 gdk_gc_unref(sheet->xor_gc);
2740 sheet->xor_gc = gdk_gc_new_with_values (widget->window,
2746 if(sheet->sheet_entry->parent){
2747 gtk_widget_ref(sheet->sheet_entry);
2748 gtk_widget_unparent(sheet->sheet_entry);
2750 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
2751 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
2753 if(sheet->button && sheet->button->parent){
2754 gtk_widget_ref(sheet->button);
2755 gtk_widget_unparent(sheet->button);
2757 gtk_widget_set_parent_window(sheet->button, sheet->sheet_window);
2758 gtk_widget_set_parent(sheet->button, GTK_WIDGET(sheet));
2761 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
2763 if(!sheet->cursor_drag)
2764 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
2766 if(sheet->column_titles_visible)
2767 gdk_window_show(sheet->column_title_window);
2768 if(sheet->row_titles_visible)
2769 gdk_window_show(sheet->row_title_window);
2771 size_allocate_row_title_buttons(sheet);
2772 size_allocate_column_title_buttons(sheet);
2774 name = g_strdup(sheet->name);
2775 gtk_sheet_set_title(sheet, name);
2779 children = sheet->children;
2782 child = children->data;
2783 children = children->next;
2785 gtk_sheet_realize_child(sheet, child);
2790 create_global_button(GtkSheet *sheet)
2792 sheet->button = gtk_button_new_with_label(" ");
2794 gtk_signal_connect (GTK_OBJECT (sheet->button),
2796 (GtkSignalFunc) global_button_clicked,
2801 size_allocate_global_button(GtkSheet *sheet)
2803 GtkAllocation allocation;
2805 if(!sheet->column_titles_visible) return;
2806 if(!sheet->row_titles_visible) return;
2808 gtk_widget_size_request(sheet->button, NULL);
2812 allocation.width=sheet->row_title_area.width;
2813 allocation.height=sheet->column_title_area.height;
2815 gtk_widget_size_allocate(sheet->button, &allocation);
2816 gtk_widget_show(sheet->button);
2820 global_button_clicked(GtkWidget *widget, gpointer data)
2824 gtk_sheet_click_cell(GTK_SHEET(data), -1, -1, &veto);
2825 gtk_widget_grab_focus(GTK_WIDGET(data));
2830 gtk_sheet_unrealize (GtkWidget * widget)
2834 g_return_if_fail (widget != NULL);
2835 g_return_if_fail (GTK_IS_SHEET (widget));
2837 sheet = GTK_SHEET (widget);
2839 gdk_cursor_destroy (sheet->cursor_drag);
2841 gdk_gc_destroy (sheet->xor_gc);
2842 gdk_gc_destroy (sheet->fg_gc);
2843 gdk_gc_destroy (sheet->bg_gc);
2845 gdk_window_destroy (sheet->sheet_window);
2846 gdk_window_destroy (sheet->column_title_window);
2847 gdk_window_destroy (sheet->row_title_window);
2850 g_object_unref(sheet->pixmap);
2851 sheet->pixmap = NULL;
2854 sheet->column_title_window=NULL;
2855 sheet->sheet_window = NULL;
2856 sheet->cursor_drag = NULL;
2857 sheet->xor_gc = NULL;
2858 sheet->fg_gc = NULL;
2859 sheet->bg_gc = NULL;
2861 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2862 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2866 gtk_sheet_map (GtkWidget * widget)
2869 GtkSheetChild *child;
2872 g_return_if_fail (widget != NULL);
2873 g_return_if_fail (GTK_IS_SHEET (widget));
2875 sheet = GTK_SHEET (widget);
2877 if (!GTK_WIDGET_MAPPED (widget))
2879 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2881 if(!sheet->cursor_drag) sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
2883 gdk_window_show (widget->window);
2885 gdk_window_show (sheet->sheet_window);
2887 if(sheet->column_titles_visible){
2888 size_allocate_column_title_buttons(sheet);
2889 gdk_window_show (sheet->column_title_window);
2891 if(sheet->row_titles_visible){
2892 size_allocate_row_title_buttons(sheet);
2893 gdk_window_show (sheet->row_title_window);
2896 if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)
2897 && ! gtk_sheet_locked(sheet)
2898 && sheet->active_cell.row >=0
2899 && sheet->active_cell.col >=0 )
2901 gtk_widget_show (sheet->sheet_entry);
2902 gtk_widget_map (sheet->sheet_entry);
2905 if (GTK_WIDGET_VISIBLE (sheet->button) &&
2906 !GTK_WIDGET_MAPPED (sheet->button)){
2907 gtk_widget_show(sheet->button);
2908 gtk_widget_map (sheet->button);
2911 if(GTK_BIN(sheet->button)->child)
2912 if (GTK_WIDGET_VISIBLE (GTK_BIN(sheet->button)->child) &&
2913 !GTK_WIDGET_MAPPED (GTK_BIN(sheet->button)->child))
2914 gtk_widget_map (GTK_BIN(sheet->button)->child);
2916 gtk_sheet_range_draw(sheet, NULL);
2917 gtk_sheet_activate_cell(sheet,
2918 sheet->active_cell.row,
2919 sheet->active_cell.col);
2921 children = sheet->children;
2924 child = children->data;
2925 children = children->next;
2927 if (GTK_WIDGET_VISIBLE (child->widget) &&
2928 !GTK_WIDGET_MAPPED (child->widget)){
2929 gtk_widget_map (child->widget);
2930 gtk_sheet_position_child(sheet, child);
2938 gtk_sheet_unmap (GtkWidget * widget)
2941 GtkSheetChild *child;
2944 g_return_if_fail (widget != NULL);
2945 g_return_if_fail (GTK_IS_SHEET (widget));
2947 sheet = GTK_SHEET (widget);
2949 if (GTK_WIDGET_MAPPED (widget))
2951 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2953 gdk_window_hide (sheet->sheet_window);
2954 if(sheet->column_titles_visible)
2955 gdk_window_hide (sheet->column_title_window);
2956 if(sheet->row_titles_visible)
2957 gdk_window_hide (sheet->row_title_window);
2958 gdk_window_hide (widget->window);
2960 if (GTK_WIDGET_MAPPED (sheet->sheet_entry))
2961 gtk_widget_unmap (sheet->sheet_entry);
2963 if (GTK_WIDGET_MAPPED (sheet->button))
2964 gtk_widget_unmap (sheet->button);
2966 children = sheet->children;
2969 child = children->data;
2970 children = children->next;
2972 if (GTK_WIDGET_VISIBLE (child->widget) &&
2973 GTK_WIDGET_MAPPED (child->widget))
2975 gtk_widget_unmap (child->widget);
2984 gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
2987 GdkGC *fg_gc, *bg_gc;
2988 GtkSheetCellAttr attributes;
2991 g_return_if_fail (sheet != NULL);
2993 /* bail now if we arn't drawable yet */
2994 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
2996 if (row < 0 || row >= yyy_row_count(sheet)) return;
2997 if (col < 0 || col >= xxx_column_count(sheet)) return;
2998 if (! xxx_column_is_visible(sheet, col)) return;
2999 if (! yyy_row_is_visible(sheet, row)) return;
3001 widget = GTK_WIDGET (sheet);
3003 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3005 /* select GC for background rectangle */
3006 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3007 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3009 fg_gc = sheet->fg_gc;
3010 bg_gc = sheet->bg_gc;
3012 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3013 area.y=ROW_TOP_YPIXEL(sheet,row);
3014 area.width= xxx_column_width(sheet, col);
3015 area.height=yyy_row_height(sheet, row);
3017 gdk_draw_rectangle (sheet->pixmap,
3025 gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0);
3027 if(sheet->show_grid){
3028 gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color);
3030 gdk_draw_rectangle (sheet->pixmap,
3034 area.width, area.height);
3039 gtk_sheet_cell_draw_border (GtkSheet *sheet, gint row, gint col, gint mask)
3042 GdkGC *fg_gc, *bg_gc;
3043 GtkSheetCellAttr attributes;
3047 g_return_if_fail (sheet != NULL);
3049 /* bail now if we arn't drawable yet */
3050 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
3052 if (row < 0 || row >= yyy_row_count(sheet)) return;
3053 if (col < 0 || col >= xxx_column_count(sheet)) return;
3054 if (!xxx_column_is_visible(sheet, col)) return;
3055 if (!yyy_row_is_visible(sheet, row)) return;
3057 widget = GTK_WIDGET (sheet);
3059 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3061 /* select GC for background rectangle */
3062 gdk_gc_set_foreground (sheet->fg_gc, &attributes.border.color);
3063 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3065 fg_gc = sheet->fg_gc;
3066 bg_gc = sheet->bg_gc;
3068 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3069 area.y=ROW_TOP_YPIXEL(sheet,row);
3070 area.width=xxx_column_width(sheet, col);
3071 area.height=yyy_row_height(sheet, row);
3073 width = attributes.border.width;
3074 gdk_gc_set_line_attributes(sheet->fg_gc, attributes.border.width,
3075 attributes.border.line_style,
3076 attributes.border.cap_style,
3077 attributes.border.join_style);
3080 if(attributes.border.mask & GTK_SHEET_LEFT_BORDER & mask)
3081 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3082 area.x, area.y-width/2,
3083 area.x, area.y+area.height+width/2+1);
3085 if(attributes.border.mask & GTK_SHEET_RIGHT_BORDER & mask)
3086 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3087 area.x+area.width, area.y-width/2,
3089 area.y+area.height+width/2+1);
3091 if(attributes.border.mask & GTK_SHEET_TOP_BORDER & mask)
3092 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3093 area.x-width/2,area.y,
3094 area.x+area.width+width/2+1,
3097 if(attributes.border.mask & GTK_SHEET_BOTTOM_BORDER & mask)
3098 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3099 area.x-width/2, area.y+area.height,
3100 area.x+area.width+width/2+1,
3101 area.y+area.height);
3108 gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
3111 GdkRectangle area, clip_area;
3113 gint text_width, text_height, y;
3115 gint size, sizel, sizer;
3116 GdkGC *fg_gc, *bg_gc;
3117 GtkSheetCellAttr attributes;
3118 PangoLayout *layout;
3119 PangoRectangle rect;
3120 PangoRectangle logical_rect;
3121 PangoLayoutLine *line;
3122 PangoFontMetrics *metrics;
3123 PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet));
3124 gint ascent, descent, y_pos;
3128 g_return_if_fail (sheet != NULL);
3130 /* bail now if we aren't drawable yet */
3131 if (!GTK_WIDGET_DRAWABLE (sheet))
3134 label = gtk_sheet_cell_get_text(sheet, row, col);
3138 if (row < 0 || row >= yyy_row_count(sheet)) return;
3139 if (col < 0 || col >= xxx_column_count(sheet)) return;
3140 if (! xxx_column_is_visible(sheet, col)) return;
3141 if (!yyy_row_is_visible(sheet, row)) return;
3144 widget = GTK_WIDGET(sheet);
3146 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3148 /* select GC for background rectangle */
3149 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3150 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3152 fg_gc = sheet->fg_gc;
3153 bg_gc = sheet->bg_gc;
3155 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3156 area.y=ROW_TOP_YPIXEL(sheet,row);
3157 area.width = xxx_column_width(sheet, col);
3158 area.height = yyy_row_height(sheet, row);
3162 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label);
3163 dispose_string(sheet, label);
3164 pango_layout_set_font_description (layout, attributes.font_desc);
3166 pango_layout_get_pixel_extents (layout, NULL, &rect);
3168 line = pango_layout_get_lines (layout)->data;
3169 pango_layout_line_get_extents (line, NULL, &logical_rect);
3171 metrics = pango_context_get_metrics(context,
3172 attributes.font_desc,
3173 pango_context_get_language(context));
3175 ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
3176 descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
3178 pango_font_metrics_unref(metrics);
3180 /* Align primarily for locale's ascent/descent */
3182 logical_rect.height /= PANGO_SCALE;
3183 logical_rect.y /= PANGO_SCALE;
3184 y_pos = area.height - logical_rect.height;
3186 if (logical_rect.height > area.height)
3187 y_pos = (logical_rect.height - area.height - 2*CELLOFFSET) / 2;
3190 else if (y_pos + logical_rect.height > area.height)
3191 y_pos = area.height - logical_rect.height;
3193 text_width = rect.width;
3194 text_height = rect.height;
3195 y = area.y + y_pos - CELLOFFSET;
3197 switch(attributes.justification){
3198 case GTK_JUSTIFY_RIGHT:
3201 if(!gtk_sheet_clip_text(sheet)){
3202 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3203 if( !gtk_sheet_cell_empty(sheet, row, i)) break;
3204 if(size>=text_width+CELLOFFSET) break;
3205 size+=xxx_column_width(sheet, i);
3206 xxx_column_set_right_column(sheet, i,
3208 xxx_column_right_column(sheet, i)));
3213 xoffset+=area.width-text_width - 2 * CELLOFFSET -
3214 attributes.border.width/2;
3216 case GTK_JUSTIFY_CENTER:
3219 area.x+=area.width/2;
3220 if(!gtk_sheet_clip_text(sheet)){
3221 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3222 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3223 if(sizer>=text_width/2) break;
3224 sizer+= xxx_column_width(sheet, i);
3225 xxx_column_set_left_column(sheet, i,
3228 xxx_column_left_column(sheet, i)));
3230 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3231 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3232 if(sizel>=text_width/2) break;
3233 sizel+=xxx_column_width(sheet, i);
3234 xxx_column_set_right_column(sheet, i,
3236 xxx_column_right_column(sheet, i)));
3238 size=MIN(sizel, sizer);
3241 xoffset+= sizel - text_width/2 - CELLOFFSET;
3242 area.width=sizel+sizer;
3244 case GTK_JUSTIFY_LEFT:
3247 if(!gtk_sheet_clip_text(sheet)){
3248 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3249 if(! gtk_sheet_cell_empty(sheet, row, i)) break;
3250 if(size>=text_width+CELLOFFSET) break;
3251 size+=xxx_column_width(sheet, i);
3252 xxx_column_set_left_column(sheet, i,
3255 xxx_column_left_column(sheet, i)));
3260 xoffset += attributes.border.width/2;
3264 if(!gtk_sheet_clip_text(sheet)) clip_area = area;
3265 gdk_gc_set_clip_rectangle(fg_gc, &clip_area);
3268 gdk_draw_layout (sheet->pixmap, fg_gc,
3269 area.x + xoffset + CELLOFFSET,
3273 gdk_gc_set_clip_rectangle(fg_gc, NULL);
3274 g_object_unref(G_OBJECT(layout));
3276 gdk_draw_pixmap(sheet->sheet_window,
3277 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3291 gtk_sheet_range_draw(GtkSheet *sheet, const GtkSheetRange *range)
3294 GtkSheetRange drawing_range;
3297 g_return_if_fail(sheet != NULL);
3298 g_return_if_fail(GTK_SHEET(sheet));
3300 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
3301 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3302 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
3306 drawing_range.row0=MIN_VISIBLE_ROW(sheet);
3307 drawing_range.col0=MIN_VISIBLE_COLUMN(sheet);
3308 drawing_range.rowi=MAX_VISIBLE_ROW(sheet);
3309 drawing_range.coli=MAX_VISIBLE_COLUMN(sheet);
3311 gdk_draw_rectangle (sheet->pixmap,
3312 GTK_WIDGET(sheet)->style->white_gc,
3315 sheet->sheet_window_width,sheet->sheet_window_height);
3320 drawing_range.row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
3321 drawing_range.col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
3322 drawing_range.rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
3323 drawing_range.coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
3327 if(drawing_range.coli == xxx_column_count(sheet) - 1)
3329 area.x=COLUMN_LEFT_XPIXEL(sheet,
3330 xxx_column_count(sheet) - 1) +
3331 xxx_column_width(sheet, xxx_column_count(sheet) - 1) + 1;
3335 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3337 gdk_draw_rectangle (sheet->pixmap,
3341 sheet->sheet_window_width - area.x,
3342 sheet->sheet_window_height);
3344 gdk_draw_pixmap(sheet->sheet_window,
3345 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3351 sheet->sheet_window_width - area.x,
3352 sheet->sheet_window_height);
3355 if(drawing_range.rowi == yyy_row_count(sheet) - 1){
3357 area.y=ROW_TOP_YPIXEL(sheet,
3358 yyy_row_count(sheet) - 1) +
3359 yyy_row_height(sheet, yyy_row_count(sheet) - 1) + 1;
3361 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3363 gdk_draw_rectangle (sheet->pixmap,
3367 sheet->sheet_window_width,
3368 sheet->sheet_window_height - area.y);
3370 gdk_draw_pixmap(sheet->sheet_window,
3371 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3377 sheet->sheet_window_width,
3378 sheet->sheet_window_height - area.y);
3381 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3382 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3383 gtk_sheet_cell_draw_default(sheet, i, j);
3386 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3387 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3388 gtk_sheet_cell_draw_border(sheet, i-1, j, GTK_SHEET_BOTTOM_BORDER);
3389 gtk_sheet_cell_draw_border(sheet, i+1, j, GTK_SHEET_TOP_BORDER);
3390 gtk_sheet_cell_draw_border(sheet, i, j-1, GTK_SHEET_RIGHT_BORDER);
3391 gtk_sheet_cell_draw_border(sheet, i, j+1, GTK_SHEET_LEFT_BORDER);
3392 gtk_sheet_cell_draw_border(sheet, i, j, 15);
3395 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3396 for(j=drawing_range.col0; j<=drawing_range.coli; j++)
3397 gtk_sheet_cell_draw_label (sheet, i, j);
3399 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3400 for(j= xxx_column_left_column(sheet, drawing_range.col0);
3401 j<drawing_range.col0; j++)
3402 gtk_sheet_cell_draw_label (sheet, i, j);
3404 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3405 for(j = drawing_range.coli+1;
3406 j <= xxx_column_right_column(sheet, drawing_range.coli);
3408 gtk_sheet_cell_draw_label (sheet, i, j);
3410 gtk_sheet_draw_backing_pixmap(sheet, drawing_range);
3412 if(sheet->state != GTK_SHEET_NORMAL && gtk_sheet_range_isvisible(sheet, sheet->range))
3413 gtk_sheet_range_draw_selection(sheet, drawing_range);
3415 if(sheet->state == GTK_STATE_NORMAL &&
3416 sheet->active_cell.row >= drawing_range.row0 &&
3417 sheet->active_cell.row <= drawing_range.rowi &&
3418 sheet->active_cell.col >= drawing_range.col0 &&
3419 sheet->active_cell.col <= drawing_range.coli)
3420 gtk_sheet_show_active_cell(sheet);
3425 gtk_sheet_range_draw_selection(GtkSheet *sheet, GtkSheetRange range)
3431 if(range.col0 > sheet->range.coli || range.coli < sheet->range.col0 ||
3432 range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0)
3435 if(!gtk_sheet_range_isvisible(sheet, range)) return;
3436 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3440 range.col0=MAX(sheet->range.col0, range.col0);
3441 range.coli=MIN(sheet->range.coli, range.coli);
3442 range.row0=MAX(sheet->range.row0, range.row0);
3443 range.rowi=MIN(sheet->range.rowi, range.rowi);
3445 range.col0=MAX(range.col0, MIN_VISIBLE_COLUMN(sheet));
3446 range.coli=MIN(range.coli, MAX_VISIBLE_COLUMN(sheet));
3447 range.row0=MAX(range.row0, MIN_VISIBLE_ROW(sheet));
3448 range.rowi=MIN(range.rowi, MAX_VISIBLE_ROW(sheet));
3450 for(i=range.row0; i<=range.rowi; i++){
3451 for(j=range.col0; j<=range.coli; j++){
3453 if(gtk_sheet_cell_get_state(sheet, i, j)==GTK_STATE_SELECTED &&
3454 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
3457 row_button_set(sheet, i);
3458 column_button_set(sheet, j);
3461 area.x=COLUMN_LEFT_XPIXEL(sheet,j);
3462 area.y=ROW_TOP_YPIXEL(sheet,i);
3463 area.width= xxx_column_width(sheet, j);
3464 area.height=yyy_row_height(sheet, i);
3466 if(i==sheet->range.row0){
3468 area.height=area.height-2;
3470 if(i==sheet->range.rowi) area.height=area.height-3;
3471 if(j==sheet->range.col0){
3473 area.width=area.width-2;
3475 if(j==sheet->range.coli) area.width=area.width-3;
3477 if(i!=sheet->active_cell.row || j!=sheet->active_cell.col){
3478 gdk_draw_rectangle (sheet->sheet_window,
3482 area.width,area.height);
3489 gtk_sheet_draw_border(sheet, sheet->range);
3494 gtk_sheet_draw_backing_pixmap(GtkSheet *sheet, GtkSheetRange range)
3496 gint x,y,width,height;
3498 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3500 x = COLUMN_LEFT_XPIXEL(sheet,range.col0);
3501 y = ROW_TOP_YPIXEL(sheet, range.row0);
3502 width = COLUMN_LEFT_XPIXEL(sheet, range.coli) - x +
3503 xxx_column_width(sheet, range.coli);
3505 height=ROW_TOP_YPIXEL(sheet, range.rowi)-y+yyy_row_height(sheet, range.rowi);
3507 if(range.row0==sheet->range.row0){
3511 if(range.rowi==sheet->range.rowi) height=height+5;
3512 if(range.col0==sheet->range.col0){
3516 if(range.coli==sheet->range.coli) width=width+5;
3519 width=MIN(width, sheet->sheet_window_width-x);
3520 height=MIN(height, sheet->sheet_window_height-y);
3527 x = (sheet->row_titles_visible)
3528 ? MAX(x, sheet->row_title_area.width) : MAX(x, 0);
3529 y = (sheet->column_titles_visible)
3530 ? MAX(y, sheet->column_title_area.height) : MAX(y, 0);
3532 if(range.coli == xxx_column_count(sheet) - 1)
3533 width = sheet->sheet_window_width - x;
3534 if(range.rowi == yyy_row_count(sheet) - 1)
3535 height=sheet->sheet_window_height - y;
3537 gdk_draw_pixmap(sheet->sheet_window,
3538 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3550 gtk_sheet_set_cell_text(GtkSheet *sheet, gint row, gint col, const gchar *text)
3552 GtkSheetCellAttr attributes;
3554 g_return_if_fail (sheet != NULL);
3555 g_return_if_fail (GTK_IS_SHEET (sheet));
3556 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3557 if (col < 0 || row < 0) return;
3559 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3560 gtk_sheet_set_cell(sheet, row, col, attributes.justification, text);
3564 safe_strcmp(const gchar *s1, const gchar *s2)
3566 if ( !s1 && !s2) return 0;
3567 if ( !s1) return -1;
3568 if ( !s2) return +1;
3569 return strcmp(s1, s2);
3573 gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col,
3574 GtkJustification justification,
3577 GSheetModel *model ;
3581 GtkSheetRange range;
3583 GtkSheetCellAttr attributes;
3585 g_return_if_fail (sheet != NULL);
3586 g_return_if_fail (GTK_IS_SHEET (sheet));
3587 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3588 if (col < 0 || row < 0) return;
3590 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3592 attributes.justification = justification;
3594 model = gtk_sheet_get_model(sheet);
3596 old_text = g_sheet_model_get_string(model, row, col);
3600 if (0 != safe_strcmp(old_text, text))
3601 changed = g_sheet_model_set_string(model, text, row, col);
3603 if ( g_sheet_model_free_strings(model))
3607 if(changed && attributes.is_visible)
3609 gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
3611 if(s && strlen(s) > 0) {
3612 text_width = STRING_WIDTH(GTK_WIDGET(sheet),
3613 attributes.font_desc, text);
3615 dispose_string(sheet, s);
3619 range.col0 = sheet->view.col0;
3620 range.coli = sheet->view.coli;
3622 if(gtk_sheet_autoresize(sheet) &&
3623 text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
3624 gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width);
3625 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3628 if(!GTK_SHEET_IS_FROZEN(sheet))
3629 gtk_sheet_range_draw(sheet, &range);
3633 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
3639 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
3641 GtkSheetRange range;
3643 g_return_if_fail (sheet != NULL);
3644 g_return_if_fail (GTK_IS_SHEET (sheet));
3645 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3646 if (column < 0 || row < 0) return;
3650 range.col0 = sheet->view.col0;
3651 range.coli = sheet->view.coli;
3653 gtk_sheet_real_cell_clear(sheet, row, column, FALSE);
3655 if(!GTK_SHEET_IS_FROZEN(sheet)){
3656 gtk_sheet_range_draw(sheet, &range);
3661 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
3663 GtkSheetRange range;
3665 g_return_if_fail (sheet != NULL);
3666 g_return_if_fail (GTK_IS_SHEET (sheet));
3667 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3668 if (column < 0 || row < 0) return;
3672 range.col0 = sheet->view.col0;
3673 range.coli = sheet->view.coli;
3675 gtk_sheet_real_cell_clear(sheet, row, column, TRUE);
3677 if(!GTK_SHEET_IS_FROZEN(sheet)){
3678 gtk_sheet_range_draw(sheet, &range);
3683 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
3685 GSheetModel *model = gtk_sheet_get_model(sheet);
3687 gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column);
3689 if (old_text && strlen(old_text) > 0 )
3691 g_sheet_model_datum_clear(model, row, column);
3693 if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0)
3694 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL],
3698 dispose_string (sheet, old_text);
3702 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
3704 g_return_if_fail (sheet != NULL);
3705 g_return_if_fail (GTK_IS_SHEET (sheet));
3707 gtk_sheet_real_range_clear(sheet, range, FALSE);
3711 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range)
3713 g_return_if_fail (sheet != NULL);
3714 g_return_if_fail (GTK_IS_SHEET (sheet));
3716 gtk_sheet_real_range_clear(sheet, range, TRUE);
3721 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
3725 GtkSheetRange clear;
3729 clear.rowi = yyy_row_count(sheet) - 1;
3731 clear.coli = xxx_column_count(sheet) - 1;
3735 clear.row0=MAX(clear.row0, 0);
3736 clear.col0=MAX(clear.col0, 0);
3737 clear.rowi=MIN(clear.rowi, yyy_row_count(sheet) - 1 );
3738 clear.coli=MIN(clear.coli, xxx_column_count(sheet) - 1 );
3740 for(i=clear.row0; i<=clear.rowi; i++)
3741 for(j=clear.col0; j<=clear.coli; j++){
3742 gtk_sheet_real_cell_clear(sheet, i, j, delete);
3745 gtk_sheet_range_draw(sheet, NULL);
3750 gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col)
3753 char *text = gtk_sheet_cell_get_text(sheet, row, col);
3754 empty = (text == NULL );
3756 dispose_string(sheet, text);
3763 gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
3766 g_return_val_if_fail (sheet != NULL, NULL);
3767 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
3769 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet))
3771 if(col < 0 || row < 0) return NULL;
3773 model = gtk_sheet_get_model(sheet);
3778 return g_sheet_model_get_string(model, row, col);
3783 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
3786 GtkSheetRange *range;
3788 g_return_val_if_fail (sheet != NULL, 0);
3789 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3790 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return 0;
3791 if(col < 0 || row < 0) return 0;
3793 state = sheet->state;
3794 range = &sheet->range;
3798 case GTK_SHEET_NORMAL:
3799 return GTK_STATE_NORMAL;
3801 case GTK_SHEET_ROW_SELECTED:
3802 if(row>=range->row0 && row<=range->rowi)
3803 return GTK_STATE_SELECTED;
3805 case GTK_SHEET_COLUMN_SELECTED:
3806 if(col>=range->col0 && col<=range->coli)
3807 return GTK_STATE_SELECTED;
3809 case GTK_SHEET_RANGE_SELECTED:
3810 if(row >= range->row0 && row <= range->rowi && \
3811 col >= range->col0 && col <= range->coli)
3812 return GTK_STATE_SELECTED;
3815 return GTK_STATE_NORMAL;
3819 gtk_sheet_get_pixel_info (GtkSheet * sheet,
3827 g_return_val_if_fail (sheet != NULL, 0);
3828 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3830 /* bounds checking, return false if the user clicked
3831 * on a blank area */
3832 trow = ROW_FROM_YPIXEL (sheet, y);
3833 if (trow >= yyy_row_count(sheet))
3838 tcol = COLUMN_FROM_XPIXEL (sheet, x);
3839 if (tcol >= xxx_column_count(sheet))
3848 gtk_sheet_get_cell_area (GtkSheet * sheet,
3853 g_return_val_if_fail (sheet != NULL, 0);
3854 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3856 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3859 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) -
3860 (sheet->row_titles_visible
3861 ? sheet->row_title_area.width
3863 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL(sheet, row) -
3864 (sheet->column_titles_visible
3865 ? sheet->column_title_area.height
3867 area->width= (column == -1) ? sheet->row_title_area.width
3868 : xxx_column_width(sheet, column);
3870 area->height= (row == -1) ? sheet->column_title_area.height
3871 : yyy_row_height(sheet, row);
3874 if(row < 0 || column < 0) return FALSE;
3876 area->x = COLUMN_LEFT_XPIXEL(sheet, column);
3877 area->y = ROW_TOP_YPIXEL(sheet, row);
3878 if(sheet->row_titles_visible)
3879 area->x -= sheet->row_title_area.width;
3880 if(sheet->column_titles_visible)
3881 area->y -= sheet->column_title_area.height;
3883 area->width=sheet->column[column].width;
3884 area->height=yyy_row_height(sheet, row);
3890 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
3892 g_return_val_if_fail (sheet != NULL, 0);
3893 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3895 if(row < -1 || column < -1) return FALSE;
3896 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3899 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
3901 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
3904 sheet->active_cell.row = row;
3905 sheet->active_cell.col = column;
3907 if ( row == -1 || column == -1)
3909 gtk_sheet_hide_active_cell(sheet);
3913 if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE;
3915 if(gtk_sheet_autoscroll(sheet))
3916 gtk_sheet_move_query(sheet, row, column);
3922 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column)
3924 g_return_if_fail (sheet != NULL);
3925 g_return_if_fail (GTK_IS_SHEET (sheet));
3927 *row = sheet->active_cell.row;
3928 *column = sheet->active_cell.col;
3932 gtk_sheet_entry_changed(GtkWidget *widget, gpointer data)
3937 GtkJustification justification;
3938 GtkSheetCellAttr attributes;
3940 g_return_if_fail (data != NULL);
3941 g_return_if_fail (GTK_IS_SHEET (data));
3943 sheet=GTK_SHEET(data);
3945 if(!GTK_WIDGET_VISIBLE(widget)) return;
3946 if(sheet->state != GTK_STATE_NORMAL) return;
3948 row=sheet->active_cell.row;
3949 col=sheet->active_cell.col;
3951 if(row<0 || col<0) return;
3953 sheet->active_cell.row=-1;
3954 sheet->active_cell.col=-1;
3956 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3958 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3960 if(text && strlen(text) > 0){
3961 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3962 justification=attributes.justification;
3963 gtk_sheet_set_cell(sheet, row, col, justification, text);
3966 if(sheet->freeze_count == 0)
3967 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3969 sheet->active_cell.row=row;;
3970 sheet->active_cell.col=col;
3975 gtk_sheet_deactivate_cell(GtkSheet *sheet)
3977 gboolean veto = TRUE;
3979 g_return_val_if_fail (sheet != NULL, FALSE);
3980 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
3982 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return FALSE;
3983 if(sheet->state != GTK_SHEET_NORMAL) return FALSE;
3985 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[DEACTIVATE],
3986 sheet->active_cell.row,
3987 sheet->active_cell.col, &veto);
3989 if(!veto) return FALSE;
3991 if ( sheet->active_cell.row == -1 || sheet->active_cell.col == -1 )
3994 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
3995 (GtkSignalFunc) gtk_sheet_entry_changed,
3996 GTK_OBJECT(GTK_WIDGET(sheet)));
3998 gtk_sheet_hide_active_cell(sheet);
3999 sheet->active_cell.row = -1;
4000 sheet->active_cell.col = -1;
4002 if(GTK_SHEET_REDRAW_PENDING(sheet)){
4003 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
4004 gtk_sheet_range_draw(sheet, NULL);
4011 gtk_sheet_hide_active_cell(GtkSheet *sheet)
4015 GtkJustification justification;
4016 GtkSheetCellAttr attributes;
4018 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4020 row=sheet->active_cell.row;
4021 col=sheet->active_cell.col;
4023 if(row < 0 || col < 0) return;
4025 if(sheet->freeze_count == 0)
4026 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
4028 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
4030 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4031 justification=attributes.justification;
4033 if(text && strlen(text)!=0){
4034 gtk_sheet_set_cell(sheet, row, col, justification, text);
4035 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col);
4036 gtk_entry_set_text(GTK_ENTRY(sheet->sheet_entry), "");
4040 gtk_sheet_cell_clear(sheet, row, col);
4043 row=sheet->active_cell.row;
4044 col=sheet->active_cell.col;
4047 column_button_release(sheet, col);
4048 row_button_release(sheet, row);
4051 gtk_widget_hide(sheet->sheet_entry);
4052 gtk_widget_unmap(sheet->sheet_entry);
4054 if(row != -1 && col != -1)
4055 gdk_draw_pixmap(sheet->sheet_window,
4056 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4058 COLUMN_LEFT_XPIXEL(sheet,col)-1,
4059 ROW_TOP_YPIXEL(sheet,row)-1,
4060 COLUMN_LEFT_XPIXEL(sheet,col)-1,
4061 ROW_TOP_YPIXEL(sheet,row)-1,
4062 xxx_column_width(sheet, col) + 4,
4063 yyy_row_height(sheet, row)+4);
4065 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4067 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4072 gtk_sheet_activate_cell(GtkSheet *sheet, gint row, gint col)
4074 gboolean veto = TRUE;
4076 g_return_val_if_fail (sheet != NULL, FALSE);
4077 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
4079 if(row < 0 || col < 0) return FALSE;
4080 if(row >= yyy_row_count(sheet) || col >= xxx_column_count(sheet))
4083 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4084 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
4087 if(!veto) return FALSE;
4088 if(sheet->state != GTK_SHEET_NORMAL){
4089 sheet->state=GTK_SHEET_NORMAL;
4090 gtk_sheet_real_unselect_range(sheet, NULL);
4093 sheet->range.row0=row;
4094 sheet->range.col0=col;
4095 sheet->range.rowi=row;
4096 sheet->range.coli=col;
4097 sheet->active_cell.row=row;
4098 sheet->active_cell.col=col;
4099 sheet->selection_cell.row=row;
4100 sheet->selection_cell.col=col;
4102 row_button_set(sheet, row);
4103 column_button_set(sheet, col);
4106 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4107 gtk_sheet_show_active_cell(sheet);
4109 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
4111 G_CALLBACK(gtk_sheet_entry_changed),
4114 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4120 gtk_sheet_show_active_cell(GtkSheet *sheet)
4122 GtkEntry *sheet_entry;
4123 GtkSheetCellAttr attributes;
4125 const gchar *old_text;
4126 GtkJustification justification;
4129 g_return_if_fail (sheet != NULL);
4130 g_return_if_fail (GTK_IS_SHEET (sheet));
4132 row = sheet->active_cell.row;
4133 col = sheet->active_cell.col;
4135 /* Don't show the active cell, if there is no active cell: */
4136 if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */
4139 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4140 if(sheet->state != GTK_SHEET_NORMAL) return;
4141 if(GTK_SHEET_IN_SELECTION(sheet)) return;
4143 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4145 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
4147 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4149 justification = GTK_JUSTIFY_LEFT;
4151 if(gtk_sheet_justify_entry(sheet))
4152 justification = attributes.justification;
4154 text = gtk_sheet_cell_get_text(sheet, row, col);
4156 text = g_strdup("");
4158 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible);
4160 if(gtk_sheet_locked(sheet) || !attributes.is_editable)
4161 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
4163 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
4165 /*** Added by John Gotts. Mar 25, 2005 *********/
4166 old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
4167 if (strcmp(old_text, text) != 0)
4169 if(!GTK_IS_ITEM_ENTRY(sheet_entry))
4170 gtk_entry_set_text(GTK_ENTRY(sheet_entry), text);
4172 gtk_item_entry_set_text(GTK_ITEM_ENTRY(sheet_entry), text, justification);
4175 gtk_sheet_entry_set_max_size(sheet);
4176 gtk_sheet_size_allocate_entry(sheet);
4178 gtk_widget_map(sheet->sheet_entry);
4179 gtk_sheet_draw_active_cell(sheet);
4181 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
4183 dispose_string(sheet, text);
4187 gtk_sheet_draw_active_cell(GtkSheet *sheet)
4191 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
4192 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4194 row = sheet->active_cell.row;
4195 col = sheet->active_cell.col;
4197 if(row < 0 || col < 0) return;
4199 if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
4201 row_button_set(sheet, row);
4202 column_button_set(sheet, col);
4204 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4205 gtk_sheet_draw_border(sheet, sheet->range);
4210 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
4212 gint pixmap_width, pixmap_height;
4214 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4216 if(width == 0 && height == 0){
4217 width=sheet->sheet_window_width+80;
4218 height=sheet->sheet_window_height+80;
4224 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4227 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4231 /* reallocate if sizes don't match */
4232 gdk_window_get_size (sheet->pixmap,
4233 &pixmap_width, &pixmap_height);
4234 if ((pixmap_width != width) || (pixmap_height != height))
4236 g_object_unref(sheet->pixmap);
4237 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4240 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4246 gtk_sheet_new_selection(GtkSheet *sheet, GtkSheetRange *range)
4248 gint i,j, mask1, mask2;
4249 gint state, selected;
4250 gint x,y,width,height;
4251 GtkSheetRange new_range, aux_range;
4253 g_return_if_fail (sheet != NULL);
4255 if(range==NULL) range=&sheet->range;
4259 range->row0=MIN(range->row0, sheet->range.row0);
4260 range->rowi=MAX(range->rowi, sheet->range.rowi);
4261 range->col0=MIN(range->col0, sheet->range.col0);
4262 range->coli=MAX(range->coli, sheet->range.coli);
4264 range->row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
4265 range->rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
4266 range->col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
4267 range->coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
4269 aux_range.row0=MAX(new_range.row0, MIN_VISIBLE_ROW(sheet));
4270 aux_range.rowi=MIN(new_range.rowi, MAX_VISIBLE_ROW(sheet));
4271 aux_range.col0=MAX(new_range.col0, MIN_VISIBLE_COLUMN(sheet));
4272 aux_range.coli=MIN(new_range.coli, MAX_VISIBLE_COLUMN(sheet));
4274 for(i=range->row0; i<=range->rowi; i++){
4275 for(j=range->col0; j<=range->coli; j++){
4277 state=gtk_sheet_cell_get_state(sheet, i, j);
4278 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4279 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4281 if(state==GTK_STATE_SELECTED && selected &&
4282 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4283 (i==sheet->range.row0 || i==sheet->range.rowi ||
4284 j==sheet->range.col0 || j==sheet->range.coli ||
4285 i==new_range.row0 || i==new_range.rowi ||
4286 j==new_range.col0 || j==new_range.coli)){
4288 mask1 = i==sheet->range.row0 ? 1 : 0;
4289 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4290 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4291 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4293 mask2 = i==new_range.row0 ? 1 : 0;
4294 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4295 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4296 mask2 = j==new_range.coli ? mask2+8 : mask2;
4299 x=COLUMN_LEFT_XPIXEL(sheet,j);
4300 y=ROW_TOP_YPIXEL(sheet, i);
4301 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4302 xxx_column_width(sheet, j);
4303 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4305 if(i==sheet->range.row0){
4309 if(i==sheet->range.rowi) height=height+3;
4310 if(j==sheet->range.col0){
4314 if(j==sheet->range.coli) width=width+3;
4316 gdk_draw_pixmap(sheet->sheet_window,
4317 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4326 if(i != sheet->active_cell.row || j != sheet->active_cell.col){
4327 x=COLUMN_LEFT_XPIXEL(sheet,j);
4328 y=ROW_TOP_YPIXEL(sheet, i);
4329 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4330 xxx_column_width(sheet, j);
4332 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4334 if(i==new_range.row0){
4338 if(i==new_range.rowi) height=height-3;
4339 if(j==new_range.col0){
4343 if(j==new_range.coli) width=width-3;
4345 gdk_draw_rectangle (sheet->sheet_window,
4356 for(i=range->row0; i<=range->rowi; i++){
4357 for(j=range->col0; j<=range->coli; j++){
4359 state=gtk_sheet_cell_get_state(sheet, i, j);
4360 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4361 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4363 if(state==GTK_STATE_SELECTED && !selected &&
4364 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4366 x=COLUMN_LEFT_XPIXEL(sheet,j);
4367 y=ROW_TOP_YPIXEL(sheet, i);
4368 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4369 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4371 if(i==sheet->range.row0){
4375 if(i==sheet->range.rowi) height=height+3;
4376 if(j==sheet->range.col0){
4380 if(j==sheet->range.coli) width=width+3;
4382 gdk_draw_pixmap(sheet->sheet_window,
4383 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4395 for(i=range->row0; i<=range->rowi; i++){
4396 for(j=range->col0; j<=range->coli; j++){
4398 state=gtk_sheet_cell_get_state(sheet, i, j);
4399 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4400 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4402 if(state!=GTK_STATE_SELECTED && selected &&
4403 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4404 (i != sheet->active_cell.row || j != sheet->active_cell.col)){
4406 x=COLUMN_LEFT_XPIXEL(sheet,j);
4407 y=ROW_TOP_YPIXEL(sheet, i);
4408 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4409 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4411 if(i==new_range.row0){
4415 if(i==new_range.rowi) height=height-3;
4416 if(j==new_range.col0){
4420 if(j==new_range.coli) width=width-3;
4422 gdk_draw_rectangle (sheet->sheet_window,
4433 for(i=aux_range.row0; i<=aux_range.rowi; i++){
4434 for(j=aux_range.col0; j<=aux_range.coli; j++){
4436 if(xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4438 state=gtk_sheet_cell_get_state(sheet, i, j);
4440 mask1 = i==sheet->range.row0 ? 1 : 0;
4441 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4442 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4443 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4445 mask2 = i==new_range.row0 ? 1 : 0;
4446 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4447 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4448 mask2 = j==new_range.coli ? mask2+8 : mask2;
4449 if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){
4450 x=COLUMN_LEFT_XPIXEL(sheet,j);
4451 y=ROW_TOP_YPIXEL(sheet, i);
4452 width=xxx_column_width(sheet, j);
4453 height=yyy_row_height(sheet, i);
4455 gdk_draw_rectangle (sheet->sheet_window,
4463 gdk_draw_rectangle (sheet->sheet_window,
4470 gdk_draw_rectangle (sheet->sheet_window,
4478 gdk_draw_rectangle (sheet->sheet_window,
4495 gtk_sheet_draw_corners(sheet, new_range);
4500 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
4505 gint x,y,width,height;
4507 widget = GTK_WIDGET(sheet);
4509 x=COLUMN_LEFT_XPIXEL(sheet,new_range.col0);
4510 y=ROW_TOP_YPIXEL(sheet,new_range.row0);
4511 width=COLUMN_LEFT_XPIXEL(sheet,new_range.coli)-x+
4512 xxx_column_width(sheet, new_range.coli);
4514 height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+
4515 yyy_row_height(sheet, new_range.rowi);
4517 area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
4518 area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
4519 area.width=sheet->sheet_window_width;
4520 area.height=sheet->sheet_window_height;
4526 if(width>area.width) width=area.width+10;
4531 if(height>area.height) height=area.height+10;
4533 gdk_gc_set_clip_rectangle(sheet->xor_gc, &area);
4535 for(i=-1; i<=1; ++i)
4536 gdk_draw_rectangle (sheet->sheet_window,
4540 width-2*i,height-2*i);
4542 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
4544 gtk_sheet_draw_corners(sheet, new_range);
4549 gtk_sheet_draw_corners(GtkSheet *sheet, GtkSheetRange range)
4554 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.col0)){
4555 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4556 y=ROW_TOP_YPIXEL(sheet,range.row0);
4557 gdk_draw_pixmap(sheet->sheet_window,
4558 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4566 gdk_draw_rectangle (sheet->sheet_window,
4573 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) ||
4574 sheet->state == GTK_SHEET_COLUMN_SELECTED){
4575 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4576 xxx_column_width(sheet, range.coli);
4577 y=ROW_TOP_YPIXEL(sheet,range.row0);
4579 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
4581 y = ROW_TOP_YPIXEL(sheet, sheet->view.row0)+3;
4584 gdk_draw_pixmap(sheet->sheet_window,
4585 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4593 gdk_draw_rectangle (sheet->sheet_window,
4596 x-width+width/2,y-width+width/2,
4600 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.col0) ||
4601 sheet->state == GTK_SHEET_ROW_SELECTED){
4602 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4603 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4604 yyy_row_height(sheet, range.rowi);
4606 if(sheet->state == GTK_SHEET_ROW_SELECTED)
4608 x = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0)+3;
4611 gdk_draw_pixmap(sheet->sheet_window,
4612 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4620 gdk_draw_rectangle (sheet->sheet_window,
4623 x-width+width/2,y-width+width/2,
4627 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){
4628 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4629 xxx_column_width(sheet, range.coli);
4630 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4631 yyy_row_height(sheet, range.rowi);
4633 if(sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
4634 if(sheet->state == GTK_SHEET_NORMAL) width = 3;
4635 gdk_draw_pixmap(sheet->sheet_window,
4636 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4644 gdk_draw_rectangle (sheet->sheet_window,
4647 x-width+width/2,y-width+width/2,
4656 gtk_sheet_real_select_range (GtkSheet * sheet,
4657 GtkSheetRange * range)
4661 g_return_if_fail (sheet != NULL);
4663 if(range==NULL) range=&sheet->range;
4665 if(range->row0 < 0 || range->rowi < 0) return;
4666 if(range->col0 < 0 || range->coli < 0) return;
4671 if(state==GTK_SHEET_COLUMN_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4672 for(i=sheet->range.col0; i< range->col0; i++)
4673 column_button_release(sheet, i);
4674 for(i=range->coli+1; i<= sheet->range.coli; i++)
4675 column_button_release(sheet, i);
4676 for(i=range->col0; i<=range->coli; i++){
4677 column_button_set(sheet, i);
4681 if(state==GTK_SHEET_ROW_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4682 for(i=sheet->range.row0; i< range->row0; i++)
4683 row_button_release(sheet, i);
4684 for(i=range->rowi+1; i<= sheet->range.rowi; i++)
4685 row_button_release(sheet, i);
4686 for(i=range->row0; i<=range->rowi; i++){
4687 row_button_set(sheet, i);
4692 if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
4693 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
4696 gtk_sheet_new_selection(sheet, range);
4698 sheet->range.col0=range->col0;
4699 sheet->range.coli=range->coli;
4700 sheet->range.row0=range->row0;
4701 sheet->range.rowi=range->rowi;
4706 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4707 gtk_sheet_range_draw_selection(sheet, sheet->range);
4710 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[SELECT_RANGE], range);
4714 gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range)
4716 g_return_if_fail (sheet != NULL);
4718 if(range==NULL) range=&sheet->range;
4720 if(range->row0 < 0 || range->rowi < 0) return;
4721 if(range->col0 < 0 || range->coli < 0) return;
4724 if ( gtk_sheet_locked(sheet)) return ;
4726 if(sheet->state != GTK_SHEET_NORMAL)
4727 gtk_sheet_real_unselect_range(sheet, NULL);
4730 gboolean veto = TRUE;
4731 veto = gtk_sheet_deactivate_cell(sheet);
4735 sheet->range.row0=range->row0;
4736 sheet->range.rowi=range->rowi;
4737 sheet->range.col0=range->col0;
4738 sheet->range.coli=range->coli;
4739 sheet->active_cell.row=range->row0;
4740 sheet->active_cell.col=range->col0;
4741 sheet->selection_cell.row=range->rowi;
4742 sheet->selection_cell.col=range->coli;
4744 sheet->state = GTK_SHEET_RANGE_SELECTED;
4745 gtk_sheet_real_select_range(sheet, NULL);
4750 gtk_sheet_unselect_range (GtkSheet * sheet)
4752 gtk_sheet_real_unselect_range(sheet, NULL);
4753 sheet->state = GTK_STATE_NORMAL;
4754 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
4759 gtk_sheet_real_unselect_range (GtkSheet * sheet,
4760 const GtkSheetRange *range)
4762 g_return_if_fail (sheet != NULL);
4763 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)));
4766 range=&sheet->range;
4769 if(range->row0 < 0 || range->rowi < 0) return;
4770 if(range->col0 < 0 || range->coli < 0) return;
4772 if (gtk_sheet_range_isvisible (sheet, *range)){
4773 gtk_sheet_draw_backing_pixmap(sheet, *range);
4777 for(i=range->col0; i<=range->coli; i++){
4778 column_button_release(sheet, i);
4781 for(i=range->row0; i<=range->rowi; i++){
4782 row_button_release(sheet, i);
4786 gtk_sheet_position_children(sheet);
4791 gtk_sheet_expose (GtkWidget * widget,
4792 GdkEventExpose * event)
4795 GtkSheetRange range;
4797 g_return_val_if_fail (widget != NULL, FALSE);
4798 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4799 g_return_val_if_fail (event != NULL, FALSE);
4801 sheet = GTK_SHEET (widget);
4803 if (GTK_WIDGET_DRAWABLE (widget))
4805 range.row0=ROW_FROM_YPIXEL(sheet,event->area.y);
4806 range.col0=COLUMN_FROM_XPIXEL(sheet,event->area.x);
4807 range.rowi=ROW_FROM_YPIXEL(sheet,event->area.y+event->area.height);
4808 range.coli=COLUMN_FROM_XPIXEL(sheet,event->area.x+event->area.width);
4810 /* exposure events on the sheet */
4812 if(event->window == sheet->row_title_window && sheet->row_titles_visible){
4814 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
4815 gtk_sheet_button_draw(sheet,i,-1);
4818 if(event->window == sheet->column_title_window && sheet->column_titles_visible){
4820 for(i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
4821 gtk_sheet_button_draw(sheet,-1,i);
4824 if (event->window == sheet->sheet_window){
4825 gtk_sheet_draw_backing_pixmap(sheet, range);
4827 if(sheet->state != GTK_SHEET_NORMAL){
4828 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4829 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4830 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4831 gtk_sheet_draw_backing_pixmap(sheet, sheet->drag_range);
4833 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4834 gtk_sheet_range_draw_selection(sheet, sheet->range);
4835 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4836 draw_xor_rectangle(sheet, sheet->drag_range);
4839 if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet))){
4840 if(sheet->state == GTK_SHEET_NORMAL){
4841 gtk_sheet_draw_active_cell(sheet);
4842 if(!GTK_SHEET_IN_SELECTION(sheet))
4843 gtk_widget_queue_draw(sheet->sheet_entry);
4852 if(sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet))
4853 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4855 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
4862 gtk_sheet_button_press (GtkWidget * widget,
4863 GdkEventButton * event)
4866 GdkModifierType mods;
4867 gint x, y, row, column;
4870 g_return_val_if_fail (widget != NULL, FALSE);
4871 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4872 g_return_val_if_fail (event != NULL, FALSE);
4874 sheet = GTK_SHEET (widget);
4876 if ( event->type == GDK_2BUTTON_PRESS)
4878 gtk_widget_get_pointer (widget, &x, &y);
4879 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4881 if (event->window == sheet->column_title_window )
4883 gtk_signal_emit (GTK_OBJECT (sheet),
4884 sheet_signals[DOUBLE_CLICK_COLUMN], column);
4886 else if (event->window == sheet->row_title_window )
4888 gtk_signal_emit (GTK_OBJECT (sheet),
4889 sheet_signals[DOUBLE_CLICK_ROW], row);
4895 if(event->type != GDK_BUTTON_PRESS) return TRUE;
4897 gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
4899 if(!(mods & GDK_BUTTON1_MASK)) return TRUE;
4902 /* press on resize windows */
4903 if (event->window == sheet->column_title_window &&
4904 gtk_sheet_columns_resizable(sheet))
4906 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
4907 if(POSSIBLE_XDRAG(sheet, sheet->x_drag, &sheet->drag_cell.col)){
4909 if (event->type == GDK_2BUTTON_PRESS){
4910 gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
4911 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_XDRAG);
4914 gtk_sheet_column_size_request(sheet, sheet->drag_cell.col, &req);
4915 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4916 gdk_pointer_grab (sheet->column_title_window, FALSE,
4917 GDK_POINTER_MOTION_HINT_MASK |
4918 GDK_BUTTON1_MOTION_MASK |
4919 GDK_BUTTON_RELEASE_MASK,
4920 NULL, NULL, event->time);
4922 draw_xor_vline (sheet);
4927 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet))
4929 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
4931 if(POSSIBLE_YDRAG(sheet, sheet->y_drag, &sheet->drag_cell.row)){
4933 gtk_sheet_row_size_request(sheet, sheet->drag_cell.row, &req);
4934 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
4935 gdk_pointer_grab (sheet->row_title_window, FALSE,
4936 GDK_POINTER_MOTION_HINT_MASK |
4937 GDK_BUTTON1_MOTION_MASK |
4938 GDK_BUTTON_RELEASE_MASK,
4939 NULL, NULL, event->time);
4941 draw_xor_hline (sheet);
4946 /* the sheet itself does not handle other than single click events */
4947 if(event->type != GDK_BUTTON_PRESS) return FALSE;
4949 /* selections on the sheet */
4950 if(event->window == sheet->sheet_window){
4951 gtk_widget_get_pointer (widget, &x, &y);
4952 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4953 gdk_pointer_grab (sheet->sheet_window, FALSE,
4954 GDK_POINTER_MOTION_HINT_MASK |
4955 GDK_BUTTON1_MOTION_MASK |
4956 GDK_BUTTON_RELEASE_MASK,
4957 NULL, NULL, event->time);
4958 gtk_grab_add(GTK_WIDGET(sheet));
4959 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4960 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4962 if(sheet->selection_mode != GTK_SELECTION_SINGLE &&
4963 sheet->cursor_drag->type==GDK_SIZING &&
4964 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_RESIZE(sheet)){
4965 if(sheet->state==GTK_STATE_NORMAL) {
4966 row=sheet->active_cell.row;
4967 column=sheet->active_cell.col;
4968 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4969 sheet->active_cell.row=row;
4970 sheet->active_cell.col=column;
4971 sheet->drag_range=sheet->range;
4972 sheet->state=GTK_SHEET_RANGE_SELECTED;
4973 gtk_sheet_select_range(sheet, &sheet->drag_range);
4977 if(row > sheet->range.rowi) row--;
4978 if(column > sheet->range.coli) column--;
4979 sheet->drag_cell.row = row;
4980 sheet->drag_cell.col = column;
4981 sheet->drag_range=sheet->range;
4982 draw_xor_rectangle(sheet, sheet->drag_range);
4983 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
4985 else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW &&
4986 !GTK_SHEET_IN_SELECTION(sheet)
4987 && ! GTK_SHEET_IN_DRAG(sheet)
4988 && ! gtk_sheet_locked(sheet)
4989 && sheet->active_cell.row >= 0
4990 && sheet->active_cell.col >= 0
4993 if(sheet->state==GTK_STATE_NORMAL) {
4994 row=sheet->active_cell.row;
4995 column=sheet->active_cell.col;
4996 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4997 sheet->active_cell.row=row;
4998 sheet->active_cell.col=column;
4999 sheet->drag_range=sheet->range;
5000 sheet->state=GTK_SHEET_RANGE_SELECTED;
5001 gtk_sheet_select_range(sheet, &sheet->drag_range);
5005 if(row < sheet->range.row0) row++;
5006 if(row > sheet->range.rowi) row--;
5007 if(column < sheet->range.col0) column++;
5008 if(column > sheet->range.coli) column--;
5009 sheet->drag_cell.row=row;
5010 sheet->drag_cell.col=column;
5011 sheet->drag_range=sheet->range;
5012 draw_xor_rectangle(sheet, sheet->drag_range);
5013 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5017 gtk_sheet_click_cell(sheet, row, column, &veto);
5018 if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5022 if(event->window == sheet->column_title_window){
5023 gtk_widget_get_pointer (widget, &x, &y);
5024 column = COLUMN_FROM_XPIXEL(sheet, x);
5025 if(xxx_column_is_sensitive(sheet, column)){
5026 gtk_sheet_click_cell(sheet, -1, column, &veto);
5027 gtk_grab_add(GTK_WIDGET(sheet));
5028 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5029 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5030 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5034 if(event->window == sheet->row_title_window){
5035 gtk_widget_get_pointer (widget, &x, &y);
5036 row = ROW_FROM_YPIXEL(sheet, y);
5037 if(yyy_row_is_sensitive(sheet, row)){
5038 gtk_sheet_click_cell(sheet, row, -1, &veto);
5039 gtk_grab_add(GTK_WIDGET(sheet));
5040 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5041 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5042 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5050 gtk_sheet_scroll(gpointer data)
5053 gint x,y,row,column;
5056 sheet=GTK_SHEET(data);
5058 GDK_THREADS_ENTER();
5060 gtk_widget_get_pointer (GTK_WIDGET(sheet), &x, &y);
5061 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5065 if(GTK_SHEET_IN_SELECTION(sheet))
5066 gtk_sheet_extend_selection(sheet, row, column);
5068 if(GTK_SHEET_IN_DRAG(sheet) || GTK_SHEET_IN_RESIZE(sheet)){
5069 move=gtk_sheet_move_query(sheet, row, column);
5070 if(move) draw_xor_rectangle(sheet, sheet->drag_range);
5073 GDK_THREADS_LEAVE();
5080 gtk_sheet_click_cell(GtkSheet *sheet, gint row, gint column, gboolean *veto)
5084 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)){
5089 if(column >= 0 && row >= 0)
5090 if(! xxx_column_is_visible(sheet, column) || !yyy_row_is_visible(sheet, row))
5096 _gtkextra_signal_emit(GTK_OBJECT(sheet), sheet_signals[TRAVERSE],
5097 sheet->active_cell.row, sheet->active_cell.col,
5098 &row, &column, veto);
5101 if(sheet->state == GTK_STATE_NORMAL) return;
5103 row = sheet->active_cell.row;
5104 column = sheet->active_cell.col;
5106 gtk_sheet_activate_cell(sheet, row, column);
5110 if(row == -1 && column >= 0){
5111 if(gtk_sheet_autoscroll(sheet))
5112 gtk_sheet_move_query(sheet, row, column);
5113 gtk_sheet_select_column(sheet, column);
5116 if(column == -1 && row >= 0){
5117 if(gtk_sheet_autoscroll(sheet))
5118 gtk_sheet_move_query(sheet, row, column);
5119 gtk_sheet_select_row(sheet, row);
5123 if(row==-1 && column ==-1){
5124 sheet->range.row0=0;
5125 sheet->range.col0=0;
5126 sheet->range.rowi = yyy_row_count(sheet) - 1;
5127 sheet->range.coli = xxx_column_count(sheet) - 1;
5128 sheet->active_cell.row=0;
5129 sheet->active_cell.col=0;
5130 gtk_sheet_select_range(sheet, NULL);
5134 if(row!=-1 && column !=-1){
5135 if(sheet->state != GTK_SHEET_NORMAL){
5136 sheet->state = GTK_SHEET_NORMAL;
5137 gtk_sheet_real_unselect_range(sheet, NULL);
5141 if(!gtk_sheet_deactivate_cell(sheet)){
5147 if(gtk_sheet_autoscroll(sheet))
5148 gtk_sheet_move_query(sheet, row, column);
5149 sheet->active_cell.row=row;
5150 sheet->active_cell.col=column;
5151 sheet->selection_cell.row=row;
5152 sheet->selection_cell.col=column;
5153 sheet->range.row0=row;
5154 sheet->range.col0=column;
5155 sheet->range.rowi=row;
5156 sheet->range.coli=column;
5157 sheet->state=GTK_SHEET_NORMAL;
5158 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5159 gtk_sheet_draw_active_cell(sheet);
5163 g_assert_not_reached();
5164 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5165 sheet->active_cell.col);
5169 gtk_sheet_button_release (GtkWidget * widget,
5170 GdkEventButton * event)
5175 sheet=GTK_SHEET(widget);
5177 /* release on resize windows */
5178 if (GTK_SHEET_IN_XDRAG (sheet)){
5179 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
5180 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5181 gtk_widget_get_pointer (widget, &x, NULL);
5182 gdk_pointer_ungrab (event->time);
5183 draw_xor_vline (sheet);
5185 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col, new_column_width (sheet, sheet->drag_cell.col, &x));
5186 sheet->old_hadjustment = -1.;
5187 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed");
5191 if (GTK_SHEET_IN_YDRAG (sheet)){
5192 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5193 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5194 gtk_widget_get_pointer (widget, NULL, &y);
5195 gdk_pointer_ungrab (event->time);
5196 draw_xor_hline (sheet);
5198 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
5199 sheet->old_vadjustment = -1.;
5200 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed");
5205 if (GTK_SHEET_IN_DRAG(sheet)){
5206 GtkSheetRange old_range;
5207 draw_xor_rectangle(sheet, sheet->drag_range);
5208 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5209 gdk_pointer_ungrab (event->time);
5211 gtk_sheet_real_unselect_range(sheet, NULL);
5213 sheet->active_cell.row = sheet->active_cell.row +
5214 (sheet->drag_range.row0 - sheet->range.row0);
5215 sheet->active_cell.col = sheet->active_cell.col +
5216 (sheet->drag_range.col0 - sheet->range.col0);
5217 sheet->selection_cell.row = sheet->selection_cell.row +
5218 (sheet->drag_range.row0 - sheet->range.row0);
5219 sheet->selection_cell.col = sheet->selection_cell.col +
5220 (sheet->drag_range.col0 - sheet->range.col0);
5221 old_range=sheet->range;
5222 sheet->range=sheet->drag_range;
5223 sheet->drag_range=old_range;
5224 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[MOVE_RANGE],
5225 &sheet->drag_range, &sheet->range);
5226 gtk_sheet_select_range(sheet, &sheet->range);
5229 if (GTK_SHEET_IN_RESIZE(sheet)){
5230 GtkSheetRange old_range;
5231 draw_xor_rectangle(sheet, sheet->drag_range);
5232 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5233 gdk_pointer_ungrab (event->time);
5235 gtk_sheet_real_unselect_range(sheet, NULL);
5237 sheet->active_cell.row = sheet->active_cell.row +
5238 (sheet->drag_range.row0 - sheet->range.row0);
5239 sheet->active_cell.col = sheet->active_cell.col +
5240 (sheet->drag_range.col0 - sheet->range.col0);
5241 if(sheet->drag_range.row0 < sheet->range.row0)
5242 sheet->selection_cell.row = sheet->drag_range.row0;
5243 if(sheet->drag_range.rowi >= sheet->range.rowi)
5244 sheet->selection_cell.row = sheet->drag_range.rowi;
5245 if(sheet->drag_range.col0 < sheet->range.col0)
5246 sheet->selection_cell.col = sheet->drag_range.col0;
5247 if(sheet->drag_range.coli >= sheet->range.coli)
5248 sheet->selection_cell.col = sheet->drag_range.coli;
5249 old_range = sheet->range;
5250 sheet->range = sheet->drag_range;
5251 sheet->drag_range = old_range;
5253 if(sheet->state==GTK_STATE_NORMAL) sheet->state=GTK_SHEET_RANGE_SELECTED;
5254 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[RESIZE_RANGE],
5255 &sheet->drag_range, &sheet->range);
5256 gtk_sheet_select_range(sheet, &sheet->range);
5259 if(sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)){
5260 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5261 gdk_pointer_ungrab (event->time);
5262 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5263 sheet->active_cell.col);
5266 if(GTK_SHEET_IN_SELECTION)
5267 gdk_pointer_ungrab (event->time);
5269 gtk_timeout_remove(sheet->timer);
5270 gtk_grab_remove(GTK_WIDGET(sheet));
5272 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5278 gtk_sheet_motion (GtkWidget * widget,
5279 GdkEventMotion * event)
5282 GdkModifierType mods;
5283 GdkCursorType new_cursor;
5284 gint x, y, row, column;
5286 g_return_val_if_fail (widget != NULL, FALSE);
5287 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
5288 g_return_val_if_fail (event != NULL, FALSE);
5291 sheet = GTK_SHEET (widget);
5293 /* selections on the sheet */
5297 if(event->window == sheet->column_title_window && gtk_sheet_columns_resizable(sheet)){
5298 gtk_widget_get_pointer(widget, &x, &y);
5299 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_XDRAG(sheet, x, &column)){
5300 new_cursor=GDK_SB_H_DOUBLE_ARROW;
5301 if(new_cursor != sheet->cursor_drag->type){
5302 gdk_cursor_destroy(sheet->cursor_drag);
5303 sheet->cursor_drag=gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
5304 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5307 new_cursor=GDK_TOP_LEFT_ARROW;
5308 if(!GTK_SHEET_IN_XDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5309 gdk_cursor_destroy(sheet->cursor_drag);
5310 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5311 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5316 if(event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet)){
5317 gtk_widget_get_pointer(widget, &x, &y);
5318 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_YDRAG(sheet,y, &column)){
5319 new_cursor=GDK_SB_V_DOUBLE_ARROW;
5320 if(new_cursor != sheet->cursor_drag->type){
5321 gdk_cursor_destroy(sheet->cursor_drag);
5322 sheet->cursor_drag=gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
5323 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5326 new_cursor=GDK_TOP_LEFT_ARROW;
5327 if(!GTK_SHEET_IN_YDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5328 gdk_cursor_destroy(sheet->cursor_drag);
5329 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5330 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5335 new_cursor=GDK_PLUS;
5336 if(!POSSIBLE_DRAG(sheet,x,y,&row,&column) && !GTK_SHEET_IN_DRAG(sheet) &&
5337 !POSSIBLE_RESIZE(sheet,x,y,&row,&column) && !GTK_SHEET_IN_RESIZE(sheet) &&
5338 event->window == sheet->sheet_window &&
5339 new_cursor != sheet->cursor_drag->type){
5340 gdk_cursor_destroy(sheet->cursor_drag);
5341 sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
5342 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5345 new_cursor=GDK_TOP_LEFT_ARROW;
5346 if(!(POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5347 (POSSIBLE_DRAG(sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG(sheet)) &&
5348 event->window == sheet->sheet_window &&
5349 new_cursor != sheet->cursor_drag->type){
5350 gdk_cursor_destroy(sheet->cursor_drag);
5351 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5352 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5355 new_cursor=GDK_SIZING;
5356 if(!GTK_SHEET_IN_DRAG(sheet) &&
5357 (POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5358 event->window == sheet->sheet_window &&
5359 new_cursor != sheet->cursor_drag->type){
5360 gdk_cursor_destroy(sheet->cursor_drag);
5361 sheet->cursor_drag=gdk_cursor_new(GDK_SIZING);
5362 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5365 gdk_window_get_pointer (widget->window, &x, &y, &mods);
5366 if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
5368 if (GTK_SHEET_IN_XDRAG (sheet)){
5369 if (event->is_hint || event->window != widget->window)
5370 gtk_widget_get_pointer (widget, &x, NULL);
5374 new_column_width (sheet, sheet->drag_cell.col, &x);
5375 if (x != sheet->x_drag)
5377 draw_xor_vline (sheet);
5379 draw_xor_vline (sheet);
5384 if (GTK_SHEET_IN_YDRAG (sheet)){
5385 if (event->is_hint || event->window != widget->window)
5386 gtk_widget_get_pointer (widget, NULL, &y);
5390 new_row_height (sheet, sheet->drag_cell.row, &y);
5391 if (y != sheet->y_drag)
5393 draw_xor_hline (sheet);
5395 draw_xor_hline (sheet);
5400 if (GTK_SHEET_IN_DRAG(sheet)){
5402 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col;
5403 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row;
5404 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5405 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5409 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5410 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5411 aux=sheet->drag_range;
5412 sheet->drag_range.row0=sheet->range.row0+row;
5413 sheet->drag_range.col0=sheet->range.col0+column;
5414 sheet->drag_range.rowi=sheet->range.rowi+row;
5415 sheet->drag_range.coli=sheet->range.coli+column;
5416 if(aux.row0 != sheet->drag_range.row0 ||
5417 aux.col0 != sheet->drag_range.col0){
5418 draw_xor_rectangle (sheet, aux);
5419 draw_xor_rectangle (sheet, sheet->drag_range);
5425 if (GTK_SHEET_IN_RESIZE(sheet)){
5427 gint v_h, current_col, current_row, col_threshold, row_threshold;
5430 if(abs(x-COLUMN_LEFT_XPIXEL(sheet,sheet->drag_cell.col)) >
5431 abs(y-ROW_TOP_YPIXEL(sheet,sheet->drag_cell.row))) v_h=2;
5433 current_col = COLUMN_FROM_XPIXEL(sheet,x);
5434 current_row = ROW_FROM_YPIXEL(sheet,y);
5435 column = current_col-sheet->drag_cell.col;
5436 row = current_row-sheet->drag_cell.row;
5438 /*use half of column width resp. row height as threshold to expand selection*/
5439 col_threshold = COLUMN_LEFT_XPIXEL(sheet,current_col)+xxx_column_width (sheet,current_col)/2;
5441 if (x < col_threshold)
5444 else if (column < 0){
5445 if (x > col_threshold)
5448 row_threshold = ROW_TOP_YPIXEL(sheet,current_row)+yyy_row_height (sheet, current_row)/2;
5450 if(y < row_threshold)
5454 if(y > row_threshold)
5458 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5459 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5469 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5470 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5472 aux=sheet->drag_range;
5473 sheet->drag_range=sheet->range;
5475 if(row<0) sheet->drag_range.row0=sheet->range.row0+row;
5476 if(row>0) sheet->drag_range.rowi=sheet->range.rowi+row;
5477 if(column<0) sheet->drag_range.col0=sheet->range.col0+column;
5478 if(column>0) sheet->drag_range.coli=sheet->range.coli+column;
5480 if(aux.row0 != sheet->drag_range.row0 ||
5481 aux.rowi != sheet->drag_range.rowi ||
5482 aux.col0 != sheet->drag_range.col0 ||
5483 aux.coli != sheet->drag_range.coli){
5484 draw_xor_rectangle (sheet, aux);
5485 draw_xor_rectangle (sheet, sheet->drag_range);
5493 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5495 if(sheet->state==GTK_SHEET_NORMAL && row==sheet->active_cell.row &&
5496 column==sheet->active_cell.col) return TRUE;
5498 if(GTK_SHEET_IN_SELECTION(sheet) && mods&GDK_BUTTON1_MASK)
5499 gtk_sheet_extend_selection(sheet, row, column);
5505 gtk_sheet_move_query(GtkSheet *sheet, gint row, gint column)
5507 gint row_move, column_move;
5508 gfloat row_align, col_align;
5509 guint height, width;
5511 gint new_col = column;
5518 height = sheet->sheet_window_height;
5519 width = sheet->sheet_window_width;
5521 if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5523 new_row = MIN(yyy_row_count(sheet), row + 1);
5525 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet) - 1 &&
5526 ROW_TOP_YPIXEL(sheet, yyy_row_count(sheet)-1) +
5527 yyy_row_height(sheet, yyy_row_count(sheet)-1) < height){
5532 if(row<MIN_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5536 if(column>=MAX_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5538 new_col = MIN(xxx_column_count(sheet) - 1, column + 1);
5540 if(MAX_VISIBLE_COLUMN(sheet) == (xxx_column_count(sheet) - 1) &&
5541 COLUMN_LEFT_XPIXEL(sheet, xxx_column_count(sheet) - 1) +
5542 xxx_column_width(sheet, xxx_column_count(sheet) - 1) < width)
5544 column_move = FALSE;
5548 if(column<MIN_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5553 if(row_move || column_move){
5554 gtk_sheet_moveto(sheet, new_row, new_col, row_align, col_align);
5557 return(row_move || column_move);
5561 gtk_sheet_extend_selection(GtkSheet *sheet, gint row, gint column)
5563 GtkSheetRange range;
5567 if(row == sheet->selection_cell.row && column == sheet->selection_cell.col)
5570 if(sheet->selection_mode == GTK_SELECTION_SINGLE) return;
5572 gtk_sheet_move_query(sheet, row, column);
5573 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5575 if(GTK_SHEET_IN_DRAG(sheet)) return;
5579 switch(sheet->state){
5580 case GTK_SHEET_ROW_SELECTED:
5581 column = xxx_column_count(sheet) - 1;
5583 case GTK_SHEET_COLUMN_SELECTED:
5584 row = yyy_row_count(sheet) - 1;
5586 case GTK_SHEET_NORMAL:
5587 sheet->state=GTK_SHEET_RANGE_SELECTED;
5588 r=sheet->active_cell.row;
5589 c=sheet->active_cell.col;
5590 sheet->range.col0=c;
5591 sheet->range.row0=r;
5592 sheet->range.coli=c;
5593 sheet->range.rowi=r;
5594 gdk_draw_pixmap(sheet->sheet_window,
5595 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
5597 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5598 ROW_TOP_YPIXEL(sheet,r)-1,
5599 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5600 ROW_TOP_YPIXEL(sheet,r)-1,
5601 xxx_column_width(sheet, c)+4,
5602 yyy_row_height(sheet, r)+4);
5603 gtk_sheet_range_draw_selection(sheet, sheet->range);
5604 case GTK_SHEET_RANGE_SELECTED:
5605 sheet->state=GTK_SHEET_RANGE_SELECTED;
5608 sheet->selection_cell.row = row;
5609 sheet->selection_cell.col = column;
5611 range.col0=MIN(column,sheet->active_cell.col);
5612 range.coli=MAX(column,sheet->active_cell.col);
5613 range.row0=MIN(row,sheet->active_cell.row);
5614 range.rowi=MAX(row,sheet->active_cell.row);
5616 if(range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi ||
5617 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli ||
5618 state==GTK_SHEET_NORMAL)
5619 gtk_sheet_real_select_range(sheet, &range);
5624 gtk_sheet_entry_key_press(GtkWidget *widget,
5628 gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", key, &focus);
5633 gtk_sheet_key_press(GtkWidget *widget,
5639 gboolean extend_selection = FALSE;
5640 gboolean force_move = FALSE;
5641 gboolean in_selection = FALSE;
5642 gboolean veto = TRUE;
5645 sheet = GTK_SHEET(widget);
5647 if(key->state & GDK_CONTROL_MASK || key->keyval==GDK_Control_L ||
5648 key->keyval==GDK_Control_R) return FALSE;
5652 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL)
5653 gtk_sheet_clip_range(sheet, sheet->range);
5654 if(key->keyval=='x' || key->keyval == 'X')
5655 gtk_sheet_unclip_range(sheet);
5660 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval==GDK_Shift_L
5661 || key->keyval==GDK_Shift_R;
5664 in_selection = GTK_SHEET_IN_SELECTION(sheet);
5665 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5667 switch(key->keyval){
5668 case GDK_Return: case GDK_KP_Enter:
5669 if(sheet->state == GTK_SHEET_NORMAL &&
5670 !GTK_SHEET_IN_SELECTION(sheet))
5671 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
5673 row = sheet->active_cell.row;
5674 col = sheet->active_cell.col;
5675 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5676 row = MIN_VISIBLE_ROW(sheet)-1;
5677 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5678 col = MIN_VISIBLE_COLUMN(sheet);
5679 if(row < yyy_row_count(sheet) - 1){
5681 while(!yyy_row_is_visible(sheet, row) && row<yyy_row_count(sheet)-1)
5684 gtk_sheet_click_cell(sheet, row, col, &veto);
5685 extend_selection = FALSE;
5687 case GDK_ISO_Left_Tab:
5688 row = sheet->active_cell.row;
5689 col = sheet->active_cell.col;
5690 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5691 col = MIN_VISIBLE_COLUMN(sheet)-1;
5692 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5693 row = MIN_VISIBLE_ROW(sheet);
5696 while(! xxx_column_is_visible(sheet, col) && col>0) col--;
5699 gtk_sheet_click_cell(sheet, row, col, &veto);
5700 extend_selection = FALSE;
5703 row = sheet->active_cell.row;
5704 col = sheet->active_cell.col;
5705 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5706 col = MIN_VISIBLE_COLUMN(sheet)-1;
5707 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5708 row = MIN_VISIBLE_ROW(sheet);
5709 if(col < xxx_column_count(sheet) - 1)
5712 while(! xxx_column_is_visible(sheet, col) &&
5713 col < xxx_column_count(sheet) - 1)
5716 gtk_sheet_click_cell(sheet, row, col, &veto);
5717 extend_selection = FALSE;
5719 /* case GDK_BackSpace:
5720 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){
5721 if(sheet->active_cell.col > 0){
5722 col = sheet->active_cell.col - scroll;
5723 row = sheet->active_cell.row;
5724 while(!sheet->column[col].is_visible && col > 0) col--;
5727 gtk_sheet_click_cell(sheet, row, col, &veto);
5728 extend_selection = FALSE;
5732 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5734 if(extend_selection){
5735 if(state==GTK_STATE_NORMAL){
5736 row=sheet->active_cell.row;
5737 col=sheet->active_cell.col;
5738 gtk_sheet_click_cell(sheet, row, col, &veto);
5741 if(sheet->selection_cell.row > 0){
5742 row = sheet->selection_cell.row - scroll;
5743 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5745 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5749 col = sheet->active_cell.col;
5750 row = sheet->active_cell.row;
5751 if(state==GTK_SHEET_COLUMN_SELECTED)
5752 row = MIN_VISIBLE_ROW(sheet);
5753 if(state==GTK_SHEET_ROW_SELECTED)
5754 col = MIN_VISIBLE_COLUMN(sheet);
5756 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5758 gtk_sheet_click_cell(sheet, row, col, &veto);
5759 extend_selection = FALSE;
5762 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5764 if(extend_selection){
5765 if(state==GTK_STATE_NORMAL){
5766 row=sheet->active_cell.row;
5767 col=sheet->active_cell.col;
5768 gtk_sheet_click_cell(sheet, row, col, &veto);
5771 if(sheet->selection_cell.row < yyy_row_count(sheet)-1){
5772 row = sheet->selection_cell.row + scroll;
5773 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5774 row = MIN(yyy_row_count(sheet)-1, row);
5775 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5779 col = sheet->active_cell.col;
5780 row = sheet->active_cell.row;
5781 if(sheet->active_cell.row < yyy_row_count(sheet)-1){
5782 if(state==GTK_SHEET_COLUMN_SELECTED)
5783 row = MIN_VISIBLE_ROW(sheet)-1;
5784 if(state==GTK_SHEET_ROW_SELECTED)
5785 col = MIN_VISIBLE_COLUMN(sheet);
5787 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5788 row = MIN(yyy_row_count(sheet)-1, row);
5790 gtk_sheet_click_cell(sheet, row, col, &veto);
5791 extend_selection = FALSE;
5794 if(extend_selection){
5795 if(state==GTK_STATE_NORMAL){
5796 row=sheet->active_cell.row;
5797 col=sheet->active_cell.col;
5798 gtk_sheet_click_cell(sheet, row, col, &veto);
5801 if(sheet->selection_cell.col < xxx_column_count(sheet) - 1)
5803 col = sheet->selection_cell.col + 1;
5804 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1)
5806 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5810 col = sheet->active_cell.col;
5811 row = sheet->active_cell.row;
5812 if(sheet->active_cell.col < xxx_column_count(sheet) - 1){
5814 if(state==GTK_SHEET_ROW_SELECTED)
5815 col = MIN_VISIBLE_COLUMN(sheet)-1;
5816 if(state==GTK_SHEET_COLUMN_SELECTED)
5817 row = MIN_VISIBLE_ROW(sheet);
5818 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1) col++;
5819 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5821 gtk_sheet_click_cell(sheet, row, col, &veto);
5826 extend_selection = FALSE;
5829 if(extend_selection){
5830 if(state==GTK_STATE_NORMAL){
5831 row=sheet->active_cell.row;
5832 col=sheet->active_cell.col;
5833 gtk_sheet_click_cell(sheet, row, col, &veto);
5836 if(sheet->selection_cell.col > 0){
5837 col = sheet->selection_cell.col - 1;
5838 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5839 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5843 col = sheet->active_cell.col - 1;
5844 row = sheet->active_cell.row;
5845 if(state==GTK_SHEET_ROW_SELECTED)
5846 col = MIN_VISIBLE_COLUMN(sheet)-1;
5847 if(state==GTK_SHEET_COLUMN_SELECTED)
5848 row = MIN_VISIBLE_ROW(sheet);
5849 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5852 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5854 gtk_sheet_click_cell(sheet, row, col, &veto);
5858 extend_selection = FALSE;
5862 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5863 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5864 extend_selection = FALSE;
5867 row=yyy_row_count(sheet)-1;
5868 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5869 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5870 extend_selection = FALSE;
5874 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5875 if(extend_selection) return TRUE;
5877 if(state == GTK_SHEET_ROW_SELECTED)
5878 sheet->active_cell.col=MIN_VISIBLE_COLUMN(sheet);
5879 if(state == GTK_SHEET_COLUMN_SELECTED)
5880 sheet->active_cell.row=MIN_VISIBLE_ROW(sheet);
5884 if(extend_selection) return TRUE;
5886 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5887 sheet->active_cell.col);
5893 gtk_sheet_size_request (GtkWidget * widget,
5894 GtkRequisition * requisition)
5898 GtkSheetChild *child;
5899 GtkRequisition child_requisition;
5901 g_return_if_fail (widget != NULL);
5902 g_return_if_fail (GTK_IS_SHEET (widget));
5903 g_return_if_fail (requisition != NULL);
5905 sheet = GTK_SHEET (widget);
5907 requisition->width = 3*DEFAULT_COLUMN_WIDTH;
5908 requisition->height = 3*DEFAULT_ROW_HEIGHT(widget);
5910 /* compute the size of the column title area */
5911 if(sheet->column_titles_visible)
5912 requisition->height += sheet->column_title_area.height;
5914 /* compute the size of the row title area */
5915 if(sheet->row_titles_visible)
5916 requisition->width += sheet->row_title_area.width;
5918 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5919 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5920 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5921 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5923 if(!sheet->column_titles_visible)
5924 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5926 if(!sheet->row_titles_visible)
5927 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5929 children = sheet->children;
5932 child = children->data;
5933 children = children->next;
5935 gtk_widget_size_request(child->widget, &child_requisition);
5941 gtk_sheet_size_allocate (GtkWidget * widget,
5942 GtkAllocation * allocation)
5945 GtkAllocation sheet_allocation;
5948 g_return_if_fail (widget != NULL);
5949 g_return_if_fail (GTK_IS_SHEET (widget));
5950 g_return_if_fail (allocation != NULL);
5952 sheet = GTK_SHEET (widget);
5953 widget->allocation = *allocation;
5954 border_width = GTK_CONTAINER(widget)->border_width;
5956 if (GTK_WIDGET_REALIZED (widget))
5957 gdk_window_move_resize (widget->window,
5958 allocation->x + border_width,
5959 allocation->y + border_width,
5960 allocation->width - 2*border_width,
5961 allocation->height - 2*border_width);
5963 /* use internal allocation structure for all the math
5964 * because it's easier than always subtracting the container
5966 sheet->internal_allocation.x = 0;
5967 sheet->internal_allocation.y = 0;
5968 sheet->internal_allocation.width = allocation->width - 2*border_width;
5969 sheet->internal_allocation.height = allocation->height - 2*border_width;
5971 sheet_allocation.x = 0;
5972 sheet_allocation.y = 0;
5973 sheet_allocation.width = allocation->width - 2*border_width;
5974 sheet_allocation.height = allocation->height - 2*border_width;
5976 sheet->sheet_window_width = sheet_allocation.width;
5977 sheet->sheet_window_height = sheet_allocation.height;
5979 if (GTK_WIDGET_REALIZED (widget))
5980 gdk_window_move_resize (sheet->sheet_window,
5983 sheet_allocation.width,
5984 sheet_allocation.height);
5986 /* position the window which holds the column title buttons */
5987 sheet->column_title_area.x = 0;
5988 sheet->column_title_area.y = 0;
5989 if(sheet->row_titles_visible)
5990 sheet->column_title_area.x = sheet->row_title_area.width;
5991 sheet->column_title_area.width = sheet_allocation.width -
5992 sheet->column_title_area.x;
5993 if(GTK_WIDGET_REALIZED(widget) && sheet->column_titles_visible)
5994 gdk_window_move_resize (sheet->column_title_window,
5995 sheet->column_title_area.x,
5996 sheet->column_title_area.y,
5997 sheet->column_title_area.width,
5998 sheet->column_title_area.height);
6000 sheet->sheet_window_width = sheet_allocation.width;
6001 sheet->sheet_window_height = sheet_allocation.height;
6003 /* column button allocation */
6004 size_allocate_column_title_buttons (sheet);
6006 /* position the window which holds the row title buttons */
6007 sheet->row_title_area.x = 0;
6008 sheet->row_title_area.y = 0;
6009 if(sheet->column_titles_visible)
6010 sheet->row_title_area.y = sheet->column_title_area.height;
6011 sheet->row_title_area.height = sheet_allocation.height -
6012 sheet->row_title_area.y;
6014 if(GTK_WIDGET_REALIZED(widget) && sheet->row_titles_visible)
6015 gdk_window_move_resize (sheet->row_title_window,
6016 sheet->row_title_area.x,
6017 sheet->row_title_area.y,
6018 sheet->row_title_area.width,
6019 sheet->row_title_area.height);
6022 /* row button allocation */
6023 size_allocate_row_title_buttons (sheet);
6025 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6026 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6027 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6028 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6030 if(!sheet->column_titles_visible)
6031 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6033 if(!sheet->row_titles_visible)
6034 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6036 size_allocate_column_title_buttons(sheet);
6037 size_allocate_row_title_buttons(sheet);
6039 /* re-scale backing pixmap */
6040 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
6041 gtk_sheet_position_children(sheet);
6043 /* set the scrollbars adjustments */
6044 adjust_scrollbars (sheet);
6048 size_allocate_column_title_buttons (GtkSheet * sheet)
6053 if (!sheet->column_titles_visible) return;
6054 if (!GTK_WIDGET_REALIZED (sheet))
6057 width = sheet->sheet_window_width;
6060 if(sheet->row_titles_visible)
6062 width -= sheet->row_title_area.width;
6063 x = sheet->row_title_area.width;
6066 if(sheet->column_title_area.width != width || sheet->column_title_area.x != x)
6068 sheet->column_title_area.width = width;
6069 sheet->column_title_area.x = x;
6070 gdk_window_move_resize (sheet->column_title_window,
6071 sheet->column_title_area.x,
6072 sheet->column_title_area.y,
6073 sheet->column_title_area.width,
6074 sheet->column_title_area.height);
6078 if(MAX_VISIBLE_COLUMN(sheet) == xxx_column_count(sheet) - 1)
6079 gdk_window_clear_area (sheet->column_title_window,
6081 sheet->column_title_area.width,
6082 sheet->column_title_area.height);
6084 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6086 for (i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
6087 gtk_sheet_button_draw(sheet,-1,i);
6091 size_allocate_row_title_buttons (GtkSheet * sheet)
6096 if (!sheet->row_titles_visible) return;
6097 if (!GTK_WIDGET_REALIZED (sheet))
6100 height = sheet->sheet_window_height;
6103 if(sheet->column_titles_visible)
6105 height -= sheet->column_title_area.height;
6106 y = sheet->column_title_area.height;
6109 if(sheet->row_title_area.height != height || sheet->row_title_area.y != y)
6111 sheet->row_title_area.y = y;
6112 sheet->row_title_area.height = height;
6113 gdk_window_move_resize (sheet->row_title_window,
6114 sheet->row_title_area.x,
6115 sheet->row_title_area.y,
6116 sheet->row_title_area.width,
6117 sheet->row_title_area.height);
6119 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet)-1)
6120 gdk_window_clear_area (sheet->row_title_window,
6122 sheet->row_title_area.width,
6123 sheet->row_title_area.height);
6125 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6127 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
6128 gtk_sheet_button_draw(sheet,i,-1);
6133 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
6135 GtkAllocation shentry_allocation;
6136 GtkSheetCellAttr attributes;
6137 GtkEntry *sheet_entry;
6138 GtkStyle *style = NULL, *previous_style = NULL;
6140 gint size, max_size, text_size, column_width;
6143 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6144 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
6146 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
6148 gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes);
6150 if(GTK_WIDGET_REALIZED(sheet->sheet_entry)){
6152 if(!GTK_WIDGET(sheet_entry)->style)
6153 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry));
6155 previous_style = GTK_WIDGET(sheet_entry)->style;
6157 style = gtk_style_copy(previous_style);
6158 style->bg[GTK_STATE_NORMAL] = attributes.background;
6159 style->fg[GTK_STATE_NORMAL] = attributes.foreground;
6160 style->text[GTK_STATE_NORMAL] = attributes.foreground;
6161 style->bg[GTK_STATE_ACTIVE] = attributes.background;
6162 style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
6163 style->text[GTK_STATE_ACTIVE] = attributes.foreground;
6165 pango_font_description_free(style->font_desc);
6166 style->font_desc = pango_font_description_copy(attributes.font_desc);
6168 GTK_WIDGET(sheet_entry)->style = style;
6169 gtk_widget_size_request(sheet->sheet_entry, NULL);
6170 GTK_WIDGET(sheet_entry)->style = previous_style;
6172 if(style != previous_style){
6173 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6174 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
6175 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
6176 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
6177 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
6179 gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
6183 if(GTK_IS_ITEM_ENTRY(sheet_entry))
6184 max_size = GTK_ITEM_ENTRY(sheet_entry)->text_max_size;
6189 text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
6190 if(text && strlen(text) > 0){
6191 text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
6194 column_width=xxx_column_width(sheet, sheet->active_cell.col);
6196 size=MIN(text_size, max_size);
6197 size=MAX(size,column_width-2*CELLOFFSET);
6199 row=sheet->active_cell.row;
6200 col=sheet->active_cell.col;
6202 shentry_allocation.x = COLUMN_LEFT_XPIXEL(sheet,sheet->active_cell.col);
6203 shentry_allocation.y = ROW_TOP_YPIXEL(sheet,sheet->active_cell.row);
6204 shentry_allocation.width = column_width;
6205 shentry_allocation.height = yyy_row_height(sheet, sheet->active_cell.row);
6207 if(GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6209 shentry_allocation.height -= 2*CELLOFFSET;
6210 shentry_allocation.y += CELLOFFSET;
6211 if(gtk_sheet_clip_text(sheet))
6212 shentry_allocation.width = column_width - 2*CELLOFFSET;
6214 shentry_allocation.width = size;
6216 switch(GTK_ITEM_ENTRY(sheet_entry)->justification){
6217 case GTK_JUSTIFY_CENTER:
6218 shentry_allocation.x += (column_width)/2 - size/2;
6220 case GTK_JUSTIFY_RIGHT:
6221 shentry_allocation.x += column_width - size - CELLOFFSET;
6223 case GTK_JUSTIFY_LEFT:
6224 case GTK_JUSTIFY_FILL:
6225 shentry_allocation.x += CELLOFFSET;
6231 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6232 shentry_allocation.x += 2;
6233 shentry_allocation.y += 2;
6234 shentry_allocation.width -= MIN(shentry_allocation.width, 3);
6235 shentry_allocation.height -= MIN(shentry_allocation.height, 3);
6238 gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation);
6240 if(previous_style == style) gtk_style_unref(previous_style);
6244 gtk_sheet_entry_set_max_size(GtkSheet *sheet)
6248 gint sizel=0, sizer=0;
6250 GtkJustification justification;
6252 row=sheet->active_cell.row;
6253 col=sheet->active_cell.col;
6255 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry) || gtk_sheet_clip_text(sheet)) return;
6257 justification = GTK_ITEM_ENTRY(sheet->sheet_entry)->justification;
6259 switch(justification){
6260 case GTK_JUSTIFY_FILL:
6261 case GTK_JUSTIFY_LEFT:
6262 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6263 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6264 size+=xxx_column_width(sheet, i);
6266 size = MIN(size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL(sheet, col));
6268 case GTK_JUSTIFY_RIGHT:
6269 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
6270 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6271 size+=xxx_column_width(sheet, i);
6274 case GTK_JUSTIFY_CENTER:
6275 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6276 /* if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6278 sizer+=xxx_column_width(sheet, i);
6280 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
6281 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6282 sizel+=xxx_column_width(sheet, i);
6284 size=2*MIN(sizel, sizer);
6288 if(size!=0) size+=xxx_column_width(sheet, col);
6289 GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size=size;
6294 create_sheet_entry(GtkSheet *sheet)
6299 gint found_entry = FALSE;
6301 widget = GTK_WIDGET(sheet);
6303 if(sheet->sheet_entry){
6304 /* avoids warnings */
6305 gtk_widget_ref(sheet->sheet_entry);
6306 gtk_widget_unparent(sheet->sheet_entry);
6307 gtk_widget_destroy(sheet->sheet_entry);
6310 if(sheet->entry_type){
6312 if(!g_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY)){
6314 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6316 sheet->sheet_entry = parent;
6318 entry = gtk_sheet_get_entry (sheet);
6319 if(GTK_IS_ENTRY(entry)) found_entry = TRUE;
6323 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6331 g_warning ("Entry type must be GtkEntry subclass, using default");
6332 entry = gtk_item_entry_new();
6333 sheet->sheet_entry = entry;
6337 sheet->sheet_entry = parent;
6344 entry = gtk_item_entry_new();
6345 sheet->sheet_entry = entry;
6349 gtk_widget_size_request(sheet->sheet_entry, NULL);
6351 if(GTK_WIDGET_REALIZED(sheet))
6353 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
6354 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
6355 gtk_widget_realize(sheet->sheet_entry);
6358 gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event",
6359 (GtkSignalFunc) gtk_sheet_entry_key_press,
6362 gtk_widget_show (sheet->sheet_entry);
6366 /* Finds the last child widget that happens to be of type GtkEntry */
6368 find_entry(GtkWidget *w, gpointer user_data)
6370 GtkWidget **entry = user_data;
6371 if ( GTK_IS_ENTRY(w))
6378 gtk_sheet_get_entry(GtkSheet *sheet)
6381 GtkWidget *entry = NULL;
6382 GtkTableChild *table_child;
6383 GtkBoxChild *box_child;
6384 GList *children = NULL;
6386 g_return_val_if_fail (sheet != NULL, NULL);
6387 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6388 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6390 if(GTK_IS_ENTRY(sheet->sheet_entry)) return (sheet->sheet_entry);
6392 parent = GTK_WIDGET(sheet->sheet_entry);
6394 if(GTK_IS_TABLE(parent)) children = GTK_TABLE(parent)->children;
6395 if(GTK_IS_BOX(parent)) children = GTK_BOX(parent)->children;
6397 if(GTK_IS_CONTAINER(parent))
6399 gtk_container_forall(GTK_CONTAINER(parent), find_entry, &entry);
6401 if(GTK_IS_ENTRY(entry))
6405 if(!children) return NULL;
6408 if(GTK_IS_TABLE(parent)) {
6409 table_child = children->data;
6410 entry = table_child->widget;
6412 if(GTK_IS_BOX(parent)){
6413 box_child = children->data;
6414 entry = box_child->widget;
6417 if(GTK_IS_ENTRY(entry))
6419 children = children->next;
6423 if(!GTK_IS_ENTRY(entry)) return NULL;
6430 gtk_sheet_get_entry_widget(GtkSheet *sheet)
6432 g_return_val_if_fail (sheet != NULL, NULL);
6433 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6434 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6436 return (sheet->sheet_entry);
6442 row_button_set (GtkSheet *sheet, gint row)
6444 if(sheet->row[row].button.state == GTK_STATE_ACTIVE) return;
6446 sheet->row[row].button.state = GTK_STATE_ACTIVE;
6447 gtk_sheet_button_draw(sheet, row, -1);
6452 row_button_release (GtkSheet *sheet, gint row)
6454 if(sheet->row[row].button.state == GTK_STATE_NORMAL) return;
6456 sheet->row[row].button.state = GTK_STATE_NORMAL;
6457 gtk_sheet_button_draw(sheet, row, -1);
6462 gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
6464 GdkWindow *window = NULL;
6465 GtkShadowType shadow_type;
6466 guint width = 0, height = 0;
6469 gint text_width = 0, text_height = 0;
6470 const GtkSheetButton *button = NULL;
6471 GtkSheetChild *child = NULL;
6472 GdkRectangle allocation;
6473 gboolean is_sensitive = FALSE;
6478 PangoAlignment align = PANGO_ALIGN_LEFT;
6481 rtl = gtk_widget_get_direction(GTK_WIDGET(sheet)) == GTK_TEXT_DIR_RTL;
6483 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6485 if(row >= 0 && !yyy_row_is_visible(sheet, row)) return;
6486 if(column >= 0 && ! xxx_column_is_visible(sheet, column)) return;
6487 if(row >= 0 && !sheet->row_titles_visible) return;
6488 if(column >= 0 && !sheet->column_titles_visible) return;
6489 if(column>=0 && column < MIN_VISIBLE_COLUMN(sheet)) return;
6490 if(column>=0 && column > MAX_VISIBLE_COLUMN(sheet)) return;
6491 if(row>=0 && row < MIN_VISIBLE_ROW(sheet)) return;
6492 if(row>=0 && row > MAX_VISIBLE_ROW(sheet)) return;
6493 if( (row == -1) && (column == -1) ) return;
6496 window=sheet->column_title_window;
6497 button= xxx_column_button(sheet, column);
6499 x = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING;
6500 if(sheet->row_titles_visible) x -= sheet->row_title_area.width;
6502 width = xxx_column_width(sheet, column);
6503 height = sheet->column_title_area.height;
6504 is_sensitive=xxx_column_is_sensitive(sheet, column);
6507 window=sheet->row_title_window;
6508 button = yyy_row_button(sheet, row);
6511 y = ROW_TOP_YPIXEL(sheet, row)+CELL_SPACING;
6512 if(sheet->column_titles_visible) y-=sheet->column_title_area.height;
6513 width = sheet->row_title_area.width;
6514 height = yyy_row_height(sheet, row);
6515 is_sensitive=yyy_row_is_sensitive(sheet, row);
6520 allocation.width = width;
6521 allocation.height = height;
6523 gdk_window_clear_area (window,
6527 gtk_paint_box (sheet->button->style, window,
6528 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
6529 &allocation, GTK_WIDGET(sheet->button),
6530 "buttondefault", x, y, width, height);
6532 state = button->state;
6533 if(!is_sensitive) state=GTK_STATE_INSENSITIVE;
6535 if (state == GTK_STATE_ACTIVE)
6536 shadow_type = GTK_SHADOW_IN;
6538 shadow_type = GTK_SHADOW_OUT;
6540 if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
6541 gtk_paint_box (sheet->button->style, window,
6542 button->state, shadow_type,
6543 &allocation, GTK_WIDGET(sheet->button),
6544 "button", x, y, width, height);
6546 if(button->label_visible){
6548 text_height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))-2*CELLOFFSET;
6550 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6552 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation);
6554 y += 2*sheet->button->style->ythickness;
6557 if(button->label && strlen(button->label)>0){
6559 PangoLayout *layout = NULL;
6560 gint real_x = x, real_y = y;
6562 words=button->label;
6563 line = g_new(gchar, 1);
6566 while(words && *words != '\0'){
6569 line=g_realloc(line, len+2);
6573 if(*words == '\n' || *(words+1) == '\0'){
6574 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, line);
6576 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), line);
6577 switch(button->justification){
6578 case GTK_JUSTIFY_LEFT:
6579 real_x = x + CELLOFFSET;
6580 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6582 case GTK_JUSTIFY_RIGHT:
6583 real_x = x + width - text_width - CELLOFFSET;
6584 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6586 case GTK_JUSTIFY_CENTER:
6588 real_x = x + (width - text_width)/2;
6589 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6590 pango_layout_set_justify (layout, TRUE);
6592 pango_layout_set_alignment (layout, align);
6593 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6602 g_object_unref(G_OBJECT(layout));
6604 real_y += text_height + 2;
6607 line = g_new(gchar, 1);
6615 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6617 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, NULL);
6621 if((child = button->child) && (child->widget)){
6622 child->x = allocation.x;
6623 child->y = allocation.y;
6625 child->x += (width - child->widget->requisition.width) / 2;
6626 child->y += (height - child->widget->requisition.height) / 2;
6627 allocation.x = child->x;
6628 allocation.y = child->y;
6629 allocation.width = child->widget->requisition.width;
6630 allocation.height = child->widget->requisition.height;
6635 gtk_widget_set_state(child->widget, button->state);
6637 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
6638 GTK_WIDGET_MAPPED(child->widget))
6640 gtk_widget_size_allocate(child->widget,
6642 gtk_widget_queue_draw(child->widget);
6653 * vadjustment_changed
6654 * hadjustment_changed
6655 * vadjustment_value_changed
6656 * hadjustment_value_changed */
6659 adjust_scrollbars (GtkSheet * sheet)
6662 if(sheet->vadjustment){
6663 sheet->vadjustment->page_size = sheet->sheet_window_height;
6664 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
6665 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
6666 sheet->vadjustment->lower = 0;
6667 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
6669 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet))
6671 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) -
6672 sheet->sheet_window_height);
6673 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
6677 gtk_signal_emit_by_name (GTK_OBJECT(sheet->vadjustment), "changed");
6681 if(sheet->hadjustment){
6682 sheet->hadjustment->page_size = sheet->sheet_window_width;
6683 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
6684 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
6685 sheet->hadjustment->lower = 0;
6686 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
6688 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet))
6690 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) -
6691 sheet->sheet_window_width);
6692 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment),
6696 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), "changed");
6700 if(GTK_WIDGET_REALIZED(sheet))
6702 if(sheet->row_titles_visible){
6703 size_allocate_row_title_buttons(sheet);
6704 gdk_window_show(sheet->row_title_window);
6707 if(sheet->column_titles_visible){
6708 size_allocate_column_title_buttons(sheet);
6709 gdk_window_show(sheet->column_title_window);
6712 gtk_sheet_range_draw(sheet, NULL);
6719 vadjustment_changed (GtkAdjustment * adjustment,
6724 g_return_if_fail (adjustment != NULL);
6725 g_return_if_fail (data != NULL);
6727 sheet = GTK_SHEET (data);
6732 hadjustment_changed (GtkAdjustment * adjustment,
6737 g_return_if_fail (adjustment != NULL);
6738 g_return_if_fail (data != NULL);
6740 sheet = GTK_SHEET (data);
6745 vadjustment_value_changed (GtkAdjustment * adjustment,
6749 gint diff, value, old_value;
6753 g_return_if_fail (adjustment != NULL);
6754 g_return_if_fail (data != NULL);
6755 g_return_if_fail (GTK_IS_SHEET (data));
6757 sheet = GTK_SHEET (data);
6759 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6761 row=ROW_FROM_YPIXEL(sheet,sheet->column_title_area.height + CELL_SPACING);
6762 if(!sheet->column_titles_visible)
6763 row=ROW_FROM_YPIXEL(sheet,CELL_SPACING);
6765 old_value = -sheet->voffset;
6767 new_row = g_sheet_row_pixel_to_row(sheet->row_geometry,
6768 adjustment->value,sheet);
6770 y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
6772 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
6773 yyy_row_height(sheet, row) > sheet->vadjustment->step_increment){
6774 /* This avoids embarrassing twitching */
6775 if(row == new_row && row != yyy_row_count(sheet) - 1 &&
6776 adjustment->value - sheet->old_vadjustment >=
6777 sheet->vadjustment->step_increment &&
6778 new_row + 1 != MIN_VISIBLE_ROW(sheet)){
6780 y=y+yyy_row_height(sheet, row);
6784 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6785 if(sheet->old_vadjustment >= 0. && row == new_row){
6786 sheet->old_vadjustment = sheet->vadjustment->value;
6790 sheet->old_vadjustment = sheet->vadjustment->value;
6791 adjustment->value=y;
6795 sheet->vadjustment->step_increment= yyy_row_height(sheet, 0);
6797 sheet->vadjustment->step_increment=
6798 MIN(yyy_row_height(sheet, new_row), yyy_row_height(sheet, new_row-1));
6801 sheet->vadjustment->value=adjustment->value;
6803 value = adjustment->value;
6805 if (value >= -sheet->voffset)
6808 diff = value + sheet->voffset;
6813 diff = -sheet->voffset - value;
6816 sheet->voffset = -value;
6818 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6819 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6820 if(!sheet->column_titles_visible)
6821 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6823 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6824 sheet->state == GTK_SHEET_NORMAL &&
6825 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6826 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6827 sheet->active_cell.col))
6831 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6833 if(!text || strlen(text)==0)
6834 gtk_sheet_cell_clear(sheet,
6835 sheet->active_cell.row,
6836 sheet->active_cell.col);
6837 gtk_widget_unmap(sheet->sheet_entry);
6840 gtk_sheet_position_children(sheet);
6842 gtk_sheet_range_draw(sheet, NULL);
6843 size_allocate_row_title_buttons(sheet);
6844 size_allocate_global_button(sheet);
6848 hadjustment_value_changed (GtkAdjustment * adjustment,
6852 gint i, diff, value, old_value;
6853 gint column, new_column;
6856 g_return_if_fail (adjustment != NULL);
6857 g_return_if_fail (data != NULL);
6858 g_return_if_fail (GTK_IS_SHEET (data));
6860 sheet = GTK_SHEET (data);
6862 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6864 column=COLUMN_FROM_XPIXEL(sheet,sheet->row_title_area.width + CELL_SPACING);
6865 if(!sheet->row_titles_visible)
6866 column=COLUMN_FROM_XPIXEL(sheet, CELL_SPACING);
6868 old_value = -sheet->hoffset;
6870 for(i=0; i < xxx_column_count(sheet); i++)
6872 if(xxx_column_is_visible(sheet, i)) x += xxx_column_width(sheet, i);
6873 if(x > adjustment->value) break;
6875 x-=xxx_column_width(sheet, i);
6878 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
6879 xxx_column_width(sheet, i) > sheet->hadjustment->step_increment){
6880 /* This avoids embarrassing twitching */
6881 if(column == new_column && column != xxx_column_count(sheet) - 1 &&
6882 adjustment->value - sheet->old_hadjustment >=
6883 sheet->hadjustment->step_increment &&
6884 new_column + 1 != MIN_VISIBLE_COLUMN(sheet)){
6886 x=x+xxx_column_width(sheet, column);
6890 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6891 if(sheet->old_hadjustment >= 0. && new_column == column){
6892 sheet->old_hadjustment = sheet->hadjustment->value;
6896 sheet->old_hadjustment = sheet->hadjustment->value;
6897 adjustment->value=x;
6899 if(new_column == 0){
6900 sheet->hadjustment->step_increment=
6901 xxx_column_width(sheet, 0);
6903 sheet->hadjustment->step_increment=
6904 MIN(xxx_column_width(sheet, new_column), xxx_column_width(sheet, new_column-1));
6908 sheet->hadjustment->value=adjustment->value;
6910 value = adjustment->value;
6912 if (value >= -sheet->hoffset)
6915 diff = value + sheet->hoffset;
6920 diff = -sheet->hoffset - value;
6923 sheet->hoffset = -value;
6925 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6926 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6927 if(!sheet->row_titles_visible)
6928 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6930 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6931 sheet->state == GTK_SHEET_NORMAL &&
6932 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6933 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6934 sheet->active_cell.col))
6938 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6939 if(!text || strlen(text)==0)
6940 gtk_sheet_cell_clear(sheet,
6941 sheet->active_cell.row,
6942 sheet->active_cell.col);
6944 gtk_widget_unmap(sheet->sheet_entry);
6947 gtk_sheet_position_children(sheet);
6949 gtk_sheet_range_draw(sheet, NULL);
6950 size_allocate_column_title_buttons(sheet);
6954 /* COLUMN RESIZING */
6956 draw_xor_vline (GtkSheet * sheet)
6960 g_return_if_fail (sheet != NULL);
6962 widget = GTK_WIDGET (sheet);
6964 gdk_draw_line (widget->window, sheet->xor_gc,
6966 sheet->column_title_area.height,
6968 sheet->sheet_window_height + 1);
6973 draw_xor_hline (GtkSheet * sheet)
6977 g_return_if_fail (sheet != NULL);
6979 widget = GTK_WIDGET (sheet);
6981 gdk_draw_line (widget->window, sheet->xor_gc,
6982 sheet->row_title_area.width,
6985 sheet->sheet_window_width + 1,
6989 /* SELECTED RANGE */
6991 draw_xor_rectangle(GtkSheet *sheet, GtkSheetRange range)
6994 GdkRectangle clip_area, area;
6997 area.x=COLUMN_LEFT_XPIXEL(sheet, range.col0);
6998 area.y=ROW_TOP_YPIXEL(sheet, range.row0);
6999 area.width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-area.x+
7000 xxx_column_width(sheet, range.coli);
7001 area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+
7002 yyy_row_height(sheet, range.rowi);
7004 clip_area.x=sheet->row_title_area.width;
7005 clip_area.y=sheet->column_title_area.height;
7006 clip_area.width=sheet->sheet_window_width;
7007 clip_area.height=sheet->sheet_window_height;
7009 if(!sheet->row_titles_visible) clip_area.x = 0;
7010 if(!sheet->column_titles_visible) clip_area.y = 0;
7013 area.width=area.width+area.x;
7016 if(area.width>clip_area.width) area.width=clip_area.width+10;
7018 area.height=area.height+area.y;
7021 if(area.height>clip_area.height) area.height=clip_area.height+10;
7026 clip_area.height+=3;
7028 gdk_gc_get_values(sheet->xor_gc, &values);
7030 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
7033 gdk_draw_rectangle(sheet->sheet_window,
7037 area.width-2*i, area.height-2*i);
7040 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
7042 gdk_gc_set_foreground(sheet->xor_gc, &values.foreground);
7047 /* this function returns the new width of the column being resized given
7048 * the column and x position of the cursor; the x cursor position is passed
7049 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7051 new_column_width (GtkSheet * sheet,
7060 min_width = sheet->column_requisition;
7062 /* you can't shrink a column to less than its minimum width */
7063 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
7065 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
7068 /* don't grow past the end of the window */
7070 if (cx > sheet->sheet_window_width)
7072 *x = cx = sheet->sheet_window_width;
7075 /* calculate new column width making sure it doesn't end up
7076 * less than the minimum width */
7077 width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
7078 if (width < min_width)
7081 xxx_set_column_width(sheet, column, width);
7082 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7083 size_allocate_column_title_buttons (sheet);
7088 /* this function returns the new height of the row being resized given
7089 * the row and y position of the cursor; the y cursor position is passed
7090 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7092 new_row_height (GtkSheet * sheet,
7100 min_height = sheet->row_requisition;
7102 /* you can't shrink a row to less than its minimum height */
7103 if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
7106 *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
7109 /* don't grow past the end of the window */
7111 if (cy > sheet->sheet_window_height)
7113 *y = cy = sheet->sheet_window_height;
7116 /* calculate new row height making sure it doesn't end up
7117 * less than the minimum height */
7118 height = (cy - ROW_TOP_YPIXEL (sheet, row));
7119 if (height < min_height)
7120 height = min_height;
7122 yyy_set_row_height(sheet, row, height);
7123 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
7124 size_allocate_row_title_buttons (sheet);
7130 gtk_sheet_set_column_width (GtkSheet * sheet,
7136 g_return_if_fail (sheet != NULL);
7137 g_return_if_fail (GTK_IS_SHEET (sheet));
7139 if (column < 0 || column >= xxx_column_count(sheet))
7142 gtk_sheet_column_size_request(sheet, column, &min_width);
7143 if(width < min_width) return;
7145 xxx_set_column_width(sheet, column, width);
7147 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7148 size_allocate_column_title_buttons (sheet);
7149 adjust_scrollbars (sheet);
7150 gtk_sheet_size_allocate_entry(sheet);
7151 gtk_sheet_range_draw (sheet, NULL);
7154 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, column);
7155 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_COL_WIDTH], column, width);
7162 gtk_sheet_set_row_height (GtkSheet * sheet,
7168 g_return_if_fail (sheet != NULL);
7169 g_return_if_fail (GTK_IS_SHEET (sheet));
7171 if (row < 0 || row >= yyy_row_count(sheet))
7174 gtk_sheet_row_size_request(sheet, row, &min_height);
7175 if(height < min_height) return;
7177 yyy_set_row_height(sheet, row, height);
7179 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7180 size_allocate_row_title_buttons (sheet);
7181 adjust_scrollbars (sheet);
7182 gtk_sheet_size_allocate_entry(sheet);
7183 gtk_sheet_range_draw (sheet, NULL);
7186 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], row, -1);
7187 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_ROW_HEIGHT], row, height);
7193 gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr *attributes)
7195 const GdkColor *fg, *bg;
7196 const GtkJustification *j ;
7197 const PangoFontDescription *font_desc ;
7198 const GtkSheetCellBorder *border ;
7200 g_return_val_if_fail (sheet != NULL, FALSE);
7201 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
7203 if(row < 0 || col < 0) return FALSE;
7205 init_attributes(sheet, col, attributes);
7210 attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
7211 attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
7213 fg = g_sheet_model_get_foreground(sheet->model, row, col);
7215 attributes->foreground = *fg;
7217 bg = g_sheet_model_get_background(sheet->model, row, col);
7219 attributes->background = *bg;
7221 j = g_sheet_model_get_justification(sheet->model, row, col);
7222 if (j) attributes->justification = *j;
7224 font_desc = g_sheet_model_get_font_desc(sheet->model, row, col);
7225 if ( font_desc ) attributes->font_desc = font_desc;
7227 border = g_sheet_model_get_cell_border(sheet->model, row, col);
7229 if ( border ) attributes->border = *border;
7235 init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
7237 /* DEFAULT VALUES */
7238 attributes->foreground = GTK_WIDGET(sheet)->style->black;
7239 attributes->background = sheet->bg_color;
7240 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
7241 GdkColormap *colormap;
7242 colormap=gdk_colormap_get_system();
7243 gdk_color_black(colormap, &attributes->foreground);
7244 attributes->background = sheet->bg_color;
7246 attributes->justification = xxx_column_justification(sheet, col);
7247 attributes->border.width = 0;
7248 attributes->border.line_style = GDK_LINE_SOLID;
7249 attributes->border.cap_style = GDK_CAP_NOT_LAST;
7250 attributes->border.join_style = GDK_JOIN_MITER;
7251 attributes->border.mask = 0;
7252 attributes->border.color = GTK_WIDGET(sheet)->style->black;
7253 attributes->is_editable = TRUE;
7254 attributes->is_visible = TRUE;
7255 attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
7261 /********************************************************************
7262 * Container Functions:
7267 * gtk_sheet_move_child
7268 * gtk_sheet_position_child
7269 * gtk_sheet_position_children
7270 * gtk_sheet_realize_child
7271 * gtk_sheet_get_child_at
7272 ********************************************************************/
7275 gtk_sheet_put(GtkSheet *sheet, GtkWidget *child, gint x, gint y)
7277 GtkRequisition child_requisition;
7278 GtkSheetChild *child_info;
7280 g_return_val_if_fail(sheet != NULL, NULL);
7281 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7282 g_return_val_if_fail(child != NULL, NULL);
7283 g_return_val_if_fail(child->parent == NULL, NULL);
7285 child_info = g_new (GtkSheetChild, 1);
7286 child_info->widget = child;
7289 child_info->attached_to_cell = FALSE;
7290 child_info->floating = TRUE;
7291 child_info->xpadding = child_info->ypadding = 0;
7292 child_info->xexpand = child_info->yexpand = FALSE;
7293 child_info->xshrink = child_info->yshrink = FALSE;
7294 child_info->xfill = child_info->yfill = FALSE;
7296 sheet->children = g_list_append(sheet->children, child_info);
7298 gtk_widget_set_parent (child, GTK_WIDGET(sheet));
7300 gtk_widget_size_request(child, &child_requisition);
7302 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7304 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7305 (!GTK_WIDGET_REALIZED(child) || GTK_WIDGET_NO_WINDOW(child)))
7306 gtk_sheet_realize_child(sheet, child_info);
7308 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7309 !GTK_WIDGET_MAPPED(child))
7310 gtk_widget_map(child);
7313 gtk_sheet_position_child(sheet, child_info);
7315 /* This will avoid drawing on the titles */
7317 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7319 if(sheet->row_titles_visible)
7320 gdk_window_show(sheet->row_title_window);
7321 if(sheet->column_titles_visible)
7322 gdk_window_show(sheet->column_title_window);
7325 return (child_info);
7329 gtk_sheet_attach_floating (GtkSheet *sheet,
7334 GtkSheetChild *child;
7336 if(row < 0 || col < 0){
7337 gtk_sheet_button_attach(sheet, widget, row, col);
7341 gtk_sheet_get_cell_area(sheet, row, col, &area);
7342 child = gtk_sheet_put(sheet, widget, area.x, area.y);
7343 child->attached_to_cell = TRUE;
7349 gtk_sheet_attach_default (GtkSheet *sheet,
7353 if(row < 0 || col < 0){
7354 gtk_sheet_button_attach(sheet, widget, row, col);
7358 gtk_sheet_attach(sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
7362 gtk_sheet_attach (GtkSheet *sheet,
7371 GtkSheetChild *child = NULL;
7373 if(row < 0 || col < 0){
7374 gtk_sheet_button_attach(sheet, widget, row, col);
7378 child = g_new0(GtkSheetChild, 1);
7379 child->attached_to_cell = TRUE;
7380 child->floating = FALSE;
7381 child->widget = widget;
7384 child->xpadding = xpadding;
7385 child->ypadding = ypadding;
7386 child->xexpand = (xoptions & GTK_EXPAND) != 0;
7387 child->yexpand = (yoptions & GTK_EXPAND) != 0;
7388 child->xshrink = (xoptions & GTK_SHRINK) != 0;
7389 child->yshrink = (yoptions & GTK_SHRINK) != 0;
7390 child->xfill = (xoptions & GTK_FILL) != 0;
7391 child->yfill = (yoptions & GTK_FILL) != 0;
7393 sheet->children = g_list_append(sheet->children, child);
7395 gtk_sheet_get_cell_area(sheet, row, col, &area);
7397 child->x = area.x + child->xpadding;
7398 child->y = area.y + child->ypadding;
7400 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7402 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7403 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7404 gtk_sheet_realize_child(sheet, child);
7406 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7407 !GTK_WIDGET_MAPPED(widget))
7408 gtk_widget_map(widget);
7411 gtk_sheet_position_child(sheet, child);
7413 /* This will avoid drawing on the titles */
7415 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7417 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
7418 gdk_window_show(sheet->row_title_window);
7419 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
7420 gdk_window_show(sheet->column_title_window);
7426 gtk_sheet_button_attach (GtkSheet *sheet,
7430 GtkSheetButton *button = 0;
7431 GtkSheetChild *child;
7432 GtkRequisition button_requisition;
7434 if(row >= 0 && col >= 0) return;
7435 if(row < 0 && col < 0) return;
7437 child = g_new (GtkSheetChild, 1);
7438 child->widget = widget;
7441 child->attached_to_cell = TRUE;
7442 child->floating = FALSE;
7445 child->xpadding = child->ypadding = 0;
7446 child->xshrink = child->yshrink = FALSE;
7447 child->xfill = child->yfill = FALSE;
7450 sheet->children = g_list_append(sheet->children, child);
7452 gtk_sheet_button_size_request(sheet, button, &button_requisition);
7455 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7457 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7458 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7459 gtk_sheet_realize_child(sheet, child);
7461 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7462 !GTK_WIDGET_MAPPED(widget))
7463 gtk_widget_map(widget);
7466 if(row == -1) size_allocate_column_title_buttons(sheet);
7467 if(col == -1) size_allocate_row_title_buttons(sheet);
7472 label_size_request(GtkSheet *sheet, gchar *label, GtkRequisition *req)
7477 gint row_height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)) - 2*CELLOFFSET + 2;
7483 while(words && *words != '\0'){
7484 if(*words == '\n' || *(words+1) == '\0'){
7485 req->height += row_height;
7488 req->width = MAX(req->width, STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, word));
7496 if(n > 0) req->height -= 2;
7500 gtk_sheet_button_size_request (GtkSheet *sheet,
7501 const GtkSheetButton *button,
7502 GtkRequisition *button_requisition)
7504 GtkRequisition requisition;
7505 GtkRequisition label_requisition;
7507 if(gtk_sheet_autoresize(sheet) && button->label && strlen(button->label) > 0){
7508 label_size_request(sheet, button->label, &label_requisition);
7509 label_requisition.width += 2*CELLOFFSET;
7510 label_requisition.height += 2*CELLOFFSET;
7512 label_requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7513 label_requisition.width = COLUMN_MIN_WIDTH;
7518 gtk_widget_size_request(button->child->widget, &requisition);
7519 requisition.width += 2*button->child->xpadding;
7520 requisition.height += 2*button->child->ypadding;
7521 requisition.width += 2*sheet->button->style->xthickness;
7522 requisition.height += 2*sheet->button->style->ythickness;
7526 requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7527 requisition.width = COLUMN_MIN_WIDTH;
7530 *button_requisition = requisition;
7531 button_requisition->width = MAX(requisition.width, label_requisition.width);
7532 button_requisition->height = MAX(requisition.height, label_requisition.height);
7537 gtk_sheet_row_size_request (GtkSheet *sheet,
7541 GtkRequisition button_requisition;
7544 gtk_sheet_button_size_request(sheet,
7545 yyy_row_button(sheet, row),
7546 &button_requisition);
7548 *requisition = button_requisition.height;
7550 children = sheet->children;
7552 GtkSheetChild *child = (GtkSheetChild *)children->data;
7553 GtkRequisition child_requisition;
7555 if(child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink){
7556 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7558 if(child_requisition.height + 2 * child->ypadding > *requisition)
7559 *requisition = child_requisition.height + 2 * child->ypadding;
7561 children = children->next;
7564 sheet->row_requisition = * requisition;
7568 gtk_sheet_column_size_request (GtkSheet *sheet,
7572 GtkRequisition button_requisition;
7575 gtk_sheet_button_size_request(sheet,
7576 xxx_column_button(sheet, col),
7577 &button_requisition);
7579 *requisition = button_requisition.width;
7581 children = sheet->children;
7583 GtkSheetChild *child = (GtkSheetChild *)children->data;
7584 GtkRequisition child_requisition;
7586 if(child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink){
7587 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7589 if(child_requisition.width + 2 * child->xpadding > *requisition)
7590 *requisition = child_requisition.width + 2 * child->xpadding;
7592 children = children->next;
7595 sheet->column_requisition = *requisition;
7599 gtk_sheet_move_child(GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
7601 GtkSheetChild *child;
7604 g_return_if_fail(sheet != NULL);
7605 g_return_if_fail(GTK_IS_SHEET(sheet));
7607 children = sheet->children;
7610 child = children->data;
7612 if(child->widget == widget){
7615 child->row = ROW_FROM_YPIXEL(sheet, y);
7616 child->col = COLUMN_FROM_XPIXEL(sheet, x);
7617 gtk_sheet_position_child(sheet, child);
7621 children = children->next;
7624 g_warning("Widget must be a GtkSheet child");
7629 gtk_sheet_position_child(GtkSheet *sheet, GtkSheetChild *child)
7631 GtkRequisition child_requisition;
7632 GtkAllocation child_allocation;
7638 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7640 if(sheet->column_titles_visible)
7641 yoffset = sheet->column_title_area.height;
7643 if(sheet->row_titles_visible)
7644 xoffset = sheet->row_title_area.width;
7646 if(child->attached_to_cell){
7648 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col);
7649 child->y = ROW_TOP_YPIXEL(sheet, child->row);
7651 if(sheet->row_titles_visible)
7652 child->x-=sheet->row_title_area.width;
7653 if(sheet->column_titles_visible)
7654 child->y-=sheet->column_title_area.height;
7656 width = xxx_column_width(sheet, child->col);
7657 height = yyy_row_height(sheet, child->row);
7660 gtk_sheet_get_cell_area(sheet, child->row, child->col, &area);
7661 child->x = area.x + child->xpadding;
7662 child->y = area.y + child->ypadding;
7664 if(!child->floating){
7665 if(child_requisition.width + 2*child->xpadding <= xxx_column_width(sheet, child->col)){
7667 child_requisition.width = child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7670 child->x = area.x + xxx_column_width(sheet, child->col) / 2 -
7671 child_requisition.width / 2;
7673 child_allocation.width = child_requisition.width;
7676 if(!child->xshrink){
7677 gtk_sheet_set_column_width(sheet, child->col, child_requisition.width + 2 * child->xpadding);
7679 child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7682 if(child_requisition.height + 2*child->ypadding <= yyy_row_height(sheet, child->row)){
7684 child_requisition.height = child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7687 child->y = area.y + yyy_row_height(sheet, child->row) / 2 -
7688 child_requisition.height / 2;
7690 child_allocation.height = child_requisition.height;
7693 if(!child->yshrink){
7694 gtk_sheet_set_row_height(sheet, child->row, child_requisition.height + 2 * child->ypadding);
7696 child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7699 child_allocation.width = child_requisition.width;
7700 child_allocation.height = child_requisition.height;
7703 x = child_allocation.x = child->x + xoffset;
7704 y = child_allocation.y = child->y + yoffset;
7708 x = child_allocation.x = child->x + sheet->hoffset + xoffset;
7709 x = child_allocation.x = child->x + xoffset;
7710 y = child_allocation.y = child->y + sheet->voffset + yoffset;
7711 y = child_allocation.y = child->y + yoffset;
7712 child_allocation.width = child_requisition.width;
7713 child_allocation.height = child_requisition.height;
7716 gtk_widget_size_allocate(child->widget, &child_allocation);
7717 gtk_widget_queue_draw(child->widget);
7721 gtk_sheet_forall (GtkContainer *container,
7722 gboolean include_internals,
7723 GtkCallback callback,
7724 gpointer callback_data)
7727 GtkSheetChild *child;
7730 g_return_if_fail (GTK_IS_SHEET (container));
7731 g_return_if_fail (callback != NULL);
7733 sheet = GTK_SHEET (container);
7734 children = sheet->children;
7737 child = children->data;
7738 children = children->next;
7740 (* callback) (child->widget, callback_data);
7743 (* callback) (sheet->button, callback_data);
7744 if(sheet->sheet_entry)
7745 (* callback) (sheet->sheet_entry, callback_data);
7750 gtk_sheet_position_children(GtkSheet *sheet)
7753 GtkSheetChild *child;
7755 children = sheet->children;
7759 child = (GtkSheetChild *)children->data;
7761 if(child->col !=-1 && child->row != -1)
7762 gtk_sheet_position_child(sheet, child);
7764 if(child->row == -1){
7765 if(child->col < MIN_VISIBLE_COLUMN(sheet) ||
7766 child->col > MAX_VISIBLE_COLUMN(sheet))
7767 gtk_sheet_child_hide(child);
7769 gtk_sheet_child_show(child);
7771 if(child->col == -1){
7772 if(child->row < MIN_VISIBLE_ROW(sheet) ||
7773 child->row > MAX_VISIBLE_ROW(sheet))
7774 gtk_sheet_child_hide(child);
7776 gtk_sheet_child_show(child);
7779 children = children->next;
7785 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
7789 GtkSheetChild *child = 0;
7791 g_return_if_fail(container != NULL);
7792 g_return_if_fail(GTK_IS_SHEET(container));
7794 sheet = GTK_SHEET(container);
7796 children = sheet->children;
7800 child = (GtkSheetChild *)children->data;
7802 if(child->widget == widget) break;
7804 children = children->next;
7809 gtk_widget_unparent (widget);
7810 child->widget = NULL;
7812 sheet->children = g_list_remove_link (sheet->children, children);
7813 g_list_free_1 (children);
7820 gtk_sheet_realize_child(GtkSheet *sheet, GtkSheetChild *child)
7824 widget = GTK_WIDGET(sheet);
7826 if(GTK_WIDGET_REALIZED(widget)){
7827 if(child->row == -1)
7828 gtk_widget_set_parent_window(child->widget, sheet->column_title_window);
7829 else if(child->col == -1)
7830 gtk_widget_set_parent_window(child->widget, sheet->row_title_window);
7832 gtk_widget_set_parent_window(child->widget, sheet->sheet_window);
7835 gtk_widget_set_parent(child->widget, widget);
7841 gtk_sheet_get_child_at(GtkSheet *sheet, gint row, gint col)
7844 GtkSheetChild *child = 0;
7846 g_return_val_if_fail(sheet != NULL, NULL);
7847 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7849 children = sheet->children;
7853 child = (GtkSheetChild *)children->data;
7855 if(child->attached_to_cell)
7856 if(child->row == row && child->col == col) break;
7858 children = children->next;
7861 if(children) return child;
7867 gtk_sheet_child_hide(GtkSheetChild *child)
7869 g_return_if_fail(child != NULL);
7870 gtk_widget_hide(child->widget);
7874 gtk_sheet_child_show(GtkSheetChild *child)
7876 g_return_if_fail(child != NULL);
7878 gtk_widget_show(child->widget);
7882 gtk_sheet_get_model(const GtkSheet *sheet)
7884 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
7886 return sheet->model;