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_FROZEN(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN)
83 #define GTK_SHEET_IN_XDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG)
84 #define GTK_SHEET_IN_YDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG)
85 #define GTK_SHEET_IN_DRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_DRAG)
86 #define GTK_SHEET_IN_SELECTION(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_SELECTION)
87 #define GTK_SHEET_IN_RESIZE(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_RESIZE)
88 #define GTK_SHEET_IN_CLIP(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_CLIP)
89 #define GTK_SHEET_REDRAW_PENDING(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_REDRAW_PENDING)
91 #define CELL_SPACING 1
93 #define TIMEOUT_SCROLL 20
94 #define TIMEOUT_FLASH 200
95 #define TIME_INTERVAL 8
96 #define COLUMN_MIN_WIDTH 10
101 #define DEFAULT_COLUMN_WIDTH 80
108 guint DEFAULT_ROW_HEIGHT(GtkWidget *widget)
110 if(!widget->style->font_desc) return 24;
112 PangoContext *context = gtk_widget_get_pango_context(widget);
113 PangoFontMetrics *metrics = pango_context_get_metrics(context,
114 widget->style->font_desc,
115 pango_context_get_language(context));
116 guint val = pango_font_metrics_get_descent(metrics) +
117 pango_font_metrics_get_ascent(metrics);
118 pango_font_metrics_unref(metrics);
119 return PANGO_PIXELS(val)+2*CELLOFFSET;
122 static inline guint DEFAULT_FONT_ASCENT(GtkWidget *widget)
124 if(!widget->style->font_desc) return 12;
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_ascent(metrics);
131 pango_font_metrics_unref(metrics);
132 return PANGO_PIXELS(val);
135 static inline guint STRING_WIDTH(GtkWidget *widget,
136 const PangoFontDescription *font, const gchar *text)
141 layout = gtk_widget_create_pango_layout (widget, text);
142 pango_layout_set_font_description (layout, font);
144 pango_layout_get_extents (layout, NULL, &rect);
146 g_object_unref(G_OBJECT(layout));
147 return PANGO_PIXELS(rect.width);
150 static inline guint DEFAULT_FONT_DESCENT(GtkWidget *widget)
152 if(!widget->style->font_desc) return 12;
154 PangoContext *context = gtk_widget_get_pango_context(widget);
155 PangoFontMetrics *metrics = pango_context_get_metrics(context,
156 widget->style->font_desc,
157 pango_context_get_language(context));
158 guint val = pango_font_metrics_get_descent(metrics);
159 pango_font_metrics_unref(metrics);
160 return PANGO_PIXELS(val);
166 yyy_row_is_visible(GtkSheet *sheet, gint row)
168 GSheetRow *row_geo = sheet->row_geometry;
170 return g_sheet_row_get_visibility(row_geo, row, sheet);
175 yyy_row_is_sensitive(GtkSheet *sheet, gint row)
177 GSheetRow *row_geo = sheet->row_geometry;
179 return g_sheet_row_get_sensitivity(row_geo, row, sheet);
185 yyy_row_count(const GtkSheet *sheet)
187 GSheetRow *row_geo = sheet->row_geometry;
189 return g_sheet_row_get_row_count(row_geo, sheet);
193 yyy_row_height(const GtkSheet *sheet, gint row)
195 GSheetRow *row_geo = sheet->row_geometry;
197 return g_sheet_row_get_height(row_geo, row, sheet);
201 yyy_row_top_ypixel(GtkSheet *sheet, gint row)
203 GSheetRow *geo = sheet->row_geometry;
205 gint y = g_sheet_row_start_pixel(geo, row, sheet);
207 if ( sheet->column_titles_visible )
208 y += sheet->column_title_area.height;
214 /* Return the row containing pixel Y */
216 yyy_row_ypixel_to_row(GtkSheet *sheet, gint y)
218 GSheetRow *geo = sheet->row_geometry;
220 gint cy = sheet->voffset;
222 if(sheet->column_titles_visible)
223 cy += sheet->column_title_area.height;
228 return g_sheet_row_pixel_to_row(geo, y - cy, sheet);
232 /* gives the top pixel of the given row in context of
233 * the sheet's voffset */
235 ROW_TOP_YPIXEL(GtkSheet *sheet, gint row)
237 return (sheet->voffset + yyy_row_top_ypixel(sheet, row));
241 /* returns the row index from a y pixel location in the
242 * context of the sheet's voffset */
244 ROW_FROM_YPIXEL(GtkSheet *sheet, gint y)
246 return (yyy_row_ypixel_to_row(sheet, y));
249 static inline const GtkSheetButton *
250 xxx_column_button(GtkSheet *sheet, gint col)
252 GSheetColumn *col_geo = sheet->column_geometry;
254 return g_sheet_column_get_button(col_geo, col, sheet);
259 xxx_column_left_xpixel(GtkSheet *sheet, gint col)
261 GSheetColumn *geo = sheet->column_geometry;
263 gint x = g_sheet_column_start_pixel(geo, col, sheet);
265 if ( sheet->row_titles_visible )
266 x += sheet->row_title_area.width;
272 xxx_column_width(const GtkSheet *sheet, gint col)
274 GSheetColumn *col_geo = sheet->column_geometry;
276 return g_sheet_column_get_width(col_geo, col, sheet);
281 xxx_set_column_width(GtkSheet *sheet, gint col, gint width)
283 if ( sheet->column_geometry )
284 g_sheet_column_set_width(sheet->column_geometry, col, width, sheet);
288 xxx_column_set_left_column(GtkSheet *sheet, gint col, gint i)
290 GSheetColumn *col_geo = sheet->column_geometry;
292 g_sheet_column_set_left_text_column(col_geo, col, i, sheet);
296 xxx_column_left_column(const GtkSheet *sheet, gint col)
298 GSheetColumn *col_geo = sheet->column_geometry;
300 return g_sheet_column_get_left_text_column(col_geo, col, sheet);
304 xxx_column_set_right_column(GtkSheet *sheet, gint col, gint i)
306 GSheetColumn *col_geo = sheet->column_geometry;
308 g_sheet_column_set_right_text_column(col_geo, col, i, sheet);
312 xxx_column_right_column(const GtkSheet *sheet, gint col)
314 GSheetColumn *col_geo = sheet->column_geometry;
316 return g_sheet_column_get_right_text_column(col_geo, col, sheet);
319 static inline GtkJustification
320 xxx_column_justification(const GtkSheet *sheet, gint col)
322 GSheetColumn *col_geo = sheet->column_geometry;
324 return g_sheet_column_get_justification(col_geo, col, sheet);
328 xxx_column_is_visible(GtkSheet *sheet, gint col)
330 GSheetColumn *col_geo = sheet->column_geometry;
332 return g_sheet_column_get_visibility(col_geo, col, sheet);
337 xxx_column_is_sensitive(GtkSheet *sheet, gint col)
339 GSheetColumn *col_geo = sheet->column_geometry;
341 return g_sheet_column_get_sensitivity(col_geo, col, sheet);
345 /* gives the left pixel of the given column in context of
346 * the sheet's hoffset */
348 COLUMN_LEFT_XPIXEL(GtkSheet *sheet, gint ncol)
350 return (sheet->hoffset + xxx_column_left_xpixel(sheet, ncol));
354 xxx_column_count(const GtkSheet *sheet)
356 GSheetColumn *col_geo = sheet->column_geometry;
358 return g_sheet_column_get_column_count(col_geo, sheet);
361 /* returns the column index from a x pixel location in the
362 * context of the sheet's hoffset */
364 COLUMN_FROM_XPIXEL (GtkSheet * sheet,
370 if( sheet->row_titles_visible )
371 cx += sheet->row_title_area.width;
374 for (i = 0; i < xxx_column_count(sheet); i++)
376 if (x >= cx && x <= (cx + xxx_column_width(sheet, i)) &&
377 xxx_column_is_visible(sheet, i))
379 if( xxx_column_is_visible(sheet, i))
380 cx += xxx_column_width(sheet, i);
384 return xxx_column_count(sheet) - 1;
387 /* returns the total height of the sheet */
388 static inline gint SHEET_HEIGHT(GtkSheet *sheet)
390 const gint n_rows = yyy_row_count(sheet);
392 return yyy_row_top_ypixel(sheet, n_rows - 1) +
393 yyy_row_height(sheet, n_rows - 1);
397 static inline const GtkSheetButton *
398 yyy_row_button(GtkSheet *sheet, gint row)
400 GSheetRow *row_geo = sheet->row_geometry;
402 return g_sheet_row_get_button(row_geo, row, sheet);
409 yyy_set_row_height(GtkSheet *sheet, gint row, gint height)
411 if ( sheet->row_geometry )
412 g_sheet_row_set_height(sheet->row_geometry, row, height, sheet);
417 /* returns the total width of the sheet */
418 static inline gint SHEET_WIDTH(GtkSheet *sheet)
422 cx = ( sheet->row_titles_visible ? sheet->row_title_area.width : 0);
424 for (i=0; i < xxx_column_count(sheet); i++)
425 if(xxx_column_is_visible(sheet, i)) cx += xxx_column_width(sheet, i);
430 #define MIN_VISIBLE_ROW(sheet) sheet->view.row0
431 #define MAX_VISIBLE_ROW(sheet) sheet->view.rowi
432 #define MIN_VISIBLE_COLUMN(sheet) sheet->view.col0
433 #define MAX_VISIBLE_COLUMN(sheet) sheet->view.coli
437 POSSIBLE_XDRAG(GtkSheet *sheet, gint x, gint *drag_column)
441 column=COLUMN_FROM_XPIXEL(sheet, x);
444 xdrag=COLUMN_LEFT_XPIXEL(sheet,column)+CELL_SPACING;
445 if(x <= xdrag+DRAG_WIDTH/2 && column != 0){
446 while(! xxx_column_is_visible(sheet, column-1) && column>0) column--;
447 *drag_column=column-1;
448 return xxx_column_is_sensitive(sheet, column-1);
451 xdrag+= xxx_column_width(sheet, column);
452 if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag+DRAG_WIDTH/2)
453 return xxx_column_is_sensitive(sheet, column);
459 POSSIBLE_YDRAG(GtkSheet *sheet, gint y, gint *drag_row)
463 row=ROW_FROM_YPIXEL(sheet, y);
466 ydrag=ROW_TOP_YPIXEL(sheet,row)+CELL_SPACING;
467 if(y <= ydrag+DRAG_WIDTH/2 && row != 0){
468 while(!yyy_row_is_visible(sheet, row-1) && row>0) row--;
470 return yyy_row_is_sensitive(sheet, row-1);
473 ydrag+=yyy_row_height(sheet, row);
475 if(y >= ydrag-DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2)
476 return yyy_row_is_sensitive(sheet, row);
482 static inline gint POSSIBLE_DRAG(GtkSheet *sheet, gint x, gint y,
483 gint *drag_row, gint *drag_column)
487 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
488 *drag_row=ROW_FROM_YPIXEL(sheet,y);
490 if(x>=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0)-DRAG_WIDTH/2 &&
491 x<=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
492 xxx_column_width(sheet, sheet->range.coli) + DRAG_WIDTH/2){
493 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.row0);
494 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
495 *drag_row=sheet->range.row0;
498 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
499 yyy_row_height(sheet, sheet->range.rowi);
500 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
501 *drag_row=sheet->range.rowi;
506 if(y>=ROW_TOP_YPIXEL(sheet,sheet->range.row0)-DRAG_WIDTH/2 &&
507 y<=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
508 yyy_row_height(sheet, sheet->range.rowi)+DRAG_WIDTH/2){
509 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0);
510 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
511 *drag_column=sheet->range.col0;
514 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
515 xxx_column_width(sheet, sheet->range.coli);
516 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
517 *drag_column=sheet->range.coli;
524 static inline gint POSSIBLE_RESIZE(GtkSheet *sheet, gint x, gint y,
525 gint *drag_row, gint *drag_column)
529 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
530 xxx_column_width(sheet, sheet->range.coli);
532 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
533 yyy_row_height(sheet, sheet->range.rowi);
535 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
536 ydrag = ROW_TOP_YPIXEL(sheet, sheet->view.row0);
538 if(sheet->state == GTK_SHEET_ROW_SELECTED)
539 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0);
541 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
542 *drag_row=ROW_FROM_YPIXEL(sheet,y);
544 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2 &&
545 y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2) return TRUE;
550 static void gtk_sheet_class_init (GtkSheetClass * klass);
551 static void gtk_sheet_init (GtkSheet * sheet);
552 static void gtk_sheet_destroy (GtkObject * object);
553 static void gtk_sheet_finalize (GObject * object);
554 static void gtk_sheet_style_set (GtkWidget *widget,
555 GtkStyle *previous_style);
556 static void gtk_sheet_realize (GtkWidget * widget);
557 static void gtk_sheet_unrealize (GtkWidget * widget);
558 static void gtk_sheet_map (GtkWidget * widget);
559 static void gtk_sheet_unmap (GtkWidget * widget);
560 static gint gtk_sheet_expose (GtkWidget * widget,
561 GdkEventExpose * event);
562 static void gtk_sheet_forall (GtkContainer *container,
563 gboolean include_internals,
564 GtkCallback callback,
565 gpointer callback_data);
567 static void gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
568 GtkAdjustment *hadjustment,
569 GtkAdjustment *vadjustment);
571 static gint gtk_sheet_button_press (GtkWidget * widget,
572 GdkEventButton * event);
573 static gint gtk_sheet_button_release (GtkWidget * widget,
574 GdkEventButton * event);
575 static gint gtk_sheet_motion (GtkWidget * widget,
576 GdkEventMotion * event);
577 static gint gtk_sheet_entry_key_press (GtkWidget *widget,
579 static gint gtk_sheet_key_press (GtkWidget *widget,
581 static void gtk_sheet_size_request (GtkWidget * widget,
582 GtkRequisition * requisition);
583 static void gtk_sheet_size_allocate (GtkWidget * widget,
584 GtkAllocation * allocation);
588 static gint gtk_sheet_range_isvisible (GtkSheet * sheet,
589 GtkSheetRange range);
590 static gint gtk_sheet_cell_isvisible (GtkSheet * sheet,
591 gint row, gint column);
594 static gint gtk_sheet_scroll (gpointer data);
595 static gint gtk_sheet_flash (gpointer data);
597 /* Drawing Routines */
599 /* draw cell background and frame */
600 static void gtk_sheet_cell_draw_default (GtkSheet *sheet,
601 gint row, gint column);
603 /* draw cell border */
604 static void gtk_sheet_cell_draw_border (GtkSheet *sheet,
605 gint row, gint column,
608 /* draw cell contents */
609 static void gtk_sheet_cell_draw_label (GtkSheet *sheet,
610 gint row, gint column);
612 /* draw visible part of range. If range==NULL then draw the whole screen */
613 static void gtk_sheet_range_draw (GtkSheet *sheet,
614 const GtkSheetRange *range);
616 /* highlight the visible part of the selected range */
617 static void gtk_sheet_range_draw_selection (GtkSheet *sheet,
618 GtkSheetRange range);
622 static gint gtk_sheet_move_query (GtkSheet *sheet,
623 gint row, gint column);
624 static void gtk_sheet_real_select_range (GtkSheet * sheet,
625 GtkSheetRange * range);
626 static void gtk_sheet_real_unselect_range (GtkSheet * sheet,
627 const GtkSheetRange * range);
628 static void gtk_sheet_extend_selection (GtkSheet *sheet,
629 gint row, gint column);
630 static void gtk_sheet_new_selection (GtkSheet *sheet,
631 GtkSheetRange *range);
632 static void gtk_sheet_draw_border (GtkSheet *sheet,
633 GtkSheetRange range);
634 static void gtk_sheet_draw_corners (GtkSheet *sheet,
635 GtkSheetRange range);
638 /* Active Cell handling */
640 static void gtk_sheet_entry_changed (GtkWidget *widget,
642 static gboolean gtk_sheet_deactivate_cell (GtkSheet *sheet);
643 static void gtk_sheet_hide_active_cell (GtkSheet *sheet);
644 static gboolean gtk_sheet_activate_cell (GtkSheet *sheet,
646 static void gtk_sheet_draw_active_cell (GtkSheet *sheet);
647 static void gtk_sheet_show_active_cell (GtkSheet *sheet);
648 static void gtk_sheet_click_cell (GtkSheet *sheet,
655 static void gtk_sheet_make_backing_pixmap (GtkSheet *sheet,
656 guint width, guint height);
657 static void gtk_sheet_draw_backing_pixmap (GtkSheet *sheet,
658 GtkSheetRange range);
661 static void adjust_scrollbars (GtkSheet * sheet);
662 static void vadjustment_changed (GtkAdjustment * adjustment,
664 static void hadjustment_changed (GtkAdjustment * adjustment,
666 static void vadjustment_value_changed (GtkAdjustment * adjustment,
668 static void hadjustment_value_changed (GtkAdjustment * adjustment,
672 static void draw_xor_vline (GtkSheet * sheet);
673 static void draw_xor_hline (GtkSheet * sheet);
674 static void draw_xor_rectangle (GtkSheet *sheet,
675 GtkSheetRange range);
676 static void gtk_sheet_draw_flashing_range (GtkSheet *sheet,
677 GtkSheetRange range);
678 static guint new_column_width (GtkSheet * sheet,
681 static guint new_row_height (GtkSheet * sheet,
686 static void create_global_button (GtkSheet *sheet);
687 static void global_button_clicked (GtkWidget *widget,
691 static void create_sheet_entry (GtkSheet *sheet);
692 static void gtk_sheet_size_allocate_entry (GtkSheet *sheet);
693 static void gtk_sheet_entry_set_max_size (GtkSheet *sheet);
695 /* Sheet button gadgets */
697 static void size_allocate_column_title_buttons (GtkSheet * sheet);
698 static void size_allocate_row_title_buttons (GtkSheet * sheet);
701 static void gtk_sheet_button_draw (GtkSheet *sheet,
702 gint row, gint column);
703 static void size_allocate_global_button (GtkSheet *sheet);
704 static void gtk_sheet_button_size_request (GtkSheet *sheet,
705 const GtkSheetButton *button,
706 GtkRequisition *requisition);
708 /* Attributes routines */
709 static void init_attributes (GtkSheet *sheet, gint col,
710 GtkSheetCellAttr *attributes);
713 /* Memory allocation routines */
714 static void gtk_sheet_real_range_clear (GtkSheet *sheet,
715 const GtkSheetRange *range,
717 static void gtk_sheet_real_cell_clear (GtkSheet *sheet,
723 /* Container Functions */
724 static void gtk_sheet_remove (GtkContainer *container,
726 static void gtk_sheet_realize_child (GtkSheet *sheet,
727 GtkSheetChild *child);
728 static void gtk_sheet_position_child (GtkSheet *sheet,
729 GtkSheetChild *child);
730 static void gtk_sheet_position_children (GtkSheet *sheet);
731 static void gtk_sheet_child_show (GtkSheetChild *child);
732 static void gtk_sheet_child_hide (GtkSheetChild *child);
733 static void gtk_sheet_column_size_request (GtkSheet *sheet,
736 static void gtk_sheet_row_size_request (GtkSheet *sheet,
744 _gtkextra_signal_emit(GtkObject *object, guint signal_id, ...);
766 static GtkContainerClass *parent_class = NULL;
767 static guint sheet_signals[LAST_SIGNAL] = {0};
771 gtk_sheet_get_type ()
773 static GType sheet_type = 0;
777 static const GTypeInfo sheet_info =
779 sizeof (GtkSheetClass),
782 (GClassInitFunc) gtk_sheet_class_init,
787 (GInstanceInitFunc) gtk_sheet_init,
791 g_type_register_static (GTK_TYPE_CONTAINER, "GtkSheet",
797 static GtkSheetRange*
798 gtk_sheet_range_copy (const GtkSheetRange *range)
800 GtkSheetRange *new_range;
802 g_return_val_if_fail (range != NULL, NULL);
804 new_range = g_new (GtkSheetRange, 1);
812 gtk_sheet_range_free (GtkSheetRange *range)
814 g_return_if_fail (range != NULL);
820 gtk_sheet_range_get_type (void)
822 static GType sheet_range_type=0;
824 if(!sheet_range_type)
826 sheet_range_type = g_boxed_type_register_static("GtkSheetRange", (GBoxedCopyFunc)gtk_sheet_range_copy, (GBoxedFreeFunc)gtk_sheet_range_free);
828 return sheet_range_type;
833 gtk_sheet_class_init (GtkSheetClass * klass)
835 GtkObjectClass *object_class;
836 GtkWidgetClass *widget_class;
837 GtkContainerClass *container_class;
838 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
840 object_class = (GtkObjectClass *) klass;
841 widget_class = (GtkWidgetClass *) klass;
842 container_class = (GtkContainerClass *) klass;
844 parent_class = g_type_class_peek_parent (klass);
847 * GtkSheet::select-row
848 * @sheet: the sheet widget that emitted the signal
849 * @row: the newly selected row index
851 * A row has been selected.
853 sheet_signals[SELECT_ROW] =
854 gtk_signal_new ("select-row",
856 GTK_CLASS_TYPE(object_class),
857 GTK_SIGNAL_OFFSET (GtkSheetClass, select_row),
859 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
862 * GtkSheet::select-column
863 * @sheet: the sheet widget that emitted the signal
864 * @column: the newly selected column index
866 * A column has been selected.
868 sheet_signals[SELECT_COLUMN] =
869 gtk_signal_new ("select-column",
871 GTK_CLASS_TYPE(object_class),
872 GTK_SIGNAL_OFFSET (GtkSheetClass, select_column),
874 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
878 * GtkSheet::double-click-row
879 * @sheet: the sheet widget that emitted the signal
880 * @row: the row that was double clicked.
882 * A row's title button has been double clicked
884 sheet_signals[DOUBLE_CLICK_ROW] =
885 gtk_signal_new ("double-click-row",
887 GTK_CLASS_TYPE(object_class),
890 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
894 * GtkSheet::double-click-column
895 * @sheet: the sheet widget that emitted the signal
896 * @column: the column that was double clicked.
898 * A column's title button has been double clicked
900 sheet_signals[DOUBLE_CLICK_COLUMN] =
901 gtk_signal_new ("double-click-column",
903 GTK_CLASS_TYPE(object_class),
906 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
908 sheet_signals[SELECT_RANGE] =
909 gtk_signal_new ("select-range",
911 GTK_CLASS_TYPE(object_class),
912 GTK_SIGNAL_OFFSET (GtkSheetClass, select_range),
913 gtkextra_VOID__BOXED,
914 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
916 sheet_signals[CLIP_RANGE] =
917 gtk_signal_new ("clip-range",
919 GTK_CLASS_TYPE(object_class),
920 GTK_SIGNAL_OFFSET (GtkSheetClass, clip_range),
921 gtkextra_VOID__BOXED,
922 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
924 sheet_signals[RESIZE_RANGE] =
925 gtk_signal_new ("resize-range",
927 GTK_CLASS_TYPE(object_class),
928 GTK_SIGNAL_OFFSET (GtkSheetClass, resize_range),
929 gtkextra_VOID__BOXED_BOXED,
930 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
931 sheet_signals[MOVE_RANGE] =
932 gtk_signal_new ("move-range",
934 GTK_CLASS_TYPE(object_class),
935 GTK_SIGNAL_OFFSET (GtkSheetClass, move_range),
936 gtkextra_VOID__BOXED_BOXED,
937 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
938 sheet_signals[TRAVERSE] =
939 gtk_signal_new ("traverse",
941 GTK_CLASS_TYPE(object_class),
942 GTK_SIGNAL_OFFSET (GtkSheetClass, traverse),
943 gtkextra_BOOLEAN__INT_INT_POINTER_POINTER,
944 GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT,
945 GTK_TYPE_POINTER, GTK_TYPE_POINTER);
947 sheet_signals[DEACTIVATE] =
948 gtk_signal_new ("deactivate",
950 GTK_CLASS_TYPE(object_class),
951 GTK_SIGNAL_OFFSET (GtkSheetClass, deactivate),
952 gtkextra_BOOLEAN__INT_INT,
953 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
955 sheet_signals[ACTIVATE] =
956 gtk_signal_new ("activate",
958 GTK_CLASS_TYPE(object_class),
959 GTK_SIGNAL_OFFSET (GtkSheetClass, activate),
960 gtkextra_BOOLEAN__INT_INT,
961 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
963 sheet_signals[SET_CELL] =
964 gtk_signal_new ("set-cell",
966 GTK_CLASS_TYPE(object_class),
967 GTK_SIGNAL_OFFSET (GtkSheetClass, set_cell),
968 gtkextra_VOID__INT_INT,
969 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
971 sheet_signals[CLEAR_CELL] =
972 gtk_signal_new ("clear-cell",
974 GTK_CLASS_TYPE(object_class),
975 GTK_SIGNAL_OFFSET (GtkSheetClass, clear_cell),
976 gtkextra_VOID__INT_INT,
977 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
979 sheet_signals[CHANGED] =
980 gtk_signal_new ("changed",
982 GTK_CLASS_TYPE(object_class),
983 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
984 gtkextra_VOID__INT_INT,
985 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
987 sheet_signals[NEW_COL_WIDTH] =
988 gtk_signal_new ("new-column-width",
990 GTK_CLASS_TYPE(object_class),
991 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
992 gtkextra_VOID__INT_INT,
993 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
995 sheet_signals[NEW_ROW_HEIGHT] =
996 gtk_signal_new ("new-row-height",
998 GTK_CLASS_TYPE(object_class),
999 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1000 gtkextra_VOID__INT_INT,
1001 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1003 widget_class->set_scroll_adjustments_signal =
1004 gtk_signal_new ("set-scroll-adjustments",
1006 GTK_CLASS_TYPE(object_class),
1007 GTK_SIGNAL_OFFSET (GtkSheetClass, set_scroll_adjustments),
1008 gtkextra_VOID__OBJECT_OBJECT,
1009 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1012 container_class->add = NULL;
1013 container_class->remove = gtk_sheet_remove;
1014 container_class->forall = gtk_sheet_forall;
1016 object_class->destroy = gtk_sheet_destroy;
1017 gobject_class->finalize = gtk_sheet_finalize;
1019 widget_class->realize = gtk_sheet_realize;
1020 widget_class->unrealize = gtk_sheet_unrealize;
1021 widget_class->map = gtk_sheet_map;
1022 widget_class->unmap = gtk_sheet_unmap;
1023 widget_class->style_set = gtk_sheet_style_set;
1024 widget_class->button_press_event = gtk_sheet_button_press;
1025 widget_class->button_release_event = gtk_sheet_button_release;
1026 widget_class->motion_notify_event = gtk_sheet_motion;
1027 widget_class->key_press_event = gtk_sheet_key_press;
1028 widget_class->expose_event = gtk_sheet_expose;
1029 widget_class->size_request = gtk_sheet_size_request;
1030 widget_class->size_allocate = gtk_sheet_size_allocate;
1031 widget_class->focus_in_event = NULL;
1032 widget_class->focus_out_event = NULL;
1034 klass->set_scroll_adjustments = gtk_sheet_set_scroll_adjustments;
1035 klass->select_row = NULL;
1036 klass->select_column = NULL;
1037 klass->select_range = NULL;
1038 klass->clip_range = NULL;
1039 klass->resize_range = NULL;
1040 klass->move_range = NULL;
1041 klass->traverse = NULL;
1042 klass->deactivate = NULL;
1043 klass->activate = NULL;
1044 klass->set_cell = NULL;
1045 klass->clear_cell = NULL;
1046 klass->changed = NULL;
1051 gtk_sheet_init (GtkSheet *sheet)
1053 sheet->column_geometry = NULL;
1054 sheet->row_geometry = NULL;
1056 sheet->children = NULL;
1059 sheet->selection_mode = GTK_SELECTION_BROWSE;
1060 sheet->freeze_count = 0;
1061 sheet->state = GTK_SHEET_NORMAL;
1063 GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW);
1064 GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS);
1066 sheet->view.row0 = 0;
1067 sheet->view.col0 = 0;
1068 sheet->view.rowi = 0;
1069 sheet->view.coli = 0;
1071 sheet->column_title_window=NULL;
1072 sheet->column_title_area.x=0;
1073 sheet->column_title_area.y=0;
1074 sheet->column_title_area.width=0;
1075 sheet->column_title_area.height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
1077 sheet->row_title_window=NULL;
1078 sheet->row_title_area.x=0;
1079 sheet->row_title_area.y=0;
1080 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1081 sheet->row_title_area.height=0;
1084 sheet->active_cell.row=0;
1085 sheet->active_cell.col=0;
1086 sheet->selection_cell.row=0;
1087 sheet->selection_cell.col=0;
1089 sheet->sheet_entry=NULL;
1092 sheet->range.row0=0;
1093 sheet->range.rowi=0;
1094 sheet->range.col0=0;
1095 sheet->range.coli=0;
1097 sheet->state=GTK_SHEET_NORMAL;
1099 sheet->sheet_window = NULL;
1100 sheet->sheet_window_width = 0;
1101 sheet->sheet_window_height = 0;
1102 sheet->sheet_entry = NULL;
1103 sheet->button = NULL;
1108 sheet->hadjustment = NULL;
1109 sheet->vadjustment = NULL;
1111 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
1112 sheet->xor_gc = NULL;
1113 sheet->fg_gc = NULL;
1114 sheet->bg_gc = NULL;
1118 gdk_color_parse("white", &sheet->bg_color);
1119 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1120 gdk_color_parse("gray", &sheet->grid_color);
1121 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1122 sheet->show_grid = TRUE;
1127 rows_deleted_callback (GSheetModel *m, gint first_row, gint n_rows,
1130 GtkSheet *sheet = GTK_SHEET(data);
1132 GtkSheetRange range;
1134 range.row0 = first_row;
1136 range.rowi = yyy_row_count(sheet) - 1;
1137 range.coli = xxx_column_count(sheet) - 1;
1139 gtk_sheet_range_draw(sheet, &range);
1143 If row0 or rowi are negative, then all rows will be updated.
1144 If col0 or coli are negative, then all columns will be updated.
1147 range_update_callback (GSheetModel *m, gint row0, gint col0,
1148 gint rowi, gint coli, gpointer data)
1150 GtkSheet *sheet = GTK_SHEET(data);
1152 GtkSheetRange range;
1159 if( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
1161 gtk_sheet_range_draw(sheet, NULL);
1164 else if ( row0 < 0 || rowi < 0 )
1166 range.row0=MIN_VISIBLE_ROW(sheet);
1167 range.rowi=MAX_VISIBLE_ROW(sheet);
1169 else if ( col0 < 0 || coli < 0 )
1171 range.col0=MIN_VISIBLE_COLUMN(sheet);
1172 range.coli=MAX_VISIBLE_COLUMN(sheet);
1175 gtk_sheet_range_draw(sheet, &range);
1179 static void gtk_sheet_construct (GtkSheet *sheet,
1182 const gchar *title);
1187 * @rows: initial number of rows
1188 * @columns: initial number of columns
1189 * @title: sheet title
1190 * @model: the model to use for the sheet data
1192 * Creates a new sheet widget with the given number of rows and columns.
1194 * Returns: the new sheet widget
1197 gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, const gchar *title,
1202 widget = gtk_type_new (gtk_sheet_get_type ());
1204 gtk_sheet_construct(GTK_SHEET(widget), vgeo, hgeo, title);
1207 gtk_sheet_set_model(GTK_SHEET(widget), model);
1215 * gtk_sheet_set_model
1216 * @sheet: the sheet to set the model for
1217 * @model: the model to use for the sheet data
1219 * Sets the model for a GtkSheet
1223 gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model)
1225 g_return_if_fail (GTK_IS_SHEET (sheet));
1226 g_return_if_fail (G_IS_SHEET_MODEL (model));
1228 sheet->model = model;
1230 g_signal_connect(model, "range_changed",
1231 G_CALLBACK(range_update_callback), sheet);
1233 g_signal_connect(model, "rows_deleted",
1234 G_CALLBACK(rows_deleted_callback), sheet);
1241 column_titles_changed(GtkWidget *w, gint first, gint n_columns, gpointer data)
1243 GtkSheet *sheet = GTK_SHEET(data);
1246 if(!GTK_SHEET_IS_FROZEN(sheet)){
1248 for ( i = first ; i <= MAX_VISIBLE_COLUMN(sheet) ; ++i )
1250 gtk_sheet_button_draw(sheet, -1, i);
1251 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, i);
1257 gtk_sheet_construct (GtkSheet *sheet,
1262 g_return_if_fail(G_IS_SHEET_COLUMN(hgeo));
1263 g_return_if_fail(G_IS_SHEET_ROW(vgeo));
1265 sheet->column_geometry = hgeo;
1266 sheet->row_geometry = vgeo;
1269 sheet->columns_resizable = TRUE;
1270 sheet->rows_resizable = TRUE;
1272 sheet->row_titles_visible = TRUE;
1273 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1275 sheet->column_titles_visible = TRUE;
1276 sheet->autoscroll = TRUE;
1277 sheet->justify_entry = TRUE;
1278 sheet->locked = FALSE;
1281 /* create sheet entry */
1282 sheet->entry_type = 0;
1283 create_sheet_entry (sheet);
1285 /* create global selection button */
1286 create_global_button(sheet);
1289 sheet->name = g_strdup(title);
1291 g_signal_connect(sheet->column_geometry, "columns_changed",
1292 G_CALLBACK(column_titles_changed), sheet);
1298 gtk_sheet_new_with_custom_entry (GSheetRow *rows, GSheetColumn *columns, const gchar *title,
1303 widget = gtk_type_new (gtk_sheet_get_type ());
1305 gtk_sheet_construct_with_custom_entry(GTK_SHEET(widget),
1306 rows, columns, title, entry_type);
1312 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet,
1318 gtk_sheet_construct(sheet, vgeo, hgeo, title);
1320 sheet->entry_type = entry_type;
1321 create_sheet_entry(sheet);
1327 gtk_sheet_change_entry(GtkSheet *sheet, GtkType entry_type)
1331 g_return_if_fail (sheet != NULL);
1332 g_return_if_fail (GTK_IS_SHEET (sheet));
1334 state = sheet->state;
1336 if(sheet->state == GTK_SHEET_NORMAL)
1337 gtk_sheet_hide_active_cell(sheet);
1339 sheet->entry_type = entry_type;
1341 create_sheet_entry(sheet);
1343 if(state == GTK_SHEET_NORMAL)
1345 gtk_sheet_show_active_cell(sheet);
1346 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
1348 G_CALLBACK(gtk_sheet_entry_changed),
1357 gtk_sheet_show_grid(GtkSheet *sheet, gboolean show)
1359 g_return_if_fail (sheet != NULL);
1360 g_return_if_fail (GTK_IS_SHEET (sheet));
1362 if(show == sheet->show_grid) return;
1364 sheet->show_grid = show;
1366 if(!GTK_SHEET_IS_FROZEN(sheet))
1367 gtk_sheet_range_draw(sheet, NULL);
1371 gtk_sheet_grid_visible(GtkSheet *sheet)
1373 g_return_val_if_fail (sheet != NULL, 0);
1374 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1376 return sheet->show_grid;
1380 gtk_sheet_set_background(GtkSheet *sheet, GdkColor *color)
1382 g_return_if_fail (sheet != NULL);
1383 g_return_if_fail (GTK_IS_SHEET (sheet));
1386 gdk_color_parse("white", &sheet->bg_color);
1387 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1389 sheet->bg_color = *color;
1391 if(!GTK_SHEET_IS_FROZEN(sheet))
1392 gtk_sheet_range_draw(sheet, NULL);
1396 gtk_sheet_set_grid(GtkSheet *sheet, GdkColor *color)
1398 g_return_if_fail (sheet != NULL);
1399 g_return_if_fail (GTK_IS_SHEET (sheet));
1402 gdk_color_parse("black", &sheet->grid_color);
1403 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1405 sheet->grid_color = *color;
1407 if(!GTK_SHEET_IS_FROZEN(sheet))
1408 gtk_sheet_range_draw(sheet, NULL);
1412 gtk_sheet_get_columns_count(GtkSheet *sheet)
1414 g_return_val_if_fail (sheet != NULL, 0);
1415 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1417 return xxx_column_count(sheet);
1421 gtk_sheet_get_rows_count(GtkSheet *sheet)
1423 g_return_val_if_fail (sheet != NULL, 0);
1424 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1426 return yyy_row_count(sheet);
1430 gtk_sheet_get_state(GtkSheet *sheet)
1432 g_return_val_if_fail (sheet != NULL, 0);
1433 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1435 return (sheet->state);
1439 gtk_sheet_set_selection_mode(GtkSheet *sheet, gint mode)
1441 g_return_if_fail (sheet != NULL);
1442 g_return_if_fail (GTK_IS_SHEET (sheet));
1444 if(GTK_WIDGET_REALIZED(sheet))
1445 gtk_sheet_real_unselect_range(sheet, NULL);
1447 sheet->selection_mode = mode;
1451 gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize)
1453 g_return_if_fail (sheet != NULL);
1454 g_return_if_fail (GTK_IS_SHEET (sheet));
1456 sheet->autoresize = autoresize;
1460 gtk_sheet_autoresize (GtkSheet *sheet)
1462 g_return_val_if_fail (sheet != NULL, FALSE);
1463 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1465 return sheet->autoresize;
1469 gtk_sheet_set_column_width (GtkSheet * sheet,
1475 gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
1477 gint text_width = 0;
1480 g_return_if_fail (sheet != NULL);
1481 g_return_if_fail (GTK_IS_SHEET (sheet));
1482 if (column >= xxx_column_count(sheet) || column < 0) return;
1484 g_print("%s:%d Iterating rows\n",__FILE__, __LINE__);
1485 for (row = 0; row < yyy_row_count(sheet); row++){
1486 const gchar *text = gtk_sheet_cell_get_text(sheet, row, column);
1487 if (text && strlen(text) > 0){
1488 GtkSheetCellAttr attributes;
1490 gtk_sheet_get_attributes(sheet, row, column, &attributes);
1491 if(attributes.is_visible){
1492 gint width = STRING_WIDTH(GTK_WIDGET(sheet),
1493 attributes.font_desc,
1495 + 2*CELLOFFSET + attributes.border.width;
1496 text_width = MAX (text_width, width);
1501 if(text_width > xxx_column_width(sheet, column) )
1503 gtk_sheet_set_column_width(sheet, column, text_width);
1504 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
1510 gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll)
1512 g_return_if_fail (sheet != NULL);
1513 g_return_if_fail (GTK_IS_SHEET (sheet));
1515 sheet->autoscroll = autoscroll;
1519 gtk_sheet_autoscroll (GtkSheet *sheet)
1521 g_return_val_if_fail (sheet != NULL, FALSE);
1522 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1524 return sheet->autoscroll;
1528 gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text)
1530 g_return_if_fail (sheet != NULL);
1531 g_return_if_fail (GTK_IS_SHEET (sheet));
1533 sheet->clip_text = clip_text;
1537 gtk_sheet_clip_text (GtkSheet *sheet)
1539 g_return_val_if_fail (sheet != NULL, FALSE);
1540 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1542 return sheet->clip_text;
1546 gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify)
1548 g_return_if_fail (sheet != NULL);
1549 g_return_if_fail (GTK_IS_SHEET (sheet));
1551 sheet->justify_entry = justify;
1555 gtk_sheet_justify_entry (GtkSheet *sheet)
1557 g_return_val_if_fail (sheet != NULL, FALSE);
1558 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1560 return sheet->justify_entry;
1564 gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked)
1566 g_return_if_fail (sheet != NULL);
1567 g_return_if_fail (GTK_IS_SHEET (sheet));
1569 sheet->locked = locked;
1573 gtk_sheet_locked (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->locked;
1581 /* This routine has problems with gtk+-1.2 related with the
1582 * label/button drawing - I think it's a bug in gtk+-1.2 */
1585 gtk_sheet_set_title(GtkSheet *sheet, const gchar *title)
1587 /* GtkWidget *old_widget;
1588 */ GtkWidget *label;
1590 g_return_if_fail (sheet != NULL);
1591 g_return_if_fail (title != NULL);
1592 g_return_if_fail (GTK_IS_SHEET (sheet));
1595 g_free (sheet->name);
1597 sheet->name = g_strdup (title);
1599 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) || !title) return;
1601 if(GTK_BIN(sheet->button)->child)
1602 label = GTK_BIN(sheet->button)->child;
1604 gtk_label_set_text(GTK_LABEL(label), title);
1606 size_allocate_global_button(sheet);
1608 /* remove and destroy the old widget */
1610 old_widget = GTK_BIN (sheet->button)->child;
1613 gtk_container_remove (GTK_CONTAINER (sheet->button), old_widget);
1616 label = gtk_label_new (title);
1617 gtk_misc_set_alignment(GTK_MISC(label), 0.5 , 0.5 );
1619 gtk_container_add (GTK_CONTAINER (sheet->button), label);
1620 gtk_widget_show (label);
1622 size_allocate_global_button(sheet);
1624 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, -1);
1627 gtk_widget_destroy (old_widget);
1632 gtk_sheet_freeze (GtkSheet *sheet)
1634 g_return_if_fail (sheet != NULL);
1635 g_return_if_fail (GTK_IS_SHEET (sheet));
1637 sheet->freeze_count++;
1638 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1642 gtk_sheet_thaw(GtkSheet *sheet)
1644 g_return_if_fail (sheet != NULL);
1645 g_return_if_fail (GTK_IS_SHEET (sheet));
1647 if(sheet->freeze_count == 0) return;
1649 sheet->freeze_count--;
1650 if(sheet->freeze_count > 0) return;
1652 adjust_scrollbars(sheet);
1654 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1656 sheet->old_vadjustment = -1.;
1657 sheet->old_hadjustment = -1.;
1659 if(sheet->hadjustment)
1660 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1662 if(sheet->vadjustment)
1663 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1666 if(sheet->state == GTK_STATE_NORMAL)
1667 if(sheet->sheet_entry && GTK_WIDGET_MAPPED(sheet->sheet_entry)){
1668 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
1670 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
1672 (GtkSignalFunc)gtk_sheet_entry_changed,
1673 GTK_OBJECT(GTK_WIDGET(sheet)));
1674 gtk_sheet_show_active_cell(sheet);
1681 gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width)
1683 if(width < COLUMN_MIN_WIDTH) return;
1685 sheet->row_title_area.width = width;
1686 sheet->view.col0 = COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
1687 sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
1690 adjust_scrollbars(sheet);
1692 sheet->old_hadjustment = -1.;
1693 if(sheet->hadjustment)
1694 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1696 size_allocate_global_button(sheet);
1700 gtk_sheet_set_column_titles_height(GtkSheet *sheet, guint height)
1702 if(height < DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))) return;
1704 sheet->column_title_area.height = height;
1705 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
1706 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
1708 adjust_scrollbars(sheet);
1710 sheet->old_vadjustment = -1.;
1711 if(sheet->vadjustment)
1712 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1714 size_allocate_global_button(sheet);
1718 gtk_sheet_show_column_titles(GtkSheet *sheet)
1722 if(sheet->column_titles_visible) return;
1724 sheet->column_titles_visible = TRUE;
1727 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1728 gdk_window_show(sheet->column_title_window);
1729 gdk_window_move_resize (sheet->column_title_window,
1730 sheet->column_title_area.x,
1731 sheet->column_title_area.y,
1732 sheet->column_title_area.width,
1733 sheet->column_title_area.height);
1735 for(col = MIN_VISIBLE_COLUMN(sheet);
1736 col <= MAX_VISIBLE_COLUMN(sheet);
1739 const GtkSheetButton *button = xxx_column_button(sheet, col);
1740 GtkSheetChild *child = button->child;
1742 gtk_sheet_child_show(child);
1744 adjust_scrollbars(sheet);
1747 sheet->old_vadjustment = -1.;
1748 if(sheet->vadjustment)
1749 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1751 size_allocate_global_button(sheet);
1756 gtk_sheet_show_row_titles(GtkSheet *sheet)
1760 if(sheet->row_titles_visible) return;
1762 sheet->row_titles_visible = TRUE;
1765 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1766 gdk_window_show(sheet->row_title_window);
1767 gdk_window_move_resize (sheet->row_title_window,
1768 sheet->row_title_area.x,
1769 sheet->row_title_area.y,
1770 sheet->row_title_area.width,
1771 sheet->row_title_area.height);
1773 for(row = MIN_VISIBLE_ROW(sheet);
1774 row <= MAX_VISIBLE_ROW(sheet);
1777 const GtkSheetButton *button = yyy_row_button(sheet, row);
1778 GtkSheetChild *child = button->child;
1781 gtk_sheet_child_show(child);
1784 adjust_scrollbars(sheet);
1787 sheet->old_hadjustment = -1.;
1788 if(sheet->hadjustment)
1789 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1791 size_allocate_global_button(sheet);
1795 gtk_sheet_hide_column_titles(GtkSheet *sheet)
1799 if(!sheet->column_titles_visible) return;
1801 sheet->column_titles_visible = FALSE;
1803 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1804 if(sheet->column_title_window)
1805 gdk_window_hide(sheet->column_title_window);
1806 if(GTK_WIDGET_VISIBLE(sheet->button))
1807 gtk_widget_hide(sheet->button);
1809 for(col = MIN_VISIBLE_COLUMN(sheet);
1810 col <= MAX_VISIBLE_COLUMN(sheet);
1813 const GtkSheetButton *button = xxx_column_button(sheet, col);
1814 GtkSheetChild *child = button->child;
1816 gtk_sheet_child_hide(child);
1818 adjust_scrollbars(sheet);
1821 sheet->old_vadjustment = -1.;
1822 if(sheet->vadjustment)
1823 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1828 gtk_sheet_hide_row_titles(GtkSheet *sheet)
1832 if(!sheet->row_titles_visible) return;
1834 sheet->row_titles_visible = FALSE;
1837 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1838 if(sheet->row_title_window)
1839 gdk_window_hide(sheet->row_title_window);
1840 if(GTK_WIDGET_VISIBLE(sheet->button))
1841 gtk_widget_hide(sheet->button);
1842 for(row = MIN_VISIBLE_ROW(sheet);
1843 row <= MAX_VISIBLE_ROW(sheet);
1846 const GtkSheetButton *button = yyy_row_button(sheet, row);
1847 GtkSheetChild *child = button->child;
1850 gtk_sheet_child_hide(child);
1852 adjust_scrollbars(sheet);
1855 sheet->old_hadjustment = -1.;
1856 if(sheet->hadjustment)
1857 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1862 gtk_sheet_column_titles_visible(GtkSheet *sheet)
1864 g_return_val_if_fail (sheet != NULL, FALSE);
1865 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1866 return sheet->column_titles_visible;
1870 gtk_sheet_row_titles_visible(GtkSheet *sheet)
1872 g_return_val_if_fail (sheet != NULL, FALSE);
1873 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1874 return sheet->row_titles_visible;
1880 gtk_sheet_moveto (GtkSheet * sheet,
1887 guint width, height;
1889 gint min_row, min_col;
1891 g_return_if_fail (sheet != NULL);
1892 g_return_if_fail (GTK_IS_SHEET (sheet));
1893 g_return_if_fail (sheet->hadjustment != NULL);
1894 g_return_if_fail (sheet->vadjustment != NULL);
1896 if (row < 0 || row >= yyy_row_count(sheet))
1898 if (column < 0 || column >= xxx_column_count(sheet))
1901 height = sheet->sheet_window_height;
1902 width = sheet->sheet_window_width;
1904 /* adjust vertical scrollbar */
1906 if (row >= 0 && row_align >=0.)
1909 y = ROW_TOP_YPIXEL(sheet, row) - sheet->voffset -
1911 (1.-row_align)*yyy_row_height(sheet, row);
1913 y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
1914 - (gint) ( row_align*height + (1. - row_align) * yyy_row_height(sheet, row));
1916 /* This forces the sheet to scroll when you don't see the entire cell */
1919 if(row_align == 1.){
1920 while(min_row >= 0 && min_row > MIN_VISIBLE_ROW(sheet)){
1921 if(yyy_row_is_visible(sheet, min_row))
1922 adjust += yyy_row_height(sheet, min_row);
1923 if(adjust >= height){
1928 min_row = MAX(min_row, 0);
1929 y = ROW_TOP_YPIXEL(sheet, min_row) - sheet->voffset +
1930 yyy_row_height(sheet, min_row) - 1;
1934 sheet->vadjustment->value = 0.0;
1936 sheet->vadjustment->value = y;
1938 sheet->old_vadjustment = -1.;
1939 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1944 /* adjust horizontal scrollbar */
1945 if (column >= 0 && col_align >= 0.)
1948 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset -
1950 (1.-col_align)*sheet->column[column].width;
1952 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
1953 - (gint) ( col_align*width + (1.-col_align)*
1954 xxx_column_width(sheet, column));
1957 /* This forces the sheet to scroll when you don't see the entire cell */
1960 if(col_align == 1.){
1961 while(min_col >= 0 && min_col > MIN_VISIBLE_COLUMN(sheet)){
1962 if(xxx_column_is_visible(sheet, min_col))
1963 adjust += xxx_column_width(sheet, min_col);
1965 if(adjust >= width){
1970 min_col = MAX(min_col, 0);
1971 x = COLUMN_LEFT_XPIXEL(sheet, min_col) - sheet->hoffset +
1972 xxx_column_width(sheet, min_col) - 1;
1976 sheet->hadjustment->value = 0.0;
1978 sheet->hadjustment->value = x;
1980 sheet->old_vadjustment = -1.;
1981 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1989 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
1991 g_return_if_fail (sheet != NULL);
1992 g_return_if_fail (GTK_IS_SHEET (sheet));
1994 sheet->columns_resizable = resizable;
1998 gtk_sheet_columns_resizable (GtkSheet *sheet)
2000 g_return_val_if_fail (sheet != NULL, FALSE);
2001 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2003 return sheet->columns_resizable;
2008 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
2010 g_return_if_fail (sheet != NULL);
2011 g_return_if_fail (GTK_IS_SHEET (sheet));
2013 sheet->rows_resizable = resizable;
2017 gtk_sheet_rows_resizable (GtkSheet *sheet)
2019 g_return_val_if_fail (sheet != NULL, FALSE);
2020 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2022 return sheet->rows_resizable;
2027 gtk_sheet_select_row (GtkSheet * sheet,
2030 g_return_if_fail (sheet != NULL);
2031 g_return_if_fail (GTK_IS_SHEET (sheet));
2033 if (row < 0 || row >= yyy_row_count(sheet))
2036 if(sheet->state != GTK_SHEET_NORMAL)
2037 gtk_sheet_real_unselect_range(sheet, NULL);
2040 gboolean veto = TRUE;
2041 veto = gtk_sheet_deactivate_cell(sheet);
2045 sheet->state=GTK_SHEET_ROW_SELECTED;
2046 sheet->range.row0=row;
2047 sheet->range.col0=0;
2048 sheet->range.rowi=row;
2049 sheet->range.coli = xxx_column_count(sheet) - 1;
2050 sheet->active_cell.row=row;
2051 sheet->active_cell.col=0;
2053 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_ROW], row);
2054 gtk_sheet_real_select_range(sheet, NULL);
2060 gtk_sheet_select_column (GtkSheet * sheet,
2064 g_return_if_fail (sheet != NULL);
2065 g_return_if_fail (GTK_IS_SHEET (sheet));
2067 if (column < 0 || column >= xxx_column_count(sheet))
2070 if(sheet->state != GTK_SHEET_NORMAL)
2071 gtk_sheet_real_unselect_range(sheet, NULL);
2074 gboolean veto = TRUE;
2075 veto = gtk_sheet_deactivate_cell(sheet);
2079 sheet->state=GTK_SHEET_COLUMN_SELECTED;
2080 sheet->range.row0=0;
2081 sheet->range.col0=column;
2082 sheet->range.rowi= yyy_row_count(sheet) - 1;
2083 sheet->range.coli=column;
2084 sheet->active_cell.row=0;
2085 sheet->active_cell.col=column;
2087 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_COLUMN], column);
2088 gtk_sheet_real_select_range(sheet, NULL);
2093 gtk_sheet_clip_range (GtkSheet *sheet, const GtkSheetRange *range)
2096 g_return_if_fail (sheet != NULL);
2097 g_return_if_fail (GTK_IS_SHEET (sheet));
2099 if(GTK_SHEET_IN_CLIP(sheet)) return;
2101 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2104 sheet->clip_range = sheet->range;
2106 sheet->clip_range=*range;
2109 sheet->clip_timer=gtk_timeout_add(TIMEOUT_FLASH, gtk_sheet_flash, sheet);
2111 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CLIP_RANGE],
2112 &sheet->clip_range);
2117 gtk_sheet_unclip_range(GtkSheet *sheet)
2120 g_return_if_fail (sheet != NULL);
2121 g_return_if_fail (GTK_IS_SHEET (sheet));
2123 if(!GTK_SHEET_IN_CLIP(sheet)) return;
2125 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2126 gtk_timeout_remove(sheet->clip_timer);
2127 gtk_sheet_range_draw(sheet, &sheet->clip_range);
2129 if(gtk_sheet_range_isvisible(sheet, sheet->range))
2130 gtk_sheet_range_draw(sheet, &sheet->range);
2134 gtk_sheet_in_clip (GtkSheet *sheet)
2136 g_return_val_if_fail (sheet != NULL, FALSE);
2137 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2139 return GTK_SHEET_IN_CLIP(sheet);
2143 gtk_sheet_flash(gpointer data)
2146 gint x,y,width,height;
2147 GdkRectangle clip_area;
2149 sheet=GTK_SHEET(data);
2151 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return TRUE;
2152 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return TRUE;
2153 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return TRUE;
2154 if(GTK_SHEET_IN_XDRAG(sheet)) return TRUE;
2155 if(GTK_SHEET_IN_YDRAG(sheet)) return TRUE;
2157 GDK_THREADS_ENTER();
2159 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2160 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2161 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2162 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2163 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2164 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2166 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2167 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2168 clip_area.width=sheet->sheet_window_width;
2169 clip_area.height=sheet->sheet_window_height;
2175 if(width>clip_area.width) width=clip_area.width+10;
2180 if(height>clip_area.height) height=clip_area.height+10;
2182 gdk_draw_pixmap(sheet->sheet_window,
2183 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2189 gdk_draw_pixmap(sheet->sheet_window,
2190 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2196 gdk_draw_pixmap(sheet->sheet_window,
2197 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2203 gdk_draw_pixmap(sheet->sheet_window,
2204 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2211 sheet->interval=sheet->interval+1;
2212 if(sheet->interval==TIME_INTERVAL) sheet->interval=0;
2214 gdk_gc_set_dashes(sheet->xor_gc, sheet->interval, (gint8*)"\4\4", 2);
2215 gtk_sheet_draw_flashing_range(sheet,sheet->clip_range);
2216 gdk_gc_set_dashes(sheet->xor_gc, 0, (gint8*)"\4\4", 2);
2218 GDK_THREADS_LEAVE();
2225 gtk_sheet_draw_flashing_range(GtkSheet *sheet, GtkSheetRange range)
2227 GdkRectangle clip_area;
2228 gint x,y,width,height;
2230 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return;
2232 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2233 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2234 clip_area.width=sheet->sheet_window_width;
2235 clip_area.height=sheet->sheet_window_height;
2237 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
2239 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2240 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2241 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2242 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2243 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2244 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2250 if(width>clip_area.width) width=clip_area.width+10;
2255 if(height>clip_area.height) height=clip_area.height+10;
2257 gdk_gc_set_line_attributes(sheet->xor_gc, 1, 1, 0 ,0 );
2259 gdk_draw_rectangle(sheet->sheet_window, sheet->xor_gc, FALSE,
2263 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 0, 0, 0);
2265 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
2270 gtk_sheet_range_isvisible (GtkSheet * sheet,
2271 GtkSheetRange range)
2273 g_return_val_if_fail (sheet != NULL, FALSE);
2275 if (range.row0 < 0 || range.row0 >= yyy_row_count(sheet))
2278 if (range.rowi < 0 || range.rowi >= yyy_row_count(sheet))
2281 if (range.col0 < 0 || range.col0 >= xxx_column_count(sheet))
2284 if (range.coli < 0 || range.coli >= xxx_column_count(sheet))
2287 if (range.rowi < MIN_VISIBLE_ROW (sheet))
2290 if (range.row0 > MAX_VISIBLE_ROW (sheet))
2293 if (range.coli < MIN_VISIBLE_COLUMN (sheet))
2296 if (range.col0 > MAX_VISIBLE_COLUMN (sheet))
2303 gtk_sheet_cell_isvisible (GtkSheet * sheet,
2304 gint row, gint column)
2306 GtkSheetRange range;
2309 range.col0 = column;
2311 range.coli = column;
2313 return gtk_sheet_range_isvisible(sheet, range);
2317 gtk_sheet_get_visible_range(GtkSheet *sheet, GtkSheetRange *range)
2320 g_return_if_fail (sheet != NULL);
2321 g_return_if_fail (GTK_IS_SHEET (sheet)) ;
2322 g_return_if_fail (range != NULL);
2324 range->row0 = MIN_VISIBLE_ROW(sheet);
2325 range->col0 = MIN_VISIBLE_COLUMN(sheet);
2326 range->rowi = MAX_VISIBLE_ROW(sheet);
2327 range->coli = MAX_VISIBLE_COLUMN(sheet);
2332 gtk_sheet_get_vadjustment (GtkSheet * sheet)
2334 g_return_val_if_fail (sheet != NULL, NULL);
2335 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2337 return sheet->vadjustment;
2341 gtk_sheet_get_hadjustment (GtkSheet * sheet)
2343 g_return_val_if_fail (sheet != NULL, NULL);
2344 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2346 return sheet->hadjustment;
2350 gtk_sheet_set_vadjustment (GtkSheet *sheet,
2351 GtkAdjustment *adjustment)
2353 GtkAdjustment *old_adjustment;
2355 g_return_if_fail (sheet != NULL);
2356 g_return_if_fail (GTK_IS_SHEET (sheet));
2358 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2360 if (sheet->vadjustment == adjustment)
2363 old_adjustment = sheet->vadjustment;
2365 if (sheet->vadjustment)
2367 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2368 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2371 sheet->vadjustment = adjustment;
2373 if (sheet->vadjustment)
2375 gtk_object_ref (GTK_OBJECT (sheet->vadjustment));
2376 gtk_object_sink (GTK_OBJECT (sheet->vadjustment));
2378 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "changed",
2379 (GtkSignalFunc) vadjustment_changed,
2381 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "value_changed",
2382 (GtkSignalFunc) vadjustment_value_changed,
2386 if (!sheet->vadjustment || !old_adjustment)
2388 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2392 sheet->old_vadjustment = sheet->vadjustment->value;
2396 gtk_sheet_set_hadjustment (GtkSheet *sheet,
2397 GtkAdjustment *adjustment)
2399 GtkAdjustment *old_adjustment;
2401 g_return_if_fail (sheet != NULL);
2402 g_return_if_fail (GTK_IS_SHEET (sheet));
2404 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2406 if (sheet->hadjustment == adjustment)
2409 old_adjustment = sheet->hadjustment;
2411 if (sheet->hadjustment)
2413 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2414 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2417 sheet->hadjustment = adjustment;
2419 if (sheet->hadjustment)
2421 gtk_object_ref (GTK_OBJECT (sheet->hadjustment));
2422 gtk_object_sink (GTK_OBJECT (sheet->hadjustment));
2424 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "changed",
2425 (GtkSignalFunc) hadjustment_changed,
2427 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "value_changed",
2428 (GtkSignalFunc) hadjustment_value_changed,
2432 if (!sheet->hadjustment || !old_adjustment)
2434 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2438 sheet->old_hadjustment = sheet->hadjustment->value;
2442 gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
2443 GtkAdjustment *hadjustment,
2444 GtkAdjustment *vadjustment)
2446 if(sheet->hadjustment != hadjustment)
2447 gtk_sheet_set_hadjustment (sheet, hadjustment);
2448 if(sheet->vadjustment != vadjustment)
2449 gtk_sheet_set_vadjustment (sheet, vadjustment);
2453 gtk_sheet_finalize (GObject * object)
2457 g_return_if_fail (object != NULL);
2458 g_return_if_fail (GTK_IS_SHEET (object));
2460 sheet = GTK_SHEET (object);
2462 /* get rid of all the cells */
2463 gtk_sheet_range_clear (sheet, NULL);
2464 gtk_sheet_range_delete(sheet, NULL);
2467 g_free(sheet->name);
2471 if (G_OBJECT_CLASS (parent_class)->finalize)
2472 (*G_OBJECT_CLASS (parent_class)->finalize) (object);
2476 gtk_sheet_destroy (GtkObject * object)
2481 g_return_if_fail (object != NULL);
2482 g_return_if_fail (GTK_IS_SHEET (object));
2484 sheet = GTK_SHEET (object);
2486 /* destroy the entry */
2487 if(sheet->sheet_entry && GTK_IS_WIDGET(sheet->sheet_entry)){
2488 gtk_widget_destroy (sheet->sheet_entry);
2489 sheet->sheet_entry = NULL;
2492 /* destroy the global selection button */
2493 if(sheet->button && GTK_IS_WIDGET(sheet->button)){
2494 gtk_widget_destroy (sheet->button);
2495 sheet->button = NULL;
2499 gtk_timeout_remove(sheet->timer);
2503 if(sheet->clip_timer){
2504 gtk_timeout_remove(sheet->clip_timer);
2505 sheet->clip_timer = 0;
2508 /* unref adjustments */
2509 if (sheet->hadjustment)
2511 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2512 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2513 sheet->hadjustment = NULL;
2515 if (sheet->vadjustment)
2517 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2518 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2519 sheet->vadjustment = NULL;
2522 children = sheet->children;
2524 GtkSheetChild *child = (GtkSheetChild *)children->data;
2525 if(child && child->widget)
2526 gtk_sheet_remove(GTK_CONTAINER(sheet), child->widget);
2527 children = sheet->children;
2529 sheet->children = NULL;
2531 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2532 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2536 gtk_sheet_style_set (GtkWidget *widget,
2537 GtkStyle *previous_style)
2541 g_return_if_fail (widget != NULL);
2542 g_return_if_fail (GTK_IS_SHEET (widget));
2544 if (GTK_WIDGET_CLASS (parent_class)->style_set)
2545 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
2547 sheet = GTK_SHEET (widget);
2549 if(GTK_WIDGET_REALIZED(widget))
2551 gtk_style_set_background (widget->style, widget->window, widget->state);
2557 gtk_sheet_realize (GtkWidget * widget)
2560 GdkWindowAttr attributes;
2561 gint attributes_mask;
2562 GdkGCValues values, auxvalues;
2563 GdkColormap *colormap;
2565 GtkSheetChild *child;
2568 g_return_if_fail (widget != NULL);
2569 g_return_if_fail (GTK_IS_SHEET (widget));
2571 sheet = GTK_SHEET (widget);
2573 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2575 attributes.window_type = GDK_WINDOW_CHILD;
2576 attributes.x = widget->allocation.x;
2577 attributes.y = widget->allocation.y;
2578 attributes.width = widget->allocation.width;
2579 attributes.height = widget->allocation.height;
2580 attributes.wclass = GDK_INPUT_OUTPUT;
2582 attributes.visual = gtk_widget_get_visual (widget);
2583 attributes.colormap = gtk_widget_get_colormap (widget);
2585 attributes.event_mask = gtk_widget_get_events (widget);
2586 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2587 GDK_BUTTON_PRESS_MASK |
2588 GDK_BUTTON_RELEASE_MASK |
2589 GDK_KEY_PRESS_MASK |
2590 GDK_POINTER_MOTION_MASK |
2591 GDK_POINTER_MOTION_HINT_MASK);
2592 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
2595 attributes.cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
2598 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2600 gdk_window_set_user_data (widget->window, sheet);
2602 widget->style = gtk_style_attach (widget->style, widget->window);
2604 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2607 if(sheet->row_titles_visible)
2608 attributes.x = sheet->row_title_area.width;
2610 attributes.width = sheet->column_title_area.width;
2611 attributes.height = sheet->column_title_area.height;
2613 /* column-title window */
2614 sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2615 gdk_window_set_user_data (sheet->column_title_window, sheet);
2616 gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL);
2620 if(sheet->column_titles_visible)
2621 attributes.y = sheet->column_title_area.height;
2622 attributes.width = sheet->row_title_area.width;
2623 attributes.height = sheet->row_title_area.height;
2625 /* row-title window */
2626 sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2627 gdk_window_set_user_data (sheet->row_title_window, sheet);
2628 gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL);
2631 attributes.cursor = gdk_cursor_new(GDK_PLUS);
2635 attributes.width = sheet->sheet_window_width,
2636 attributes.height = sheet->sheet_window_height;
2638 sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2639 gdk_window_set_user_data (sheet->sheet_window, sheet);
2641 gdk_cursor_unref(attributes.cursor);
2643 gdk_window_set_background (sheet->sheet_window, &widget->style->white);
2644 gdk_window_show (sheet->sheet_window);
2646 /* backing_pixmap */
2647 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
2651 gdk_gc_unref(sheet->fg_gc);
2653 gdk_gc_unref(sheet->bg_gc);
2654 sheet->fg_gc = gdk_gc_new (widget->window);
2655 sheet->bg_gc = gdk_gc_new (widget->window);
2657 colormap = gtk_widget_get_colormap(widget);
2659 gdk_color_white(colormap, &widget->style->white);
2660 gdk_color_black(colormap, &widget->style->black);
2662 gdk_gc_get_values(sheet->fg_gc, &auxvalues);
2664 values.foreground = widget->style->white;
2665 values.function = GDK_INVERT;
2666 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2668 gdk_gc_unref(sheet->xor_gc);
2669 sheet->xor_gc = gdk_gc_new_with_values (widget->window,
2675 if(sheet->sheet_entry->parent){
2676 gtk_widget_ref(sheet->sheet_entry);
2677 gtk_widget_unparent(sheet->sheet_entry);
2679 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
2680 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
2682 if(sheet->button && sheet->button->parent){
2683 gtk_widget_ref(sheet->button);
2684 gtk_widget_unparent(sheet->button);
2686 gtk_widget_set_parent_window(sheet->button, sheet->sheet_window);
2687 gtk_widget_set_parent(sheet->button, GTK_WIDGET(sheet));
2690 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
2692 if(!sheet->cursor_drag)
2693 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
2695 if(sheet->column_titles_visible)
2696 gdk_window_show(sheet->column_title_window);
2697 if(sheet->row_titles_visible)
2698 gdk_window_show(sheet->row_title_window);
2700 size_allocate_row_title_buttons(sheet);
2701 size_allocate_column_title_buttons(sheet);
2703 name = g_strdup(sheet->name);
2704 gtk_sheet_set_title(sheet, name);
2708 children = sheet->children;
2711 child = children->data;
2712 children = children->next;
2714 gtk_sheet_realize_child(sheet, child);
2719 create_global_button(GtkSheet *sheet)
2721 sheet->button = gtk_button_new_with_label(" ");
2723 gtk_signal_connect (GTK_OBJECT (sheet->button),
2725 (GtkSignalFunc) global_button_clicked,
2730 size_allocate_global_button(GtkSheet *sheet)
2732 GtkAllocation allocation;
2734 if(!sheet->column_titles_visible) return;
2735 if(!sheet->row_titles_visible) return;
2737 gtk_widget_size_request(sheet->button, NULL);
2741 allocation.width=sheet->row_title_area.width;
2742 allocation.height=sheet->column_title_area.height;
2744 gtk_widget_size_allocate(sheet->button, &allocation);
2745 gtk_widget_show(sheet->button);
2749 global_button_clicked(GtkWidget *widget, gpointer data)
2753 gtk_sheet_click_cell(GTK_SHEET(data), -1, -1, &veto);
2754 gtk_widget_grab_focus(GTK_WIDGET(data));
2759 gtk_sheet_unrealize (GtkWidget * widget)
2763 g_return_if_fail (widget != NULL);
2764 g_return_if_fail (GTK_IS_SHEET (widget));
2766 sheet = GTK_SHEET (widget);
2768 gdk_cursor_destroy (sheet->cursor_drag);
2770 gdk_gc_destroy (sheet->xor_gc);
2771 gdk_gc_destroy (sheet->fg_gc);
2772 gdk_gc_destroy (sheet->bg_gc);
2774 gdk_window_destroy (sheet->sheet_window);
2775 gdk_window_destroy (sheet->column_title_window);
2776 gdk_window_destroy (sheet->row_title_window);
2779 g_free (sheet->pixmap);
2780 sheet->pixmap = NULL;
2783 sheet->column_title_window=NULL;
2784 sheet->sheet_window = NULL;
2785 sheet->cursor_drag = NULL;
2786 sheet->xor_gc = NULL;
2787 sheet->fg_gc = NULL;
2788 sheet->bg_gc = NULL;
2790 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2791 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2795 gtk_sheet_map (GtkWidget * widget)
2798 GtkSheetChild *child;
2801 g_return_if_fail (widget != NULL);
2802 g_return_if_fail (GTK_IS_SHEET (widget));
2804 sheet = GTK_SHEET (widget);
2806 if (!GTK_WIDGET_MAPPED (widget))
2808 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2810 if(!sheet->cursor_drag) sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
2812 gdk_window_show (widget->window);
2814 gdk_window_show (sheet->sheet_window);
2816 if(sheet->column_titles_visible){
2817 size_allocate_column_title_buttons(sheet);
2818 gdk_window_show (sheet->column_title_window);
2820 if(sheet->row_titles_visible){
2821 size_allocate_row_title_buttons(sheet);
2822 gdk_window_show (sheet->row_title_window);
2825 if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)){
2826 gtk_widget_show (sheet->sheet_entry);
2827 gtk_widget_map (sheet->sheet_entry);
2830 if (GTK_WIDGET_VISIBLE (sheet->button) &&
2831 !GTK_WIDGET_MAPPED (sheet->button)){
2832 gtk_widget_show(sheet->button);
2833 gtk_widget_map (sheet->button);
2836 if(GTK_BIN(sheet->button)->child)
2837 if (GTK_WIDGET_VISIBLE (GTK_BIN(sheet->button)->child) &&
2838 !GTK_WIDGET_MAPPED (GTK_BIN(sheet->button)->child))
2839 gtk_widget_map (GTK_BIN(sheet->button)->child);
2841 gtk_sheet_range_draw(sheet, NULL);
2842 gtk_sheet_activate_cell(sheet,
2843 sheet->active_cell.row,
2844 sheet->active_cell.col);
2846 children = sheet->children;
2849 child = children->data;
2850 children = children->next;
2852 if (GTK_WIDGET_VISIBLE (child->widget) &&
2853 !GTK_WIDGET_MAPPED (child->widget)){
2854 gtk_widget_map (child->widget);
2855 gtk_sheet_position_child(sheet, child);
2863 gtk_sheet_unmap (GtkWidget * widget)
2866 GtkSheetChild *child;
2869 g_return_if_fail (widget != NULL);
2870 g_return_if_fail (GTK_IS_SHEET (widget));
2872 sheet = GTK_SHEET (widget);
2874 if (GTK_WIDGET_MAPPED (widget))
2876 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2878 gdk_window_hide (sheet->sheet_window);
2879 if(sheet->column_titles_visible)
2880 gdk_window_hide (sheet->column_title_window);
2881 if(sheet->row_titles_visible)
2882 gdk_window_hide (sheet->row_title_window);
2883 gdk_window_hide (widget->window);
2885 if (GTK_WIDGET_MAPPED (sheet->sheet_entry))
2886 gtk_widget_unmap (sheet->sheet_entry);
2888 if (GTK_WIDGET_MAPPED (sheet->button))
2889 gtk_widget_unmap (sheet->button);
2891 children = sheet->children;
2894 child = children->data;
2895 children = children->next;
2897 if (GTK_WIDGET_VISIBLE (child->widget) &&
2898 GTK_WIDGET_MAPPED (child->widget))
2900 gtk_widget_unmap (child->widget);
2909 gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
2912 GdkGC *fg_gc, *bg_gc;
2913 GtkSheetCellAttr attributes;
2916 g_return_if_fail (sheet != NULL);
2918 /* bail now if we arn't drawable yet */
2919 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
2921 if (row < 0 || row >= yyy_row_count(sheet)) return;
2922 if (col < 0 || col >= xxx_column_count(sheet)) return;
2923 if (! xxx_column_is_visible(sheet, col)) return;
2924 if (! yyy_row_is_visible(sheet, row)) return;
2926 widget = GTK_WIDGET (sheet);
2928 gtk_sheet_get_attributes(sheet, row, col, &attributes);
2930 /* select GC for background rectangle */
2931 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
2932 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
2934 fg_gc = sheet->fg_gc;
2935 bg_gc = sheet->bg_gc;
2937 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
2938 area.y=ROW_TOP_YPIXEL(sheet,row);
2939 area.width= xxx_column_width(sheet, col);
2940 area.height=yyy_row_height(sheet, row);
2942 gdk_draw_rectangle (sheet->pixmap,
2950 gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0);
2952 if(sheet->show_grid){
2953 gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color);
2955 gdk_draw_rectangle (sheet->pixmap,
2959 area.width, area.height);
2964 gtk_sheet_cell_draw_border (GtkSheet *sheet, gint row, gint col, gint mask)
2967 GdkGC *fg_gc, *bg_gc;
2968 GtkSheetCellAttr attributes;
2972 g_return_if_fail (sheet != NULL);
2974 /* bail now if we arn't drawable yet */
2975 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
2977 if (row < 0 || row >= yyy_row_count(sheet)) return;
2978 if (col < 0 || col >= xxx_column_count(sheet)) return;
2979 if (!xxx_column_is_visible(sheet, col)) return;
2980 if (!yyy_row_is_visible(sheet, row)) return;
2982 widget = GTK_WIDGET (sheet);
2984 gtk_sheet_get_attributes(sheet, row, col, &attributes);
2986 /* select GC for background rectangle */
2987 gdk_gc_set_foreground (sheet->fg_gc, &attributes.border.color);
2988 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
2990 fg_gc = sheet->fg_gc;
2991 bg_gc = sheet->bg_gc;
2993 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
2994 area.y=ROW_TOP_YPIXEL(sheet,row);
2995 area.width=xxx_column_width(sheet, col);
2996 area.height=yyy_row_height(sheet, row);
2998 width = attributes.border.width;
2999 gdk_gc_set_line_attributes(sheet->fg_gc, attributes.border.width,
3000 attributes.border.line_style,
3001 attributes.border.cap_style,
3002 attributes.border.join_style);
3005 if(attributes.border.mask & GTK_SHEET_LEFT_BORDER & mask)
3006 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3007 area.x, area.y-width/2,
3008 area.x, area.y+area.height+width/2+1);
3010 if(attributes.border.mask & GTK_SHEET_RIGHT_BORDER & mask)
3011 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3012 area.x+area.width, area.y-width/2,
3014 area.y+area.height+width/2+1);
3016 if(attributes.border.mask & GTK_SHEET_TOP_BORDER & mask)
3017 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3018 area.x-width/2,area.y,
3019 area.x+area.width+width/2+1,
3022 if(attributes.border.mask & GTK_SHEET_BOTTOM_BORDER & mask)
3023 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3024 area.x-width/2, area.y+area.height,
3025 area.x+area.width+width/2+1,
3026 area.y+area.height);
3033 gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
3036 GdkRectangle area, clip_area;
3038 gint text_width, text_height, y;
3040 gint size, sizel, sizer;
3041 GdkGC *fg_gc, *bg_gc;
3042 GtkSheetCellAttr attributes;
3043 PangoLayout *layout;
3044 PangoRectangle rect;
3045 PangoRectangle logical_rect;
3046 PangoLayoutLine *line;
3047 PangoFontMetrics *metrics;
3048 PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet));
3049 gint ascent, descent, y_pos;
3053 g_return_if_fail (sheet != NULL);
3055 /* bail now if we aren't drawable yet */
3056 if (!GTK_WIDGET_DRAWABLE (sheet))
3059 label = gtk_sheet_cell_get_text(sheet, row, col);
3063 if (row < 0 || row >= yyy_row_count(sheet)) return;
3064 if (col < 0 || col >= xxx_column_count(sheet)) return;
3065 if (! xxx_column_is_visible(sheet, col)) return;
3066 if (!yyy_row_is_visible(sheet, row)) return;
3069 widget = GTK_WIDGET(sheet);
3071 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3073 /* select GC for background rectangle */
3074 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3075 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3077 fg_gc = sheet->fg_gc;
3078 bg_gc = sheet->bg_gc;
3080 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3081 area.y=ROW_TOP_YPIXEL(sheet,row);
3082 area.width = xxx_column_width(sheet, col);
3083 area.height = yyy_row_height(sheet, row);
3087 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label);
3088 pango_layout_set_font_description (layout, attributes.font_desc);
3090 pango_layout_get_pixel_extents (layout, NULL, &rect);
3092 line = pango_layout_get_lines (layout)->data;
3093 pango_layout_line_get_extents (line, NULL, &logical_rect);
3095 metrics = pango_context_get_metrics(context,
3096 attributes.font_desc,
3097 pango_context_get_language(context));
3099 ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
3100 descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
3102 pango_font_metrics_unref(metrics);
3104 /* Align primarily for locale's ascent/descent */
3106 logical_rect.height /= PANGO_SCALE;
3107 logical_rect.y /= PANGO_SCALE;
3108 y_pos = area.height - logical_rect.height;
3110 if (logical_rect.height > area.height)
3111 y_pos = (logical_rect.height - area.height - 2*CELLOFFSET) / 2;
3114 else if (y_pos + logical_rect.height > area.height)
3115 y_pos = area.height - logical_rect.height;
3117 text_width = rect.width;
3118 text_height = rect.height;
3119 y = area.y + y_pos - CELLOFFSET;
3121 switch(attributes.justification){
3122 case GTK_JUSTIFY_RIGHT:
3125 if(!gtk_sheet_clip_text(sheet)){
3126 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3127 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
3128 if(size>=text_width+CELLOFFSET) break;
3129 size+=xxx_column_width(sheet, i);
3130 xxx_column_set_right_column(sheet, i,
3132 xxx_column_right_column(sheet, i)));
3137 xoffset+=area.width-text_width - 2 * CELLOFFSET -
3138 attributes.border.width/2;
3140 case GTK_JUSTIFY_CENTER:
3143 area.x+=area.width/2;
3144 if(!gtk_sheet_clip_text(sheet)){
3145 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3146 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
3147 if(sizer>=text_width/2) break;
3148 sizer+= xxx_column_width(sheet, i);
3149 xxx_column_set_left_column(sheet, i,
3152 xxx_column_left_column(sheet, i)));
3154 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3155 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
3156 if(sizel>=text_width/2) break;
3157 sizel+=xxx_column_width(sheet, i);
3158 xxx_column_set_right_column(sheet, i,
3160 xxx_column_right_column(sheet, i)));
3162 size=MIN(sizel, sizer);
3165 xoffset+= sizel - text_width/2 - CELLOFFSET;
3166 area.width=sizel+sizer;
3168 case GTK_JUSTIFY_LEFT:
3171 if(!gtk_sheet_clip_text(sheet)){
3172 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3173 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
3174 if(size>=text_width+CELLOFFSET) break;
3175 size+=xxx_column_width(sheet, i);
3176 xxx_column_set_left_column(sheet, i,
3179 xxx_column_left_column(sheet, i)));
3184 xoffset += attributes.border.width/2;
3188 if(!gtk_sheet_clip_text(sheet)) clip_area = area;
3189 gdk_gc_set_clip_rectangle(fg_gc, &clip_area);
3192 gdk_draw_layout (sheet->pixmap, fg_gc,
3193 area.x + xoffset + CELLOFFSET,
3197 gdk_gc_set_clip_rectangle(fg_gc, NULL);
3198 g_object_unref(G_OBJECT(layout));
3200 gdk_draw_pixmap(sheet->sheet_window,
3201 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3215 gtk_sheet_range_draw(GtkSheet *sheet, const GtkSheetRange *range)
3218 GtkSheetRange drawing_range;
3221 g_return_if_fail(sheet != NULL);
3222 g_return_if_fail(GTK_SHEET(sheet));
3224 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
3225 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3226 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
3230 drawing_range.row0=MIN_VISIBLE_ROW(sheet);
3231 drawing_range.col0=MIN_VISIBLE_COLUMN(sheet);
3232 drawing_range.rowi=MAX_VISIBLE_ROW(sheet);
3233 drawing_range.coli=MAX_VISIBLE_COLUMN(sheet);
3235 gdk_draw_rectangle (sheet->pixmap,
3236 GTK_WIDGET(sheet)->style->white_gc,
3239 sheet->sheet_window_width,sheet->sheet_window_height);
3244 drawing_range.row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
3245 drawing_range.col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
3246 drawing_range.rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
3247 drawing_range.coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
3251 if(drawing_range.coli == xxx_column_count(sheet) - 1)
3253 area.x=COLUMN_LEFT_XPIXEL(sheet,
3254 xxx_column_count(sheet) - 1) +
3255 xxx_column_width(sheet, xxx_column_count(sheet) - 1) + 1;
3259 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3261 gdk_draw_rectangle (sheet->pixmap,
3265 sheet->sheet_window_width - area.x,
3266 sheet->sheet_window_height);
3268 gdk_draw_pixmap(sheet->sheet_window,
3269 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3275 sheet->sheet_window_width - area.x,
3276 sheet->sheet_window_height);
3279 if(drawing_range.rowi == yyy_row_count(sheet) - 1){
3281 area.y=ROW_TOP_YPIXEL(sheet,
3282 yyy_row_count(sheet) - 1) +
3283 yyy_row_height(sheet, yyy_row_count(sheet) - 1) + 1;
3285 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3287 gdk_draw_rectangle (sheet->pixmap,
3291 sheet->sheet_window_width,
3292 sheet->sheet_window_height - area.y);
3294 gdk_draw_pixmap(sheet->sheet_window,
3295 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3301 sheet->sheet_window_width,
3302 sheet->sheet_window_height - area.y);
3305 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3306 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3307 gtk_sheet_cell_draw_default(sheet, i, j);
3310 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3311 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3312 gtk_sheet_cell_draw_border(sheet, i-1, j, GTK_SHEET_BOTTOM_BORDER);
3313 gtk_sheet_cell_draw_border(sheet, i+1, j, GTK_SHEET_TOP_BORDER);
3314 gtk_sheet_cell_draw_border(sheet, i, j-1, GTK_SHEET_RIGHT_BORDER);
3315 gtk_sheet_cell_draw_border(sheet, i, j+1, GTK_SHEET_LEFT_BORDER);
3316 gtk_sheet_cell_draw_border(sheet, i, j, 15);
3319 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3320 for(j=drawing_range.col0; j<=drawing_range.coli; j++)
3321 gtk_sheet_cell_draw_label (sheet, i, j);
3323 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3324 for(j= xxx_column_left_column(sheet, drawing_range.col0);
3325 j<drawing_range.col0; j++)
3326 gtk_sheet_cell_draw_label (sheet, i, j);
3328 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3329 for(j = drawing_range.coli+1;
3330 j <= xxx_column_right_column(sheet, drawing_range.coli);
3332 gtk_sheet_cell_draw_label (sheet, i, j);
3334 gtk_sheet_draw_backing_pixmap(sheet, drawing_range);
3336 if(sheet->state != GTK_SHEET_NORMAL && gtk_sheet_range_isvisible(sheet, sheet->range))
3337 gtk_sheet_range_draw_selection(sheet, drawing_range);
3339 if(sheet->state == GTK_STATE_NORMAL &&
3340 sheet->active_cell.row >= drawing_range.row0 &&
3341 sheet->active_cell.row <= drawing_range.rowi &&
3342 sheet->active_cell.col >= drawing_range.col0 &&
3343 sheet->active_cell.col <= drawing_range.coli)
3344 gtk_sheet_show_active_cell(sheet);
3349 gtk_sheet_range_draw_selection(GtkSheet *sheet, GtkSheetRange range)
3355 if(range.col0 > sheet->range.coli || range.coli < sheet->range.col0 ||
3356 range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0)
3359 if(!gtk_sheet_range_isvisible(sheet, range)) return;
3360 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3364 range.col0=MAX(sheet->range.col0, range.col0);
3365 range.coli=MIN(sheet->range.coli, range.coli);
3366 range.row0=MAX(sheet->range.row0, range.row0);
3367 range.rowi=MIN(sheet->range.rowi, range.rowi);
3369 range.col0=MAX(range.col0, MIN_VISIBLE_COLUMN(sheet));
3370 range.coli=MIN(range.coli, MAX_VISIBLE_COLUMN(sheet));
3371 range.row0=MAX(range.row0, MIN_VISIBLE_ROW(sheet));
3372 range.rowi=MIN(range.rowi, MAX_VISIBLE_ROW(sheet));
3374 for(i=range.row0; i<=range.rowi; i++){
3375 for(j=range.col0; j<=range.coli; j++){
3377 if(gtk_sheet_cell_get_state(sheet, i, j)==GTK_STATE_SELECTED &&
3378 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
3381 row_button_set(sheet, i);
3382 column_button_set(sheet, j);
3385 area.x=COLUMN_LEFT_XPIXEL(sheet,j);
3386 area.y=ROW_TOP_YPIXEL(sheet,i);
3387 area.width= xxx_column_width(sheet, j);
3388 area.height=yyy_row_height(sheet, i);
3390 if(i==sheet->range.row0){
3392 area.height=area.height-2;
3394 if(i==sheet->range.rowi) area.height=area.height-3;
3395 if(j==sheet->range.col0){
3397 area.width=area.width-2;
3399 if(j==sheet->range.coli) area.width=area.width-3;
3401 if(i!=sheet->active_cell.row || j!=sheet->active_cell.col){
3402 gdk_draw_rectangle (sheet->sheet_window,
3406 area.width,area.height);
3413 gtk_sheet_draw_border(sheet, sheet->range);
3418 gtk_sheet_draw_backing_pixmap(GtkSheet *sheet, GtkSheetRange range)
3420 gint x,y,width,height;
3422 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3424 x = COLUMN_LEFT_XPIXEL(sheet,range.col0);
3425 y = ROW_TOP_YPIXEL(sheet, range.row0);
3426 width = COLUMN_LEFT_XPIXEL(sheet, range.coli) - x +
3427 xxx_column_width(sheet, range.coli);
3429 height=ROW_TOP_YPIXEL(sheet, range.rowi)-y+yyy_row_height(sheet, range.rowi);
3431 if(range.row0==sheet->range.row0){
3435 if(range.rowi==sheet->range.rowi) height=height+5;
3436 if(range.col0==sheet->range.col0){
3440 if(range.coli==sheet->range.coli) width=width+5;
3443 width=MIN(width, sheet->sheet_window_width-x);
3444 height=MIN(height, sheet->sheet_window_height-y);
3451 x = (sheet->row_titles_visible)
3452 ? MAX(x, sheet->row_title_area.width) : MAX(x, 0);
3453 y = (sheet->column_titles_visible)
3454 ? MAX(y, sheet->column_title_area.height) : MAX(y, 0);
3456 if(range.coli == xxx_column_count(sheet) - 1)
3457 width = sheet->sheet_window_width - x;
3458 if(range.rowi == yyy_row_count(sheet) - 1)
3459 height=sheet->sheet_window_height - y;
3461 gdk_draw_pixmap(sheet->sheet_window,
3462 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3474 gtk_sheet_set_cell_text(GtkSheet *sheet, gint row, gint col, const gchar *text)
3476 GtkSheetCellAttr attributes;
3478 g_return_if_fail (sheet != NULL);
3479 g_return_if_fail (GTK_IS_SHEET (sheet));
3480 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3481 if (col < 0 || row < 0) return;
3483 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3484 gtk_sheet_set_cell(sheet, row, col, attributes.justification, text);
3488 safe_strcmp(const gchar *s1, const gchar *s2)
3490 if ( !s1 && !s2) return 0;
3491 if ( !s1) return -1;
3492 if ( !s2) return +1;
3493 return strcmp(s1, s2);
3497 gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col,
3498 GtkJustification justification,
3501 GtkSheetRange range;
3503 GtkSheetCellAttr attributes;
3505 g_return_if_fail (sheet != NULL);
3506 g_return_if_fail (GTK_IS_SHEET (sheet));
3507 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3508 if (col < 0 || row < 0) return;
3510 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3512 attributes.justification = justification;
3514 GSheetModel *model = gtk_sheet_get_model(sheet);
3516 const gchar *old_text = g_sheet_model_get_string(model, row, col);
3518 gboolean changed = FALSE;
3520 if (0 != safe_strcmp(old_text, text))
3521 changed = g_sheet_model_set_string(model, text, row, col);
3523 if(changed && attributes.is_visible){
3524 const gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
3526 if(s && strlen(s) > 0) {
3527 text_width = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
3532 range.col0 = sheet->view.col0;
3533 range.coli = sheet->view.coli;
3535 if(gtk_sheet_autoresize(sheet) &&
3536 text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
3537 gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width);
3538 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3541 if(!GTK_SHEET_IS_FROZEN(sheet))
3542 gtk_sheet_range_draw(sheet, &range);
3546 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
3552 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
3554 GtkSheetRange range;
3556 g_return_if_fail (sheet != NULL);
3557 g_return_if_fail (GTK_IS_SHEET (sheet));
3558 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3559 if (column < 0 || row < 0) return;
3563 range.col0 = sheet->view.col0;
3564 range.coli = sheet->view.coli;
3566 gtk_sheet_real_cell_clear(sheet, row, column, FALSE);
3568 if(!GTK_SHEET_IS_FROZEN(sheet)){
3569 gtk_sheet_range_draw(sheet, &range);
3574 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
3576 GtkSheetRange range;
3578 g_return_if_fail (sheet != NULL);
3579 g_return_if_fail (GTK_IS_SHEET (sheet));
3580 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3581 if (column < 0 || row < 0) return;
3585 range.col0 = sheet->view.col0;
3586 range.coli = sheet->view.coli;
3588 gtk_sheet_real_cell_clear(sheet, row, column, TRUE);
3590 if(!GTK_SHEET_IS_FROZEN(sheet)){
3591 gtk_sheet_range_draw(sheet, &range);
3596 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
3598 const gchar *old_text;
3600 old_text = gtk_sheet_cell_get_text(sheet, row, column);
3602 GSheetModel *model = gtk_sheet_get_model(sheet);
3604 if (old_text && strlen(old_text) > 0 )
3606 g_sheet_model_datum_clear(model, row, column);
3608 if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0)
3609 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL],
3616 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
3618 g_return_if_fail (sheet != NULL);
3619 g_return_if_fail (GTK_IS_SHEET (sheet));
3621 gtk_sheet_real_range_clear(sheet, range, FALSE);
3625 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range)
3627 g_return_if_fail (sheet != NULL);
3628 g_return_if_fail (GTK_IS_SHEET (sheet));
3630 gtk_sheet_real_range_clear(sheet, range, TRUE);
3635 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
3639 GtkSheetRange clear;
3643 clear.rowi = yyy_row_count(sheet) - 1;
3645 clear.coli = xxx_column_count(sheet) - 1;
3649 clear.row0=MAX(clear.row0, 0);
3650 clear.col0=MAX(clear.col0, 0);
3651 clear.rowi=MIN(clear.rowi, yyy_row_count(sheet) - 1 );
3652 clear.coli=MIN(clear.coli, xxx_column_count(sheet) - 1 );
3654 for(i=clear.row0; i<=clear.rowi; i++)
3655 for(j=clear.col0; j<=clear.coli; j++){
3656 gtk_sheet_real_cell_clear(sheet, i, j, delete);
3659 gtk_sheet_range_draw(sheet, NULL);
3664 gtk_sheet_cell_get_text (GtkSheet *sheet, gint row, gint col)
3667 g_return_val_if_fail (sheet != NULL, NULL);
3668 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
3670 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet))
3672 if(col < 0 || row < 0) return NULL;
3674 model = gtk_sheet_get_model(sheet);
3679 return g_sheet_model_get_string(model, row, col);
3684 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
3687 GtkSheetRange *range;
3689 g_return_val_if_fail (sheet != NULL, 0);
3690 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3691 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return 0;
3692 if(col < 0 || row < 0) return 0;
3694 state = sheet->state;
3695 range = &sheet->range;
3699 case GTK_SHEET_NORMAL:
3700 return GTK_STATE_NORMAL;
3702 case GTK_SHEET_ROW_SELECTED:
3703 if(row>=range->row0 && row<=range->rowi)
3704 return GTK_STATE_SELECTED;
3706 case GTK_SHEET_COLUMN_SELECTED:
3707 if(col>=range->col0 && col<=range->coli)
3708 return GTK_STATE_SELECTED;
3710 case GTK_SHEET_RANGE_SELECTED:
3711 if(row >= range->row0 && row <= range->rowi && \
3712 col >= range->col0 && col <= range->coli)
3713 return GTK_STATE_SELECTED;
3716 return GTK_STATE_NORMAL;
3720 gtk_sheet_get_pixel_info (GtkSheet * sheet,
3728 g_return_val_if_fail (sheet != NULL, 0);
3729 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3731 /* bounds checking, return false if the user clicked
3732 * on a blank area */
3733 trow = ROW_FROM_YPIXEL (sheet, y);
3734 if (trow >= yyy_row_count(sheet))
3739 tcol = COLUMN_FROM_XPIXEL (sheet, x);
3740 if (tcol >= xxx_column_count(sheet))
3749 gtk_sheet_get_cell_area (GtkSheet * sheet,
3754 g_return_val_if_fail (sheet != NULL, 0);
3755 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3757 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3760 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) -
3761 (sheet->row_titles_visible
3762 ? sheet->row_title_area.width
3764 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL(sheet, row) -
3765 (sheet->column_titles_visible
3766 ? sheet->column_title_area.height
3768 area->width= (column == -1) ? sheet->row_title_area.width
3769 : xxx_column_width(sheet, column);
3771 area->height= (row == -1) ? sheet->column_title_area.height
3772 : yyy_row_height(sheet, row);
3775 if(row < 0 || column < 0) return FALSE;
3777 area->x = COLUMN_LEFT_XPIXEL(sheet, column);
3778 area->y = ROW_TOP_YPIXEL(sheet, row);
3779 if(sheet->row_titles_visible)
3780 area->x -= sheet->row_title_area.width;
3781 if(sheet->column_titles_visible)
3782 area->y -= sheet->column_title_area.height;
3784 area->width=sheet->column[column].width;
3785 area->height=yyy_row_height(sheet, row);
3791 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
3793 g_return_val_if_fail (sheet != NULL, 0);
3794 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3796 if(row < 0 || column < 0) return FALSE;
3797 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3800 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
3802 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
3805 sheet->active_cell.row=row;
3806 sheet->active_cell.col=column;
3808 if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE;
3810 if(gtk_sheet_autoscroll(sheet))
3811 gtk_sheet_move_query(sheet, row, column);
3817 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column)
3819 g_return_if_fail (sheet != NULL);
3820 g_return_if_fail (GTK_IS_SHEET (sheet));
3822 *row = sheet->active_cell.row;
3823 *column = sheet->active_cell.col;
3827 gtk_sheet_entry_changed(GtkWidget *widget, gpointer data)
3832 GtkJustification justification;
3833 GtkSheetCellAttr attributes;
3835 g_return_if_fail (data != NULL);
3836 g_return_if_fail (GTK_IS_SHEET (data));
3838 sheet=GTK_SHEET(data);
3840 if(!GTK_WIDGET_VISIBLE(widget)) return;
3841 if(sheet->state != GTK_STATE_NORMAL) return;
3843 row=sheet->active_cell.row;
3844 col=sheet->active_cell.col;
3846 if(row<0 || col<0) return;
3848 sheet->active_cell.row=-1;
3849 sheet->active_cell.col=-1;
3851 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3853 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3855 if(text && strlen(text) > 0){
3856 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3857 justification=attributes.justification;
3858 gtk_sheet_set_cell(sheet, row, col, justification, text);
3861 if(sheet->freeze_count == 0)
3862 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3864 sheet->active_cell.row=row;;
3865 sheet->active_cell.col=col;
3870 gtk_sheet_deactivate_cell(GtkSheet *sheet)
3872 gboolean veto = TRUE;
3874 g_return_val_if_fail (sheet != NULL, FALSE);
3875 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
3877 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return FALSE;
3878 if(sheet->state != GTK_SHEET_NORMAL) return FALSE;
3880 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[DEACTIVATE],
3881 sheet->active_cell.row,
3882 sheet->active_cell.col, &veto);
3884 if(!veto) return FALSE;
3886 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
3887 (GtkSignalFunc) gtk_sheet_entry_changed,
3888 GTK_OBJECT(GTK_WIDGET(sheet)));
3890 gtk_sheet_hide_active_cell(sheet);
3891 sheet->active_cell.row=-1;
3892 sheet->active_cell.col=-1;
3894 if(GTK_SHEET_REDRAW_PENDING(sheet)){
3895 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3896 gtk_sheet_range_draw(sheet, NULL);
3903 gtk_sheet_hide_active_cell(GtkSheet *sheet)
3907 GtkJustification justification;
3908 GtkSheetCellAttr attributes;
3910 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3912 row=sheet->active_cell.row;
3913 col=sheet->active_cell.col;
3915 if(row < 0 || col < 0) return;
3917 if(sheet->freeze_count == 0)
3918 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3920 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3922 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3923 justification=attributes.justification;
3925 if(text && strlen(text)!=0){
3926 gtk_sheet_set_cell(sheet, row, col, justification, text);
3927 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col);
3931 gtk_sheet_cell_clear(sheet, row, col);
3934 row=sheet->active_cell.row;
3935 col=sheet->active_cell.col;
3938 column_button_release(sheet, col);
3939 row_button_release(sheet, row);
3942 gtk_widget_unmap(sheet->sheet_entry);
3944 if(row != -1 && col != -1)
3945 gdk_draw_pixmap(sheet->sheet_window,
3946 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3948 COLUMN_LEFT_XPIXEL(sheet,col)-1,
3949 ROW_TOP_YPIXEL(sheet,row)-1,
3950 COLUMN_LEFT_XPIXEL(sheet,col)-1,
3951 ROW_TOP_YPIXEL(sheet,row)-1,
3952 xxx_column_width(sheet, col) + 4,
3953 yyy_row_height(sheet, row)+4);
3955 gtk_widget_grab_focus(GTK_WIDGET(sheet));
3957 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
3962 gtk_sheet_activate_cell(GtkSheet *sheet, gint row, gint col)
3964 gboolean veto = TRUE;
3966 g_return_val_if_fail (sheet != NULL, FALSE);
3967 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
3969 if(row < 0 || col < 0) return FALSE;
3970 if(row >= yyy_row_count(sheet) || col >= xxx_column_count(sheet))
3973 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
3974 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
3977 if(!veto) return FALSE;
3978 if(sheet->state != GTK_SHEET_NORMAL){
3979 sheet->state=GTK_SHEET_NORMAL;
3980 gtk_sheet_real_unselect_range(sheet, NULL);
3983 sheet->range.row0=row;
3984 sheet->range.col0=col;
3985 sheet->range.rowi=row;
3986 sheet->range.coli=col;
3987 sheet->active_cell.row=row;
3988 sheet->active_cell.col=col;
3989 sheet->selection_cell.row=row;
3990 sheet->selection_cell.col=col;
3992 row_button_set(sheet, row);
3993 column_button_set(sheet, col);
3996 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
3997 gtk_sheet_show_active_cell(sheet);
3999 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
4001 G_CALLBACK(gtk_sheet_entry_changed),
4004 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4010 gtk_sheet_show_active_cell(GtkSheet *sheet)
4012 GtkEntry *sheet_entry;
4013 GtkSheetCellAttr attributes;
4015 const gchar *old_text;
4016 GtkJustification justification;
4019 g_return_if_fail (sheet != NULL);
4020 g_return_if_fail (GTK_IS_SHEET (sheet));
4022 row = sheet->active_cell.row;
4023 col = sheet->active_cell.col;
4025 /* Don't show the active cell, if there is no active cell: */
4026 if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */
4029 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4030 if(sheet->state != GTK_SHEET_NORMAL) return;
4031 if(GTK_SHEET_IN_SELECTION(sheet)) return;
4033 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4035 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
4037 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4039 justification = GTK_JUSTIFY_LEFT;
4041 if(gtk_sheet_justify_entry(sheet))
4042 justification = attributes.justification;
4044 text = g_strdup(gtk_sheet_cell_get_text(sheet, row, col));
4046 if(!text) text = g_strdup("");
4048 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible);
4050 if(gtk_sheet_locked(sheet) || !attributes.is_editable){
4051 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
4053 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
4056 /*** Added by John Gotts. Mar 25, 2005 *********/
4057 old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
4058 if (strcmp(old_text, text) != 0)
4060 if(!GTK_IS_ITEM_ENTRY(sheet_entry))
4061 gtk_entry_set_text(GTK_ENTRY(sheet_entry), text);
4063 gtk_item_entry_set_text(GTK_ITEM_ENTRY(sheet_entry), text, justification);
4066 gtk_sheet_entry_set_max_size(sheet);
4067 gtk_sheet_size_allocate_entry(sheet);
4069 gtk_widget_map(sheet->sheet_entry);
4070 gtk_sheet_draw_active_cell(sheet);
4072 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
4078 gtk_sheet_draw_active_cell(GtkSheet *sheet)
4082 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
4083 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4085 row = sheet->active_cell.row;
4086 col = sheet->active_cell.col;
4088 if(row<0 || col<0) return;
4090 if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
4092 row_button_set(sheet, row);
4093 column_button_set(sheet, col);
4095 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4096 gtk_sheet_draw_border(sheet, sheet->range);
4102 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
4104 gint pixmap_width, pixmap_height;
4106 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4108 if(width == 0 && height == 0){
4109 width=sheet->sheet_window_width+80;
4110 height=sheet->sheet_window_height+80;
4116 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4119 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4123 /* reallocate if sizes don't match */
4124 gdk_window_get_size (sheet->pixmap,
4125 &pixmap_width, &pixmap_height);
4126 if ((pixmap_width != width) || (pixmap_height != height))
4128 g_free(sheet->pixmap);
4129 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4132 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4138 gtk_sheet_new_selection(GtkSheet *sheet, GtkSheetRange *range)
4140 gint i,j, mask1, mask2;
4141 gint state, selected;
4142 gint x,y,width,height;
4143 GtkSheetRange new_range, aux_range;
4145 g_return_if_fail (sheet != NULL);
4147 if(range==NULL) range=&sheet->range;
4151 range->row0=MIN(range->row0, sheet->range.row0);
4152 range->rowi=MAX(range->rowi, sheet->range.rowi);
4153 range->col0=MIN(range->col0, sheet->range.col0);
4154 range->coli=MAX(range->coli, sheet->range.coli);
4156 range->row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
4157 range->rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
4158 range->col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
4159 range->coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
4161 aux_range.row0=MAX(new_range.row0, MIN_VISIBLE_ROW(sheet));
4162 aux_range.rowi=MIN(new_range.rowi, MAX_VISIBLE_ROW(sheet));
4163 aux_range.col0=MAX(new_range.col0, MIN_VISIBLE_COLUMN(sheet));
4164 aux_range.coli=MIN(new_range.coli, MAX_VISIBLE_COLUMN(sheet));
4166 for(i=range->row0; i<=range->rowi; i++){
4167 for(j=range->col0; j<=range->coli; j++){
4169 state=gtk_sheet_cell_get_state(sheet, i, j);
4170 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4171 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4173 if(state==GTK_STATE_SELECTED && selected &&
4174 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4175 (i==sheet->range.row0 || i==sheet->range.rowi ||
4176 j==sheet->range.col0 || j==sheet->range.coli ||
4177 i==new_range.row0 || i==new_range.rowi ||
4178 j==new_range.col0 || j==new_range.coli)){
4180 mask1 = i==sheet->range.row0 ? 1 : 0;
4181 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4182 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4183 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4185 mask2 = i==new_range.row0 ? 1 : 0;
4186 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4187 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4188 mask2 = j==new_range.coli ? mask2+8 : mask2;
4191 x=COLUMN_LEFT_XPIXEL(sheet,j);
4192 y=ROW_TOP_YPIXEL(sheet, i);
4193 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4194 xxx_column_width(sheet, j);
4195 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4197 if(i==sheet->range.row0){
4201 if(i==sheet->range.rowi) height=height+3;
4202 if(j==sheet->range.col0){
4206 if(j==sheet->range.coli) width=width+3;
4208 gdk_draw_pixmap(sheet->sheet_window,
4209 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4218 if(i != sheet->active_cell.row || j != sheet->active_cell.col){
4219 x=COLUMN_LEFT_XPIXEL(sheet,j);
4220 y=ROW_TOP_YPIXEL(sheet, i);
4221 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4222 xxx_column_width(sheet, j);
4224 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4226 if(i==new_range.row0){
4230 if(i==new_range.rowi) height=height-3;
4231 if(j==new_range.col0){
4235 if(j==new_range.coli) width=width-3;
4237 gdk_draw_rectangle (sheet->sheet_window,
4248 for(i=range->row0; i<=range->rowi; i++){
4249 for(j=range->col0; j<=range->coli; j++){
4251 state=gtk_sheet_cell_get_state(sheet, i, j);
4252 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4253 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4255 if(state==GTK_STATE_SELECTED && !selected &&
4256 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4258 x=COLUMN_LEFT_XPIXEL(sheet,j);
4259 y=ROW_TOP_YPIXEL(sheet, i);
4260 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4261 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4263 if(i==sheet->range.row0){
4267 if(i==sheet->range.rowi) height=height+3;
4268 if(j==sheet->range.col0){
4272 if(j==sheet->range.coli) width=width+3;
4274 gdk_draw_pixmap(sheet->sheet_window,
4275 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4287 for(i=range->row0; i<=range->rowi; i++){
4288 for(j=range->col0; j<=range->coli; j++){
4290 state=gtk_sheet_cell_get_state(sheet, i, j);
4291 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4292 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4294 if(state!=GTK_STATE_SELECTED && selected &&
4295 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4296 (i != sheet->active_cell.row || j != sheet->active_cell.col)){
4298 x=COLUMN_LEFT_XPIXEL(sheet,j);
4299 y=ROW_TOP_YPIXEL(sheet, i);
4300 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4301 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4303 if(i==new_range.row0){
4307 if(i==new_range.rowi) height=height-3;
4308 if(j==new_range.col0){
4312 if(j==new_range.coli) width=width-3;
4314 gdk_draw_rectangle (sheet->sheet_window,
4325 for(i=aux_range.row0; i<=aux_range.rowi; i++){
4326 for(j=aux_range.col0; j<=aux_range.coli; j++){
4328 if(xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4330 state=gtk_sheet_cell_get_state(sheet, i, j);
4332 mask1 = i==sheet->range.row0 ? 1 : 0;
4333 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4334 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4335 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4337 mask2 = i==new_range.row0 ? 1 : 0;
4338 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4339 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4340 mask2 = j==new_range.coli ? mask2+8 : mask2;
4341 if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){
4342 x=COLUMN_LEFT_XPIXEL(sheet,j);
4343 y=ROW_TOP_YPIXEL(sheet, i);
4344 width=xxx_column_width(sheet, j);
4345 height=yyy_row_height(sheet, i);
4347 gdk_draw_rectangle (sheet->sheet_window,
4355 gdk_draw_rectangle (sheet->sheet_window,
4362 gdk_draw_rectangle (sheet->sheet_window,
4370 gdk_draw_rectangle (sheet->sheet_window,
4387 gtk_sheet_draw_corners(sheet, new_range);
4392 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
4397 gint x,y,width,height;
4399 widget = GTK_WIDGET(sheet);
4401 x=COLUMN_LEFT_XPIXEL(sheet,new_range.col0);
4402 y=ROW_TOP_YPIXEL(sheet,new_range.row0);
4403 width=COLUMN_LEFT_XPIXEL(sheet,new_range.coli)-x+
4404 xxx_column_width(sheet, new_range.coli);
4406 height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+
4407 yyy_row_height(sheet, new_range.rowi);
4409 area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
4410 area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
4411 area.width=sheet->sheet_window_width;
4412 area.height=sheet->sheet_window_height;
4418 if(width>area.width) width=area.width+10;
4423 if(height>area.height) height=area.height+10;
4425 gdk_gc_set_clip_rectangle(sheet->xor_gc, &area);
4427 for(i=-1; i<=1; ++i)
4428 gdk_draw_rectangle (sheet->sheet_window,
4432 width-2*i,height-2*i);
4434 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
4436 gtk_sheet_draw_corners(sheet, new_range);
4441 gtk_sheet_draw_corners(GtkSheet *sheet, GtkSheetRange range)
4446 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.col0)){
4447 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4448 y=ROW_TOP_YPIXEL(sheet,range.row0);
4449 gdk_draw_pixmap(sheet->sheet_window,
4450 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4458 gdk_draw_rectangle (sheet->sheet_window,
4465 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) ||
4466 sheet->state == GTK_SHEET_COLUMN_SELECTED){
4467 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4468 xxx_column_width(sheet, range.coli);
4469 y=ROW_TOP_YPIXEL(sheet,range.row0);
4471 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
4473 y = ROW_TOP_YPIXEL(sheet, sheet->view.row0)+3;
4476 gdk_draw_pixmap(sheet->sheet_window,
4477 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4485 gdk_draw_rectangle (sheet->sheet_window,
4488 x-width+width/2,y-width+width/2,
4492 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.col0) ||
4493 sheet->state == GTK_SHEET_ROW_SELECTED){
4494 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4495 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4496 yyy_row_height(sheet, range.rowi);
4498 if(sheet->state == GTK_SHEET_ROW_SELECTED)
4500 x = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0)+3;
4503 gdk_draw_pixmap(sheet->sheet_window,
4504 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4512 gdk_draw_rectangle (sheet->sheet_window,
4515 x-width+width/2,y-width+width/2,
4519 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){
4520 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4521 xxx_column_width(sheet, range.coli);
4522 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4523 yyy_row_height(sheet, range.rowi);
4525 if(sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
4526 if(sheet->state == GTK_SHEET_NORMAL) width = 3;
4527 gdk_draw_pixmap(sheet->sheet_window,
4528 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4536 gdk_draw_rectangle (sheet->sheet_window,
4539 x-width+width/2,y-width+width/2,
4548 gtk_sheet_real_select_range (GtkSheet * sheet,
4549 GtkSheetRange * range)
4553 g_return_if_fail (sheet != NULL);
4555 if(range==NULL) range=&sheet->range;
4557 if(range->row0 < 0 || range->rowi < 0) return;
4558 if(range->col0 < 0 || range->coli < 0) return;
4563 if(state==GTK_SHEET_COLUMN_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4564 for(i=sheet->range.col0; i< range->col0; i++)
4565 column_button_release(sheet, i);
4566 for(i=range->coli+1; i<= sheet->range.coli; i++)
4567 column_button_release(sheet, i);
4568 for(i=range->col0; i<=range->coli; i++){
4569 column_button_set(sheet, i);
4573 if(state==GTK_SHEET_ROW_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4574 for(i=sheet->range.row0; i< range->row0; i++)
4575 row_button_release(sheet, i);
4576 for(i=range->rowi+1; i<= sheet->range.rowi; i++)
4577 row_button_release(sheet, i);
4578 for(i=range->row0; i<=range->rowi; i++){
4579 row_button_set(sheet, i);
4584 if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
4585 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
4588 gtk_sheet_new_selection(sheet, range);
4590 sheet->range.col0=range->col0;
4591 sheet->range.coli=range->coli;
4592 sheet->range.row0=range->row0;
4593 sheet->range.rowi=range->rowi;
4598 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4599 gtk_sheet_range_draw_selection(sheet, sheet->range);
4602 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[SELECT_RANGE], range);
4606 gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range)
4608 g_return_if_fail (sheet != NULL);
4610 if(range==NULL) range=&sheet->range;
4612 if(range->row0 < 0 || range->rowi < 0) return;
4613 if(range->col0 < 0 || range->coli < 0) return;
4615 if(sheet->state != GTK_SHEET_NORMAL)
4616 gtk_sheet_real_unselect_range(sheet, NULL);
4619 gboolean veto = TRUE;
4620 veto = gtk_sheet_deactivate_cell(sheet);
4624 sheet->range.row0=range->row0;
4625 sheet->range.rowi=range->rowi;
4626 sheet->range.col0=range->col0;
4627 sheet->range.coli=range->coli;
4628 sheet->active_cell.row=range->row0;
4629 sheet->active_cell.col=range->col0;
4630 sheet->selection_cell.row=range->rowi;
4631 sheet->selection_cell.col=range->coli;
4633 sheet->state = GTK_SHEET_RANGE_SELECTED;
4634 gtk_sheet_real_select_range(sheet, NULL);
4639 gtk_sheet_unselect_range (GtkSheet * sheet)
4641 gtk_sheet_real_unselect_range(sheet, NULL);
4642 sheet->state = GTK_STATE_NORMAL;
4643 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
4648 gtk_sheet_real_unselect_range (GtkSheet * sheet,
4649 const GtkSheetRange *range)
4651 g_return_if_fail (sheet != NULL);
4652 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)));
4655 range=&sheet->range;
4658 if(range->row0 < 0 || range->rowi < 0) return;
4659 if(range->col0 < 0 || range->coli < 0) return;
4661 if (gtk_sheet_range_isvisible (sheet, *range)){
4662 gtk_sheet_draw_backing_pixmap(sheet, *range);
4666 for(i=range->col0; i<=range->coli; i++){
4667 column_button_release(sheet, i);
4670 for(i=range->row0; i<=range->rowi; i++){
4671 row_button_release(sheet, i);
4675 gtk_sheet_position_children(sheet);
4680 gtk_sheet_expose (GtkWidget * widget,
4681 GdkEventExpose * event)
4684 GtkSheetRange range;
4686 g_return_val_if_fail (widget != NULL, FALSE);
4687 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4688 g_return_val_if_fail (event != NULL, FALSE);
4690 sheet = GTK_SHEET (widget);
4692 if (GTK_WIDGET_DRAWABLE (widget))
4694 range.row0=ROW_FROM_YPIXEL(sheet,event->area.y);
4695 range.col0=COLUMN_FROM_XPIXEL(sheet,event->area.x);
4696 range.rowi=ROW_FROM_YPIXEL(sheet,event->area.y+event->area.height);
4697 range.coli=COLUMN_FROM_XPIXEL(sheet,event->area.x+event->area.width);
4699 /* exposure events on the sheet */
4701 if(event->window == sheet->row_title_window && sheet->row_titles_visible){
4703 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
4704 gtk_sheet_button_draw(sheet,i,-1);
4707 if(event->window == sheet->column_title_window && sheet->column_titles_visible){
4709 for(i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
4710 gtk_sheet_button_draw(sheet,-1,i);
4713 if (event->window == sheet->sheet_window){
4714 gtk_sheet_draw_backing_pixmap(sheet, range);
4716 if(sheet->state != GTK_SHEET_NORMAL){
4717 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4718 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4719 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4720 gtk_sheet_draw_backing_pixmap(sheet, sheet->drag_range);
4722 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4723 gtk_sheet_range_draw_selection(sheet, sheet->range);
4724 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4725 draw_xor_rectangle(sheet, sheet->drag_range);
4728 if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet))){
4729 if(sheet->state == GTK_SHEET_NORMAL){
4730 gtk_sheet_draw_active_cell(sheet);
4731 if(!GTK_SHEET_IN_SELECTION(sheet))
4732 gtk_widget_queue_draw(sheet->sheet_entry);
4741 if(sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet))
4742 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4744 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
4751 gtk_sheet_button_press (GtkWidget * widget,
4752 GdkEventButton * event)
4755 GdkModifierType mods;
4756 gint x, y, row, column;
4759 g_return_val_if_fail (widget != NULL, FALSE);
4760 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4761 g_return_val_if_fail (event != NULL, FALSE);
4763 sheet = GTK_SHEET (widget);
4765 if ( event->type == GDK_2BUTTON_PRESS)
4767 gtk_widget_get_pointer (widget, &x, &y);
4768 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4770 if (event->window == sheet->column_title_window )
4772 gtk_signal_emit (GTK_OBJECT (sheet),
4773 sheet_signals[DOUBLE_CLICK_COLUMN], column);
4775 else if (event->window == sheet->row_title_window )
4777 gtk_signal_emit (GTK_OBJECT (sheet),
4778 sheet_signals[DOUBLE_CLICK_ROW], row);
4784 if(event->type != GDK_BUTTON_PRESS) return TRUE;
4786 gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
4788 if(!(mods & GDK_BUTTON1_MASK)) return TRUE;
4791 /* press on resize windows */
4792 if (event->window == sheet->column_title_window &&
4793 gtk_sheet_columns_resizable(sheet))
4795 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
4796 if(POSSIBLE_XDRAG(sheet, sheet->x_drag, &sheet->drag_cell.col)){
4798 if (event->type == GDK_2BUTTON_PRESS){
4799 gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
4800 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_XDRAG);
4803 gtk_sheet_column_size_request(sheet, sheet->drag_cell.col, &req);
4804 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4805 gdk_pointer_grab (sheet->column_title_window, FALSE,
4806 GDK_POINTER_MOTION_HINT_MASK |
4807 GDK_BUTTON1_MOTION_MASK |
4808 GDK_BUTTON_RELEASE_MASK,
4809 NULL, NULL, event->time);
4811 draw_xor_vline (sheet);
4816 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet))
4818 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
4820 if(POSSIBLE_YDRAG(sheet, sheet->y_drag, &sheet->drag_cell.row)){
4822 gtk_sheet_row_size_request(sheet, sheet->drag_cell.row, &req);
4823 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
4824 gdk_pointer_grab (sheet->row_title_window, FALSE,
4825 GDK_POINTER_MOTION_HINT_MASK |
4826 GDK_BUTTON1_MOTION_MASK |
4827 GDK_BUTTON_RELEASE_MASK,
4828 NULL, NULL, event->time);
4830 draw_xor_hline (sheet);
4835 /* the sheet itself does not handle other than single click events */
4836 if(event->type != GDK_BUTTON_PRESS) return FALSE;
4838 /* selections on the sheet */
4839 if(event->window == sheet->sheet_window){
4840 gtk_widget_get_pointer (widget, &x, &y);
4841 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4842 gdk_pointer_grab (sheet->sheet_window, FALSE,
4843 GDK_POINTER_MOTION_HINT_MASK |
4844 GDK_BUTTON1_MOTION_MASK |
4845 GDK_BUTTON_RELEASE_MASK,
4846 NULL, NULL, event->time);
4847 gtk_grab_add(GTK_WIDGET(sheet));
4848 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4849 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4851 if(sheet->selection_mode != GTK_SELECTION_SINGLE &&
4852 sheet->cursor_drag->type==GDK_SIZING &&
4853 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_RESIZE(sheet)){
4854 if(sheet->state==GTK_STATE_NORMAL) {
4855 row=sheet->active_cell.row;
4856 column=sheet->active_cell.col;
4857 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4858 sheet->active_cell.row=row;
4859 sheet->active_cell.col=column;
4860 sheet->drag_range=sheet->range;
4861 sheet->state=GTK_SHEET_RANGE_SELECTED;
4862 gtk_sheet_select_range(sheet, &sheet->drag_range);
4866 if(row > sheet->range.rowi) row--;
4867 if(column > sheet->range.coli) column--;
4868 sheet->drag_cell.row = row;
4869 sheet->drag_cell.col = column;
4870 sheet->drag_range=sheet->range;
4871 draw_xor_rectangle(sheet, sheet->drag_range);
4872 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
4874 else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW &&
4875 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_DRAG(sheet)) {
4876 if(sheet->state==GTK_STATE_NORMAL) {
4877 row=sheet->active_cell.row;
4878 column=sheet->active_cell.col;
4879 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4880 sheet->active_cell.row=row;
4881 sheet->active_cell.col=column;
4882 sheet->drag_range=sheet->range;
4883 sheet->state=GTK_SHEET_RANGE_SELECTED;
4884 gtk_sheet_select_range(sheet, &sheet->drag_range);
4888 if(row < sheet->range.row0) row++;
4889 if(row > sheet->range.rowi) row--;
4890 if(column < sheet->range.col0) column++;
4891 if(column > sheet->range.coli) column--;
4892 sheet->drag_cell.row=row;
4893 sheet->drag_cell.col=column;
4894 sheet->drag_range=sheet->range;
4895 draw_xor_rectangle(sheet, sheet->drag_range);
4896 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
4900 gtk_sheet_click_cell(sheet, row, column, &veto);
4901 if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4906 if(event->window == sheet->column_title_window){
4907 gtk_widget_get_pointer (widget, &x, &y);
4908 column = COLUMN_FROM_XPIXEL(sheet, x);
4909 if(xxx_column_is_sensitive(sheet, column)){
4910 gtk_sheet_click_cell(sheet, -1, column, &veto);
4911 gtk_grab_add(GTK_WIDGET(sheet));
4912 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4913 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4914 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4918 if(event->window == sheet->row_title_window){
4919 gtk_widget_get_pointer (widget, &x, &y);
4920 row = ROW_FROM_YPIXEL(sheet, y);
4921 if(yyy_row_is_sensitive(sheet, row)){
4922 gtk_sheet_click_cell(sheet, row, -1, &veto);
4923 gtk_grab_add(GTK_WIDGET(sheet));
4924 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4925 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4926 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4934 gtk_sheet_scroll(gpointer data)
4937 gint x,y,row,column;
4940 sheet=GTK_SHEET(data);
4942 GDK_THREADS_ENTER();
4944 gtk_widget_get_pointer (GTK_WIDGET(sheet), &x, &y);
4945 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4949 if(GTK_SHEET_IN_SELECTION(sheet))
4950 gtk_sheet_extend_selection(sheet, row, column);
4952 if(GTK_SHEET_IN_DRAG(sheet) || GTK_SHEET_IN_RESIZE(sheet)){
4953 move=gtk_sheet_move_query(sheet, row, column);
4954 if(move) draw_xor_rectangle(sheet, sheet->drag_range);
4957 GDK_THREADS_LEAVE();
4964 gtk_sheet_click_cell(GtkSheet *sheet, gint row, gint column, gboolean *veto)
4968 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)){
4973 if(column >= 0 && row >= 0)
4974 if(! xxx_column_is_visible(sheet, column) || !yyy_row_is_visible(sheet, row))
4980 _gtkextra_signal_emit(GTK_OBJECT(sheet), sheet_signals[TRAVERSE],
4981 sheet->active_cell.row, sheet->active_cell.col,
4982 &row, &column, veto);
4985 if(sheet->state == GTK_STATE_NORMAL) return;
4987 row = sheet->active_cell.row;
4988 column = sheet->active_cell.col;
4990 gtk_sheet_activate_cell(sheet, row, column);
4994 if(row == -1 && column >= 0){
4995 if(gtk_sheet_autoscroll(sheet))
4996 gtk_sheet_move_query(sheet, row, column);
4997 gtk_sheet_select_column(sheet, column);
5000 if(column == -1 && row >= 0){
5001 if(gtk_sheet_autoscroll(sheet))
5002 gtk_sheet_move_query(sheet, row, column);
5003 gtk_sheet_select_row(sheet, row);
5007 if(row==-1 && column ==-1){
5008 sheet->range.row0=0;
5009 sheet->range.col0=0;
5010 sheet->range.rowi = yyy_row_count(sheet) - 1;
5011 sheet->range.coli = xxx_column_count(sheet) - 1;
5012 sheet->active_cell.row=0;
5013 sheet->active_cell.col=0;
5014 gtk_sheet_select_range(sheet, NULL);
5018 if(row!=-1 && column !=-1){
5019 if(sheet->state != GTK_SHEET_NORMAL){
5020 sheet->state = GTK_SHEET_NORMAL;
5021 gtk_sheet_real_unselect_range(sheet, NULL);
5025 if(!gtk_sheet_deactivate_cell(sheet)){
5031 if(gtk_sheet_autoscroll(sheet))
5032 gtk_sheet_move_query(sheet, row, column);
5033 sheet->active_cell.row=row;
5034 sheet->active_cell.col=column;
5035 sheet->selection_cell.row=row;
5036 sheet->selection_cell.col=column;
5037 sheet->range.row0=row;
5038 sheet->range.col0=column;
5039 sheet->range.rowi=row;
5040 sheet->range.coli=column;
5041 sheet->state=GTK_SHEET_NORMAL;
5042 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5043 gtk_sheet_draw_active_cell(sheet);
5047 g_assert_not_reached();
5048 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5049 sheet->active_cell.col);
5053 gtk_sheet_button_release (GtkWidget * widget,
5054 GdkEventButton * event)
5059 sheet=GTK_SHEET(widget);
5061 /* release on resize windows */
5062 if (GTK_SHEET_IN_XDRAG (sheet)){
5063 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
5064 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5065 gtk_widget_get_pointer (widget, &x, NULL);
5066 gdk_pointer_ungrab (event->time);
5067 draw_xor_vline (sheet);
5069 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col, new_column_width (sheet, sheet->drag_cell.col, &x));
5070 sheet->old_hadjustment = -1.;
5071 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed");
5075 if (GTK_SHEET_IN_YDRAG (sheet)){
5076 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5077 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5078 gtk_widget_get_pointer (widget, NULL, &y);
5079 gdk_pointer_ungrab (event->time);
5080 draw_xor_hline (sheet);
5082 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
5083 sheet->old_vadjustment = -1.;
5084 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed");
5089 if (GTK_SHEET_IN_DRAG(sheet)){
5090 GtkSheetRange old_range;
5091 draw_xor_rectangle(sheet, sheet->drag_range);
5092 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5093 gdk_pointer_ungrab (event->time);
5095 gtk_sheet_real_unselect_range(sheet, NULL);
5097 sheet->active_cell.row = sheet->active_cell.row +
5098 (sheet->drag_range.row0 - sheet->range.row0);
5099 sheet->active_cell.col = sheet->active_cell.col +
5100 (sheet->drag_range.col0 - sheet->range.col0);
5101 sheet->selection_cell.row = sheet->selection_cell.row +
5102 (sheet->drag_range.row0 - sheet->range.row0);
5103 sheet->selection_cell.col = sheet->selection_cell.col +
5104 (sheet->drag_range.col0 - sheet->range.col0);
5105 old_range=sheet->range;
5106 sheet->range=sheet->drag_range;
5107 sheet->drag_range=old_range;
5108 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[MOVE_RANGE],
5109 &sheet->drag_range, &sheet->range);
5110 gtk_sheet_select_range(sheet, &sheet->range);
5113 if (GTK_SHEET_IN_RESIZE(sheet)){
5114 GtkSheetRange old_range;
5115 draw_xor_rectangle(sheet, sheet->drag_range);
5116 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5117 gdk_pointer_ungrab (event->time);
5119 gtk_sheet_real_unselect_range(sheet, NULL);
5121 sheet->active_cell.row = sheet->active_cell.row +
5122 (sheet->drag_range.row0 - sheet->range.row0);
5123 sheet->active_cell.col = sheet->active_cell.col +
5124 (sheet->drag_range.col0 - sheet->range.col0);
5125 if(sheet->drag_range.row0 < sheet->range.row0)
5126 sheet->selection_cell.row = sheet->drag_range.row0;
5127 if(sheet->drag_range.rowi >= sheet->range.rowi)
5128 sheet->selection_cell.row = sheet->drag_range.rowi;
5129 if(sheet->drag_range.col0 < sheet->range.col0)
5130 sheet->selection_cell.col = sheet->drag_range.col0;
5131 if(sheet->drag_range.coli >= sheet->range.coli)
5132 sheet->selection_cell.col = sheet->drag_range.coli;
5133 old_range = sheet->range;
5134 sheet->range = sheet->drag_range;
5135 sheet->drag_range = old_range;
5137 if(sheet->state==GTK_STATE_NORMAL) sheet->state=GTK_SHEET_RANGE_SELECTED;
5138 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[RESIZE_RANGE],
5139 &sheet->drag_range, &sheet->range);
5140 gtk_sheet_select_range(sheet, &sheet->range);
5143 if(sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)){
5144 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5145 gdk_pointer_ungrab (event->time);
5146 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5147 sheet->active_cell.col);
5150 if(GTK_SHEET_IN_SELECTION)
5151 gdk_pointer_ungrab (event->time);
5153 gtk_timeout_remove(sheet->timer);
5154 gtk_grab_remove(GTK_WIDGET(sheet));
5156 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5162 gtk_sheet_motion (GtkWidget * widget,
5163 GdkEventMotion * event)
5166 GdkModifierType mods;
5167 GdkCursorType new_cursor;
5168 gint x, y, row, column;
5170 g_return_val_if_fail (widget != NULL, FALSE);
5171 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
5172 g_return_val_if_fail (event != NULL, FALSE);
5175 sheet = GTK_SHEET (widget);
5177 /* selections on the sheet */
5181 if(event->window == sheet->column_title_window && gtk_sheet_columns_resizable(sheet)){
5182 gtk_widget_get_pointer(widget, &x, &y);
5183 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_XDRAG(sheet, x, &column)){
5184 new_cursor=GDK_SB_H_DOUBLE_ARROW;
5185 if(new_cursor != sheet->cursor_drag->type){
5186 gdk_cursor_destroy(sheet->cursor_drag);
5187 sheet->cursor_drag=gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
5188 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5191 new_cursor=GDK_TOP_LEFT_ARROW;
5192 if(!GTK_SHEET_IN_XDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5193 gdk_cursor_destroy(sheet->cursor_drag);
5194 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5195 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5200 if(event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet)){
5201 gtk_widget_get_pointer(widget, &x, &y);
5202 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_YDRAG(sheet,y, &column)){
5203 new_cursor=GDK_SB_V_DOUBLE_ARROW;
5204 if(new_cursor != sheet->cursor_drag->type){
5205 gdk_cursor_destroy(sheet->cursor_drag);
5206 sheet->cursor_drag=gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
5207 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5210 new_cursor=GDK_TOP_LEFT_ARROW;
5211 if(!GTK_SHEET_IN_YDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5212 gdk_cursor_destroy(sheet->cursor_drag);
5213 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5214 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5219 new_cursor=GDK_PLUS;
5220 if(!POSSIBLE_DRAG(sheet,x,y,&row,&column) && !GTK_SHEET_IN_DRAG(sheet) &&
5221 !POSSIBLE_RESIZE(sheet,x,y,&row,&column) && !GTK_SHEET_IN_RESIZE(sheet) &&
5222 event->window == sheet->sheet_window &&
5223 new_cursor != sheet->cursor_drag->type){
5224 gdk_cursor_destroy(sheet->cursor_drag);
5225 sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
5226 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5229 new_cursor=GDK_TOP_LEFT_ARROW;
5230 if(!(POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5231 (POSSIBLE_DRAG(sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG(sheet)) &&
5232 event->window == sheet->sheet_window &&
5233 new_cursor != sheet->cursor_drag->type){
5234 gdk_cursor_destroy(sheet->cursor_drag);
5235 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5236 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5239 new_cursor=GDK_SIZING;
5240 if(!GTK_SHEET_IN_DRAG(sheet) &&
5241 (POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5242 event->window == sheet->sheet_window &&
5243 new_cursor != sheet->cursor_drag->type){
5244 gdk_cursor_destroy(sheet->cursor_drag);
5245 sheet->cursor_drag=gdk_cursor_new(GDK_SIZING);
5246 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5249 gdk_window_get_pointer (widget->window, &x, &y, &mods);
5250 if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
5252 if (GTK_SHEET_IN_XDRAG (sheet)){
5253 if (event->is_hint || event->window != widget->window)
5254 gtk_widget_get_pointer (widget, &x, NULL);
5258 new_column_width (sheet, sheet->drag_cell.col, &x);
5259 if (x != sheet->x_drag)
5261 draw_xor_vline (sheet);
5263 draw_xor_vline (sheet);
5268 if (GTK_SHEET_IN_YDRAG (sheet)){
5269 if (event->is_hint || event->window != widget->window)
5270 gtk_widget_get_pointer (widget, NULL, &y);
5274 new_row_height (sheet, sheet->drag_cell.row, &y);
5275 if (y != sheet->y_drag)
5277 draw_xor_hline (sheet);
5279 draw_xor_hline (sheet);
5284 if (GTK_SHEET_IN_DRAG(sheet)){
5286 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col;
5287 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row;
5288 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5289 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5293 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5294 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5295 aux=sheet->drag_range;
5296 sheet->drag_range.row0=sheet->range.row0+row;
5297 sheet->drag_range.col0=sheet->range.col0+column;
5298 sheet->drag_range.rowi=sheet->range.rowi+row;
5299 sheet->drag_range.coli=sheet->range.coli+column;
5300 if(aux.row0 != sheet->drag_range.row0 ||
5301 aux.col0 != sheet->drag_range.col0){
5302 draw_xor_rectangle (sheet, aux);
5303 draw_xor_rectangle (sheet, sheet->drag_range);
5309 if (GTK_SHEET_IN_RESIZE(sheet)){
5311 gint v_h, current_col, current_row, col_threshold, row_threshold;
5314 if(abs(x-COLUMN_LEFT_XPIXEL(sheet,sheet->drag_cell.col)) >
5315 abs(y-ROW_TOP_YPIXEL(sheet,sheet->drag_cell.row))) v_h=2;
5317 current_col = COLUMN_FROM_XPIXEL(sheet,x);
5318 current_row = ROW_FROM_YPIXEL(sheet,y);
5319 column = current_col-sheet->drag_cell.col;
5320 row = current_row-sheet->drag_cell.row;
5322 /*use half of column width resp. row height as threshold to expand selection*/
5323 col_threshold = COLUMN_LEFT_XPIXEL(sheet,current_col)+xxx_column_width (sheet,current_col)/2;
5325 if (x < col_threshold)
5328 else if (column < 0){
5329 if (x > col_threshold)
5332 row_threshold = ROW_TOP_YPIXEL(sheet,current_row)+yyy_row_height (sheet, current_row)/2;
5334 if(y < row_threshold)
5338 if(y > row_threshold)
5342 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5343 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5353 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5354 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5356 aux=sheet->drag_range;
5357 sheet->drag_range=sheet->range;
5359 if(row<0) sheet->drag_range.row0=sheet->range.row0+row;
5360 if(row>0) sheet->drag_range.rowi=sheet->range.rowi+row;
5361 if(column<0) sheet->drag_range.col0=sheet->range.col0+column;
5362 if(column>0) sheet->drag_range.coli=sheet->range.coli+column;
5364 if(aux.row0 != sheet->drag_range.row0 ||
5365 aux.rowi != sheet->drag_range.rowi ||
5366 aux.col0 != sheet->drag_range.col0 ||
5367 aux.coli != sheet->drag_range.coli){
5368 draw_xor_rectangle (sheet, aux);
5369 draw_xor_rectangle (sheet, sheet->drag_range);
5377 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5379 if(sheet->state==GTK_SHEET_NORMAL && row==sheet->active_cell.row &&
5380 column==sheet->active_cell.col) return TRUE;
5382 if(GTK_SHEET_IN_SELECTION(sheet) && mods&GDK_BUTTON1_MASK)
5383 gtk_sheet_extend_selection(sheet, row, column);
5389 gtk_sheet_move_query(GtkSheet *sheet, gint row, gint column)
5391 gint row_move, column_move;
5392 gfloat row_align, col_align;
5393 guint height, width;
5395 gint new_col = column;
5402 height = sheet->sheet_window_height;
5403 width = sheet->sheet_window_width;
5405 if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5407 new_row = MIN(yyy_row_count(sheet), row + 1);
5409 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet) - 1 &&
5410 ROW_TOP_YPIXEL(sheet, yyy_row_count(sheet)-1) +
5411 yyy_row_height(sheet, yyy_row_count(sheet)-1) < height){
5416 if(row<MIN_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5420 if(column>=MAX_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5422 new_col = MIN(xxx_column_count(sheet) - 1, column + 1);
5424 if(MAX_VISIBLE_COLUMN(sheet) == (xxx_column_count(sheet) - 1) &&
5425 COLUMN_LEFT_XPIXEL(sheet, xxx_column_count(sheet) - 1) +
5426 xxx_column_width(sheet, xxx_column_count(sheet) - 1) < width)
5428 column_move = FALSE;
5432 if(column<MIN_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5437 if(row_move || column_move){
5438 gtk_sheet_moveto(sheet, new_row, new_col, row_align, col_align);
5441 return(row_move || column_move);
5445 gtk_sheet_extend_selection(GtkSheet *sheet, gint row, gint column)
5447 GtkSheetRange range;
5451 if(row == sheet->selection_cell.row && column == sheet->selection_cell.col)
5454 if(sheet->selection_mode == GTK_SELECTION_SINGLE) return;
5456 gtk_sheet_move_query(sheet, row, column);
5457 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5459 if(GTK_SHEET_IN_DRAG(sheet)) return;
5463 switch(sheet->state){
5464 case GTK_SHEET_ROW_SELECTED:
5465 column = xxx_column_count(sheet) - 1;
5467 case GTK_SHEET_COLUMN_SELECTED:
5468 row = yyy_row_count(sheet) - 1;
5470 case GTK_SHEET_NORMAL:
5471 sheet->state=GTK_SHEET_RANGE_SELECTED;
5472 r=sheet->active_cell.row;
5473 c=sheet->active_cell.col;
5474 sheet->range.col0=c;
5475 sheet->range.row0=r;
5476 sheet->range.coli=c;
5477 sheet->range.rowi=r;
5478 gdk_draw_pixmap(sheet->sheet_window,
5479 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
5481 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5482 ROW_TOP_YPIXEL(sheet,r)-1,
5483 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5484 ROW_TOP_YPIXEL(sheet,r)-1,
5485 xxx_column_width(sheet, c)+4,
5486 yyy_row_height(sheet, r)+4);
5487 gtk_sheet_range_draw_selection(sheet, sheet->range);
5488 case GTK_SHEET_RANGE_SELECTED:
5489 sheet->state=GTK_SHEET_RANGE_SELECTED;
5492 sheet->selection_cell.row = row;
5493 sheet->selection_cell.col = column;
5495 range.col0=MIN(column,sheet->active_cell.col);
5496 range.coli=MAX(column,sheet->active_cell.col);
5497 range.row0=MIN(row,sheet->active_cell.row);
5498 range.rowi=MAX(row,sheet->active_cell.row);
5500 if(range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi ||
5501 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli ||
5502 state==GTK_SHEET_NORMAL)
5503 gtk_sheet_real_select_range(sheet, &range);
5508 gtk_sheet_entry_key_press(GtkWidget *widget,
5512 gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", key, &focus);
5517 gtk_sheet_key_press(GtkWidget *widget,
5523 gboolean extend_selection = FALSE;
5524 gboolean force_move = FALSE;
5525 gboolean in_selection = FALSE;
5526 gboolean veto = TRUE;
5529 sheet = GTK_SHEET(widget);
5531 if(key->state & GDK_CONTROL_MASK || key->keyval==GDK_Control_L ||
5532 key->keyval==GDK_Control_R) return FALSE;
5536 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL)
5537 gtk_sheet_clip_range(sheet, sheet->range);
5538 if(key->keyval=='x' || key->keyval == 'X')
5539 gtk_sheet_unclip_range(sheet);
5544 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval==GDK_Shift_L
5545 || key->keyval==GDK_Shift_R;
5548 in_selection = GTK_SHEET_IN_SELECTION(sheet);
5549 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5551 switch(key->keyval){
5552 case GDK_Return: case GDK_KP_Enter:
5553 if(sheet->state == GTK_SHEET_NORMAL &&
5554 !GTK_SHEET_IN_SELECTION(sheet))
5555 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
5557 row = sheet->active_cell.row;
5558 col = sheet->active_cell.col;
5559 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5560 row = MIN_VISIBLE_ROW(sheet)-1;
5561 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5562 col = MIN_VISIBLE_COLUMN(sheet);
5563 if(row < yyy_row_count(sheet) - 1){
5565 while(!yyy_row_is_visible(sheet, row) && row<yyy_row_count(sheet)-1)
5568 gtk_sheet_click_cell(sheet, row, col, &veto);
5569 extend_selection = FALSE;
5571 case GDK_ISO_Left_Tab:
5572 row = sheet->active_cell.row;
5573 col = sheet->active_cell.col;
5574 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5575 col = MIN_VISIBLE_COLUMN(sheet)-1;
5576 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5577 row = MIN_VISIBLE_ROW(sheet);
5580 while(! xxx_column_is_visible(sheet, col) && col>0) col--;
5583 gtk_sheet_click_cell(sheet, row, col, &veto);
5584 extend_selection = FALSE;
5587 row = sheet->active_cell.row;
5588 col = sheet->active_cell.col;
5589 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5590 col = MIN_VISIBLE_COLUMN(sheet)-1;
5591 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5592 row = MIN_VISIBLE_ROW(sheet);
5593 if(col < xxx_column_count(sheet) - 1)
5596 while(! xxx_column_is_visible(sheet, col) &&
5597 col < xxx_column_count(sheet) - 1)
5600 gtk_sheet_click_cell(sheet, row, col, &veto);
5601 extend_selection = FALSE;
5603 /* case GDK_BackSpace:
5604 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){
5605 if(sheet->active_cell.col > 0){
5606 col = sheet->active_cell.col - scroll;
5607 row = sheet->active_cell.row;
5608 while(!sheet->column[col].is_visible && col > 0) col--;
5611 gtk_sheet_click_cell(sheet, row, col, &veto);
5612 extend_selection = FALSE;
5616 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5618 if(extend_selection){
5619 if(state==GTK_STATE_NORMAL){
5620 row=sheet->active_cell.row;
5621 col=sheet->active_cell.col;
5622 gtk_sheet_click_cell(sheet, row, col, &veto);
5625 if(sheet->selection_cell.row > 0){
5626 row = sheet->selection_cell.row - scroll;
5627 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5629 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5633 col = sheet->active_cell.col;
5634 row = sheet->active_cell.row;
5635 if(state==GTK_SHEET_COLUMN_SELECTED)
5636 row = MIN_VISIBLE_ROW(sheet);
5637 if(state==GTK_SHEET_ROW_SELECTED)
5638 col = MIN_VISIBLE_COLUMN(sheet);
5640 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5642 gtk_sheet_click_cell(sheet, row, col, &veto);
5643 extend_selection = FALSE;
5646 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5648 if(extend_selection){
5649 if(state==GTK_STATE_NORMAL){
5650 row=sheet->active_cell.row;
5651 col=sheet->active_cell.col;
5652 gtk_sheet_click_cell(sheet, row, col, &veto);
5655 if(sheet->selection_cell.row < yyy_row_count(sheet)-1){
5656 row = sheet->selection_cell.row + scroll;
5657 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5658 row = MIN(yyy_row_count(sheet)-1, row);
5659 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5663 col = sheet->active_cell.col;
5664 row = sheet->active_cell.row;
5665 if(sheet->active_cell.row < yyy_row_count(sheet)-1){
5666 if(state==GTK_SHEET_COLUMN_SELECTED)
5667 row = MIN_VISIBLE_ROW(sheet)-1;
5668 if(state==GTK_SHEET_ROW_SELECTED)
5669 col = MIN_VISIBLE_COLUMN(sheet);
5671 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5672 row = MIN(yyy_row_count(sheet)-1, row);
5674 gtk_sheet_click_cell(sheet, row, col, &veto);
5675 extend_selection = FALSE;
5678 if(extend_selection){
5679 if(state==GTK_STATE_NORMAL){
5680 row=sheet->active_cell.row;
5681 col=sheet->active_cell.col;
5682 gtk_sheet_click_cell(sheet, row, col, &veto);
5685 if(sheet->selection_cell.col < xxx_column_count(sheet) - 1)
5687 col = sheet->selection_cell.col + 1;
5688 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1)
5690 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5694 col = sheet->active_cell.col;
5695 row = sheet->active_cell.row;
5696 if(sheet->active_cell.col < xxx_column_count(sheet) - 1){
5698 if(state==GTK_SHEET_ROW_SELECTED)
5699 col = MIN_VISIBLE_COLUMN(sheet)-1;
5700 if(state==GTK_SHEET_COLUMN_SELECTED)
5701 row = MIN_VISIBLE_ROW(sheet);
5702 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1) col++;
5703 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5705 gtk_sheet_click_cell(sheet, row, col, &veto);
5710 extend_selection = FALSE;
5713 if(extend_selection){
5714 if(state==GTK_STATE_NORMAL){
5715 row=sheet->active_cell.row;
5716 col=sheet->active_cell.col;
5717 gtk_sheet_click_cell(sheet, row, col, &veto);
5720 if(sheet->selection_cell.col > 0){
5721 col = sheet->selection_cell.col - 1;
5722 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5723 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5727 col = sheet->active_cell.col - 1;
5728 row = sheet->active_cell.row;
5729 if(state==GTK_SHEET_ROW_SELECTED)
5730 col = MIN_VISIBLE_COLUMN(sheet)-1;
5731 if(state==GTK_SHEET_COLUMN_SELECTED)
5732 row = MIN_VISIBLE_ROW(sheet);
5733 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5736 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5738 gtk_sheet_click_cell(sheet, row, col, &veto);
5742 extend_selection = FALSE;
5746 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5747 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5748 extend_selection = FALSE;
5751 row=yyy_row_count(sheet)-1;
5752 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5753 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5754 extend_selection = FALSE;
5758 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5759 if(extend_selection) return TRUE;
5761 if(state == GTK_SHEET_ROW_SELECTED)
5762 sheet->active_cell.col=MIN_VISIBLE_COLUMN(sheet);
5763 if(state == GTK_SHEET_COLUMN_SELECTED)
5764 sheet->active_cell.row=MIN_VISIBLE_ROW(sheet);
5768 if(extend_selection) return TRUE;
5770 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5771 sheet->active_cell.col);
5777 gtk_sheet_size_request (GtkWidget * widget,
5778 GtkRequisition * requisition)
5782 GtkSheetChild *child;
5783 GtkRequisition child_requisition;
5785 g_return_if_fail (widget != NULL);
5786 g_return_if_fail (GTK_IS_SHEET (widget));
5787 g_return_if_fail (requisition != NULL);
5789 sheet = GTK_SHEET (widget);
5791 requisition->width = 3*DEFAULT_COLUMN_WIDTH;
5792 requisition->height = 3*DEFAULT_ROW_HEIGHT(widget);
5794 /* compute the size of the column title area */
5795 if(sheet->column_titles_visible)
5796 requisition->height += sheet->column_title_area.height;
5798 /* compute the size of the row title area */
5799 if(sheet->row_titles_visible)
5800 requisition->width += sheet->row_title_area.width;
5802 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5803 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5804 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5805 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5807 if(!sheet->column_titles_visible)
5808 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5810 if(!sheet->row_titles_visible)
5811 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5813 children = sheet->children;
5816 child = children->data;
5817 children = children->next;
5819 gtk_widget_size_request(child->widget, &child_requisition);
5825 gtk_sheet_size_allocate (GtkWidget * widget,
5826 GtkAllocation * allocation)
5829 GtkAllocation sheet_allocation;
5832 g_return_if_fail (widget != NULL);
5833 g_return_if_fail (GTK_IS_SHEET (widget));
5834 g_return_if_fail (allocation != NULL);
5836 sheet = GTK_SHEET (widget);
5837 widget->allocation = *allocation;
5838 border_width = GTK_CONTAINER(widget)->border_width;
5840 if (GTK_WIDGET_REALIZED (widget))
5841 gdk_window_move_resize (widget->window,
5842 allocation->x + border_width,
5843 allocation->y + border_width,
5844 allocation->width - 2*border_width,
5845 allocation->height - 2*border_width);
5847 /* use internal allocation structure for all the math
5848 * because it's easier than always subtracting the container
5850 sheet->internal_allocation.x = 0;
5851 sheet->internal_allocation.y = 0;
5852 sheet->internal_allocation.width = allocation->width - 2*border_width;
5853 sheet->internal_allocation.height = allocation->height - 2*border_width;
5855 sheet_allocation.x = 0;
5856 sheet_allocation.y = 0;
5857 sheet_allocation.width = allocation->width - 2*border_width;
5858 sheet_allocation.height = allocation->height - 2*border_width;
5860 sheet->sheet_window_width = sheet_allocation.width;
5861 sheet->sheet_window_height = sheet_allocation.height;
5863 if (GTK_WIDGET_REALIZED (widget))
5864 gdk_window_move_resize (sheet->sheet_window,
5867 sheet_allocation.width,
5868 sheet_allocation.height);
5870 /* position the window which holds the column title buttons */
5871 sheet->column_title_area.x = 0;
5872 sheet->column_title_area.y = 0;
5873 if(sheet->row_titles_visible)
5874 sheet->column_title_area.x = sheet->row_title_area.width;
5875 sheet->column_title_area.width = sheet_allocation.width -
5876 sheet->column_title_area.x;
5877 if(GTK_WIDGET_REALIZED(widget) && sheet->column_titles_visible)
5878 gdk_window_move_resize (sheet->column_title_window,
5879 sheet->column_title_area.x,
5880 sheet->column_title_area.y,
5881 sheet->column_title_area.width,
5882 sheet->column_title_area.height);
5884 sheet->sheet_window_width = sheet_allocation.width;
5885 sheet->sheet_window_height = sheet_allocation.height;
5887 /* column button allocation */
5888 size_allocate_column_title_buttons (sheet);
5890 /* position the window which holds the row title buttons */
5891 sheet->row_title_area.x = 0;
5892 sheet->row_title_area.y = 0;
5893 if(sheet->column_titles_visible)
5894 sheet->row_title_area.y = sheet->column_title_area.height;
5895 sheet->row_title_area.height = sheet_allocation.height -
5896 sheet->row_title_area.y;
5898 if(GTK_WIDGET_REALIZED(widget) && sheet->row_titles_visible)
5899 gdk_window_move_resize (sheet->row_title_window,
5900 sheet->row_title_area.x,
5901 sheet->row_title_area.y,
5902 sheet->row_title_area.width,
5903 sheet->row_title_area.height);
5906 /* row button allocation */
5907 size_allocate_row_title_buttons (sheet);
5909 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5910 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5911 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5912 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5914 if(!sheet->column_titles_visible)
5915 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5917 if(!sheet->row_titles_visible)
5918 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5920 size_allocate_column_title_buttons(sheet);
5921 size_allocate_row_title_buttons(sheet);
5923 /* re-scale backing pixmap */
5924 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
5925 gtk_sheet_position_children(sheet);
5927 /* set the scrollbars adjustments */
5928 adjust_scrollbars (sheet);
5932 size_allocate_column_title_buttons (GtkSheet * sheet)
5937 if (!sheet->column_titles_visible) return;
5938 if (!GTK_WIDGET_REALIZED (sheet))
5941 width = sheet->sheet_window_width;
5944 if(sheet->row_titles_visible)
5946 width -= sheet->row_title_area.width;
5947 x = sheet->row_title_area.width;
5950 if(sheet->column_title_area.width != width || sheet->column_title_area.x != x)
5952 sheet->column_title_area.width = width;
5953 sheet->column_title_area.x = x;
5954 gdk_window_move_resize (sheet->column_title_window,
5955 sheet->column_title_area.x,
5956 sheet->column_title_area.y,
5957 sheet->column_title_area.width,
5958 sheet->column_title_area.height);
5962 if(MAX_VISIBLE_COLUMN(sheet) == xxx_column_count(sheet) - 1)
5963 gdk_window_clear_area (sheet->column_title_window,
5965 sheet->column_title_area.width,
5966 sheet->column_title_area.height);
5968 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
5970 for (i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
5971 gtk_sheet_button_draw(sheet,-1,i);
5975 size_allocate_row_title_buttons (GtkSheet * sheet)
5980 if (!sheet->row_titles_visible) return;
5981 if (!GTK_WIDGET_REALIZED (sheet))
5984 height = sheet->sheet_window_height;
5987 if(sheet->column_titles_visible)
5989 height -= sheet->column_title_area.height;
5990 y = sheet->column_title_area.height;
5993 if(sheet->row_title_area.height != height || sheet->row_title_area.y != y)
5995 sheet->row_title_area.y = y;
5996 sheet->row_title_area.height = height;
5997 gdk_window_move_resize (sheet->row_title_window,
5998 sheet->row_title_area.x,
5999 sheet->row_title_area.y,
6000 sheet->row_title_area.width,
6001 sheet->row_title_area.height);
6003 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet)-1)
6004 gdk_window_clear_area (sheet->row_title_window,
6006 sheet->row_title_area.width,
6007 sheet->row_title_area.height);
6009 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6011 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
6012 gtk_sheet_button_draw(sheet,i,-1);
6017 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
6019 GtkAllocation shentry_allocation;
6020 GtkSheetCellAttr attributes;
6021 GtkEntry *sheet_entry;
6022 GtkStyle *style = NULL, *previous_style = NULL;
6024 gint size, max_size, text_size, column_width;
6027 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6028 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
6030 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
6032 gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes);
6034 if(GTK_WIDGET_REALIZED(sheet->sheet_entry)){
6036 if(!GTK_WIDGET(sheet_entry)->style)
6037 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry));
6039 previous_style = GTK_WIDGET(sheet_entry)->style;
6041 style = gtk_style_copy(previous_style);
6042 style->bg[GTK_STATE_NORMAL] = attributes.background;
6043 style->fg[GTK_STATE_NORMAL] = attributes.foreground;
6044 style->text[GTK_STATE_NORMAL] = attributes.foreground;
6045 style->bg[GTK_STATE_ACTIVE] = attributes.background;
6046 style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
6047 style->text[GTK_STATE_ACTIVE] = attributes.foreground;
6049 pango_font_description_free(style->font_desc);
6050 style->font_desc = pango_font_description_copy(attributes.font_desc);
6052 GTK_WIDGET(sheet_entry)->style = style;
6053 gtk_widget_size_request(sheet->sheet_entry, NULL);
6054 GTK_WIDGET(sheet_entry)->style = previous_style;
6056 if(style != previous_style){
6057 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6058 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
6059 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
6060 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
6061 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
6063 gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
6067 if(GTK_IS_ITEM_ENTRY(sheet_entry))
6068 max_size = GTK_ITEM_ENTRY(sheet_entry)->text_max_size;
6073 text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
6074 if(text && strlen(text) > 0){
6075 text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
6078 column_width=xxx_column_width(sheet, sheet->active_cell.col);
6080 size=MIN(text_size, max_size);
6081 size=MAX(size,column_width-2*CELLOFFSET);
6083 row=sheet->active_cell.row;
6084 col=sheet->active_cell.col;
6086 shentry_allocation.x = COLUMN_LEFT_XPIXEL(sheet,sheet->active_cell.col);
6087 shentry_allocation.y = ROW_TOP_YPIXEL(sheet,sheet->active_cell.row);
6088 shentry_allocation.width = column_width;
6089 shentry_allocation.height = yyy_row_height(sheet, sheet->active_cell.row);
6091 if(GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6093 shentry_allocation.height -= 2*CELLOFFSET;
6094 shentry_allocation.y += CELLOFFSET;
6095 if(gtk_sheet_clip_text(sheet))
6096 shentry_allocation.width = column_width - 2*CELLOFFSET;
6098 shentry_allocation.width = size;
6100 switch(GTK_ITEM_ENTRY(sheet_entry)->justification){
6101 case GTK_JUSTIFY_CENTER:
6102 shentry_allocation.x += (column_width)/2 - size/2;
6104 case GTK_JUSTIFY_RIGHT:
6105 shentry_allocation.x += column_width - size - CELLOFFSET;
6107 case GTK_JUSTIFY_LEFT:
6108 case GTK_JUSTIFY_FILL:
6109 shentry_allocation.x += CELLOFFSET;
6115 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6116 shentry_allocation.x += 2;
6117 shentry_allocation.y += 2;
6118 shentry_allocation.width -= MIN(shentry_allocation.width, 3);
6119 shentry_allocation.height -= MIN(shentry_allocation.height, 3);
6122 gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation);
6124 if(previous_style == style) gtk_style_unref(previous_style);
6128 gtk_sheet_entry_set_max_size(GtkSheet *sheet)
6132 gint sizel=0, sizer=0;
6134 GtkJustification justification;
6136 row=sheet->active_cell.row;
6137 col=sheet->active_cell.col;
6139 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry) || gtk_sheet_clip_text(sheet)) return;
6141 justification = GTK_ITEM_ENTRY(sheet->sheet_entry)->justification;
6143 switch(justification){
6144 case GTK_JUSTIFY_FILL:
6145 case GTK_JUSTIFY_LEFT:
6146 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6147 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6148 size+=xxx_column_width(sheet, i);
6150 size = MIN(size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL(sheet, col));
6152 case GTK_JUSTIFY_RIGHT:
6153 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
6154 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6155 size+=xxx_column_width(sheet, i);
6158 case GTK_JUSTIFY_CENTER:
6159 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6160 /* if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6162 sizer+=xxx_column_width(sheet, i);
6164 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
6165 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6166 sizel+=xxx_column_width(sheet, i);
6168 size=2*MIN(sizel, sizer);
6172 if(size!=0) size+=xxx_column_width(sheet, col);
6173 GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size=size;
6178 create_sheet_entry(GtkSheet *sheet)
6183 gint found_entry = FALSE;
6185 widget = GTK_WIDGET(sheet);
6187 if(sheet->sheet_entry){
6188 /* avoids warnings */
6189 gtk_widget_ref(sheet->sheet_entry);
6190 gtk_widget_unparent(sheet->sheet_entry);
6191 gtk_widget_destroy(sheet->sheet_entry);
6194 if(sheet->entry_type){
6196 if(!g_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY)){
6198 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6200 sheet->sheet_entry = parent;
6202 entry = gtk_sheet_get_entry (sheet);
6203 if(GTK_IS_ENTRY(entry)) found_entry = TRUE;
6207 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6215 g_warning ("Entry type must be GtkEntry subclass, using default");
6216 entry = gtk_item_entry_new();
6217 sheet->sheet_entry = entry;
6221 sheet->sheet_entry = parent;
6228 entry = gtk_item_entry_new();
6229 sheet->sheet_entry = entry;
6233 gtk_widget_size_request(sheet->sheet_entry, NULL);
6235 if(GTK_WIDGET_REALIZED(sheet))
6237 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
6238 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
6239 gtk_widget_realize(sheet->sheet_entry);
6242 gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event",
6243 (GtkSignalFunc) gtk_sheet_entry_key_press,
6246 gtk_widget_show (sheet->sheet_entry);
6250 /* Finds the last child widget that happens to be of type GtkEntry */
6252 find_entry(GtkWidget *w, gpointer user_data)
6254 GtkWidget **entry = user_data;
6255 if ( GTK_IS_ENTRY(w))
6262 gtk_sheet_get_entry(GtkSheet *sheet)
6265 GtkWidget *entry = NULL;
6266 GtkTableChild *table_child;
6267 GtkBoxChild *box_child;
6268 GList *children = NULL;
6270 g_return_val_if_fail (sheet != NULL, NULL);
6271 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6272 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6274 if(GTK_IS_ENTRY(sheet->sheet_entry)) return (sheet->sheet_entry);
6276 parent = GTK_WIDGET(sheet->sheet_entry);
6278 if(GTK_IS_TABLE(parent)) children = GTK_TABLE(parent)->children;
6279 if(GTK_IS_BOX(parent)) children = GTK_BOX(parent)->children;
6281 if(GTK_IS_CONTAINER(parent))
6283 gtk_container_forall(GTK_CONTAINER(parent), find_entry, &entry);
6285 if(GTK_IS_ENTRY(entry))
6289 if(!children) return NULL;
6292 if(GTK_IS_TABLE(parent)) {
6293 table_child = children->data;
6294 entry = table_child->widget;
6296 if(GTK_IS_BOX(parent)){
6297 box_child = children->data;
6298 entry = box_child->widget;
6301 if(GTK_IS_ENTRY(entry))
6303 children = children->next;
6307 if(!GTK_IS_ENTRY(entry)) return NULL;
6314 gtk_sheet_get_entry_widget(GtkSheet *sheet)
6316 g_return_val_if_fail (sheet != NULL, NULL);
6317 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6318 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6320 return (sheet->sheet_entry);
6326 row_button_set (GtkSheet *sheet, gint row)
6328 if(sheet->row[row].button.state == GTK_STATE_ACTIVE) return;
6330 sheet->row[row].button.state = GTK_STATE_ACTIVE;
6331 gtk_sheet_button_draw(sheet, row, -1);
6336 row_button_release (GtkSheet *sheet, gint row)
6338 if(sheet->row[row].button.state == GTK_STATE_NORMAL) return;
6340 sheet->row[row].button.state = GTK_STATE_NORMAL;
6341 gtk_sheet_button_draw(sheet, row, -1);
6346 gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
6348 GdkWindow *window = NULL;
6349 GtkShadowType shadow_type;
6350 guint width = 0, height = 0;
6353 gint text_width = 0, text_height = 0;
6354 const GtkSheetButton *button = NULL;
6355 GtkSheetChild *child = NULL;
6356 GdkRectangle allocation;
6357 gboolean is_sensitive = FALSE;
6362 PangoAlignment align = PANGO_ALIGN_LEFT;
6365 rtl = gtk_widget_get_direction(GTK_WIDGET(sheet)) == GTK_TEXT_DIR_RTL;
6367 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6369 if(row >= 0 && !yyy_row_is_visible(sheet, row)) return;
6370 if(column >= 0 && ! xxx_column_is_visible(sheet, column)) return;
6371 if(row >= 0 && !sheet->row_titles_visible) return;
6372 if(column >= 0 && !sheet->column_titles_visible) return;
6373 if(column>=0 && column < MIN_VISIBLE_COLUMN(sheet)) return;
6374 if(column>=0 && column > MAX_VISIBLE_COLUMN(sheet)) return;
6375 if(row>=0 && row < MIN_VISIBLE_ROW(sheet)) return;
6376 if(row>=0 && row > MAX_VISIBLE_ROW(sheet)) return;
6377 if( (row == -1) && (column == -1) ) return;
6380 window=sheet->column_title_window;
6381 button= xxx_column_button(sheet, column);
6383 x = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING;
6384 if(sheet->row_titles_visible) x -= sheet->row_title_area.width;
6386 width = xxx_column_width(sheet, column);
6387 height = sheet->column_title_area.height;
6388 is_sensitive=xxx_column_is_sensitive(sheet, column);
6391 window=sheet->row_title_window;
6392 button = yyy_row_button(sheet, row);
6395 y = ROW_TOP_YPIXEL(sheet, row)+CELL_SPACING;
6396 if(sheet->column_titles_visible) y-=sheet->column_title_area.height;
6397 width = sheet->row_title_area.width;
6398 height = yyy_row_height(sheet, row);
6399 is_sensitive=yyy_row_is_sensitive(sheet, row);
6404 allocation.width = width;
6405 allocation.height = height;
6407 gdk_window_clear_area (window,
6411 gtk_paint_box (sheet->button->style, window,
6412 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
6413 &allocation, GTK_WIDGET(sheet->button),
6414 "buttondefault", x, y, width, height);
6416 state = button->state;
6417 if(!is_sensitive) state=GTK_STATE_INSENSITIVE;
6419 if (state == GTK_STATE_ACTIVE)
6420 shadow_type = GTK_SHADOW_IN;
6422 shadow_type = GTK_SHADOW_OUT;
6424 if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
6425 gtk_paint_box (sheet->button->style, window,
6426 button->state, shadow_type,
6427 &allocation, GTK_WIDGET(sheet->button),
6428 "button", x, y, width, height);
6430 if(button->label_visible){
6432 text_height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))-2*CELLOFFSET;
6434 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6436 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation);
6438 y += 2*sheet->button->style->ythickness;
6441 if(button->label && strlen(button->label)>0){
6443 PangoLayout *layout = NULL;
6444 gint real_x = x, real_y = y;
6446 words=button->label;
6447 line = g_new(gchar, 1);
6450 while(words && *words != '\0'){
6453 line=g_realloc(line, len+2);
6457 if(*words == '\n' || *(words+1) == '\0'){
6458 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, line);
6460 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), line);
6461 switch(button->justification){
6462 case GTK_JUSTIFY_LEFT:
6463 real_x = x + CELLOFFSET;
6464 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6466 case GTK_JUSTIFY_RIGHT:
6467 real_x = x + width - text_width - CELLOFFSET;
6468 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6470 case GTK_JUSTIFY_CENTER:
6472 real_x = x + (width - text_width)/2;
6473 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6474 pango_layout_set_justify (layout, TRUE);
6476 pango_layout_set_alignment (layout, align);
6477 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6486 g_object_unref(G_OBJECT(layout));
6488 real_y += text_height + 2;
6491 line = g_new(gchar, 1);
6498 if(button->label && strlen(button->label) > 0){
6499 PangoLayout *layout = NULL;
6500 gint real_x = x, real_y = y;
6502 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, button->label);
6504 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), button->label);
6505 switch(button->justification){
6506 case GTK_JUSTIFY_LEFT:
6507 real_x = x + CELLOFFSET;
6508 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6510 case GTK_JUSTIFY_RIGHT:
6511 real_x = x + width - text_width - CELLOFFSET;
6512 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6514 case GTK_JUSTIFY_CENTER:
6516 real_x = x + (width - text_width)/2;
6517 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6518 pango_layout_set_justify (layout, TRUE);
6520 pango_layout_set_alignment (layout, align);
6521 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6530 g_object_unref(G_OBJECT(layout));
6533 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6535 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, NULL);
6539 if((child = button->child) && (child->widget)){
6540 child->x = allocation.x;
6541 child->y = allocation.y;
6543 child->x += (width - child->widget->requisition.width) / 2;
6544 child->y += (height - child->widget->requisition.height) / 2;
6545 allocation.x = child->x;
6546 allocation.y = child->y;
6547 allocation.width = child->widget->requisition.width;
6548 allocation.height = child->widget->requisition.height;
6553 gtk_widget_set_state(child->widget, button->state);
6555 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
6556 GTK_WIDGET_MAPPED(child->widget))
6558 gtk_widget_size_allocate(child->widget,
6560 gtk_widget_queue_draw(child->widget);
6571 * vadjustment_changed
6572 * hadjustment_changed
6573 * vadjustment_value_changed
6574 * hadjustment_value_changed */
6577 adjust_scrollbars (GtkSheet * sheet)
6580 if(sheet->vadjustment){
6581 sheet->vadjustment->page_size = sheet->sheet_window_height;
6582 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
6583 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
6584 sheet->vadjustment->lower = 0;
6585 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
6587 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet))
6589 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) -
6590 sheet->sheet_window_height);
6591 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
6595 gtk_signal_emit_by_name (GTK_OBJECT(sheet->vadjustment), "changed");
6599 if(sheet->hadjustment){
6600 sheet->hadjustment->page_size = sheet->sheet_window_width;
6601 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
6602 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
6603 sheet->hadjustment->lower = 0;
6604 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
6606 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet))
6608 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) -
6609 sheet->sheet_window_width);
6610 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment),
6614 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), "changed");
6618 if(GTK_WIDGET_REALIZED(sheet))
6620 if(sheet->row_titles_visible){
6621 size_allocate_row_title_buttons(sheet);
6622 gdk_window_show(sheet->row_title_window);
6625 if(sheet->column_titles_visible){
6626 size_allocate_column_title_buttons(sheet);
6627 gdk_window_show(sheet->column_title_window);
6630 gtk_sheet_range_draw(sheet, NULL);
6637 vadjustment_changed (GtkAdjustment * adjustment,
6642 g_return_if_fail (adjustment != NULL);
6643 g_return_if_fail (data != NULL);
6645 sheet = GTK_SHEET (data);
6650 hadjustment_changed (GtkAdjustment * adjustment,
6655 g_return_if_fail (adjustment != NULL);
6656 g_return_if_fail (data != NULL);
6658 sheet = GTK_SHEET (data);
6663 vadjustment_value_changed (GtkAdjustment * adjustment,
6667 gint diff, value, old_value;
6672 g_return_if_fail (adjustment != NULL);
6673 g_return_if_fail (data != NULL);
6674 g_return_if_fail (GTK_IS_SHEET (data));
6676 sheet = GTK_SHEET (data);
6678 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6680 row=ROW_FROM_YPIXEL(sheet,sheet->column_title_area.height + CELL_SPACING);
6681 if(!sheet->column_titles_visible)
6682 row=ROW_FROM_YPIXEL(sheet,CELL_SPACING);
6684 old_value = -sheet->voffset;
6686 new_row = g_sheet_row_pixel_to_row(sheet->row_geometry,
6687 adjustment->value,sheet);
6689 y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
6691 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
6692 yyy_row_height(sheet, i) > sheet->vadjustment->step_increment){
6693 /* This avoids embarrassing twitching */
6694 if(row == new_row && row != yyy_row_count(sheet) - 1 &&
6695 adjustment->value - sheet->old_vadjustment >=
6696 sheet->vadjustment->step_increment &&
6697 new_row + 1 != MIN_VISIBLE_ROW(sheet)){
6699 y=y+yyy_row_height(sheet, row);
6703 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6704 if(sheet->old_vadjustment >= 0. && row == new_row){
6705 sheet->old_vadjustment = sheet->vadjustment->value;
6709 sheet->old_vadjustment = sheet->vadjustment->value;
6710 adjustment->value=y;
6714 sheet->vadjustment->step_increment= yyy_row_height(sheet, 0);
6716 sheet->vadjustment->step_increment=
6717 MIN(yyy_row_height(sheet, new_row), yyy_row_height(sheet, new_row-1));
6720 sheet->vadjustment->value=adjustment->value;
6722 value = adjustment->value;
6724 if (value >= -sheet->voffset)
6727 diff = value + sheet->voffset;
6732 diff = -sheet->voffset - value;
6735 sheet->voffset = -value;
6737 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6738 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6739 if(!sheet->column_titles_visible)
6740 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6742 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6743 sheet->state == GTK_SHEET_NORMAL &&
6744 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6745 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6746 sheet->active_cell.col))
6750 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6752 if(!text || strlen(text)==0)
6753 gtk_sheet_cell_clear(sheet,
6754 sheet->active_cell.row,
6755 sheet->active_cell.col);
6756 gtk_widget_unmap(sheet->sheet_entry);
6759 gtk_sheet_position_children(sheet);
6761 gtk_sheet_range_draw(sheet, NULL);
6762 size_allocate_row_title_buttons(sheet);
6763 size_allocate_global_button(sheet);
6767 hadjustment_value_changed (GtkAdjustment * adjustment,
6771 gint i, diff, value, old_value;
6772 gint column, new_column;
6775 g_return_if_fail (adjustment != NULL);
6776 g_return_if_fail (data != NULL);
6777 g_return_if_fail (GTK_IS_SHEET (data));
6779 sheet = GTK_SHEET (data);
6781 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6783 column=COLUMN_FROM_XPIXEL(sheet,sheet->row_title_area.width + CELL_SPACING);
6784 if(!sheet->row_titles_visible)
6785 column=COLUMN_FROM_XPIXEL(sheet, CELL_SPACING);
6787 old_value = -sheet->hoffset;
6789 for(i=0; i < xxx_column_count(sheet); i++)
6791 if(xxx_column_is_visible(sheet, i)) x += xxx_column_width(sheet, i);
6792 if(x > adjustment->value) break;
6794 x-=xxx_column_width(sheet, i);
6797 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
6798 xxx_column_width(sheet, i) > sheet->hadjustment->step_increment){
6799 /* This avoids embarrassing twitching */
6800 if(column == new_column && column != xxx_column_count(sheet) - 1 &&
6801 adjustment->value - sheet->old_hadjustment >=
6802 sheet->hadjustment->step_increment &&
6803 new_column + 1 != MIN_VISIBLE_COLUMN(sheet)){
6805 x=x+xxx_column_width(sheet, column);
6809 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6810 if(sheet->old_hadjustment >= 0. && new_column == column){
6811 sheet->old_hadjustment = sheet->hadjustment->value;
6815 sheet->old_hadjustment = sheet->hadjustment->value;
6816 adjustment->value=x;
6818 if(new_column == 0){
6819 sheet->hadjustment->step_increment=
6820 xxx_column_width(sheet, 0);
6822 sheet->hadjustment->step_increment=
6823 MIN(xxx_column_width(sheet, new_column), xxx_column_width(sheet, new_column-1));
6827 sheet->hadjustment->value=adjustment->value;
6829 value = adjustment->value;
6831 if (value >= -sheet->hoffset)
6834 diff = value + sheet->hoffset;
6839 diff = -sheet->hoffset - value;
6842 sheet->hoffset = -value;
6844 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6845 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6846 if(!sheet->row_titles_visible)
6847 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6849 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6850 sheet->state == GTK_SHEET_NORMAL &&
6851 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6852 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6853 sheet->active_cell.col))
6857 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6858 if(!text || strlen(text)==0)
6859 gtk_sheet_cell_clear(sheet,
6860 sheet->active_cell.row,
6861 sheet->active_cell.col);
6863 gtk_widget_unmap(sheet->sheet_entry);
6866 gtk_sheet_position_children(sheet);
6868 gtk_sheet_range_draw(sheet, NULL);
6869 size_allocate_column_title_buttons(sheet);
6873 /* COLUMN RESIZING */
6875 draw_xor_vline (GtkSheet * sheet)
6879 g_return_if_fail (sheet != NULL);
6881 widget = GTK_WIDGET (sheet);
6883 gdk_draw_line (widget->window, sheet->xor_gc,
6885 sheet->column_title_area.height,
6887 sheet->sheet_window_height + 1);
6892 draw_xor_hline (GtkSheet * sheet)
6896 g_return_if_fail (sheet != NULL);
6898 widget = GTK_WIDGET (sheet);
6900 gdk_draw_line (widget->window, sheet->xor_gc,
6901 sheet->row_title_area.width,
6904 sheet->sheet_window_width + 1,
6908 /* SELECTED RANGE */
6910 draw_xor_rectangle(GtkSheet *sheet, GtkSheetRange range)
6913 GdkRectangle clip_area, area;
6916 area.x=COLUMN_LEFT_XPIXEL(sheet, range.col0);
6917 area.y=ROW_TOP_YPIXEL(sheet, range.row0);
6918 area.width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-area.x+
6919 xxx_column_width(sheet, range.coli);
6920 area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+
6921 yyy_row_height(sheet, range.rowi);
6923 clip_area.x=sheet->row_title_area.width;
6924 clip_area.y=sheet->column_title_area.height;
6925 clip_area.width=sheet->sheet_window_width;
6926 clip_area.height=sheet->sheet_window_height;
6928 if(!sheet->row_titles_visible) clip_area.x = 0;
6929 if(!sheet->column_titles_visible) clip_area.y = 0;
6932 area.width=area.width+area.x;
6935 if(area.width>clip_area.width) area.width=clip_area.width+10;
6937 area.height=area.height+area.y;
6940 if(area.height>clip_area.height) area.height=clip_area.height+10;
6945 clip_area.height+=3;
6947 gdk_gc_get_values(sheet->xor_gc, &values);
6949 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
6952 gdk_draw_rectangle(sheet->sheet_window,
6956 area.width-2*i, area.height-2*i);
6959 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
6961 gdk_gc_set_foreground(sheet->xor_gc, &values.foreground);
6966 /* this function returns the new width of the column being resized given
6967 * the column and x position of the cursor; the x cursor position is passed
6968 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
6970 new_column_width (GtkSheet * sheet,
6979 min_width = sheet->column_requisition;
6981 /* you can't shrink a column to less than its minimum width */
6982 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
6984 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
6987 /* don't grow past the end of the window */
6989 if (cx > sheet->sheet_window_width)
6991 *x = cx = sheet->sheet_window_width;
6994 /* calculate new column width making sure it doesn't end up
6995 * less than the minimum width */
6996 width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
6997 if (width < min_width)
7000 xxx_set_column_width(sheet, column, width);
7001 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7002 size_allocate_column_title_buttons (sheet);
7007 /* this function returns the new height of the row being resized given
7008 * the row and y position of the cursor; the y cursor position is passed
7009 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7011 new_row_height (GtkSheet * sheet,
7019 min_height = sheet->row_requisition;
7021 /* you can't shrink a row to less than its minimum height */
7022 if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
7025 *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
7028 /* don't grow past the end of the window */
7030 if (cy > sheet->sheet_window_height)
7032 *y = cy = sheet->sheet_window_height;
7035 /* calculate new row height making sure it doesn't end up
7036 * less than the minimum height */
7037 height = (cy - ROW_TOP_YPIXEL (sheet, row));
7038 if (height < min_height)
7039 height = min_height;
7041 yyy_set_row_height(sheet, row, height);
7042 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
7043 size_allocate_row_title_buttons (sheet);
7049 gtk_sheet_set_column_width (GtkSheet * sheet,
7055 g_return_if_fail (sheet != NULL);
7056 g_return_if_fail (GTK_IS_SHEET (sheet));
7058 if (column < 0 || column >= xxx_column_count(sheet))
7061 gtk_sheet_column_size_request(sheet, column, &min_width);
7062 if(width < min_width) return;
7064 xxx_set_column_width(sheet, column, width);
7066 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7067 size_allocate_column_title_buttons (sheet);
7068 adjust_scrollbars (sheet);
7069 gtk_sheet_size_allocate_entry(sheet);
7070 gtk_sheet_range_draw (sheet, NULL);
7073 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, column);
7074 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_COL_WIDTH], column, width);
7081 gtk_sheet_set_row_height (GtkSheet * sheet,
7087 g_return_if_fail (sheet != NULL);
7088 g_return_if_fail (GTK_IS_SHEET (sheet));
7090 if (row < 0 || row >= yyy_row_count(sheet))
7093 gtk_sheet_row_size_request(sheet, row, &min_height);
7094 if(height < min_height) return;
7096 yyy_set_row_height(sheet, row, height);
7098 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7099 size_allocate_row_title_buttons (sheet);
7100 adjust_scrollbars (sheet);
7101 gtk_sheet_size_allocate_entry(sheet);
7102 gtk_sheet_range_draw (sheet, NULL);
7105 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], row, -1);
7106 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_ROW_HEIGHT], row, height);
7112 gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr *attributes)
7114 g_return_val_if_fail (sheet != NULL, FALSE);
7115 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
7117 if(row < 0 || col < 0) return FALSE;
7119 init_attributes(sheet, col, attributes);
7124 attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
7125 attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
7127 const GdkColor *fg = g_sheet_model_get_foreground(sheet->model, row, col);
7129 attributes->foreground = *fg;
7131 const GdkColor *bg = g_sheet_model_get_background(sheet->model, row, col);
7133 attributes->background = *bg;
7135 const GtkJustification *j = g_sheet_model_get_justification(sheet->model,
7137 if (j) attributes->justification = *j;
7139 const PangoFontDescription *font_desc =
7140 g_sheet_model_get_font_desc(sheet->model, row, col);
7141 if ( font_desc ) attributes->font_desc = font_desc;
7143 const GtkSheetCellBorder *border =
7144 g_sheet_model_get_cell_border(sheet->model, row, col);
7146 if ( border ) attributes->border = *border;
7152 init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
7154 /* DEFAULT VALUES */
7155 attributes->foreground = GTK_WIDGET(sheet)->style->black;
7156 attributes->background = sheet->bg_color;
7157 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
7158 GdkColormap *colormap;
7159 colormap=gdk_colormap_get_system();
7160 gdk_color_black(colormap, &attributes->foreground);
7161 attributes->background = sheet->bg_color;
7163 attributes->justification = xxx_column_justification(sheet, col);
7164 attributes->border.width = 0;
7165 attributes->border.line_style = GDK_LINE_SOLID;
7166 attributes->border.cap_style = GDK_CAP_NOT_LAST;
7167 attributes->border.join_style = GDK_JOIN_MITER;
7168 attributes->border.mask = 0;
7169 attributes->border.color = GTK_WIDGET(sheet)->style->black;
7170 attributes->is_editable = TRUE;
7171 attributes->is_visible = TRUE;
7172 attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
7178 /********************************************************************
7179 * Container Functions:
7184 * gtk_sheet_move_child
7185 * gtk_sheet_position_child
7186 * gtk_sheet_position_children
7187 * gtk_sheet_realize_child
7188 * gtk_sheet_get_child_at
7189 ********************************************************************/
7192 gtk_sheet_put(GtkSheet *sheet, GtkWidget *child, gint x, gint y)
7194 GtkRequisition child_requisition;
7195 GtkSheetChild *child_info;
7197 g_return_val_if_fail(sheet != NULL, NULL);
7198 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7199 g_return_val_if_fail(child != NULL, NULL);
7200 g_return_val_if_fail(child->parent == NULL, NULL);
7202 child_info = g_new (GtkSheetChild, 1);
7203 child_info->widget = child;
7206 child_info->attached_to_cell = FALSE;
7207 child_info->floating = TRUE;
7208 child_info->xpadding = child_info->ypadding = 0;
7209 child_info->xexpand = child_info->yexpand = FALSE;
7210 child_info->xshrink = child_info->yshrink = FALSE;
7211 child_info->xfill = child_info->yfill = FALSE;
7213 sheet->children = g_list_append(sheet->children, child_info);
7215 gtk_widget_set_parent (child, GTK_WIDGET(sheet));
7217 gtk_widget_size_request(child, &child_requisition);
7219 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7221 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7222 (!GTK_WIDGET_REALIZED(child) || GTK_WIDGET_NO_WINDOW(child)))
7223 gtk_sheet_realize_child(sheet, child_info);
7225 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7226 !GTK_WIDGET_MAPPED(child))
7227 gtk_widget_map(child);
7230 gtk_sheet_position_child(sheet, child_info);
7232 /* This will avoid drawing on the titles */
7234 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7236 if(sheet->row_titles_visible)
7237 gdk_window_show(sheet->row_title_window);
7238 if(sheet->column_titles_visible)
7239 gdk_window_show(sheet->column_title_window);
7242 return (child_info);
7246 gtk_sheet_attach_floating (GtkSheet *sheet,
7251 GtkSheetChild *child;
7253 if(row < 0 || col < 0){
7254 gtk_sheet_button_attach(sheet, widget, row, col);
7258 gtk_sheet_get_cell_area(sheet, row, col, &area);
7259 child = gtk_sheet_put(sheet, widget, area.x, area.y);
7260 child->attached_to_cell = TRUE;
7266 gtk_sheet_attach_default (GtkSheet *sheet,
7270 if(row < 0 || col < 0){
7271 gtk_sheet_button_attach(sheet, widget, row, col);
7275 gtk_sheet_attach(sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
7279 gtk_sheet_attach (GtkSheet *sheet,
7288 GtkSheetChild *child = NULL;
7290 if(row < 0 || col < 0){
7291 gtk_sheet_button_attach(sheet, widget, row, col);
7295 child = g_new0(GtkSheetChild, 1);
7296 child->attached_to_cell = TRUE;
7297 child->floating = FALSE;
7298 child->widget = widget;
7301 child->xpadding = xpadding;
7302 child->ypadding = ypadding;
7303 child->xexpand = (xoptions & GTK_EXPAND) != 0;
7304 child->yexpand = (yoptions & GTK_EXPAND) != 0;
7305 child->xshrink = (xoptions & GTK_SHRINK) != 0;
7306 child->yshrink = (yoptions & GTK_SHRINK) != 0;
7307 child->xfill = (xoptions & GTK_FILL) != 0;
7308 child->yfill = (yoptions & GTK_FILL) != 0;
7310 sheet->children = g_list_append(sheet->children, child);
7312 gtk_sheet_get_cell_area(sheet, row, col, &area);
7314 child->x = area.x + child->xpadding;
7315 child->y = area.y + child->ypadding;
7317 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7319 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7320 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7321 gtk_sheet_realize_child(sheet, child);
7323 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7324 !GTK_WIDGET_MAPPED(widget))
7325 gtk_widget_map(widget);
7328 gtk_sheet_position_child(sheet, child);
7330 /* This will avoid drawing on the titles */
7332 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7334 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
7335 gdk_window_show(sheet->row_title_window);
7336 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
7337 gdk_window_show(sheet->column_title_window);
7343 gtk_sheet_button_attach (GtkSheet *sheet,
7347 GtkSheetButton *button;
7348 GtkSheetChild *child;
7349 GtkRequisition button_requisition;
7351 if(row >= 0 && col >= 0) return;
7352 if(row < 0 && col < 0) return;
7354 child = g_new (GtkSheetChild, 1);
7355 child->widget = widget;
7358 child->attached_to_cell = TRUE;
7359 child->floating = FALSE;
7362 child->xpadding = child->ypadding = 0;
7363 child->xshrink = child->yshrink = FALSE;
7364 child->xfill = child->yfill = FALSE;
7367 sheet->children = g_list_append(sheet->children, child);
7369 gtk_sheet_button_size_request(sheet, button, &button_requisition);
7372 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7374 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7375 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7376 gtk_sheet_realize_child(sheet, child);
7378 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7379 !GTK_WIDGET_MAPPED(widget))
7380 gtk_widget_map(widget);
7383 if(row == -1) size_allocate_column_title_buttons(sheet);
7384 if(col == -1) size_allocate_row_title_buttons(sheet);
7389 label_size_request(GtkSheet *sheet, gchar *label, GtkRequisition *req)
7394 gint row_height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)) - 2*CELLOFFSET + 2;
7400 while(words && *words != '\0'){
7401 if(*words == '\n' || *(words+1) == '\0'){
7402 req->height += row_height;
7405 req->width = MAX(req->width, STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, word));
7413 if(n > 0) req->height -= 2;
7417 gtk_sheet_button_size_request (GtkSheet *sheet,
7418 const GtkSheetButton *button,
7419 GtkRequisition *button_requisition)
7421 GtkRequisition requisition;
7422 GtkRequisition label_requisition;
7424 if(gtk_sheet_autoresize(sheet) && button->label && strlen(button->label) > 0){
7425 label_size_request(sheet, button->label, &label_requisition);
7426 label_requisition.width += 2*CELLOFFSET;
7427 label_requisition.height += 2*CELLOFFSET;
7429 label_requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7430 label_requisition.width = COLUMN_MIN_WIDTH;
7435 gtk_widget_size_request(button->child->widget, &requisition);
7436 requisition.width += 2*button->child->xpadding;
7437 requisition.height += 2*button->child->ypadding;
7438 requisition.width += 2*sheet->button->style->xthickness;
7439 requisition.height += 2*sheet->button->style->ythickness;
7443 requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7444 requisition.width = COLUMN_MIN_WIDTH;
7447 *button_requisition = requisition;
7448 button_requisition->width = MAX(requisition.width, label_requisition.width);
7449 button_requisition->height = MAX(requisition.height, label_requisition.height);
7454 gtk_sheet_row_size_request (GtkSheet *sheet,
7458 GtkRequisition button_requisition;
7461 gtk_sheet_button_size_request(sheet,
7462 yyy_row_button(sheet, row),
7463 &button_requisition);
7465 *requisition = button_requisition.height;
7467 children = sheet->children;
7469 GtkSheetChild *child = (GtkSheetChild *)children->data;
7470 GtkRequisition child_requisition;
7472 if(child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink){
7473 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7475 if(child_requisition.height + 2 * child->ypadding > *requisition)
7476 *requisition = child_requisition.height + 2 * child->ypadding;
7478 children = children->next;
7481 sheet->row_requisition = * requisition;
7485 gtk_sheet_column_size_request (GtkSheet *sheet,
7489 GtkRequisition button_requisition;
7492 gtk_sheet_button_size_request(sheet,
7493 xxx_column_button(sheet, col),
7494 &button_requisition);
7496 *requisition = button_requisition.width;
7498 children = sheet->children;
7500 GtkSheetChild *child = (GtkSheetChild *)children->data;
7501 GtkRequisition child_requisition;
7503 if(child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink){
7504 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7506 if(child_requisition.width + 2 * child->xpadding > *requisition)
7507 *requisition = child_requisition.width + 2 * child->xpadding;
7509 children = children->next;
7512 sheet->column_requisition = *requisition;
7516 gtk_sheet_move_child(GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
7518 GtkSheetChild *child;
7521 g_return_if_fail(sheet != NULL);
7522 g_return_if_fail(GTK_IS_SHEET(sheet));
7524 children = sheet->children;
7527 child = children->data;
7529 if(child->widget == widget){
7532 child->row = ROW_FROM_YPIXEL(sheet, y);
7533 child->col = COLUMN_FROM_XPIXEL(sheet, x);
7534 gtk_sheet_position_child(sheet, child);
7538 children = children->next;
7541 g_warning("Widget must be a GtkSheet child");
7546 gtk_sheet_position_child(GtkSheet *sheet, GtkSheetChild *child)
7548 GtkRequisition child_requisition;
7549 GtkAllocation child_allocation;
7555 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7557 if(sheet->column_titles_visible)
7558 yoffset = sheet->column_title_area.height;
7560 if(sheet->row_titles_visible)
7561 xoffset = sheet->row_title_area.width;
7563 if(child->attached_to_cell){
7565 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col);
7566 child->y = ROW_TOP_YPIXEL(sheet, child->row);
7568 if(sheet->row_titles_visible)
7569 child->x-=sheet->row_title_area.width;
7570 if(sheet->column_titles_visible)
7571 child->y-=sheet->column_title_area.height;
7573 width = xxx_column_width(sheet, child->col);
7574 height = yyy_row_height(sheet, child->row);
7577 gtk_sheet_get_cell_area(sheet, child->row, child->col, &area);
7578 child->x = area.x + child->xpadding;
7579 child->y = area.y + child->ypadding;
7581 if(!child->floating){
7582 if(child_requisition.width + 2*child->xpadding <= xxx_column_width(sheet, child->col)){
7584 child_requisition.width = child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7587 child->x = area.x + xxx_column_width(sheet, child->col) / 2 -
7588 child_requisition.width / 2;
7590 child_allocation.width = child_requisition.width;
7593 if(!child->xshrink){
7594 gtk_sheet_set_column_width(sheet, child->col, child_requisition.width + 2 * child->xpadding);
7596 child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7599 if(child_requisition.height + 2*child->ypadding <= yyy_row_height(sheet, child->row)){
7601 child_requisition.height = child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7604 child->y = area.y + yyy_row_height(sheet, child->row) / 2 -
7605 child_requisition.height / 2;
7607 child_allocation.height = child_requisition.height;
7610 if(!child->yshrink){
7611 gtk_sheet_set_row_height(sheet, child->row, child_requisition.height + 2 * child->ypadding);
7613 child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7616 child_allocation.width = child_requisition.width;
7617 child_allocation.height = child_requisition.height;
7620 x = child_allocation.x = child->x + xoffset;
7621 y = child_allocation.y = child->y + yoffset;
7625 x = child_allocation.x = child->x + sheet->hoffset + xoffset;
7626 x = child_allocation.x = child->x + xoffset;
7627 y = child_allocation.y = child->y + sheet->voffset + yoffset;
7628 y = child_allocation.y = child->y + yoffset;
7629 child_allocation.width = child_requisition.width;
7630 child_allocation.height = child_requisition.height;
7633 gtk_widget_size_allocate(child->widget, &child_allocation);
7634 gtk_widget_queue_draw(child->widget);
7638 gtk_sheet_forall (GtkContainer *container,
7639 gboolean include_internals,
7640 GtkCallback callback,
7641 gpointer callback_data)
7644 GtkSheetChild *child;
7647 g_return_if_fail (GTK_IS_SHEET (container));
7648 g_return_if_fail (callback != NULL);
7650 sheet = GTK_SHEET (container);
7651 children = sheet->children;
7654 child = children->data;
7655 children = children->next;
7657 (* callback) (child->widget, callback_data);
7660 (* callback) (sheet->button, callback_data);
7661 if(sheet->sheet_entry)
7662 (* callback) (sheet->sheet_entry, callback_data);
7667 gtk_sheet_position_children(GtkSheet *sheet)
7670 GtkSheetChild *child;
7672 children = sheet->children;
7676 child = (GtkSheetChild *)children->data;
7678 if(child->col !=-1 && child->row != -1)
7679 gtk_sheet_position_child(sheet, child);
7681 if(child->row == -1){
7682 if(child->col < MIN_VISIBLE_COLUMN(sheet) ||
7683 child->col > MAX_VISIBLE_COLUMN(sheet))
7684 gtk_sheet_child_hide(child);
7686 gtk_sheet_child_show(child);
7688 if(child->col == -1){
7689 if(child->row < MIN_VISIBLE_ROW(sheet) ||
7690 child->row > MAX_VISIBLE_ROW(sheet))
7691 gtk_sheet_child_hide(child);
7693 gtk_sheet_child_show(child);
7696 children = children->next;
7702 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
7706 GtkSheetChild *child = 0;
7708 g_return_if_fail(container != NULL);
7709 g_return_if_fail(GTK_IS_SHEET(container));
7711 sheet = GTK_SHEET(container);
7713 children = sheet->children;
7717 child = (GtkSheetChild *)children->data;
7719 if(child->widget == widget) break;
7721 children = children->next;
7726 gtk_widget_unparent (widget);
7727 child->widget = NULL;
7729 sheet->children = g_list_remove_link (sheet->children, children);
7730 g_list_free_1 (children);
7737 gtk_sheet_realize_child(GtkSheet *sheet, GtkSheetChild *child)
7741 widget = GTK_WIDGET(sheet);
7743 if(GTK_WIDGET_REALIZED(widget)){
7744 if(child->row == -1)
7745 gtk_widget_set_parent_window(child->widget, sheet->column_title_window);
7746 else if(child->col == -1)
7747 gtk_widget_set_parent_window(child->widget, sheet->row_title_window);
7749 gtk_widget_set_parent_window(child->widget, sheet->sheet_window);
7752 gtk_widget_set_parent(child->widget, widget);
7758 gtk_sheet_get_child_at(GtkSheet *sheet, gint row, gint col)
7761 GtkSheetChild *child = 0;
7763 g_return_val_if_fail(sheet != NULL, NULL);
7764 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7766 children = sheet->children;
7770 child = (GtkSheetChild *)children->data;
7772 if(child->attached_to_cell)
7773 if(child->row == row && child->col == col) break;
7775 children = children->next;
7778 if(children) return child;
7784 gtk_sheet_child_hide(GtkSheetChild *child)
7786 g_return_if_fail(child != NULL);
7787 gtk_widget_hide(child->widget);
7791 gtk_sheet_child_show(GtkSheetChild *child)
7793 g_return_if_fail(child != NULL);
7795 gtk_widget_show(child->widget);
7799 gtk_sheet_get_model(const GtkSheet *sheet)
7801 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
7803 return sheet->model;