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 GSheetModel *model ;
3503 const gchar *old_text ;
3505 GtkSheetRange range;
3507 GtkSheetCellAttr attributes;
3509 g_return_if_fail (sheet != NULL);
3510 g_return_if_fail (GTK_IS_SHEET (sheet));
3511 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3512 if (col < 0 || row < 0) return;
3514 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3516 attributes.justification = justification;
3518 model = gtk_sheet_get_model(sheet);
3520 old_text = g_sheet_model_get_string(model, row, col);
3524 if (0 != safe_strcmp(old_text, text))
3525 changed = g_sheet_model_set_string(model, text, row, col);
3527 if(changed && attributes.is_visible)
3529 const gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
3531 if(s && strlen(s) > 0) {
3532 text_width = STRING_WIDTH(GTK_WIDGET(sheet),
3533 attributes.font_desc, text);
3538 range.col0 = sheet->view.col0;
3539 range.coli = sheet->view.coli;
3541 if(gtk_sheet_autoresize(sheet) &&
3542 text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
3543 gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width);
3544 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3547 if(!GTK_SHEET_IS_FROZEN(sheet))
3548 gtk_sheet_range_draw(sheet, &range);
3552 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
3558 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
3560 GtkSheetRange range;
3562 g_return_if_fail (sheet != NULL);
3563 g_return_if_fail (GTK_IS_SHEET (sheet));
3564 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3565 if (column < 0 || row < 0) return;
3569 range.col0 = sheet->view.col0;
3570 range.coli = sheet->view.coli;
3572 gtk_sheet_real_cell_clear(sheet, row, column, FALSE);
3574 if(!GTK_SHEET_IS_FROZEN(sheet)){
3575 gtk_sheet_range_draw(sheet, &range);
3580 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
3582 GtkSheetRange range;
3584 g_return_if_fail (sheet != NULL);
3585 g_return_if_fail (GTK_IS_SHEET (sheet));
3586 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3587 if (column < 0 || row < 0) return;
3591 range.col0 = sheet->view.col0;
3592 range.coli = sheet->view.coli;
3594 gtk_sheet_real_cell_clear(sheet, row, column, TRUE);
3596 if(!GTK_SHEET_IS_FROZEN(sheet)){
3597 gtk_sheet_range_draw(sheet, &range);
3602 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
3604 GSheetModel *model = gtk_sheet_get_model(sheet);
3606 const gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column);
3608 if (old_text && strlen(old_text) > 0 )
3610 g_sheet_model_datum_clear(model, row, column);
3612 if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0)
3613 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL],
3620 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
3622 g_return_if_fail (sheet != NULL);
3623 g_return_if_fail (GTK_IS_SHEET (sheet));
3625 gtk_sheet_real_range_clear(sheet, range, FALSE);
3629 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range)
3631 g_return_if_fail (sheet != NULL);
3632 g_return_if_fail (GTK_IS_SHEET (sheet));
3634 gtk_sheet_real_range_clear(sheet, range, TRUE);
3639 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
3643 GtkSheetRange clear;
3647 clear.rowi = yyy_row_count(sheet) - 1;
3649 clear.coli = xxx_column_count(sheet) - 1;
3653 clear.row0=MAX(clear.row0, 0);
3654 clear.col0=MAX(clear.col0, 0);
3655 clear.rowi=MIN(clear.rowi, yyy_row_count(sheet) - 1 );
3656 clear.coli=MIN(clear.coli, xxx_column_count(sheet) - 1 );
3658 for(i=clear.row0; i<=clear.rowi; i++)
3659 for(j=clear.col0; j<=clear.coli; j++){
3660 gtk_sheet_real_cell_clear(sheet, i, j, delete);
3663 gtk_sheet_range_draw(sheet, NULL);
3668 gtk_sheet_cell_get_text (GtkSheet *sheet, gint row, gint col)
3671 g_return_val_if_fail (sheet != NULL, NULL);
3672 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
3674 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet))
3676 if(col < 0 || row < 0) return NULL;
3678 model = gtk_sheet_get_model(sheet);
3683 return g_sheet_model_get_string(model, row, col);
3688 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
3691 GtkSheetRange *range;
3693 g_return_val_if_fail (sheet != NULL, 0);
3694 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3695 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return 0;
3696 if(col < 0 || row < 0) return 0;
3698 state = sheet->state;
3699 range = &sheet->range;
3703 case GTK_SHEET_NORMAL:
3704 return GTK_STATE_NORMAL;
3706 case GTK_SHEET_ROW_SELECTED:
3707 if(row>=range->row0 && row<=range->rowi)
3708 return GTK_STATE_SELECTED;
3710 case GTK_SHEET_COLUMN_SELECTED:
3711 if(col>=range->col0 && col<=range->coli)
3712 return GTK_STATE_SELECTED;
3714 case GTK_SHEET_RANGE_SELECTED:
3715 if(row >= range->row0 && row <= range->rowi && \
3716 col >= range->col0 && col <= range->coli)
3717 return GTK_STATE_SELECTED;
3720 return GTK_STATE_NORMAL;
3724 gtk_sheet_get_pixel_info (GtkSheet * sheet,
3732 g_return_val_if_fail (sheet != NULL, 0);
3733 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3735 /* bounds checking, return false if the user clicked
3736 * on a blank area */
3737 trow = ROW_FROM_YPIXEL (sheet, y);
3738 if (trow >= yyy_row_count(sheet))
3743 tcol = COLUMN_FROM_XPIXEL (sheet, x);
3744 if (tcol >= xxx_column_count(sheet))
3753 gtk_sheet_get_cell_area (GtkSheet * sheet,
3758 g_return_val_if_fail (sheet != NULL, 0);
3759 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3761 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3764 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) -
3765 (sheet->row_titles_visible
3766 ? sheet->row_title_area.width
3768 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL(sheet, row) -
3769 (sheet->column_titles_visible
3770 ? sheet->column_title_area.height
3772 area->width= (column == -1) ? sheet->row_title_area.width
3773 : xxx_column_width(sheet, column);
3775 area->height= (row == -1) ? sheet->column_title_area.height
3776 : yyy_row_height(sheet, row);
3779 if(row < 0 || column < 0) return FALSE;
3781 area->x = COLUMN_LEFT_XPIXEL(sheet, column);
3782 area->y = ROW_TOP_YPIXEL(sheet, row);
3783 if(sheet->row_titles_visible)
3784 area->x -= sheet->row_title_area.width;
3785 if(sheet->column_titles_visible)
3786 area->y -= sheet->column_title_area.height;
3788 area->width=sheet->column[column].width;
3789 area->height=yyy_row_height(sheet, row);
3795 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
3797 g_return_val_if_fail (sheet != NULL, 0);
3798 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3800 if(row < 0 || column < 0) return FALSE;
3801 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3804 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
3806 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
3809 sheet->active_cell.row=row;
3810 sheet->active_cell.col=column;
3812 if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE;
3814 if(gtk_sheet_autoscroll(sheet))
3815 gtk_sheet_move_query(sheet, row, column);
3821 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column)
3823 g_return_if_fail (sheet != NULL);
3824 g_return_if_fail (GTK_IS_SHEET (sheet));
3826 *row = sheet->active_cell.row;
3827 *column = sheet->active_cell.col;
3831 gtk_sheet_entry_changed(GtkWidget *widget, gpointer data)
3836 GtkJustification justification;
3837 GtkSheetCellAttr attributes;
3839 g_return_if_fail (data != NULL);
3840 g_return_if_fail (GTK_IS_SHEET (data));
3842 sheet=GTK_SHEET(data);
3844 if(!GTK_WIDGET_VISIBLE(widget)) return;
3845 if(sheet->state != GTK_STATE_NORMAL) return;
3847 row=sheet->active_cell.row;
3848 col=sheet->active_cell.col;
3850 if(row<0 || col<0) return;
3852 sheet->active_cell.row=-1;
3853 sheet->active_cell.col=-1;
3855 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3857 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3859 if(text && strlen(text) > 0){
3860 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3861 justification=attributes.justification;
3862 gtk_sheet_set_cell(sheet, row, col, justification, text);
3865 if(sheet->freeze_count == 0)
3866 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3868 sheet->active_cell.row=row;;
3869 sheet->active_cell.col=col;
3874 gtk_sheet_deactivate_cell(GtkSheet *sheet)
3876 gboolean veto = TRUE;
3878 g_return_val_if_fail (sheet != NULL, FALSE);
3879 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
3881 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return FALSE;
3882 if(sheet->state != GTK_SHEET_NORMAL) return FALSE;
3884 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[DEACTIVATE],
3885 sheet->active_cell.row,
3886 sheet->active_cell.col, &veto);
3888 if(!veto) return FALSE;
3890 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
3891 (GtkSignalFunc) gtk_sheet_entry_changed,
3892 GTK_OBJECT(GTK_WIDGET(sheet)));
3894 gtk_sheet_hide_active_cell(sheet);
3895 sheet->active_cell.row=-1;
3896 sheet->active_cell.col=-1;
3898 if(GTK_SHEET_REDRAW_PENDING(sheet)){
3899 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3900 gtk_sheet_range_draw(sheet, NULL);
3907 gtk_sheet_hide_active_cell(GtkSheet *sheet)
3911 GtkJustification justification;
3912 GtkSheetCellAttr attributes;
3914 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3916 row=sheet->active_cell.row;
3917 col=sheet->active_cell.col;
3919 if(row < 0 || col < 0) return;
3921 if(sheet->freeze_count == 0)
3922 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3924 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3926 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3927 justification=attributes.justification;
3929 if(text && strlen(text)!=0){
3930 gtk_sheet_set_cell(sheet, row, col, justification, text);
3931 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col);
3935 gtk_sheet_cell_clear(sheet, row, col);
3938 row=sheet->active_cell.row;
3939 col=sheet->active_cell.col;
3942 column_button_release(sheet, col);
3943 row_button_release(sheet, row);
3946 gtk_widget_unmap(sheet->sheet_entry);
3948 if(row != -1 && col != -1)
3949 gdk_draw_pixmap(sheet->sheet_window,
3950 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3952 COLUMN_LEFT_XPIXEL(sheet,col)-1,
3953 ROW_TOP_YPIXEL(sheet,row)-1,
3954 COLUMN_LEFT_XPIXEL(sheet,col)-1,
3955 ROW_TOP_YPIXEL(sheet,row)-1,
3956 xxx_column_width(sheet, col) + 4,
3957 yyy_row_height(sheet, row)+4);
3959 gtk_widget_grab_focus(GTK_WIDGET(sheet));
3961 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
3966 gtk_sheet_activate_cell(GtkSheet *sheet, gint row, gint col)
3968 gboolean veto = TRUE;
3970 g_return_val_if_fail (sheet != NULL, FALSE);
3971 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
3973 if(row < 0 || col < 0) return FALSE;
3974 if(row >= yyy_row_count(sheet) || col >= xxx_column_count(sheet))
3977 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
3978 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
3981 if(!veto) return FALSE;
3982 if(sheet->state != GTK_SHEET_NORMAL){
3983 sheet->state=GTK_SHEET_NORMAL;
3984 gtk_sheet_real_unselect_range(sheet, NULL);
3987 sheet->range.row0=row;
3988 sheet->range.col0=col;
3989 sheet->range.rowi=row;
3990 sheet->range.coli=col;
3991 sheet->active_cell.row=row;
3992 sheet->active_cell.col=col;
3993 sheet->selection_cell.row=row;
3994 sheet->selection_cell.col=col;
3996 row_button_set(sheet, row);
3997 column_button_set(sheet, col);
4000 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4001 gtk_sheet_show_active_cell(sheet);
4003 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
4005 G_CALLBACK(gtk_sheet_entry_changed),
4008 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4014 gtk_sheet_show_active_cell(GtkSheet *sheet)
4016 GtkEntry *sheet_entry;
4017 GtkSheetCellAttr attributes;
4019 const gchar *old_text;
4020 GtkJustification justification;
4023 g_return_if_fail (sheet != NULL);
4024 g_return_if_fail (GTK_IS_SHEET (sheet));
4026 row = sheet->active_cell.row;
4027 col = sheet->active_cell.col;
4029 /* Don't show the active cell, if there is no active cell: */
4030 if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */
4033 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4034 if(sheet->state != GTK_SHEET_NORMAL) return;
4035 if(GTK_SHEET_IN_SELECTION(sheet)) return;
4037 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4039 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
4041 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4043 justification = GTK_JUSTIFY_LEFT;
4045 if(gtk_sheet_justify_entry(sheet))
4046 justification = attributes.justification;
4048 text = g_strdup(gtk_sheet_cell_get_text(sheet, row, col));
4050 if(!text) text = g_strdup("");
4052 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible);
4054 if(gtk_sheet_locked(sheet) || !attributes.is_editable){
4055 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
4057 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
4060 /*** Added by John Gotts. Mar 25, 2005 *********/
4061 old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
4062 if (strcmp(old_text, text) != 0)
4064 if(!GTK_IS_ITEM_ENTRY(sheet_entry))
4065 gtk_entry_set_text(GTK_ENTRY(sheet_entry), text);
4067 gtk_item_entry_set_text(GTK_ITEM_ENTRY(sheet_entry), text, justification);
4070 gtk_sheet_entry_set_max_size(sheet);
4071 gtk_sheet_size_allocate_entry(sheet);
4073 gtk_widget_map(sheet->sheet_entry);
4074 gtk_sheet_draw_active_cell(sheet);
4076 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
4082 gtk_sheet_draw_active_cell(GtkSheet *sheet)
4086 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
4087 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4089 row = sheet->active_cell.row;
4090 col = sheet->active_cell.col;
4092 if(row<0 || col<0) return;
4094 if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
4096 row_button_set(sheet, row);
4097 column_button_set(sheet, col);
4099 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4100 gtk_sheet_draw_border(sheet, sheet->range);
4106 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
4108 gint pixmap_width, pixmap_height;
4110 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4112 if(width == 0 && height == 0){
4113 width=sheet->sheet_window_width+80;
4114 height=sheet->sheet_window_height+80;
4120 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4123 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4127 /* reallocate if sizes don't match */
4128 gdk_window_get_size (sheet->pixmap,
4129 &pixmap_width, &pixmap_height);
4130 if ((pixmap_width != width) || (pixmap_height != height))
4132 g_free(sheet->pixmap);
4133 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4136 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4142 gtk_sheet_new_selection(GtkSheet *sheet, GtkSheetRange *range)
4144 gint i,j, mask1, mask2;
4145 gint state, selected;
4146 gint x,y,width,height;
4147 GtkSheetRange new_range, aux_range;
4149 g_return_if_fail (sheet != NULL);
4151 if(range==NULL) range=&sheet->range;
4155 range->row0=MIN(range->row0, sheet->range.row0);
4156 range->rowi=MAX(range->rowi, sheet->range.rowi);
4157 range->col0=MIN(range->col0, sheet->range.col0);
4158 range->coli=MAX(range->coli, sheet->range.coli);
4160 range->row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
4161 range->rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
4162 range->col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
4163 range->coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
4165 aux_range.row0=MAX(new_range.row0, MIN_VISIBLE_ROW(sheet));
4166 aux_range.rowi=MIN(new_range.rowi, MAX_VISIBLE_ROW(sheet));
4167 aux_range.col0=MAX(new_range.col0, MIN_VISIBLE_COLUMN(sheet));
4168 aux_range.coli=MIN(new_range.coli, MAX_VISIBLE_COLUMN(sheet));
4170 for(i=range->row0; i<=range->rowi; i++){
4171 for(j=range->col0; j<=range->coli; j++){
4173 state=gtk_sheet_cell_get_state(sheet, i, j);
4174 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4175 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4177 if(state==GTK_STATE_SELECTED && selected &&
4178 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4179 (i==sheet->range.row0 || i==sheet->range.rowi ||
4180 j==sheet->range.col0 || j==sheet->range.coli ||
4181 i==new_range.row0 || i==new_range.rowi ||
4182 j==new_range.col0 || j==new_range.coli)){
4184 mask1 = i==sheet->range.row0 ? 1 : 0;
4185 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4186 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4187 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4189 mask2 = i==new_range.row0 ? 1 : 0;
4190 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4191 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4192 mask2 = j==new_range.coli ? mask2+8 : mask2;
4195 x=COLUMN_LEFT_XPIXEL(sheet,j);
4196 y=ROW_TOP_YPIXEL(sheet, i);
4197 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4198 xxx_column_width(sheet, j);
4199 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4201 if(i==sheet->range.row0){
4205 if(i==sheet->range.rowi) height=height+3;
4206 if(j==sheet->range.col0){
4210 if(j==sheet->range.coli) width=width+3;
4212 gdk_draw_pixmap(sheet->sheet_window,
4213 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4222 if(i != sheet->active_cell.row || j != sheet->active_cell.col){
4223 x=COLUMN_LEFT_XPIXEL(sheet,j);
4224 y=ROW_TOP_YPIXEL(sheet, i);
4225 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4226 xxx_column_width(sheet, j);
4228 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4230 if(i==new_range.row0){
4234 if(i==new_range.rowi) height=height-3;
4235 if(j==new_range.col0){
4239 if(j==new_range.coli) width=width-3;
4241 gdk_draw_rectangle (sheet->sheet_window,
4252 for(i=range->row0; i<=range->rowi; i++){
4253 for(j=range->col0; j<=range->coli; j++){
4255 state=gtk_sheet_cell_get_state(sheet, i, j);
4256 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4257 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4259 if(state==GTK_STATE_SELECTED && !selected &&
4260 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4262 x=COLUMN_LEFT_XPIXEL(sheet,j);
4263 y=ROW_TOP_YPIXEL(sheet, i);
4264 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4265 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4267 if(i==sheet->range.row0){
4271 if(i==sheet->range.rowi) height=height+3;
4272 if(j==sheet->range.col0){
4276 if(j==sheet->range.coli) width=width+3;
4278 gdk_draw_pixmap(sheet->sheet_window,
4279 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4291 for(i=range->row0; i<=range->rowi; i++){
4292 for(j=range->col0; j<=range->coli; j++){
4294 state=gtk_sheet_cell_get_state(sheet, i, j);
4295 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4296 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4298 if(state!=GTK_STATE_SELECTED && selected &&
4299 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4300 (i != sheet->active_cell.row || j != sheet->active_cell.col)){
4302 x=COLUMN_LEFT_XPIXEL(sheet,j);
4303 y=ROW_TOP_YPIXEL(sheet, i);
4304 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4305 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4307 if(i==new_range.row0){
4311 if(i==new_range.rowi) height=height-3;
4312 if(j==new_range.col0){
4316 if(j==new_range.coli) width=width-3;
4318 gdk_draw_rectangle (sheet->sheet_window,
4329 for(i=aux_range.row0; i<=aux_range.rowi; i++){
4330 for(j=aux_range.col0; j<=aux_range.coli; j++){
4332 if(xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4334 state=gtk_sheet_cell_get_state(sheet, i, j);
4336 mask1 = i==sheet->range.row0 ? 1 : 0;
4337 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4338 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4339 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4341 mask2 = i==new_range.row0 ? 1 : 0;
4342 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4343 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4344 mask2 = j==new_range.coli ? mask2+8 : mask2;
4345 if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){
4346 x=COLUMN_LEFT_XPIXEL(sheet,j);
4347 y=ROW_TOP_YPIXEL(sheet, i);
4348 width=xxx_column_width(sheet, j);
4349 height=yyy_row_height(sheet, i);
4351 gdk_draw_rectangle (sheet->sheet_window,
4359 gdk_draw_rectangle (sheet->sheet_window,
4366 gdk_draw_rectangle (sheet->sheet_window,
4374 gdk_draw_rectangle (sheet->sheet_window,
4391 gtk_sheet_draw_corners(sheet, new_range);
4396 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
4401 gint x,y,width,height;
4403 widget = GTK_WIDGET(sheet);
4405 x=COLUMN_LEFT_XPIXEL(sheet,new_range.col0);
4406 y=ROW_TOP_YPIXEL(sheet,new_range.row0);
4407 width=COLUMN_LEFT_XPIXEL(sheet,new_range.coli)-x+
4408 xxx_column_width(sheet, new_range.coli);
4410 height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+
4411 yyy_row_height(sheet, new_range.rowi);
4413 area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
4414 area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
4415 area.width=sheet->sheet_window_width;
4416 area.height=sheet->sheet_window_height;
4422 if(width>area.width) width=area.width+10;
4427 if(height>area.height) height=area.height+10;
4429 gdk_gc_set_clip_rectangle(sheet->xor_gc, &area);
4431 for(i=-1; i<=1; ++i)
4432 gdk_draw_rectangle (sheet->sheet_window,
4436 width-2*i,height-2*i);
4438 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
4440 gtk_sheet_draw_corners(sheet, new_range);
4445 gtk_sheet_draw_corners(GtkSheet *sheet, GtkSheetRange range)
4450 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.col0)){
4451 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4452 y=ROW_TOP_YPIXEL(sheet,range.row0);
4453 gdk_draw_pixmap(sheet->sheet_window,
4454 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4462 gdk_draw_rectangle (sheet->sheet_window,
4469 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) ||
4470 sheet->state == GTK_SHEET_COLUMN_SELECTED){
4471 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4472 xxx_column_width(sheet, range.coli);
4473 y=ROW_TOP_YPIXEL(sheet,range.row0);
4475 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
4477 y = ROW_TOP_YPIXEL(sheet, sheet->view.row0)+3;
4480 gdk_draw_pixmap(sheet->sheet_window,
4481 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4489 gdk_draw_rectangle (sheet->sheet_window,
4492 x-width+width/2,y-width+width/2,
4496 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.col0) ||
4497 sheet->state == GTK_SHEET_ROW_SELECTED){
4498 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4499 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4500 yyy_row_height(sheet, range.rowi);
4502 if(sheet->state == GTK_SHEET_ROW_SELECTED)
4504 x = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0)+3;
4507 gdk_draw_pixmap(sheet->sheet_window,
4508 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4516 gdk_draw_rectangle (sheet->sheet_window,
4519 x-width+width/2,y-width+width/2,
4523 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){
4524 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4525 xxx_column_width(sheet, range.coli);
4526 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4527 yyy_row_height(sheet, range.rowi);
4529 if(sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
4530 if(sheet->state == GTK_SHEET_NORMAL) width = 3;
4531 gdk_draw_pixmap(sheet->sheet_window,
4532 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4540 gdk_draw_rectangle (sheet->sheet_window,
4543 x-width+width/2,y-width+width/2,
4552 gtk_sheet_real_select_range (GtkSheet * sheet,
4553 GtkSheetRange * range)
4557 g_return_if_fail (sheet != NULL);
4559 if(range==NULL) range=&sheet->range;
4561 if(range->row0 < 0 || range->rowi < 0) return;
4562 if(range->col0 < 0 || range->coli < 0) return;
4567 if(state==GTK_SHEET_COLUMN_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4568 for(i=sheet->range.col0; i< range->col0; i++)
4569 column_button_release(sheet, i);
4570 for(i=range->coli+1; i<= sheet->range.coli; i++)
4571 column_button_release(sheet, i);
4572 for(i=range->col0; i<=range->coli; i++){
4573 column_button_set(sheet, i);
4577 if(state==GTK_SHEET_ROW_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4578 for(i=sheet->range.row0; i< range->row0; i++)
4579 row_button_release(sheet, i);
4580 for(i=range->rowi+1; i<= sheet->range.rowi; i++)
4581 row_button_release(sheet, i);
4582 for(i=range->row0; i<=range->rowi; i++){
4583 row_button_set(sheet, i);
4588 if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
4589 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
4592 gtk_sheet_new_selection(sheet, range);
4594 sheet->range.col0=range->col0;
4595 sheet->range.coli=range->coli;
4596 sheet->range.row0=range->row0;
4597 sheet->range.rowi=range->rowi;
4602 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4603 gtk_sheet_range_draw_selection(sheet, sheet->range);
4606 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[SELECT_RANGE], range);
4610 gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range)
4612 g_return_if_fail (sheet != NULL);
4614 if(range==NULL) range=&sheet->range;
4616 if(range->row0 < 0 || range->rowi < 0) return;
4617 if(range->col0 < 0 || range->coli < 0) return;
4619 if(sheet->state != GTK_SHEET_NORMAL)
4620 gtk_sheet_real_unselect_range(sheet, NULL);
4623 gboolean veto = TRUE;
4624 veto = gtk_sheet_deactivate_cell(sheet);
4628 sheet->range.row0=range->row0;
4629 sheet->range.rowi=range->rowi;
4630 sheet->range.col0=range->col0;
4631 sheet->range.coli=range->coli;
4632 sheet->active_cell.row=range->row0;
4633 sheet->active_cell.col=range->col0;
4634 sheet->selection_cell.row=range->rowi;
4635 sheet->selection_cell.col=range->coli;
4637 sheet->state = GTK_SHEET_RANGE_SELECTED;
4638 gtk_sheet_real_select_range(sheet, NULL);
4643 gtk_sheet_unselect_range (GtkSheet * sheet)
4645 gtk_sheet_real_unselect_range(sheet, NULL);
4646 sheet->state = GTK_STATE_NORMAL;
4647 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
4652 gtk_sheet_real_unselect_range (GtkSheet * sheet,
4653 const GtkSheetRange *range)
4655 g_return_if_fail (sheet != NULL);
4656 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)));
4659 range=&sheet->range;
4662 if(range->row0 < 0 || range->rowi < 0) return;
4663 if(range->col0 < 0 || range->coli < 0) return;
4665 if (gtk_sheet_range_isvisible (sheet, *range)){
4666 gtk_sheet_draw_backing_pixmap(sheet, *range);
4670 for(i=range->col0; i<=range->coli; i++){
4671 column_button_release(sheet, i);
4674 for(i=range->row0; i<=range->rowi; i++){
4675 row_button_release(sheet, i);
4679 gtk_sheet_position_children(sheet);
4684 gtk_sheet_expose (GtkWidget * widget,
4685 GdkEventExpose * event)
4688 GtkSheetRange range;
4690 g_return_val_if_fail (widget != NULL, FALSE);
4691 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4692 g_return_val_if_fail (event != NULL, FALSE);
4694 sheet = GTK_SHEET (widget);
4696 if (GTK_WIDGET_DRAWABLE (widget))
4698 range.row0=ROW_FROM_YPIXEL(sheet,event->area.y);
4699 range.col0=COLUMN_FROM_XPIXEL(sheet,event->area.x);
4700 range.rowi=ROW_FROM_YPIXEL(sheet,event->area.y+event->area.height);
4701 range.coli=COLUMN_FROM_XPIXEL(sheet,event->area.x+event->area.width);
4703 /* exposure events on the sheet */
4705 if(event->window == sheet->row_title_window && sheet->row_titles_visible){
4707 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
4708 gtk_sheet_button_draw(sheet,i,-1);
4711 if(event->window == sheet->column_title_window && sheet->column_titles_visible){
4713 for(i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
4714 gtk_sheet_button_draw(sheet,-1,i);
4717 if (event->window == sheet->sheet_window){
4718 gtk_sheet_draw_backing_pixmap(sheet, range);
4720 if(sheet->state != GTK_SHEET_NORMAL){
4721 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4722 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4723 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4724 gtk_sheet_draw_backing_pixmap(sheet, sheet->drag_range);
4726 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4727 gtk_sheet_range_draw_selection(sheet, sheet->range);
4728 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4729 draw_xor_rectangle(sheet, sheet->drag_range);
4732 if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet))){
4733 if(sheet->state == GTK_SHEET_NORMAL){
4734 gtk_sheet_draw_active_cell(sheet);
4735 if(!GTK_SHEET_IN_SELECTION(sheet))
4736 gtk_widget_queue_draw(sheet->sheet_entry);
4745 if(sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet))
4746 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4748 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
4755 gtk_sheet_button_press (GtkWidget * widget,
4756 GdkEventButton * event)
4759 GdkModifierType mods;
4760 gint x, y, row, column;
4763 g_return_val_if_fail (widget != NULL, FALSE);
4764 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4765 g_return_val_if_fail (event != NULL, FALSE);
4767 sheet = GTK_SHEET (widget);
4769 if ( event->type == GDK_2BUTTON_PRESS)
4771 gtk_widget_get_pointer (widget, &x, &y);
4772 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4774 if (event->window == sheet->column_title_window )
4776 gtk_signal_emit (GTK_OBJECT (sheet),
4777 sheet_signals[DOUBLE_CLICK_COLUMN], column);
4779 else if (event->window == sheet->row_title_window )
4781 gtk_signal_emit (GTK_OBJECT (sheet),
4782 sheet_signals[DOUBLE_CLICK_ROW], row);
4788 if(event->type != GDK_BUTTON_PRESS) return TRUE;
4790 gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
4792 if(!(mods & GDK_BUTTON1_MASK)) return TRUE;
4795 /* press on resize windows */
4796 if (event->window == sheet->column_title_window &&
4797 gtk_sheet_columns_resizable(sheet))
4799 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
4800 if(POSSIBLE_XDRAG(sheet, sheet->x_drag, &sheet->drag_cell.col)){
4802 if (event->type == GDK_2BUTTON_PRESS){
4803 gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
4804 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_XDRAG);
4807 gtk_sheet_column_size_request(sheet, sheet->drag_cell.col, &req);
4808 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4809 gdk_pointer_grab (sheet->column_title_window, FALSE,
4810 GDK_POINTER_MOTION_HINT_MASK |
4811 GDK_BUTTON1_MOTION_MASK |
4812 GDK_BUTTON_RELEASE_MASK,
4813 NULL, NULL, event->time);
4815 draw_xor_vline (sheet);
4820 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet))
4822 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
4824 if(POSSIBLE_YDRAG(sheet, sheet->y_drag, &sheet->drag_cell.row)){
4826 gtk_sheet_row_size_request(sheet, sheet->drag_cell.row, &req);
4827 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
4828 gdk_pointer_grab (sheet->row_title_window, FALSE,
4829 GDK_POINTER_MOTION_HINT_MASK |
4830 GDK_BUTTON1_MOTION_MASK |
4831 GDK_BUTTON_RELEASE_MASK,
4832 NULL, NULL, event->time);
4834 draw_xor_hline (sheet);
4839 /* the sheet itself does not handle other than single click events */
4840 if(event->type != GDK_BUTTON_PRESS) return FALSE;
4842 /* selections on the sheet */
4843 if(event->window == sheet->sheet_window){
4844 gtk_widget_get_pointer (widget, &x, &y);
4845 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4846 gdk_pointer_grab (sheet->sheet_window, FALSE,
4847 GDK_POINTER_MOTION_HINT_MASK |
4848 GDK_BUTTON1_MOTION_MASK |
4849 GDK_BUTTON_RELEASE_MASK,
4850 NULL, NULL, event->time);
4851 gtk_grab_add(GTK_WIDGET(sheet));
4852 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4853 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4855 if(sheet->selection_mode != GTK_SELECTION_SINGLE &&
4856 sheet->cursor_drag->type==GDK_SIZING &&
4857 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_RESIZE(sheet)){
4858 if(sheet->state==GTK_STATE_NORMAL) {
4859 row=sheet->active_cell.row;
4860 column=sheet->active_cell.col;
4861 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4862 sheet->active_cell.row=row;
4863 sheet->active_cell.col=column;
4864 sheet->drag_range=sheet->range;
4865 sheet->state=GTK_SHEET_RANGE_SELECTED;
4866 gtk_sheet_select_range(sheet, &sheet->drag_range);
4870 if(row > sheet->range.rowi) row--;
4871 if(column > sheet->range.coli) column--;
4872 sheet->drag_cell.row = row;
4873 sheet->drag_cell.col = column;
4874 sheet->drag_range=sheet->range;
4875 draw_xor_rectangle(sheet, sheet->drag_range);
4876 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
4878 else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW &&
4879 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_DRAG(sheet)) {
4880 if(sheet->state==GTK_STATE_NORMAL) {
4881 row=sheet->active_cell.row;
4882 column=sheet->active_cell.col;
4883 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4884 sheet->active_cell.row=row;
4885 sheet->active_cell.col=column;
4886 sheet->drag_range=sheet->range;
4887 sheet->state=GTK_SHEET_RANGE_SELECTED;
4888 gtk_sheet_select_range(sheet, &sheet->drag_range);
4892 if(row < sheet->range.row0) row++;
4893 if(row > sheet->range.rowi) row--;
4894 if(column < sheet->range.col0) column++;
4895 if(column > sheet->range.coli) column--;
4896 sheet->drag_cell.row=row;
4897 sheet->drag_cell.col=column;
4898 sheet->drag_range=sheet->range;
4899 draw_xor_rectangle(sheet, sheet->drag_range);
4900 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
4904 gtk_sheet_click_cell(sheet, row, column, &veto);
4905 if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4910 if(event->window == sheet->column_title_window){
4911 gtk_widget_get_pointer (widget, &x, &y);
4912 column = COLUMN_FROM_XPIXEL(sheet, x);
4913 if(xxx_column_is_sensitive(sheet, column)){
4914 gtk_sheet_click_cell(sheet, -1, column, &veto);
4915 gtk_grab_add(GTK_WIDGET(sheet));
4916 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4917 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4918 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4922 if(event->window == sheet->row_title_window){
4923 gtk_widget_get_pointer (widget, &x, &y);
4924 row = ROW_FROM_YPIXEL(sheet, y);
4925 if(yyy_row_is_sensitive(sheet, row)){
4926 gtk_sheet_click_cell(sheet, row, -1, &veto);
4927 gtk_grab_add(GTK_WIDGET(sheet));
4928 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4929 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4930 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4938 gtk_sheet_scroll(gpointer data)
4941 gint x,y,row,column;
4944 sheet=GTK_SHEET(data);
4946 GDK_THREADS_ENTER();
4948 gtk_widget_get_pointer (GTK_WIDGET(sheet), &x, &y);
4949 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4953 if(GTK_SHEET_IN_SELECTION(sheet))
4954 gtk_sheet_extend_selection(sheet, row, column);
4956 if(GTK_SHEET_IN_DRAG(sheet) || GTK_SHEET_IN_RESIZE(sheet)){
4957 move=gtk_sheet_move_query(sheet, row, column);
4958 if(move) draw_xor_rectangle(sheet, sheet->drag_range);
4961 GDK_THREADS_LEAVE();
4968 gtk_sheet_click_cell(GtkSheet *sheet, gint row, gint column, gboolean *veto)
4972 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)){
4977 if(column >= 0 && row >= 0)
4978 if(! xxx_column_is_visible(sheet, column) || !yyy_row_is_visible(sheet, row))
4984 _gtkextra_signal_emit(GTK_OBJECT(sheet), sheet_signals[TRAVERSE],
4985 sheet->active_cell.row, sheet->active_cell.col,
4986 &row, &column, veto);
4989 if(sheet->state == GTK_STATE_NORMAL) return;
4991 row = sheet->active_cell.row;
4992 column = sheet->active_cell.col;
4994 gtk_sheet_activate_cell(sheet, row, column);
4998 if(row == -1 && column >= 0){
4999 if(gtk_sheet_autoscroll(sheet))
5000 gtk_sheet_move_query(sheet, row, column);
5001 gtk_sheet_select_column(sheet, column);
5004 if(column == -1 && row >= 0){
5005 if(gtk_sheet_autoscroll(sheet))
5006 gtk_sheet_move_query(sheet, row, column);
5007 gtk_sheet_select_row(sheet, row);
5011 if(row==-1 && column ==-1){
5012 sheet->range.row0=0;
5013 sheet->range.col0=0;
5014 sheet->range.rowi = yyy_row_count(sheet) - 1;
5015 sheet->range.coli = xxx_column_count(sheet) - 1;
5016 sheet->active_cell.row=0;
5017 sheet->active_cell.col=0;
5018 gtk_sheet_select_range(sheet, NULL);
5022 if(row!=-1 && column !=-1){
5023 if(sheet->state != GTK_SHEET_NORMAL){
5024 sheet->state = GTK_SHEET_NORMAL;
5025 gtk_sheet_real_unselect_range(sheet, NULL);
5029 if(!gtk_sheet_deactivate_cell(sheet)){
5035 if(gtk_sheet_autoscroll(sheet))
5036 gtk_sheet_move_query(sheet, row, column);
5037 sheet->active_cell.row=row;
5038 sheet->active_cell.col=column;
5039 sheet->selection_cell.row=row;
5040 sheet->selection_cell.col=column;
5041 sheet->range.row0=row;
5042 sheet->range.col0=column;
5043 sheet->range.rowi=row;
5044 sheet->range.coli=column;
5045 sheet->state=GTK_SHEET_NORMAL;
5046 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5047 gtk_sheet_draw_active_cell(sheet);
5051 g_assert_not_reached();
5052 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5053 sheet->active_cell.col);
5057 gtk_sheet_button_release (GtkWidget * widget,
5058 GdkEventButton * event)
5063 sheet=GTK_SHEET(widget);
5065 /* release on resize windows */
5066 if (GTK_SHEET_IN_XDRAG (sheet)){
5067 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
5068 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5069 gtk_widget_get_pointer (widget, &x, NULL);
5070 gdk_pointer_ungrab (event->time);
5071 draw_xor_vline (sheet);
5073 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col, new_column_width (sheet, sheet->drag_cell.col, &x));
5074 sheet->old_hadjustment = -1.;
5075 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed");
5079 if (GTK_SHEET_IN_YDRAG (sheet)){
5080 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5081 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5082 gtk_widget_get_pointer (widget, NULL, &y);
5083 gdk_pointer_ungrab (event->time);
5084 draw_xor_hline (sheet);
5086 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
5087 sheet->old_vadjustment = -1.;
5088 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed");
5093 if (GTK_SHEET_IN_DRAG(sheet)){
5094 GtkSheetRange old_range;
5095 draw_xor_rectangle(sheet, sheet->drag_range);
5096 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5097 gdk_pointer_ungrab (event->time);
5099 gtk_sheet_real_unselect_range(sheet, NULL);
5101 sheet->active_cell.row = sheet->active_cell.row +
5102 (sheet->drag_range.row0 - sheet->range.row0);
5103 sheet->active_cell.col = sheet->active_cell.col +
5104 (sheet->drag_range.col0 - sheet->range.col0);
5105 sheet->selection_cell.row = sheet->selection_cell.row +
5106 (sheet->drag_range.row0 - sheet->range.row0);
5107 sheet->selection_cell.col = sheet->selection_cell.col +
5108 (sheet->drag_range.col0 - sheet->range.col0);
5109 old_range=sheet->range;
5110 sheet->range=sheet->drag_range;
5111 sheet->drag_range=old_range;
5112 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[MOVE_RANGE],
5113 &sheet->drag_range, &sheet->range);
5114 gtk_sheet_select_range(sheet, &sheet->range);
5117 if (GTK_SHEET_IN_RESIZE(sheet)){
5118 GtkSheetRange old_range;
5119 draw_xor_rectangle(sheet, sheet->drag_range);
5120 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5121 gdk_pointer_ungrab (event->time);
5123 gtk_sheet_real_unselect_range(sheet, NULL);
5125 sheet->active_cell.row = sheet->active_cell.row +
5126 (sheet->drag_range.row0 - sheet->range.row0);
5127 sheet->active_cell.col = sheet->active_cell.col +
5128 (sheet->drag_range.col0 - sheet->range.col0);
5129 if(sheet->drag_range.row0 < sheet->range.row0)
5130 sheet->selection_cell.row = sheet->drag_range.row0;
5131 if(sheet->drag_range.rowi >= sheet->range.rowi)
5132 sheet->selection_cell.row = sheet->drag_range.rowi;
5133 if(sheet->drag_range.col0 < sheet->range.col0)
5134 sheet->selection_cell.col = sheet->drag_range.col0;
5135 if(sheet->drag_range.coli >= sheet->range.coli)
5136 sheet->selection_cell.col = sheet->drag_range.coli;
5137 old_range = sheet->range;
5138 sheet->range = sheet->drag_range;
5139 sheet->drag_range = old_range;
5141 if(sheet->state==GTK_STATE_NORMAL) sheet->state=GTK_SHEET_RANGE_SELECTED;
5142 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[RESIZE_RANGE],
5143 &sheet->drag_range, &sheet->range);
5144 gtk_sheet_select_range(sheet, &sheet->range);
5147 if(sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)){
5148 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5149 gdk_pointer_ungrab (event->time);
5150 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5151 sheet->active_cell.col);
5154 if(GTK_SHEET_IN_SELECTION)
5155 gdk_pointer_ungrab (event->time);
5157 gtk_timeout_remove(sheet->timer);
5158 gtk_grab_remove(GTK_WIDGET(sheet));
5160 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5166 gtk_sheet_motion (GtkWidget * widget,
5167 GdkEventMotion * event)
5170 GdkModifierType mods;
5171 GdkCursorType new_cursor;
5172 gint x, y, row, column;
5174 g_return_val_if_fail (widget != NULL, FALSE);
5175 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
5176 g_return_val_if_fail (event != NULL, FALSE);
5179 sheet = GTK_SHEET (widget);
5181 /* selections on the sheet */
5185 if(event->window == sheet->column_title_window && gtk_sheet_columns_resizable(sheet)){
5186 gtk_widget_get_pointer(widget, &x, &y);
5187 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_XDRAG(sheet, x, &column)){
5188 new_cursor=GDK_SB_H_DOUBLE_ARROW;
5189 if(new_cursor != sheet->cursor_drag->type){
5190 gdk_cursor_destroy(sheet->cursor_drag);
5191 sheet->cursor_drag=gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
5192 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5195 new_cursor=GDK_TOP_LEFT_ARROW;
5196 if(!GTK_SHEET_IN_XDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5197 gdk_cursor_destroy(sheet->cursor_drag);
5198 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5199 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5204 if(event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet)){
5205 gtk_widget_get_pointer(widget, &x, &y);
5206 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_YDRAG(sheet,y, &column)){
5207 new_cursor=GDK_SB_V_DOUBLE_ARROW;
5208 if(new_cursor != sheet->cursor_drag->type){
5209 gdk_cursor_destroy(sheet->cursor_drag);
5210 sheet->cursor_drag=gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
5211 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5214 new_cursor=GDK_TOP_LEFT_ARROW;
5215 if(!GTK_SHEET_IN_YDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5216 gdk_cursor_destroy(sheet->cursor_drag);
5217 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5218 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5223 new_cursor=GDK_PLUS;
5224 if(!POSSIBLE_DRAG(sheet,x,y,&row,&column) && !GTK_SHEET_IN_DRAG(sheet) &&
5225 !POSSIBLE_RESIZE(sheet,x,y,&row,&column) && !GTK_SHEET_IN_RESIZE(sheet) &&
5226 event->window == sheet->sheet_window &&
5227 new_cursor != sheet->cursor_drag->type){
5228 gdk_cursor_destroy(sheet->cursor_drag);
5229 sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
5230 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5233 new_cursor=GDK_TOP_LEFT_ARROW;
5234 if(!(POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5235 (POSSIBLE_DRAG(sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG(sheet)) &&
5236 event->window == sheet->sheet_window &&
5237 new_cursor != sheet->cursor_drag->type){
5238 gdk_cursor_destroy(sheet->cursor_drag);
5239 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5240 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5243 new_cursor=GDK_SIZING;
5244 if(!GTK_SHEET_IN_DRAG(sheet) &&
5245 (POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5246 event->window == sheet->sheet_window &&
5247 new_cursor != sheet->cursor_drag->type){
5248 gdk_cursor_destroy(sheet->cursor_drag);
5249 sheet->cursor_drag=gdk_cursor_new(GDK_SIZING);
5250 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5253 gdk_window_get_pointer (widget->window, &x, &y, &mods);
5254 if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
5256 if (GTK_SHEET_IN_XDRAG (sheet)){
5257 if (event->is_hint || event->window != widget->window)
5258 gtk_widget_get_pointer (widget, &x, NULL);
5262 new_column_width (sheet, sheet->drag_cell.col, &x);
5263 if (x != sheet->x_drag)
5265 draw_xor_vline (sheet);
5267 draw_xor_vline (sheet);
5272 if (GTK_SHEET_IN_YDRAG (sheet)){
5273 if (event->is_hint || event->window != widget->window)
5274 gtk_widget_get_pointer (widget, NULL, &y);
5278 new_row_height (sheet, sheet->drag_cell.row, &y);
5279 if (y != sheet->y_drag)
5281 draw_xor_hline (sheet);
5283 draw_xor_hline (sheet);
5288 if (GTK_SHEET_IN_DRAG(sheet)){
5290 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col;
5291 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row;
5292 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5293 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5297 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5298 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5299 aux=sheet->drag_range;
5300 sheet->drag_range.row0=sheet->range.row0+row;
5301 sheet->drag_range.col0=sheet->range.col0+column;
5302 sheet->drag_range.rowi=sheet->range.rowi+row;
5303 sheet->drag_range.coli=sheet->range.coli+column;
5304 if(aux.row0 != sheet->drag_range.row0 ||
5305 aux.col0 != sheet->drag_range.col0){
5306 draw_xor_rectangle (sheet, aux);
5307 draw_xor_rectangle (sheet, sheet->drag_range);
5313 if (GTK_SHEET_IN_RESIZE(sheet)){
5315 gint v_h, current_col, current_row, col_threshold, row_threshold;
5318 if(abs(x-COLUMN_LEFT_XPIXEL(sheet,sheet->drag_cell.col)) >
5319 abs(y-ROW_TOP_YPIXEL(sheet,sheet->drag_cell.row))) v_h=2;
5321 current_col = COLUMN_FROM_XPIXEL(sheet,x);
5322 current_row = ROW_FROM_YPIXEL(sheet,y);
5323 column = current_col-sheet->drag_cell.col;
5324 row = current_row-sheet->drag_cell.row;
5326 /*use half of column width resp. row height as threshold to expand selection*/
5327 col_threshold = COLUMN_LEFT_XPIXEL(sheet,current_col)+xxx_column_width (sheet,current_col)/2;
5329 if (x < col_threshold)
5332 else if (column < 0){
5333 if (x > col_threshold)
5336 row_threshold = ROW_TOP_YPIXEL(sheet,current_row)+yyy_row_height (sheet, current_row)/2;
5338 if(y < row_threshold)
5342 if(y > row_threshold)
5346 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5347 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5357 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5358 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5360 aux=sheet->drag_range;
5361 sheet->drag_range=sheet->range;
5363 if(row<0) sheet->drag_range.row0=sheet->range.row0+row;
5364 if(row>0) sheet->drag_range.rowi=sheet->range.rowi+row;
5365 if(column<0) sheet->drag_range.col0=sheet->range.col0+column;
5366 if(column>0) sheet->drag_range.coli=sheet->range.coli+column;
5368 if(aux.row0 != sheet->drag_range.row0 ||
5369 aux.rowi != sheet->drag_range.rowi ||
5370 aux.col0 != sheet->drag_range.col0 ||
5371 aux.coli != sheet->drag_range.coli){
5372 draw_xor_rectangle (sheet, aux);
5373 draw_xor_rectangle (sheet, sheet->drag_range);
5381 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5383 if(sheet->state==GTK_SHEET_NORMAL && row==sheet->active_cell.row &&
5384 column==sheet->active_cell.col) return TRUE;
5386 if(GTK_SHEET_IN_SELECTION(sheet) && mods&GDK_BUTTON1_MASK)
5387 gtk_sheet_extend_selection(sheet, row, column);
5393 gtk_sheet_move_query(GtkSheet *sheet, gint row, gint column)
5395 gint row_move, column_move;
5396 gfloat row_align, col_align;
5397 guint height, width;
5399 gint new_col = column;
5406 height = sheet->sheet_window_height;
5407 width = sheet->sheet_window_width;
5409 if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5411 new_row = MIN(yyy_row_count(sheet), row + 1);
5413 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet) - 1 &&
5414 ROW_TOP_YPIXEL(sheet, yyy_row_count(sheet)-1) +
5415 yyy_row_height(sheet, yyy_row_count(sheet)-1) < height){
5420 if(row<MIN_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5424 if(column>=MAX_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5426 new_col = MIN(xxx_column_count(sheet) - 1, column + 1);
5428 if(MAX_VISIBLE_COLUMN(sheet) == (xxx_column_count(sheet) - 1) &&
5429 COLUMN_LEFT_XPIXEL(sheet, xxx_column_count(sheet) - 1) +
5430 xxx_column_width(sheet, xxx_column_count(sheet) - 1) < width)
5432 column_move = FALSE;
5436 if(column<MIN_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5441 if(row_move || column_move){
5442 gtk_sheet_moveto(sheet, new_row, new_col, row_align, col_align);
5445 return(row_move || column_move);
5449 gtk_sheet_extend_selection(GtkSheet *sheet, gint row, gint column)
5451 GtkSheetRange range;
5455 if(row == sheet->selection_cell.row && column == sheet->selection_cell.col)
5458 if(sheet->selection_mode == GTK_SELECTION_SINGLE) return;
5460 gtk_sheet_move_query(sheet, row, column);
5461 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5463 if(GTK_SHEET_IN_DRAG(sheet)) return;
5467 switch(sheet->state){
5468 case GTK_SHEET_ROW_SELECTED:
5469 column = xxx_column_count(sheet) - 1;
5471 case GTK_SHEET_COLUMN_SELECTED:
5472 row = yyy_row_count(sheet) - 1;
5474 case GTK_SHEET_NORMAL:
5475 sheet->state=GTK_SHEET_RANGE_SELECTED;
5476 r=sheet->active_cell.row;
5477 c=sheet->active_cell.col;
5478 sheet->range.col0=c;
5479 sheet->range.row0=r;
5480 sheet->range.coli=c;
5481 sheet->range.rowi=r;
5482 gdk_draw_pixmap(sheet->sheet_window,
5483 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
5485 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5486 ROW_TOP_YPIXEL(sheet,r)-1,
5487 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5488 ROW_TOP_YPIXEL(sheet,r)-1,
5489 xxx_column_width(sheet, c)+4,
5490 yyy_row_height(sheet, r)+4);
5491 gtk_sheet_range_draw_selection(sheet, sheet->range);
5492 case GTK_SHEET_RANGE_SELECTED:
5493 sheet->state=GTK_SHEET_RANGE_SELECTED;
5496 sheet->selection_cell.row = row;
5497 sheet->selection_cell.col = column;
5499 range.col0=MIN(column,sheet->active_cell.col);
5500 range.coli=MAX(column,sheet->active_cell.col);
5501 range.row0=MIN(row,sheet->active_cell.row);
5502 range.rowi=MAX(row,sheet->active_cell.row);
5504 if(range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi ||
5505 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli ||
5506 state==GTK_SHEET_NORMAL)
5507 gtk_sheet_real_select_range(sheet, &range);
5512 gtk_sheet_entry_key_press(GtkWidget *widget,
5516 gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", key, &focus);
5521 gtk_sheet_key_press(GtkWidget *widget,
5527 gboolean extend_selection = FALSE;
5528 gboolean force_move = FALSE;
5529 gboolean in_selection = FALSE;
5530 gboolean veto = TRUE;
5533 sheet = GTK_SHEET(widget);
5535 if(key->state & GDK_CONTROL_MASK || key->keyval==GDK_Control_L ||
5536 key->keyval==GDK_Control_R) return FALSE;
5540 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL)
5541 gtk_sheet_clip_range(sheet, sheet->range);
5542 if(key->keyval=='x' || key->keyval == 'X')
5543 gtk_sheet_unclip_range(sheet);
5548 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval==GDK_Shift_L
5549 || key->keyval==GDK_Shift_R;
5552 in_selection = GTK_SHEET_IN_SELECTION(sheet);
5553 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5555 switch(key->keyval){
5556 case GDK_Return: case GDK_KP_Enter:
5557 if(sheet->state == GTK_SHEET_NORMAL &&
5558 !GTK_SHEET_IN_SELECTION(sheet))
5559 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
5561 row = sheet->active_cell.row;
5562 col = sheet->active_cell.col;
5563 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5564 row = MIN_VISIBLE_ROW(sheet)-1;
5565 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5566 col = MIN_VISIBLE_COLUMN(sheet);
5567 if(row < yyy_row_count(sheet) - 1){
5569 while(!yyy_row_is_visible(sheet, row) && row<yyy_row_count(sheet)-1)
5572 gtk_sheet_click_cell(sheet, row, col, &veto);
5573 extend_selection = FALSE;
5575 case GDK_ISO_Left_Tab:
5576 row = sheet->active_cell.row;
5577 col = sheet->active_cell.col;
5578 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5579 col = MIN_VISIBLE_COLUMN(sheet)-1;
5580 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5581 row = MIN_VISIBLE_ROW(sheet);
5584 while(! xxx_column_is_visible(sheet, col) && col>0) col--;
5587 gtk_sheet_click_cell(sheet, row, col, &veto);
5588 extend_selection = FALSE;
5591 row = sheet->active_cell.row;
5592 col = sheet->active_cell.col;
5593 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5594 col = MIN_VISIBLE_COLUMN(sheet)-1;
5595 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5596 row = MIN_VISIBLE_ROW(sheet);
5597 if(col < xxx_column_count(sheet) - 1)
5600 while(! xxx_column_is_visible(sheet, col) &&
5601 col < xxx_column_count(sheet) - 1)
5604 gtk_sheet_click_cell(sheet, row, col, &veto);
5605 extend_selection = FALSE;
5607 /* case GDK_BackSpace:
5608 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){
5609 if(sheet->active_cell.col > 0){
5610 col = sheet->active_cell.col - scroll;
5611 row = sheet->active_cell.row;
5612 while(!sheet->column[col].is_visible && col > 0) col--;
5615 gtk_sheet_click_cell(sheet, row, col, &veto);
5616 extend_selection = FALSE;
5620 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5622 if(extend_selection){
5623 if(state==GTK_STATE_NORMAL){
5624 row=sheet->active_cell.row;
5625 col=sheet->active_cell.col;
5626 gtk_sheet_click_cell(sheet, row, col, &veto);
5629 if(sheet->selection_cell.row > 0){
5630 row = sheet->selection_cell.row - scroll;
5631 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5633 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5637 col = sheet->active_cell.col;
5638 row = sheet->active_cell.row;
5639 if(state==GTK_SHEET_COLUMN_SELECTED)
5640 row = MIN_VISIBLE_ROW(sheet);
5641 if(state==GTK_SHEET_ROW_SELECTED)
5642 col = MIN_VISIBLE_COLUMN(sheet);
5644 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5646 gtk_sheet_click_cell(sheet, row, col, &veto);
5647 extend_selection = FALSE;
5650 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5652 if(extend_selection){
5653 if(state==GTK_STATE_NORMAL){
5654 row=sheet->active_cell.row;
5655 col=sheet->active_cell.col;
5656 gtk_sheet_click_cell(sheet, row, col, &veto);
5659 if(sheet->selection_cell.row < yyy_row_count(sheet)-1){
5660 row = sheet->selection_cell.row + scroll;
5661 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5662 row = MIN(yyy_row_count(sheet)-1, row);
5663 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5667 col = sheet->active_cell.col;
5668 row = sheet->active_cell.row;
5669 if(sheet->active_cell.row < yyy_row_count(sheet)-1){
5670 if(state==GTK_SHEET_COLUMN_SELECTED)
5671 row = MIN_VISIBLE_ROW(sheet)-1;
5672 if(state==GTK_SHEET_ROW_SELECTED)
5673 col = MIN_VISIBLE_COLUMN(sheet);
5675 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5676 row = MIN(yyy_row_count(sheet)-1, row);
5678 gtk_sheet_click_cell(sheet, row, col, &veto);
5679 extend_selection = FALSE;
5682 if(extend_selection){
5683 if(state==GTK_STATE_NORMAL){
5684 row=sheet->active_cell.row;
5685 col=sheet->active_cell.col;
5686 gtk_sheet_click_cell(sheet, row, col, &veto);
5689 if(sheet->selection_cell.col < xxx_column_count(sheet) - 1)
5691 col = sheet->selection_cell.col + 1;
5692 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1)
5694 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5698 col = sheet->active_cell.col;
5699 row = sheet->active_cell.row;
5700 if(sheet->active_cell.col < xxx_column_count(sheet) - 1){
5702 if(state==GTK_SHEET_ROW_SELECTED)
5703 col = MIN_VISIBLE_COLUMN(sheet)-1;
5704 if(state==GTK_SHEET_COLUMN_SELECTED)
5705 row = MIN_VISIBLE_ROW(sheet);
5706 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1) col++;
5707 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5709 gtk_sheet_click_cell(sheet, row, col, &veto);
5714 extend_selection = FALSE;
5717 if(extend_selection){
5718 if(state==GTK_STATE_NORMAL){
5719 row=sheet->active_cell.row;
5720 col=sheet->active_cell.col;
5721 gtk_sheet_click_cell(sheet, row, col, &veto);
5724 if(sheet->selection_cell.col > 0){
5725 col = sheet->selection_cell.col - 1;
5726 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5727 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5731 col = sheet->active_cell.col - 1;
5732 row = sheet->active_cell.row;
5733 if(state==GTK_SHEET_ROW_SELECTED)
5734 col = MIN_VISIBLE_COLUMN(sheet)-1;
5735 if(state==GTK_SHEET_COLUMN_SELECTED)
5736 row = MIN_VISIBLE_ROW(sheet);
5737 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5740 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5742 gtk_sheet_click_cell(sheet, row, col, &veto);
5746 extend_selection = FALSE;
5750 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5751 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5752 extend_selection = FALSE;
5755 row=yyy_row_count(sheet)-1;
5756 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5757 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5758 extend_selection = FALSE;
5762 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5763 if(extend_selection) return TRUE;
5765 if(state == GTK_SHEET_ROW_SELECTED)
5766 sheet->active_cell.col=MIN_VISIBLE_COLUMN(sheet);
5767 if(state == GTK_SHEET_COLUMN_SELECTED)
5768 sheet->active_cell.row=MIN_VISIBLE_ROW(sheet);
5772 if(extend_selection) return TRUE;
5774 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5775 sheet->active_cell.col);
5781 gtk_sheet_size_request (GtkWidget * widget,
5782 GtkRequisition * requisition)
5786 GtkSheetChild *child;
5787 GtkRequisition child_requisition;
5789 g_return_if_fail (widget != NULL);
5790 g_return_if_fail (GTK_IS_SHEET (widget));
5791 g_return_if_fail (requisition != NULL);
5793 sheet = GTK_SHEET (widget);
5795 requisition->width = 3*DEFAULT_COLUMN_WIDTH;
5796 requisition->height = 3*DEFAULT_ROW_HEIGHT(widget);
5798 /* compute the size of the column title area */
5799 if(sheet->column_titles_visible)
5800 requisition->height += sheet->column_title_area.height;
5802 /* compute the size of the row title area */
5803 if(sheet->row_titles_visible)
5804 requisition->width += sheet->row_title_area.width;
5806 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5807 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5808 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5809 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5811 if(!sheet->column_titles_visible)
5812 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5814 if(!sheet->row_titles_visible)
5815 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5817 children = sheet->children;
5820 child = children->data;
5821 children = children->next;
5823 gtk_widget_size_request(child->widget, &child_requisition);
5829 gtk_sheet_size_allocate (GtkWidget * widget,
5830 GtkAllocation * allocation)
5833 GtkAllocation sheet_allocation;
5836 g_return_if_fail (widget != NULL);
5837 g_return_if_fail (GTK_IS_SHEET (widget));
5838 g_return_if_fail (allocation != NULL);
5840 sheet = GTK_SHEET (widget);
5841 widget->allocation = *allocation;
5842 border_width = GTK_CONTAINER(widget)->border_width;
5844 if (GTK_WIDGET_REALIZED (widget))
5845 gdk_window_move_resize (widget->window,
5846 allocation->x + border_width,
5847 allocation->y + border_width,
5848 allocation->width - 2*border_width,
5849 allocation->height - 2*border_width);
5851 /* use internal allocation structure for all the math
5852 * because it's easier than always subtracting the container
5854 sheet->internal_allocation.x = 0;
5855 sheet->internal_allocation.y = 0;
5856 sheet->internal_allocation.width = allocation->width - 2*border_width;
5857 sheet->internal_allocation.height = allocation->height - 2*border_width;
5859 sheet_allocation.x = 0;
5860 sheet_allocation.y = 0;
5861 sheet_allocation.width = allocation->width - 2*border_width;
5862 sheet_allocation.height = allocation->height - 2*border_width;
5864 sheet->sheet_window_width = sheet_allocation.width;
5865 sheet->sheet_window_height = sheet_allocation.height;
5867 if (GTK_WIDGET_REALIZED (widget))
5868 gdk_window_move_resize (sheet->sheet_window,
5871 sheet_allocation.width,
5872 sheet_allocation.height);
5874 /* position the window which holds the column title buttons */
5875 sheet->column_title_area.x = 0;
5876 sheet->column_title_area.y = 0;
5877 if(sheet->row_titles_visible)
5878 sheet->column_title_area.x = sheet->row_title_area.width;
5879 sheet->column_title_area.width = sheet_allocation.width -
5880 sheet->column_title_area.x;
5881 if(GTK_WIDGET_REALIZED(widget) && sheet->column_titles_visible)
5882 gdk_window_move_resize (sheet->column_title_window,
5883 sheet->column_title_area.x,
5884 sheet->column_title_area.y,
5885 sheet->column_title_area.width,
5886 sheet->column_title_area.height);
5888 sheet->sheet_window_width = sheet_allocation.width;
5889 sheet->sheet_window_height = sheet_allocation.height;
5891 /* column button allocation */
5892 size_allocate_column_title_buttons (sheet);
5894 /* position the window which holds the row title buttons */
5895 sheet->row_title_area.x = 0;
5896 sheet->row_title_area.y = 0;
5897 if(sheet->column_titles_visible)
5898 sheet->row_title_area.y = sheet->column_title_area.height;
5899 sheet->row_title_area.height = sheet_allocation.height -
5900 sheet->row_title_area.y;
5902 if(GTK_WIDGET_REALIZED(widget) && sheet->row_titles_visible)
5903 gdk_window_move_resize (sheet->row_title_window,
5904 sheet->row_title_area.x,
5905 sheet->row_title_area.y,
5906 sheet->row_title_area.width,
5907 sheet->row_title_area.height);
5910 /* row button allocation */
5911 size_allocate_row_title_buttons (sheet);
5913 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5914 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5915 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5916 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5918 if(!sheet->column_titles_visible)
5919 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5921 if(!sheet->row_titles_visible)
5922 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5924 size_allocate_column_title_buttons(sheet);
5925 size_allocate_row_title_buttons(sheet);
5927 /* re-scale backing pixmap */
5928 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
5929 gtk_sheet_position_children(sheet);
5931 /* set the scrollbars adjustments */
5932 adjust_scrollbars (sheet);
5936 size_allocate_column_title_buttons (GtkSheet * sheet)
5941 if (!sheet->column_titles_visible) return;
5942 if (!GTK_WIDGET_REALIZED (sheet))
5945 width = sheet->sheet_window_width;
5948 if(sheet->row_titles_visible)
5950 width -= sheet->row_title_area.width;
5951 x = sheet->row_title_area.width;
5954 if(sheet->column_title_area.width != width || sheet->column_title_area.x != x)
5956 sheet->column_title_area.width = width;
5957 sheet->column_title_area.x = x;
5958 gdk_window_move_resize (sheet->column_title_window,
5959 sheet->column_title_area.x,
5960 sheet->column_title_area.y,
5961 sheet->column_title_area.width,
5962 sheet->column_title_area.height);
5966 if(MAX_VISIBLE_COLUMN(sheet) == xxx_column_count(sheet) - 1)
5967 gdk_window_clear_area (sheet->column_title_window,
5969 sheet->column_title_area.width,
5970 sheet->column_title_area.height);
5972 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
5974 for (i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
5975 gtk_sheet_button_draw(sheet,-1,i);
5979 size_allocate_row_title_buttons (GtkSheet * sheet)
5984 if (!sheet->row_titles_visible) return;
5985 if (!GTK_WIDGET_REALIZED (sheet))
5988 height = sheet->sheet_window_height;
5991 if(sheet->column_titles_visible)
5993 height -= sheet->column_title_area.height;
5994 y = sheet->column_title_area.height;
5997 if(sheet->row_title_area.height != height || sheet->row_title_area.y != y)
5999 sheet->row_title_area.y = y;
6000 sheet->row_title_area.height = height;
6001 gdk_window_move_resize (sheet->row_title_window,
6002 sheet->row_title_area.x,
6003 sheet->row_title_area.y,
6004 sheet->row_title_area.width,
6005 sheet->row_title_area.height);
6007 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet)-1)
6008 gdk_window_clear_area (sheet->row_title_window,
6010 sheet->row_title_area.width,
6011 sheet->row_title_area.height);
6013 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6015 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
6016 gtk_sheet_button_draw(sheet,i,-1);
6021 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
6023 GtkAllocation shentry_allocation;
6024 GtkSheetCellAttr attributes;
6025 GtkEntry *sheet_entry;
6026 GtkStyle *style = NULL, *previous_style = NULL;
6028 gint size, max_size, text_size, column_width;
6031 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6032 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
6034 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
6036 gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes);
6038 if(GTK_WIDGET_REALIZED(sheet->sheet_entry)){
6040 if(!GTK_WIDGET(sheet_entry)->style)
6041 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry));
6043 previous_style = GTK_WIDGET(sheet_entry)->style;
6045 style = gtk_style_copy(previous_style);
6046 style->bg[GTK_STATE_NORMAL] = attributes.background;
6047 style->fg[GTK_STATE_NORMAL] = attributes.foreground;
6048 style->text[GTK_STATE_NORMAL] = attributes.foreground;
6049 style->bg[GTK_STATE_ACTIVE] = attributes.background;
6050 style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
6051 style->text[GTK_STATE_ACTIVE] = attributes.foreground;
6053 pango_font_description_free(style->font_desc);
6054 style->font_desc = pango_font_description_copy(attributes.font_desc);
6056 GTK_WIDGET(sheet_entry)->style = style;
6057 gtk_widget_size_request(sheet->sheet_entry, NULL);
6058 GTK_WIDGET(sheet_entry)->style = previous_style;
6060 if(style != previous_style){
6061 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6062 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
6063 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
6064 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
6065 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
6067 gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
6071 if(GTK_IS_ITEM_ENTRY(sheet_entry))
6072 max_size = GTK_ITEM_ENTRY(sheet_entry)->text_max_size;
6077 text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
6078 if(text && strlen(text) > 0){
6079 text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
6082 column_width=xxx_column_width(sheet, sheet->active_cell.col);
6084 size=MIN(text_size, max_size);
6085 size=MAX(size,column_width-2*CELLOFFSET);
6087 row=sheet->active_cell.row;
6088 col=sheet->active_cell.col;
6090 shentry_allocation.x = COLUMN_LEFT_XPIXEL(sheet,sheet->active_cell.col);
6091 shentry_allocation.y = ROW_TOP_YPIXEL(sheet,sheet->active_cell.row);
6092 shentry_allocation.width = column_width;
6093 shentry_allocation.height = yyy_row_height(sheet, sheet->active_cell.row);
6095 if(GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6097 shentry_allocation.height -= 2*CELLOFFSET;
6098 shentry_allocation.y += CELLOFFSET;
6099 if(gtk_sheet_clip_text(sheet))
6100 shentry_allocation.width = column_width - 2*CELLOFFSET;
6102 shentry_allocation.width = size;
6104 switch(GTK_ITEM_ENTRY(sheet_entry)->justification){
6105 case GTK_JUSTIFY_CENTER:
6106 shentry_allocation.x += (column_width)/2 - size/2;
6108 case GTK_JUSTIFY_RIGHT:
6109 shentry_allocation.x += column_width - size - CELLOFFSET;
6111 case GTK_JUSTIFY_LEFT:
6112 case GTK_JUSTIFY_FILL:
6113 shentry_allocation.x += CELLOFFSET;
6119 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6120 shentry_allocation.x += 2;
6121 shentry_allocation.y += 2;
6122 shentry_allocation.width -= MIN(shentry_allocation.width, 3);
6123 shentry_allocation.height -= MIN(shentry_allocation.height, 3);
6126 gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation);
6128 if(previous_style == style) gtk_style_unref(previous_style);
6132 gtk_sheet_entry_set_max_size(GtkSheet *sheet)
6136 gint sizel=0, sizer=0;
6138 GtkJustification justification;
6140 row=sheet->active_cell.row;
6141 col=sheet->active_cell.col;
6143 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry) || gtk_sheet_clip_text(sheet)) return;
6145 justification = GTK_ITEM_ENTRY(sheet->sheet_entry)->justification;
6147 switch(justification){
6148 case GTK_JUSTIFY_FILL:
6149 case GTK_JUSTIFY_LEFT:
6150 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6151 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6152 size+=xxx_column_width(sheet, i);
6154 size = MIN(size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL(sheet, col));
6156 case GTK_JUSTIFY_RIGHT:
6157 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
6158 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6159 size+=xxx_column_width(sheet, i);
6162 case GTK_JUSTIFY_CENTER:
6163 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6164 /* if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6166 sizer+=xxx_column_width(sheet, i);
6168 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
6169 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6170 sizel+=xxx_column_width(sheet, i);
6172 size=2*MIN(sizel, sizer);
6176 if(size!=0) size+=xxx_column_width(sheet, col);
6177 GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size=size;
6182 create_sheet_entry(GtkSheet *sheet)
6187 gint found_entry = FALSE;
6189 widget = GTK_WIDGET(sheet);
6191 if(sheet->sheet_entry){
6192 /* avoids warnings */
6193 gtk_widget_ref(sheet->sheet_entry);
6194 gtk_widget_unparent(sheet->sheet_entry);
6195 gtk_widget_destroy(sheet->sheet_entry);
6198 if(sheet->entry_type){
6200 if(!g_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY)){
6202 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6204 sheet->sheet_entry = parent;
6206 entry = gtk_sheet_get_entry (sheet);
6207 if(GTK_IS_ENTRY(entry)) found_entry = TRUE;
6211 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6219 g_warning ("Entry type must be GtkEntry subclass, using default");
6220 entry = gtk_item_entry_new();
6221 sheet->sheet_entry = entry;
6225 sheet->sheet_entry = parent;
6232 entry = gtk_item_entry_new();
6233 sheet->sheet_entry = entry;
6237 gtk_widget_size_request(sheet->sheet_entry, NULL);
6239 if(GTK_WIDGET_REALIZED(sheet))
6241 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
6242 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
6243 gtk_widget_realize(sheet->sheet_entry);
6246 gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event",
6247 (GtkSignalFunc) gtk_sheet_entry_key_press,
6250 gtk_widget_show (sheet->sheet_entry);
6254 /* Finds the last child widget that happens to be of type GtkEntry */
6256 find_entry(GtkWidget *w, gpointer user_data)
6258 GtkWidget **entry = user_data;
6259 if ( GTK_IS_ENTRY(w))
6266 gtk_sheet_get_entry(GtkSheet *sheet)
6269 GtkWidget *entry = NULL;
6270 GtkTableChild *table_child;
6271 GtkBoxChild *box_child;
6272 GList *children = NULL;
6274 g_return_val_if_fail (sheet != NULL, NULL);
6275 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6276 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6278 if(GTK_IS_ENTRY(sheet->sheet_entry)) return (sheet->sheet_entry);
6280 parent = GTK_WIDGET(sheet->sheet_entry);
6282 if(GTK_IS_TABLE(parent)) children = GTK_TABLE(parent)->children;
6283 if(GTK_IS_BOX(parent)) children = GTK_BOX(parent)->children;
6285 if(GTK_IS_CONTAINER(parent))
6287 gtk_container_forall(GTK_CONTAINER(parent), find_entry, &entry);
6289 if(GTK_IS_ENTRY(entry))
6293 if(!children) return NULL;
6296 if(GTK_IS_TABLE(parent)) {
6297 table_child = children->data;
6298 entry = table_child->widget;
6300 if(GTK_IS_BOX(parent)){
6301 box_child = children->data;
6302 entry = box_child->widget;
6305 if(GTK_IS_ENTRY(entry))
6307 children = children->next;
6311 if(!GTK_IS_ENTRY(entry)) return NULL;
6318 gtk_sheet_get_entry_widget(GtkSheet *sheet)
6320 g_return_val_if_fail (sheet != NULL, NULL);
6321 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6322 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6324 return (sheet->sheet_entry);
6330 row_button_set (GtkSheet *sheet, gint row)
6332 if(sheet->row[row].button.state == GTK_STATE_ACTIVE) return;
6334 sheet->row[row].button.state = GTK_STATE_ACTIVE;
6335 gtk_sheet_button_draw(sheet, row, -1);
6340 row_button_release (GtkSheet *sheet, gint row)
6342 if(sheet->row[row].button.state == GTK_STATE_NORMAL) return;
6344 sheet->row[row].button.state = GTK_STATE_NORMAL;
6345 gtk_sheet_button_draw(sheet, row, -1);
6350 gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
6352 GdkWindow *window = NULL;
6353 GtkShadowType shadow_type;
6354 guint width = 0, height = 0;
6357 gint text_width = 0, text_height = 0;
6358 const GtkSheetButton *button = NULL;
6359 GtkSheetChild *child = NULL;
6360 GdkRectangle allocation;
6361 gboolean is_sensitive = FALSE;
6366 PangoAlignment align = PANGO_ALIGN_LEFT;
6369 rtl = gtk_widget_get_direction(GTK_WIDGET(sheet)) == GTK_TEXT_DIR_RTL;
6371 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6373 if(row >= 0 && !yyy_row_is_visible(sheet, row)) return;
6374 if(column >= 0 && ! xxx_column_is_visible(sheet, column)) return;
6375 if(row >= 0 && !sheet->row_titles_visible) return;
6376 if(column >= 0 && !sheet->column_titles_visible) return;
6377 if(column>=0 && column < MIN_VISIBLE_COLUMN(sheet)) return;
6378 if(column>=0 && column > MAX_VISIBLE_COLUMN(sheet)) return;
6379 if(row>=0 && row < MIN_VISIBLE_ROW(sheet)) return;
6380 if(row>=0 && row > MAX_VISIBLE_ROW(sheet)) return;
6381 if( (row == -1) && (column == -1) ) return;
6384 window=sheet->column_title_window;
6385 button= xxx_column_button(sheet, column);
6387 x = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING;
6388 if(sheet->row_titles_visible) x -= sheet->row_title_area.width;
6390 width = xxx_column_width(sheet, column);
6391 height = sheet->column_title_area.height;
6392 is_sensitive=xxx_column_is_sensitive(sheet, column);
6395 window=sheet->row_title_window;
6396 button = yyy_row_button(sheet, row);
6399 y = ROW_TOP_YPIXEL(sheet, row)+CELL_SPACING;
6400 if(sheet->column_titles_visible) y-=sheet->column_title_area.height;
6401 width = sheet->row_title_area.width;
6402 height = yyy_row_height(sheet, row);
6403 is_sensitive=yyy_row_is_sensitive(sheet, row);
6408 allocation.width = width;
6409 allocation.height = height;
6411 gdk_window_clear_area (window,
6415 gtk_paint_box (sheet->button->style, window,
6416 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
6417 &allocation, GTK_WIDGET(sheet->button),
6418 "buttondefault", x, y, width, height);
6420 state = button->state;
6421 if(!is_sensitive) state=GTK_STATE_INSENSITIVE;
6423 if (state == GTK_STATE_ACTIVE)
6424 shadow_type = GTK_SHADOW_IN;
6426 shadow_type = GTK_SHADOW_OUT;
6428 if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
6429 gtk_paint_box (sheet->button->style, window,
6430 button->state, shadow_type,
6431 &allocation, GTK_WIDGET(sheet->button),
6432 "button", x, y, width, height);
6434 if(button->label_visible){
6436 text_height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))-2*CELLOFFSET;
6438 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6440 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation);
6442 y += 2*sheet->button->style->ythickness;
6445 if(button->label && strlen(button->label)>0){
6447 PangoLayout *layout = NULL;
6448 gint real_x = x, real_y = y;
6450 words=button->label;
6451 line = g_new(gchar, 1);
6454 while(words && *words != '\0'){
6457 line=g_realloc(line, len+2);
6461 if(*words == '\n' || *(words+1) == '\0'){
6462 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, line);
6464 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), line);
6465 switch(button->justification){
6466 case GTK_JUSTIFY_LEFT:
6467 real_x = x + CELLOFFSET;
6468 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6470 case GTK_JUSTIFY_RIGHT:
6471 real_x = x + width - text_width - CELLOFFSET;
6472 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6474 case GTK_JUSTIFY_CENTER:
6476 real_x = x + (width - text_width)/2;
6477 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6478 pango_layout_set_justify (layout, TRUE);
6480 pango_layout_set_alignment (layout, align);
6481 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6490 g_object_unref(G_OBJECT(layout));
6492 real_y += text_height + 2;
6495 line = g_new(gchar, 1);
6502 if(button->label && strlen(button->label) > 0){
6503 PangoLayout *layout = NULL;
6504 gint real_x = x, real_y = y;
6506 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, button->label);
6508 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), button->label);
6509 switch(button->justification){
6510 case GTK_JUSTIFY_LEFT:
6511 real_x = x + CELLOFFSET;
6512 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6514 case GTK_JUSTIFY_RIGHT:
6515 real_x = x + width - text_width - CELLOFFSET;
6516 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6518 case GTK_JUSTIFY_CENTER:
6520 real_x = x + (width - text_width)/2;
6521 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6522 pango_layout_set_justify (layout, TRUE);
6524 pango_layout_set_alignment (layout, align);
6525 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6534 g_object_unref(G_OBJECT(layout));
6537 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6539 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, NULL);
6543 if((child = button->child) && (child->widget)){
6544 child->x = allocation.x;
6545 child->y = allocation.y;
6547 child->x += (width - child->widget->requisition.width) / 2;
6548 child->y += (height - child->widget->requisition.height) / 2;
6549 allocation.x = child->x;
6550 allocation.y = child->y;
6551 allocation.width = child->widget->requisition.width;
6552 allocation.height = child->widget->requisition.height;
6557 gtk_widget_set_state(child->widget, button->state);
6559 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
6560 GTK_WIDGET_MAPPED(child->widget))
6562 gtk_widget_size_allocate(child->widget,
6564 gtk_widget_queue_draw(child->widget);
6575 * vadjustment_changed
6576 * hadjustment_changed
6577 * vadjustment_value_changed
6578 * hadjustment_value_changed */
6581 adjust_scrollbars (GtkSheet * sheet)
6584 if(sheet->vadjustment){
6585 sheet->vadjustment->page_size = sheet->sheet_window_height;
6586 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
6587 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
6588 sheet->vadjustment->lower = 0;
6589 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
6591 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet))
6593 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) -
6594 sheet->sheet_window_height);
6595 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
6599 gtk_signal_emit_by_name (GTK_OBJECT(sheet->vadjustment), "changed");
6603 if(sheet->hadjustment){
6604 sheet->hadjustment->page_size = sheet->sheet_window_width;
6605 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
6606 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
6607 sheet->hadjustment->lower = 0;
6608 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
6610 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet))
6612 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) -
6613 sheet->sheet_window_width);
6614 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment),
6618 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), "changed");
6622 if(GTK_WIDGET_REALIZED(sheet))
6624 if(sheet->row_titles_visible){
6625 size_allocate_row_title_buttons(sheet);
6626 gdk_window_show(sheet->row_title_window);
6629 if(sheet->column_titles_visible){
6630 size_allocate_column_title_buttons(sheet);
6631 gdk_window_show(sheet->column_title_window);
6634 gtk_sheet_range_draw(sheet, NULL);
6641 vadjustment_changed (GtkAdjustment * adjustment,
6646 g_return_if_fail (adjustment != NULL);
6647 g_return_if_fail (data != NULL);
6649 sheet = GTK_SHEET (data);
6654 hadjustment_changed (GtkAdjustment * adjustment,
6659 g_return_if_fail (adjustment != NULL);
6660 g_return_if_fail (data != NULL);
6662 sheet = GTK_SHEET (data);
6667 vadjustment_value_changed (GtkAdjustment * adjustment,
6671 gint diff, value, old_value;
6675 g_return_if_fail (adjustment != NULL);
6676 g_return_if_fail (data != NULL);
6677 g_return_if_fail (GTK_IS_SHEET (data));
6679 sheet = GTK_SHEET (data);
6681 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6683 row=ROW_FROM_YPIXEL(sheet,sheet->column_title_area.height + CELL_SPACING);
6684 if(!sheet->column_titles_visible)
6685 row=ROW_FROM_YPIXEL(sheet,CELL_SPACING);
6687 old_value = -sheet->voffset;
6689 new_row = g_sheet_row_pixel_to_row(sheet->row_geometry,
6690 adjustment->value,sheet);
6692 y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
6694 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
6695 yyy_row_height(sheet, row) > sheet->vadjustment->step_increment){
6696 /* This avoids embarrassing twitching */
6697 if(row == new_row && row != yyy_row_count(sheet) - 1 &&
6698 adjustment->value - sheet->old_vadjustment >=
6699 sheet->vadjustment->step_increment &&
6700 new_row + 1 != MIN_VISIBLE_ROW(sheet)){
6702 y=y+yyy_row_height(sheet, row);
6706 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6707 if(sheet->old_vadjustment >= 0. && row == new_row){
6708 sheet->old_vadjustment = sheet->vadjustment->value;
6712 sheet->old_vadjustment = sheet->vadjustment->value;
6713 adjustment->value=y;
6717 sheet->vadjustment->step_increment= yyy_row_height(sheet, 0);
6719 sheet->vadjustment->step_increment=
6720 MIN(yyy_row_height(sheet, new_row), yyy_row_height(sheet, new_row-1));
6723 sheet->vadjustment->value=adjustment->value;
6725 value = adjustment->value;
6727 if (value >= -sheet->voffset)
6730 diff = value + sheet->voffset;
6735 diff = -sheet->voffset - value;
6738 sheet->voffset = -value;
6740 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6741 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6742 if(!sheet->column_titles_visible)
6743 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6745 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6746 sheet->state == GTK_SHEET_NORMAL &&
6747 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6748 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6749 sheet->active_cell.col))
6753 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6755 if(!text || strlen(text)==0)
6756 gtk_sheet_cell_clear(sheet,
6757 sheet->active_cell.row,
6758 sheet->active_cell.col);
6759 gtk_widget_unmap(sheet->sheet_entry);
6762 gtk_sheet_position_children(sheet);
6764 gtk_sheet_range_draw(sheet, NULL);
6765 size_allocate_row_title_buttons(sheet);
6766 size_allocate_global_button(sheet);
6770 hadjustment_value_changed (GtkAdjustment * adjustment,
6774 gint i, diff, value, old_value;
6775 gint column, new_column;
6778 g_return_if_fail (adjustment != NULL);
6779 g_return_if_fail (data != NULL);
6780 g_return_if_fail (GTK_IS_SHEET (data));
6782 sheet = GTK_SHEET (data);
6784 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6786 column=COLUMN_FROM_XPIXEL(sheet,sheet->row_title_area.width + CELL_SPACING);
6787 if(!sheet->row_titles_visible)
6788 column=COLUMN_FROM_XPIXEL(sheet, CELL_SPACING);
6790 old_value = -sheet->hoffset;
6792 for(i=0; i < xxx_column_count(sheet); i++)
6794 if(xxx_column_is_visible(sheet, i)) x += xxx_column_width(sheet, i);
6795 if(x > adjustment->value) break;
6797 x-=xxx_column_width(sheet, i);
6800 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
6801 xxx_column_width(sheet, i) > sheet->hadjustment->step_increment){
6802 /* This avoids embarrassing twitching */
6803 if(column == new_column && column != xxx_column_count(sheet) - 1 &&
6804 adjustment->value - sheet->old_hadjustment >=
6805 sheet->hadjustment->step_increment &&
6806 new_column + 1 != MIN_VISIBLE_COLUMN(sheet)){
6808 x=x+xxx_column_width(sheet, column);
6812 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6813 if(sheet->old_hadjustment >= 0. && new_column == column){
6814 sheet->old_hadjustment = sheet->hadjustment->value;
6818 sheet->old_hadjustment = sheet->hadjustment->value;
6819 adjustment->value=x;
6821 if(new_column == 0){
6822 sheet->hadjustment->step_increment=
6823 xxx_column_width(sheet, 0);
6825 sheet->hadjustment->step_increment=
6826 MIN(xxx_column_width(sheet, new_column), xxx_column_width(sheet, new_column-1));
6830 sheet->hadjustment->value=adjustment->value;
6832 value = adjustment->value;
6834 if (value >= -sheet->hoffset)
6837 diff = value + sheet->hoffset;
6842 diff = -sheet->hoffset - value;
6845 sheet->hoffset = -value;
6847 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6848 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6849 if(!sheet->row_titles_visible)
6850 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6852 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6853 sheet->state == GTK_SHEET_NORMAL &&
6854 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6855 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6856 sheet->active_cell.col))
6860 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6861 if(!text || strlen(text)==0)
6862 gtk_sheet_cell_clear(sheet,
6863 sheet->active_cell.row,
6864 sheet->active_cell.col);
6866 gtk_widget_unmap(sheet->sheet_entry);
6869 gtk_sheet_position_children(sheet);
6871 gtk_sheet_range_draw(sheet, NULL);
6872 size_allocate_column_title_buttons(sheet);
6876 /* COLUMN RESIZING */
6878 draw_xor_vline (GtkSheet * sheet)
6882 g_return_if_fail (sheet != NULL);
6884 widget = GTK_WIDGET (sheet);
6886 gdk_draw_line (widget->window, sheet->xor_gc,
6888 sheet->column_title_area.height,
6890 sheet->sheet_window_height + 1);
6895 draw_xor_hline (GtkSheet * sheet)
6899 g_return_if_fail (sheet != NULL);
6901 widget = GTK_WIDGET (sheet);
6903 gdk_draw_line (widget->window, sheet->xor_gc,
6904 sheet->row_title_area.width,
6907 sheet->sheet_window_width + 1,
6911 /* SELECTED RANGE */
6913 draw_xor_rectangle(GtkSheet *sheet, GtkSheetRange range)
6916 GdkRectangle clip_area, area;
6919 area.x=COLUMN_LEFT_XPIXEL(sheet, range.col0);
6920 area.y=ROW_TOP_YPIXEL(sheet, range.row0);
6921 area.width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-area.x+
6922 xxx_column_width(sheet, range.coli);
6923 area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+
6924 yyy_row_height(sheet, range.rowi);
6926 clip_area.x=sheet->row_title_area.width;
6927 clip_area.y=sheet->column_title_area.height;
6928 clip_area.width=sheet->sheet_window_width;
6929 clip_area.height=sheet->sheet_window_height;
6931 if(!sheet->row_titles_visible) clip_area.x = 0;
6932 if(!sheet->column_titles_visible) clip_area.y = 0;
6935 area.width=area.width+area.x;
6938 if(area.width>clip_area.width) area.width=clip_area.width+10;
6940 area.height=area.height+area.y;
6943 if(area.height>clip_area.height) area.height=clip_area.height+10;
6948 clip_area.height+=3;
6950 gdk_gc_get_values(sheet->xor_gc, &values);
6952 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
6955 gdk_draw_rectangle(sheet->sheet_window,
6959 area.width-2*i, area.height-2*i);
6962 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
6964 gdk_gc_set_foreground(sheet->xor_gc, &values.foreground);
6969 /* this function returns the new width of the column being resized given
6970 * the column and x position of the cursor; the x cursor position is passed
6971 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
6973 new_column_width (GtkSheet * sheet,
6982 min_width = sheet->column_requisition;
6984 /* you can't shrink a column to less than its minimum width */
6985 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
6987 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
6990 /* don't grow past the end of the window */
6992 if (cx > sheet->sheet_window_width)
6994 *x = cx = sheet->sheet_window_width;
6997 /* calculate new column width making sure it doesn't end up
6998 * less than the minimum width */
6999 width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
7000 if (width < min_width)
7003 xxx_set_column_width(sheet, column, width);
7004 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7005 size_allocate_column_title_buttons (sheet);
7010 /* this function returns the new height of the row being resized given
7011 * the row and y position of the cursor; the y cursor position is passed
7012 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7014 new_row_height (GtkSheet * sheet,
7022 min_height = sheet->row_requisition;
7024 /* you can't shrink a row to less than its minimum height */
7025 if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
7028 *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
7031 /* don't grow past the end of the window */
7033 if (cy > sheet->sheet_window_height)
7035 *y = cy = sheet->sheet_window_height;
7038 /* calculate new row height making sure it doesn't end up
7039 * less than the minimum height */
7040 height = (cy - ROW_TOP_YPIXEL (sheet, row));
7041 if (height < min_height)
7042 height = min_height;
7044 yyy_set_row_height(sheet, row, height);
7045 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
7046 size_allocate_row_title_buttons (sheet);
7052 gtk_sheet_set_column_width (GtkSheet * sheet,
7058 g_return_if_fail (sheet != NULL);
7059 g_return_if_fail (GTK_IS_SHEET (sheet));
7061 if (column < 0 || column >= xxx_column_count(sheet))
7064 gtk_sheet_column_size_request(sheet, column, &min_width);
7065 if(width < min_width) return;
7067 xxx_set_column_width(sheet, column, width);
7069 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7070 size_allocate_column_title_buttons (sheet);
7071 adjust_scrollbars (sheet);
7072 gtk_sheet_size_allocate_entry(sheet);
7073 gtk_sheet_range_draw (sheet, NULL);
7076 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, column);
7077 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_COL_WIDTH], column, width);
7084 gtk_sheet_set_row_height (GtkSheet * sheet,
7090 g_return_if_fail (sheet != NULL);
7091 g_return_if_fail (GTK_IS_SHEET (sheet));
7093 if (row < 0 || row >= yyy_row_count(sheet))
7096 gtk_sheet_row_size_request(sheet, row, &min_height);
7097 if(height < min_height) return;
7099 yyy_set_row_height(sheet, row, height);
7101 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7102 size_allocate_row_title_buttons (sheet);
7103 adjust_scrollbars (sheet);
7104 gtk_sheet_size_allocate_entry(sheet);
7105 gtk_sheet_range_draw (sheet, NULL);
7108 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], row, -1);
7109 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_ROW_HEIGHT], row, height);
7115 gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr *attributes)
7117 const GdkColor *fg, *bg;
7118 const GtkJustification *j ;
7119 const PangoFontDescription *font_desc ;
7120 const GtkSheetCellBorder *border ;
7122 g_return_val_if_fail (sheet != NULL, FALSE);
7123 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
7125 if(row < 0 || col < 0) return FALSE;
7127 init_attributes(sheet, col, attributes);
7132 attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
7133 attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
7135 fg = g_sheet_model_get_foreground(sheet->model, row, col);
7137 attributes->foreground = *fg;
7139 bg = g_sheet_model_get_background(sheet->model, row, col);
7141 attributes->background = *bg;
7143 j = g_sheet_model_get_justification(sheet->model, row, col);
7144 if (j) attributes->justification = *j;
7146 font_desc = g_sheet_model_get_font_desc(sheet->model, row, col);
7147 if ( font_desc ) attributes->font_desc = font_desc;
7149 border = g_sheet_model_get_cell_border(sheet->model, row, col);
7151 if ( border ) attributes->border = *border;
7157 init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
7159 /* DEFAULT VALUES */
7160 attributes->foreground = GTK_WIDGET(sheet)->style->black;
7161 attributes->background = sheet->bg_color;
7162 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
7163 GdkColormap *colormap;
7164 colormap=gdk_colormap_get_system();
7165 gdk_color_black(colormap, &attributes->foreground);
7166 attributes->background = sheet->bg_color;
7168 attributes->justification = xxx_column_justification(sheet, col);
7169 attributes->border.width = 0;
7170 attributes->border.line_style = GDK_LINE_SOLID;
7171 attributes->border.cap_style = GDK_CAP_NOT_LAST;
7172 attributes->border.join_style = GDK_JOIN_MITER;
7173 attributes->border.mask = 0;
7174 attributes->border.color = GTK_WIDGET(sheet)->style->black;
7175 attributes->is_editable = TRUE;
7176 attributes->is_visible = TRUE;
7177 attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
7183 /********************************************************************
7184 * Container Functions:
7189 * gtk_sheet_move_child
7190 * gtk_sheet_position_child
7191 * gtk_sheet_position_children
7192 * gtk_sheet_realize_child
7193 * gtk_sheet_get_child_at
7194 ********************************************************************/
7197 gtk_sheet_put(GtkSheet *sheet, GtkWidget *child, gint x, gint y)
7199 GtkRequisition child_requisition;
7200 GtkSheetChild *child_info;
7202 g_return_val_if_fail(sheet != NULL, NULL);
7203 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7204 g_return_val_if_fail(child != NULL, NULL);
7205 g_return_val_if_fail(child->parent == NULL, NULL);
7207 child_info = g_new (GtkSheetChild, 1);
7208 child_info->widget = child;
7211 child_info->attached_to_cell = FALSE;
7212 child_info->floating = TRUE;
7213 child_info->xpadding = child_info->ypadding = 0;
7214 child_info->xexpand = child_info->yexpand = FALSE;
7215 child_info->xshrink = child_info->yshrink = FALSE;
7216 child_info->xfill = child_info->yfill = FALSE;
7218 sheet->children = g_list_append(sheet->children, child_info);
7220 gtk_widget_set_parent (child, GTK_WIDGET(sheet));
7222 gtk_widget_size_request(child, &child_requisition);
7224 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7226 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7227 (!GTK_WIDGET_REALIZED(child) || GTK_WIDGET_NO_WINDOW(child)))
7228 gtk_sheet_realize_child(sheet, child_info);
7230 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7231 !GTK_WIDGET_MAPPED(child))
7232 gtk_widget_map(child);
7235 gtk_sheet_position_child(sheet, child_info);
7237 /* This will avoid drawing on the titles */
7239 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7241 if(sheet->row_titles_visible)
7242 gdk_window_show(sheet->row_title_window);
7243 if(sheet->column_titles_visible)
7244 gdk_window_show(sheet->column_title_window);
7247 return (child_info);
7251 gtk_sheet_attach_floating (GtkSheet *sheet,
7256 GtkSheetChild *child;
7258 if(row < 0 || col < 0){
7259 gtk_sheet_button_attach(sheet, widget, row, col);
7263 gtk_sheet_get_cell_area(sheet, row, col, &area);
7264 child = gtk_sheet_put(sheet, widget, area.x, area.y);
7265 child->attached_to_cell = TRUE;
7271 gtk_sheet_attach_default (GtkSheet *sheet,
7275 if(row < 0 || col < 0){
7276 gtk_sheet_button_attach(sheet, widget, row, col);
7280 gtk_sheet_attach(sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
7284 gtk_sheet_attach (GtkSheet *sheet,
7293 GtkSheetChild *child = NULL;
7295 if(row < 0 || col < 0){
7296 gtk_sheet_button_attach(sheet, widget, row, col);
7300 child = g_new0(GtkSheetChild, 1);
7301 child->attached_to_cell = TRUE;
7302 child->floating = FALSE;
7303 child->widget = widget;
7306 child->xpadding = xpadding;
7307 child->ypadding = ypadding;
7308 child->xexpand = (xoptions & GTK_EXPAND) != 0;
7309 child->yexpand = (yoptions & GTK_EXPAND) != 0;
7310 child->xshrink = (xoptions & GTK_SHRINK) != 0;
7311 child->yshrink = (yoptions & GTK_SHRINK) != 0;
7312 child->xfill = (xoptions & GTK_FILL) != 0;
7313 child->yfill = (yoptions & GTK_FILL) != 0;
7315 sheet->children = g_list_append(sheet->children, child);
7317 gtk_sheet_get_cell_area(sheet, row, col, &area);
7319 child->x = area.x + child->xpadding;
7320 child->y = area.y + child->ypadding;
7322 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7324 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7325 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7326 gtk_sheet_realize_child(sheet, child);
7328 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7329 !GTK_WIDGET_MAPPED(widget))
7330 gtk_widget_map(widget);
7333 gtk_sheet_position_child(sheet, child);
7335 /* This will avoid drawing on the titles */
7337 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7339 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
7340 gdk_window_show(sheet->row_title_window);
7341 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
7342 gdk_window_show(sheet->column_title_window);
7348 gtk_sheet_button_attach (GtkSheet *sheet,
7352 GtkSheetButton *button = 0;
7353 GtkSheetChild *child;
7354 GtkRequisition button_requisition;
7356 if(row >= 0 && col >= 0) return;
7357 if(row < 0 && col < 0) return;
7359 child = g_new (GtkSheetChild, 1);
7360 child->widget = widget;
7363 child->attached_to_cell = TRUE;
7364 child->floating = FALSE;
7367 child->xpadding = child->ypadding = 0;
7368 child->xshrink = child->yshrink = FALSE;
7369 child->xfill = child->yfill = FALSE;
7372 sheet->children = g_list_append(sheet->children, child);
7374 gtk_sheet_button_size_request(sheet, button, &button_requisition);
7377 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7379 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7380 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7381 gtk_sheet_realize_child(sheet, child);
7383 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7384 !GTK_WIDGET_MAPPED(widget))
7385 gtk_widget_map(widget);
7388 if(row == -1) size_allocate_column_title_buttons(sheet);
7389 if(col == -1) size_allocate_row_title_buttons(sheet);
7394 label_size_request(GtkSheet *sheet, gchar *label, GtkRequisition *req)
7399 gint row_height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)) - 2*CELLOFFSET + 2;
7405 while(words && *words != '\0'){
7406 if(*words == '\n' || *(words+1) == '\0'){
7407 req->height += row_height;
7410 req->width = MAX(req->width, STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, word));
7418 if(n > 0) req->height -= 2;
7422 gtk_sheet_button_size_request (GtkSheet *sheet,
7423 const GtkSheetButton *button,
7424 GtkRequisition *button_requisition)
7426 GtkRequisition requisition;
7427 GtkRequisition label_requisition;
7429 if(gtk_sheet_autoresize(sheet) && button->label && strlen(button->label) > 0){
7430 label_size_request(sheet, button->label, &label_requisition);
7431 label_requisition.width += 2*CELLOFFSET;
7432 label_requisition.height += 2*CELLOFFSET;
7434 label_requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7435 label_requisition.width = COLUMN_MIN_WIDTH;
7440 gtk_widget_size_request(button->child->widget, &requisition);
7441 requisition.width += 2*button->child->xpadding;
7442 requisition.height += 2*button->child->ypadding;
7443 requisition.width += 2*sheet->button->style->xthickness;
7444 requisition.height += 2*sheet->button->style->ythickness;
7448 requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7449 requisition.width = COLUMN_MIN_WIDTH;
7452 *button_requisition = requisition;
7453 button_requisition->width = MAX(requisition.width, label_requisition.width);
7454 button_requisition->height = MAX(requisition.height, label_requisition.height);
7459 gtk_sheet_row_size_request (GtkSheet *sheet,
7463 GtkRequisition button_requisition;
7466 gtk_sheet_button_size_request(sheet,
7467 yyy_row_button(sheet, row),
7468 &button_requisition);
7470 *requisition = button_requisition.height;
7472 children = sheet->children;
7474 GtkSheetChild *child = (GtkSheetChild *)children->data;
7475 GtkRequisition child_requisition;
7477 if(child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink){
7478 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7480 if(child_requisition.height + 2 * child->ypadding > *requisition)
7481 *requisition = child_requisition.height + 2 * child->ypadding;
7483 children = children->next;
7486 sheet->row_requisition = * requisition;
7490 gtk_sheet_column_size_request (GtkSheet *sheet,
7494 GtkRequisition button_requisition;
7497 gtk_sheet_button_size_request(sheet,
7498 xxx_column_button(sheet, col),
7499 &button_requisition);
7501 *requisition = button_requisition.width;
7503 children = sheet->children;
7505 GtkSheetChild *child = (GtkSheetChild *)children->data;
7506 GtkRequisition child_requisition;
7508 if(child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink){
7509 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7511 if(child_requisition.width + 2 * child->xpadding > *requisition)
7512 *requisition = child_requisition.width + 2 * child->xpadding;
7514 children = children->next;
7517 sheet->column_requisition = *requisition;
7521 gtk_sheet_move_child(GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
7523 GtkSheetChild *child;
7526 g_return_if_fail(sheet != NULL);
7527 g_return_if_fail(GTK_IS_SHEET(sheet));
7529 children = sheet->children;
7532 child = children->data;
7534 if(child->widget == widget){
7537 child->row = ROW_FROM_YPIXEL(sheet, y);
7538 child->col = COLUMN_FROM_XPIXEL(sheet, x);
7539 gtk_sheet_position_child(sheet, child);
7543 children = children->next;
7546 g_warning("Widget must be a GtkSheet child");
7551 gtk_sheet_position_child(GtkSheet *sheet, GtkSheetChild *child)
7553 GtkRequisition child_requisition;
7554 GtkAllocation child_allocation;
7560 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7562 if(sheet->column_titles_visible)
7563 yoffset = sheet->column_title_area.height;
7565 if(sheet->row_titles_visible)
7566 xoffset = sheet->row_title_area.width;
7568 if(child->attached_to_cell){
7570 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col);
7571 child->y = ROW_TOP_YPIXEL(sheet, child->row);
7573 if(sheet->row_titles_visible)
7574 child->x-=sheet->row_title_area.width;
7575 if(sheet->column_titles_visible)
7576 child->y-=sheet->column_title_area.height;
7578 width = xxx_column_width(sheet, child->col);
7579 height = yyy_row_height(sheet, child->row);
7582 gtk_sheet_get_cell_area(sheet, child->row, child->col, &area);
7583 child->x = area.x + child->xpadding;
7584 child->y = area.y + child->ypadding;
7586 if(!child->floating){
7587 if(child_requisition.width + 2*child->xpadding <= xxx_column_width(sheet, child->col)){
7589 child_requisition.width = child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7592 child->x = area.x + xxx_column_width(sheet, child->col) / 2 -
7593 child_requisition.width / 2;
7595 child_allocation.width = child_requisition.width;
7598 if(!child->xshrink){
7599 gtk_sheet_set_column_width(sheet, child->col, child_requisition.width + 2 * child->xpadding);
7601 child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7604 if(child_requisition.height + 2*child->ypadding <= yyy_row_height(sheet, child->row)){
7606 child_requisition.height = child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7609 child->y = area.y + yyy_row_height(sheet, child->row) / 2 -
7610 child_requisition.height / 2;
7612 child_allocation.height = child_requisition.height;
7615 if(!child->yshrink){
7616 gtk_sheet_set_row_height(sheet, child->row, child_requisition.height + 2 * child->ypadding);
7618 child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7621 child_allocation.width = child_requisition.width;
7622 child_allocation.height = child_requisition.height;
7625 x = child_allocation.x = child->x + xoffset;
7626 y = child_allocation.y = child->y + yoffset;
7630 x = child_allocation.x = child->x + sheet->hoffset + xoffset;
7631 x = child_allocation.x = child->x + xoffset;
7632 y = child_allocation.y = child->y + sheet->voffset + yoffset;
7633 y = child_allocation.y = child->y + yoffset;
7634 child_allocation.width = child_requisition.width;
7635 child_allocation.height = child_requisition.height;
7638 gtk_widget_size_allocate(child->widget, &child_allocation);
7639 gtk_widget_queue_draw(child->widget);
7643 gtk_sheet_forall (GtkContainer *container,
7644 gboolean include_internals,
7645 GtkCallback callback,
7646 gpointer callback_data)
7649 GtkSheetChild *child;
7652 g_return_if_fail (GTK_IS_SHEET (container));
7653 g_return_if_fail (callback != NULL);
7655 sheet = GTK_SHEET (container);
7656 children = sheet->children;
7659 child = children->data;
7660 children = children->next;
7662 (* callback) (child->widget, callback_data);
7665 (* callback) (sheet->button, callback_data);
7666 if(sheet->sheet_entry)
7667 (* callback) (sheet->sheet_entry, callback_data);
7672 gtk_sheet_position_children(GtkSheet *sheet)
7675 GtkSheetChild *child;
7677 children = sheet->children;
7681 child = (GtkSheetChild *)children->data;
7683 if(child->col !=-1 && child->row != -1)
7684 gtk_sheet_position_child(sheet, child);
7686 if(child->row == -1){
7687 if(child->col < MIN_VISIBLE_COLUMN(sheet) ||
7688 child->col > MAX_VISIBLE_COLUMN(sheet))
7689 gtk_sheet_child_hide(child);
7691 gtk_sheet_child_show(child);
7693 if(child->col == -1){
7694 if(child->row < MIN_VISIBLE_ROW(sheet) ||
7695 child->row > MAX_VISIBLE_ROW(sheet))
7696 gtk_sheet_child_hide(child);
7698 gtk_sheet_child_show(child);
7701 children = children->next;
7707 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
7711 GtkSheetChild *child = 0;
7713 g_return_if_fail(container != NULL);
7714 g_return_if_fail(GTK_IS_SHEET(container));
7716 sheet = GTK_SHEET(container);
7718 children = sheet->children;
7722 child = (GtkSheetChild *)children->data;
7724 if(child->widget == widget) break;
7726 children = children->next;
7731 gtk_widget_unparent (widget);
7732 child->widget = NULL;
7734 sheet->children = g_list_remove_link (sheet->children, children);
7735 g_list_free_1 (children);
7742 gtk_sheet_realize_child(GtkSheet *sheet, GtkSheetChild *child)
7746 widget = GTK_WIDGET(sheet);
7748 if(GTK_WIDGET_REALIZED(widget)){
7749 if(child->row == -1)
7750 gtk_widget_set_parent_window(child->widget, sheet->column_title_window);
7751 else if(child->col == -1)
7752 gtk_widget_set_parent_window(child->widget, sheet->row_title_window);
7754 gtk_widget_set_parent_window(child->widget, sheet->sheet_window);
7757 gtk_widget_set_parent(child->widget, widget);
7763 gtk_sheet_get_child_at(GtkSheet *sheet, gint row, gint col)
7766 GtkSheetChild *child = 0;
7768 g_return_val_if_fail(sheet != NULL, NULL);
7769 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7771 children = sheet->children;
7775 child = (GtkSheetChild *)children->data;
7777 if(child->attached_to_cell)
7778 if(child->row == row && child->col == col) break;
7780 children = children->next;
7783 if(children) return child;
7789 gtk_sheet_child_hide(GtkSheetChild *child)
7791 g_return_if_fail(child != NULL);
7792 gtk_widget_hide(child->widget);
7796 gtk_sheet_child_show(GtkSheetChild *child)
7798 g_return_if_fail(child != NULL);
7800 gtk_widget_show(child->widget);
7804 gtk_sheet_get_model(const GtkSheet *sheet)
7806 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
7808 return sheet->model;