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;
1126 /* Callback which occurs whenever rows are inserted/deleted in the model */
1128 rows_inserted_deleted_callback (GSheetModel *m, gint first_row, gint n_rows,
1131 GtkSheet *sheet = GTK_SHEET(data);
1133 GtkSheetRange range;
1135 /* Need to update all the rows starting from the first row and onwards.
1136 * Previous rows are unchanged, so don't need to be updated.
1138 range.row0 = first_row;
1140 range.rowi = yyy_row_count(sheet) - 1;
1141 range.coli = xxx_column_count(sheet) - 1;
1143 gtk_sheet_range_draw(sheet, &range);
1147 If row0 or rowi are negative, then all rows will be updated.
1148 If col0 or coli are negative, then all columns will be updated.
1151 range_update_callback (GSheetModel *m, gint row0, gint col0,
1152 gint rowi, gint coli, gpointer data)
1154 GtkSheet *sheet = GTK_SHEET(data);
1156 GtkSheetRange range;
1163 if( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
1165 gtk_sheet_range_draw(sheet, NULL);
1168 else if ( row0 < 0 || rowi < 0 )
1170 range.row0=MIN_VISIBLE_ROW(sheet);
1171 range.rowi=MAX_VISIBLE_ROW(sheet);
1173 else if ( col0 < 0 || coli < 0 )
1175 range.col0=MIN_VISIBLE_COLUMN(sheet);
1176 range.coli=MAX_VISIBLE_COLUMN(sheet);
1179 gtk_sheet_range_draw(sheet, &range);
1183 static void gtk_sheet_construct (GtkSheet *sheet,
1186 const gchar *title);
1191 * @rows: initial number of rows
1192 * @columns: initial number of columns
1193 * @title: sheet title
1194 * @model: the model to use for the sheet data
1196 * Creates a new sheet widget with the given number of rows and columns.
1198 * Returns: the new sheet widget
1201 gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, const gchar *title,
1206 widget = gtk_type_new (gtk_sheet_get_type ());
1208 gtk_sheet_construct(GTK_SHEET(widget), vgeo, hgeo, title);
1211 gtk_sheet_set_model(GTK_SHEET(widget), model);
1219 * gtk_sheet_set_model
1220 * @sheet: the sheet to set the model for
1221 * @model: the model to use for the sheet data
1223 * Sets the model for a GtkSheet
1227 gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model)
1229 g_return_if_fail (GTK_IS_SHEET (sheet));
1230 g_return_if_fail (G_IS_SHEET_MODEL (model));
1232 sheet->model = model;
1234 g_signal_connect(model, "range_changed",
1235 G_CALLBACK(range_update_callback), sheet);
1237 g_signal_connect(model, "rows_inserted",
1238 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1240 g_signal_connect(model, "rows_deleted",
1241 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1248 column_titles_changed(GtkWidget *w, gint first, gint n_columns, gpointer data)
1250 GtkSheet *sheet = GTK_SHEET(data);
1253 if(!GTK_SHEET_IS_FROZEN(sheet)){
1255 for ( i = first ; i <= MAX_VISIBLE_COLUMN(sheet) ; ++i )
1257 gtk_sheet_button_draw(sheet, -1, i);
1258 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, i);
1264 gtk_sheet_construct (GtkSheet *sheet,
1269 g_return_if_fail(G_IS_SHEET_COLUMN(hgeo));
1270 g_return_if_fail(G_IS_SHEET_ROW(vgeo));
1272 sheet->column_geometry = hgeo;
1273 sheet->row_geometry = vgeo;
1276 sheet->columns_resizable = TRUE;
1277 sheet->rows_resizable = TRUE;
1279 sheet->row_titles_visible = TRUE;
1280 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1282 sheet->column_titles_visible = TRUE;
1283 sheet->autoscroll = TRUE;
1284 sheet->justify_entry = TRUE;
1285 sheet->locked = FALSE;
1288 /* create sheet entry */
1289 sheet->entry_type = 0;
1290 create_sheet_entry (sheet);
1292 /* create global selection button */
1293 create_global_button(sheet);
1296 sheet->name = g_strdup(title);
1298 g_signal_connect(sheet->column_geometry, "columns_changed",
1299 G_CALLBACK(column_titles_changed), sheet);
1305 gtk_sheet_new_with_custom_entry (GSheetRow *rows, GSheetColumn *columns, const gchar *title,
1310 widget = gtk_type_new (gtk_sheet_get_type ());
1312 gtk_sheet_construct_with_custom_entry(GTK_SHEET(widget),
1313 rows, columns, title, entry_type);
1319 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet,
1325 gtk_sheet_construct(sheet, vgeo, hgeo, title);
1327 sheet->entry_type = entry_type;
1328 create_sheet_entry(sheet);
1334 gtk_sheet_change_entry(GtkSheet *sheet, GtkType entry_type)
1338 g_return_if_fail (sheet != NULL);
1339 g_return_if_fail (GTK_IS_SHEET (sheet));
1341 state = sheet->state;
1343 if(sheet->state == GTK_SHEET_NORMAL)
1344 gtk_sheet_hide_active_cell(sheet);
1346 sheet->entry_type = entry_type;
1348 create_sheet_entry(sheet);
1350 if(state == GTK_SHEET_NORMAL)
1352 gtk_sheet_show_active_cell(sheet);
1353 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
1355 G_CALLBACK(gtk_sheet_entry_changed),
1364 gtk_sheet_show_grid(GtkSheet *sheet, gboolean show)
1366 g_return_if_fail (sheet != NULL);
1367 g_return_if_fail (GTK_IS_SHEET (sheet));
1369 if(show == sheet->show_grid) return;
1371 sheet->show_grid = show;
1373 if(!GTK_SHEET_IS_FROZEN(sheet))
1374 gtk_sheet_range_draw(sheet, NULL);
1378 gtk_sheet_grid_visible(GtkSheet *sheet)
1380 g_return_val_if_fail (sheet != NULL, 0);
1381 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1383 return sheet->show_grid;
1387 gtk_sheet_set_background(GtkSheet *sheet, GdkColor *color)
1389 g_return_if_fail (sheet != NULL);
1390 g_return_if_fail (GTK_IS_SHEET (sheet));
1393 gdk_color_parse("white", &sheet->bg_color);
1394 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1396 sheet->bg_color = *color;
1398 if(!GTK_SHEET_IS_FROZEN(sheet))
1399 gtk_sheet_range_draw(sheet, NULL);
1403 gtk_sheet_set_grid(GtkSheet *sheet, GdkColor *color)
1405 g_return_if_fail (sheet != NULL);
1406 g_return_if_fail (GTK_IS_SHEET (sheet));
1409 gdk_color_parse("black", &sheet->grid_color);
1410 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1412 sheet->grid_color = *color;
1414 if(!GTK_SHEET_IS_FROZEN(sheet))
1415 gtk_sheet_range_draw(sheet, NULL);
1419 gtk_sheet_get_columns_count(GtkSheet *sheet)
1421 g_return_val_if_fail (sheet != NULL, 0);
1422 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1424 return xxx_column_count(sheet);
1428 gtk_sheet_get_rows_count(GtkSheet *sheet)
1430 g_return_val_if_fail (sheet != NULL, 0);
1431 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1433 return yyy_row_count(sheet);
1437 gtk_sheet_get_state(GtkSheet *sheet)
1439 g_return_val_if_fail (sheet != NULL, 0);
1440 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1442 return (sheet->state);
1446 gtk_sheet_set_selection_mode(GtkSheet *sheet, gint mode)
1448 g_return_if_fail (sheet != NULL);
1449 g_return_if_fail (GTK_IS_SHEET (sheet));
1451 if(GTK_WIDGET_REALIZED(sheet))
1452 gtk_sheet_real_unselect_range(sheet, NULL);
1454 sheet->selection_mode = mode;
1458 gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize)
1460 g_return_if_fail (sheet != NULL);
1461 g_return_if_fail (GTK_IS_SHEET (sheet));
1463 sheet->autoresize = autoresize;
1467 gtk_sheet_autoresize (GtkSheet *sheet)
1469 g_return_val_if_fail (sheet != NULL, FALSE);
1470 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1472 return sheet->autoresize;
1476 gtk_sheet_set_column_width (GtkSheet * sheet,
1482 gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
1484 gint text_width = 0;
1487 g_return_if_fail (sheet != NULL);
1488 g_return_if_fail (GTK_IS_SHEET (sheet));
1489 if (column >= xxx_column_count(sheet) || column < 0) return;
1491 for (row = 0; row < yyy_row_count(sheet); row++){
1492 const gchar *text = gtk_sheet_cell_get_text(sheet, row, column);
1493 if (text && strlen(text) > 0){
1494 GtkSheetCellAttr attributes;
1496 gtk_sheet_get_attributes(sheet, row, column, &attributes);
1497 if(attributes.is_visible){
1498 gint width = STRING_WIDTH(GTK_WIDGET(sheet),
1499 attributes.font_desc,
1501 + 2*CELLOFFSET + attributes.border.width;
1502 text_width = MAX (text_width, width);
1507 if(text_width > xxx_column_width(sheet, column) )
1509 gtk_sheet_set_column_width(sheet, column, text_width);
1510 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
1516 gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll)
1518 g_return_if_fail (sheet != NULL);
1519 g_return_if_fail (GTK_IS_SHEET (sheet));
1521 sheet->autoscroll = autoscroll;
1525 gtk_sheet_autoscroll (GtkSheet *sheet)
1527 g_return_val_if_fail (sheet != NULL, FALSE);
1528 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1530 return sheet->autoscroll;
1534 gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text)
1536 g_return_if_fail (sheet != NULL);
1537 g_return_if_fail (GTK_IS_SHEET (sheet));
1539 sheet->clip_text = clip_text;
1543 gtk_sheet_clip_text (GtkSheet *sheet)
1545 g_return_val_if_fail (sheet != NULL, FALSE);
1546 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1548 return sheet->clip_text;
1552 gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify)
1554 g_return_if_fail (sheet != NULL);
1555 g_return_if_fail (GTK_IS_SHEET (sheet));
1557 sheet->justify_entry = justify;
1561 gtk_sheet_justify_entry (GtkSheet *sheet)
1563 g_return_val_if_fail (sheet != NULL, FALSE);
1564 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1566 return sheet->justify_entry;
1570 gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked)
1572 g_return_if_fail (sheet != NULL);
1573 g_return_if_fail (GTK_IS_SHEET (sheet));
1575 sheet->locked = locked;
1579 gtk_sheet_locked (GtkSheet *sheet)
1581 g_return_val_if_fail (sheet != NULL, FALSE);
1582 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1584 return sheet->locked;
1587 /* This routine has problems with gtk+-1.2 related with the
1588 * label/button drawing - I think it's a bug in gtk+-1.2 */
1591 gtk_sheet_set_title(GtkSheet *sheet, const gchar *title)
1593 /* GtkWidget *old_widget;
1594 */ GtkWidget *label;
1596 g_return_if_fail (sheet != NULL);
1597 g_return_if_fail (title != NULL);
1598 g_return_if_fail (GTK_IS_SHEET (sheet));
1601 g_free (sheet->name);
1603 sheet->name = g_strdup (title);
1605 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) || !title) return;
1607 if(GTK_BIN(sheet->button)->child)
1608 label = GTK_BIN(sheet->button)->child;
1610 gtk_label_set_text(GTK_LABEL(label), title);
1612 size_allocate_global_button(sheet);
1614 /* remove and destroy the old widget */
1616 old_widget = GTK_BIN (sheet->button)->child;
1619 gtk_container_remove (GTK_CONTAINER (sheet->button), old_widget);
1622 label = gtk_label_new (title);
1623 gtk_misc_set_alignment(GTK_MISC(label), 0.5 , 0.5 );
1625 gtk_container_add (GTK_CONTAINER (sheet->button), label);
1626 gtk_widget_show (label);
1628 size_allocate_global_button(sheet);
1630 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, -1);
1633 gtk_widget_destroy (old_widget);
1638 gtk_sheet_freeze (GtkSheet *sheet)
1640 g_return_if_fail (sheet != NULL);
1641 g_return_if_fail (GTK_IS_SHEET (sheet));
1643 sheet->freeze_count++;
1644 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1648 gtk_sheet_thaw(GtkSheet *sheet)
1650 g_return_if_fail (sheet != NULL);
1651 g_return_if_fail (GTK_IS_SHEET (sheet));
1653 if(sheet->freeze_count == 0) return;
1655 sheet->freeze_count--;
1656 if(sheet->freeze_count > 0) return;
1658 adjust_scrollbars(sheet);
1660 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1662 sheet->old_vadjustment = -1.;
1663 sheet->old_hadjustment = -1.;
1665 if(sheet->hadjustment)
1666 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1668 if(sheet->vadjustment)
1669 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1672 if(sheet->state == GTK_STATE_NORMAL)
1673 if(sheet->sheet_entry && GTK_WIDGET_MAPPED(sheet->sheet_entry)){
1674 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
1676 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
1678 (GtkSignalFunc)gtk_sheet_entry_changed,
1679 GTK_OBJECT(GTK_WIDGET(sheet)));
1680 gtk_sheet_show_active_cell(sheet);
1687 gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width)
1689 if(width < COLUMN_MIN_WIDTH) return;
1691 sheet->row_title_area.width = width;
1692 sheet->view.col0 = COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
1693 sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
1696 adjust_scrollbars(sheet);
1698 sheet->old_hadjustment = -1.;
1699 if(sheet->hadjustment)
1700 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1702 size_allocate_global_button(sheet);
1706 gtk_sheet_set_column_titles_height(GtkSheet *sheet, guint height)
1708 if(height < DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))) return;
1710 sheet->column_title_area.height = height;
1711 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
1712 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
1714 adjust_scrollbars(sheet);
1716 sheet->old_vadjustment = -1.;
1717 if(sheet->vadjustment)
1718 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1720 size_allocate_global_button(sheet);
1724 gtk_sheet_show_column_titles(GtkSheet *sheet)
1728 if(sheet->column_titles_visible) return;
1730 sheet->column_titles_visible = TRUE;
1733 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1734 gdk_window_show(sheet->column_title_window);
1735 gdk_window_move_resize (sheet->column_title_window,
1736 sheet->column_title_area.x,
1737 sheet->column_title_area.y,
1738 sheet->column_title_area.width,
1739 sheet->column_title_area.height);
1741 for(col = MIN_VISIBLE_COLUMN(sheet);
1742 col <= MAX_VISIBLE_COLUMN(sheet);
1745 const GtkSheetButton *button = xxx_column_button(sheet, col);
1746 GtkSheetChild *child = button->child;
1748 gtk_sheet_child_show(child);
1750 adjust_scrollbars(sheet);
1753 sheet->old_vadjustment = -1.;
1754 if(sheet->vadjustment)
1755 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1757 size_allocate_global_button(sheet);
1762 gtk_sheet_show_row_titles(GtkSheet *sheet)
1766 if(sheet->row_titles_visible) return;
1768 sheet->row_titles_visible = TRUE;
1771 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1772 gdk_window_show(sheet->row_title_window);
1773 gdk_window_move_resize (sheet->row_title_window,
1774 sheet->row_title_area.x,
1775 sheet->row_title_area.y,
1776 sheet->row_title_area.width,
1777 sheet->row_title_area.height);
1779 for(row = MIN_VISIBLE_ROW(sheet);
1780 row <= MAX_VISIBLE_ROW(sheet);
1783 const GtkSheetButton *button = yyy_row_button(sheet, row);
1784 GtkSheetChild *child = button->child;
1787 gtk_sheet_child_show(child);
1790 adjust_scrollbars(sheet);
1793 sheet->old_hadjustment = -1.;
1794 if(sheet->hadjustment)
1795 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1797 size_allocate_global_button(sheet);
1801 gtk_sheet_hide_column_titles(GtkSheet *sheet)
1805 if(!sheet->column_titles_visible) return;
1807 sheet->column_titles_visible = FALSE;
1809 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1810 if(sheet->column_title_window)
1811 gdk_window_hide(sheet->column_title_window);
1812 if(GTK_WIDGET_VISIBLE(sheet->button))
1813 gtk_widget_hide(sheet->button);
1815 for(col = MIN_VISIBLE_COLUMN(sheet);
1816 col <= MAX_VISIBLE_COLUMN(sheet);
1819 const GtkSheetButton *button = xxx_column_button(sheet, col);
1820 GtkSheetChild *child = button->child;
1822 gtk_sheet_child_hide(child);
1824 adjust_scrollbars(sheet);
1827 sheet->old_vadjustment = -1.;
1828 if(sheet->vadjustment)
1829 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1834 gtk_sheet_hide_row_titles(GtkSheet *sheet)
1838 if(!sheet->row_titles_visible) return;
1840 sheet->row_titles_visible = FALSE;
1843 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1844 if(sheet->row_title_window)
1845 gdk_window_hide(sheet->row_title_window);
1846 if(GTK_WIDGET_VISIBLE(sheet->button))
1847 gtk_widget_hide(sheet->button);
1848 for(row = MIN_VISIBLE_ROW(sheet);
1849 row <= MAX_VISIBLE_ROW(sheet);
1852 const GtkSheetButton *button = yyy_row_button(sheet, row);
1853 GtkSheetChild *child = button->child;
1856 gtk_sheet_child_hide(child);
1858 adjust_scrollbars(sheet);
1861 sheet->old_hadjustment = -1.;
1862 if(sheet->hadjustment)
1863 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1868 gtk_sheet_column_titles_visible(GtkSheet *sheet)
1870 g_return_val_if_fail (sheet != NULL, FALSE);
1871 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1872 return sheet->column_titles_visible;
1876 gtk_sheet_row_titles_visible(GtkSheet *sheet)
1878 g_return_val_if_fail (sheet != NULL, FALSE);
1879 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1880 return sheet->row_titles_visible;
1886 gtk_sheet_moveto (GtkSheet * sheet,
1893 guint width, height;
1895 gint min_row, min_col;
1897 g_return_if_fail (sheet != NULL);
1898 g_return_if_fail (GTK_IS_SHEET (sheet));
1899 g_return_if_fail (sheet->hadjustment != NULL);
1900 g_return_if_fail (sheet->vadjustment != NULL);
1902 if (row < 0 || row >= yyy_row_count(sheet))
1904 if (column < 0 || column >= xxx_column_count(sheet))
1907 height = sheet->sheet_window_height;
1908 width = sheet->sheet_window_width;
1910 /* adjust vertical scrollbar */
1912 if (row >= 0 && row_align >=0.)
1915 y = ROW_TOP_YPIXEL(sheet, row) - sheet->voffset -
1917 (1.-row_align)*yyy_row_height(sheet, row);
1919 y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
1920 - (gint) ( row_align*height + (1. - row_align) * yyy_row_height(sheet, row));
1922 /* This forces the sheet to scroll when you don't see the entire cell */
1925 if(row_align == 1.){
1926 while(min_row >= 0 && min_row > MIN_VISIBLE_ROW(sheet)){
1927 if(yyy_row_is_visible(sheet, min_row))
1928 adjust += yyy_row_height(sheet, min_row);
1929 if(adjust >= height){
1934 min_row = MAX(min_row, 0);
1935 y = ROW_TOP_YPIXEL(sheet, min_row) - sheet->voffset +
1936 yyy_row_height(sheet, min_row) - 1;
1940 sheet->vadjustment->value = 0.0;
1942 sheet->vadjustment->value = y;
1944 sheet->old_vadjustment = -1.;
1945 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1950 /* adjust horizontal scrollbar */
1951 if (column >= 0 && col_align >= 0.)
1954 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset -
1956 (1.-col_align)*sheet->column[column].width;
1958 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
1959 - (gint) ( col_align*width + (1.-col_align)*
1960 xxx_column_width(sheet, column));
1963 /* This forces the sheet to scroll when you don't see the entire cell */
1966 if(col_align == 1.){
1967 while(min_col >= 0 && min_col > MIN_VISIBLE_COLUMN(sheet)){
1968 if(xxx_column_is_visible(sheet, min_col))
1969 adjust += xxx_column_width(sheet, min_col);
1971 if(adjust >= width){
1976 min_col = MAX(min_col, 0);
1977 x = COLUMN_LEFT_XPIXEL(sheet, min_col) - sheet->hoffset +
1978 xxx_column_width(sheet, min_col) - 1;
1982 sheet->hadjustment->value = 0.0;
1984 sheet->hadjustment->value = x;
1986 sheet->old_vadjustment = -1.;
1987 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1995 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
1997 g_return_if_fail (sheet != NULL);
1998 g_return_if_fail (GTK_IS_SHEET (sheet));
2000 sheet->columns_resizable = resizable;
2004 gtk_sheet_columns_resizable (GtkSheet *sheet)
2006 g_return_val_if_fail (sheet != NULL, FALSE);
2007 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2009 return sheet->columns_resizable;
2014 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
2016 g_return_if_fail (sheet != NULL);
2017 g_return_if_fail (GTK_IS_SHEET (sheet));
2019 sheet->rows_resizable = resizable;
2023 gtk_sheet_rows_resizable (GtkSheet *sheet)
2025 g_return_val_if_fail (sheet != NULL, FALSE);
2026 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2028 return sheet->rows_resizable;
2033 gtk_sheet_select_row (GtkSheet * sheet,
2036 g_return_if_fail (sheet != NULL);
2037 g_return_if_fail (GTK_IS_SHEET (sheet));
2039 if (row < 0 || row >= yyy_row_count(sheet))
2042 if(sheet->state != GTK_SHEET_NORMAL)
2043 gtk_sheet_real_unselect_range(sheet, NULL);
2046 gboolean veto = TRUE;
2047 veto = gtk_sheet_deactivate_cell(sheet);
2051 sheet->state=GTK_SHEET_ROW_SELECTED;
2052 sheet->range.row0=row;
2053 sheet->range.col0=0;
2054 sheet->range.rowi=row;
2055 sheet->range.coli = xxx_column_count(sheet) - 1;
2056 sheet->active_cell.row=row;
2057 sheet->active_cell.col=0;
2059 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_ROW], row);
2060 gtk_sheet_real_select_range(sheet, NULL);
2066 gtk_sheet_select_column (GtkSheet * sheet,
2070 g_return_if_fail (sheet != NULL);
2071 g_return_if_fail (GTK_IS_SHEET (sheet));
2073 if (column < 0 || column >= xxx_column_count(sheet))
2076 if(sheet->state != GTK_SHEET_NORMAL)
2077 gtk_sheet_real_unselect_range(sheet, NULL);
2080 gboolean veto = TRUE;
2081 veto = gtk_sheet_deactivate_cell(sheet);
2085 sheet->state=GTK_SHEET_COLUMN_SELECTED;
2086 sheet->range.row0=0;
2087 sheet->range.col0=column;
2088 sheet->range.rowi= yyy_row_count(sheet) - 1;
2089 sheet->range.coli=column;
2090 sheet->active_cell.row=0;
2091 sheet->active_cell.col=column;
2093 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_COLUMN], column);
2094 gtk_sheet_real_select_range(sheet, NULL);
2099 gtk_sheet_clip_range (GtkSheet *sheet, const GtkSheetRange *range)
2102 g_return_if_fail (sheet != NULL);
2103 g_return_if_fail (GTK_IS_SHEET (sheet));
2105 if(GTK_SHEET_IN_CLIP(sheet)) return;
2107 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2110 sheet->clip_range = sheet->range;
2112 sheet->clip_range=*range;
2115 sheet->clip_timer=gtk_timeout_add(TIMEOUT_FLASH, gtk_sheet_flash, sheet);
2117 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CLIP_RANGE],
2118 &sheet->clip_range);
2123 gtk_sheet_unclip_range(GtkSheet *sheet)
2126 g_return_if_fail (sheet != NULL);
2127 g_return_if_fail (GTK_IS_SHEET (sheet));
2129 if(!GTK_SHEET_IN_CLIP(sheet)) return;
2131 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2132 gtk_timeout_remove(sheet->clip_timer);
2133 gtk_sheet_range_draw(sheet, &sheet->clip_range);
2135 if(gtk_sheet_range_isvisible(sheet, sheet->range))
2136 gtk_sheet_range_draw(sheet, &sheet->range);
2140 gtk_sheet_in_clip (GtkSheet *sheet)
2142 g_return_val_if_fail (sheet != NULL, FALSE);
2143 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2145 return GTK_SHEET_IN_CLIP(sheet);
2149 gtk_sheet_flash(gpointer data)
2152 gint x,y,width,height;
2153 GdkRectangle clip_area;
2155 sheet=GTK_SHEET(data);
2157 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return TRUE;
2158 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return TRUE;
2159 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return TRUE;
2160 if(GTK_SHEET_IN_XDRAG(sheet)) return TRUE;
2161 if(GTK_SHEET_IN_YDRAG(sheet)) return TRUE;
2163 GDK_THREADS_ENTER();
2165 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2166 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2167 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2168 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2169 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2170 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2172 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2173 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2174 clip_area.width=sheet->sheet_window_width;
2175 clip_area.height=sheet->sheet_window_height;
2181 if(width>clip_area.width) width=clip_area.width+10;
2186 if(height>clip_area.height) height=clip_area.height+10;
2188 gdk_draw_pixmap(sheet->sheet_window,
2189 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2195 gdk_draw_pixmap(sheet->sheet_window,
2196 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2202 gdk_draw_pixmap(sheet->sheet_window,
2203 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2209 gdk_draw_pixmap(sheet->sheet_window,
2210 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2217 sheet->interval=sheet->interval+1;
2218 if(sheet->interval==TIME_INTERVAL) sheet->interval=0;
2220 gdk_gc_set_dashes(sheet->xor_gc, sheet->interval, (gint8*)"\4\4", 2);
2221 gtk_sheet_draw_flashing_range(sheet,sheet->clip_range);
2222 gdk_gc_set_dashes(sheet->xor_gc, 0, (gint8*)"\4\4", 2);
2224 GDK_THREADS_LEAVE();
2231 gtk_sheet_draw_flashing_range(GtkSheet *sheet, GtkSheetRange range)
2233 GdkRectangle clip_area;
2234 gint x,y,width,height;
2236 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return;
2238 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2239 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2240 clip_area.width=sheet->sheet_window_width;
2241 clip_area.height=sheet->sheet_window_height;
2243 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
2245 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2246 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2247 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2248 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2249 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2250 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2256 if(width>clip_area.width) width=clip_area.width+10;
2261 if(height>clip_area.height) height=clip_area.height+10;
2263 gdk_gc_set_line_attributes(sheet->xor_gc, 1, 1, 0 ,0 );
2265 gdk_draw_rectangle(sheet->sheet_window, sheet->xor_gc, FALSE,
2269 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 0, 0, 0);
2271 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
2276 gtk_sheet_range_isvisible (GtkSheet * sheet,
2277 GtkSheetRange range)
2279 g_return_val_if_fail (sheet != NULL, FALSE);
2281 if (range.row0 < 0 || range.row0 >= yyy_row_count(sheet))
2284 if (range.rowi < 0 || range.rowi >= yyy_row_count(sheet))
2287 if (range.col0 < 0 || range.col0 >= xxx_column_count(sheet))
2290 if (range.coli < 0 || range.coli >= xxx_column_count(sheet))
2293 if (range.rowi < MIN_VISIBLE_ROW (sheet))
2296 if (range.row0 > MAX_VISIBLE_ROW (sheet))
2299 if (range.coli < MIN_VISIBLE_COLUMN (sheet))
2302 if (range.col0 > MAX_VISIBLE_COLUMN (sheet))
2309 gtk_sheet_cell_isvisible (GtkSheet * sheet,
2310 gint row, gint column)
2312 GtkSheetRange range;
2315 range.col0 = column;
2317 range.coli = column;
2319 return gtk_sheet_range_isvisible(sheet, range);
2323 gtk_sheet_get_visible_range(GtkSheet *sheet, GtkSheetRange *range)
2326 g_return_if_fail (sheet != NULL);
2327 g_return_if_fail (GTK_IS_SHEET (sheet)) ;
2328 g_return_if_fail (range != NULL);
2330 range->row0 = MIN_VISIBLE_ROW(sheet);
2331 range->col0 = MIN_VISIBLE_COLUMN(sheet);
2332 range->rowi = MAX_VISIBLE_ROW(sheet);
2333 range->coli = MAX_VISIBLE_COLUMN(sheet);
2338 gtk_sheet_get_vadjustment (GtkSheet * sheet)
2340 g_return_val_if_fail (sheet != NULL, NULL);
2341 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2343 return sheet->vadjustment;
2347 gtk_sheet_get_hadjustment (GtkSheet * sheet)
2349 g_return_val_if_fail (sheet != NULL, NULL);
2350 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2352 return sheet->hadjustment;
2356 gtk_sheet_set_vadjustment (GtkSheet *sheet,
2357 GtkAdjustment *adjustment)
2359 GtkAdjustment *old_adjustment;
2361 g_return_if_fail (sheet != NULL);
2362 g_return_if_fail (GTK_IS_SHEET (sheet));
2364 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2366 if (sheet->vadjustment == adjustment)
2369 old_adjustment = sheet->vadjustment;
2371 if (sheet->vadjustment)
2373 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2374 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2377 sheet->vadjustment = adjustment;
2379 if (sheet->vadjustment)
2381 gtk_object_ref (GTK_OBJECT (sheet->vadjustment));
2382 gtk_object_sink (GTK_OBJECT (sheet->vadjustment));
2384 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "changed",
2385 (GtkSignalFunc) vadjustment_changed,
2387 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "value_changed",
2388 (GtkSignalFunc) vadjustment_value_changed,
2392 if (!sheet->vadjustment || !old_adjustment)
2394 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2398 sheet->old_vadjustment = sheet->vadjustment->value;
2402 gtk_sheet_set_hadjustment (GtkSheet *sheet,
2403 GtkAdjustment *adjustment)
2405 GtkAdjustment *old_adjustment;
2407 g_return_if_fail (sheet != NULL);
2408 g_return_if_fail (GTK_IS_SHEET (sheet));
2410 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2412 if (sheet->hadjustment == adjustment)
2415 old_adjustment = sheet->hadjustment;
2417 if (sheet->hadjustment)
2419 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2420 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2423 sheet->hadjustment = adjustment;
2425 if (sheet->hadjustment)
2427 gtk_object_ref (GTK_OBJECT (sheet->hadjustment));
2428 gtk_object_sink (GTK_OBJECT (sheet->hadjustment));
2430 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "changed",
2431 (GtkSignalFunc) hadjustment_changed,
2433 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "value_changed",
2434 (GtkSignalFunc) hadjustment_value_changed,
2438 if (!sheet->hadjustment || !old_adjustment)
2440 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2444 sheet->old_hadjustment = sheet->hadjustment->value;
2448 gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
2449 GtkAdjustment *hadjustment,
2450 GtkAdjustment *vadjustment)
2452 if(sheet->hadjustment != hadjustment)
2453 gtk_sheet_set_hadjustment (sheet, hadjustment);
2454 if(sheet->vadjustment != vadjustment)
2455 gtk_sheet_set_vadjustment (sheet, vadjustment);
2459 gtk_sheet_finalize (GObject * object)
2463 g_return_if_fail (object != NULL);
2464 g_return_if_fail (GTK_IS_SHEET (object));
2466 sheet = GTK_SHEET (object);
2468 /* get rid of all the cells */
2469 gtk_sheet_range_clear (sheet, NULL);
2470 gtk_sheet_range_delete(sheet, NULL);
2473 g_free(sheet->name);
2477 if (G_OBJECT_CLASS (parent_class)->finalize)
2478 (*G_OBJECT_CLASS (parent_class)->finalize) (object);
2482 gtk_sheet_destroy (GtkObject * object)
2487 g_return_if_fail (object != NULL);
2488 g_return_if_fail (GTK_IS_SHEET (object));
2490 sheet = GTK_SHEET (object);
2492 /* destroy the entry */
2493 if(sheet->sheet_entry && GTK_IS_WIDGET(sheet->sheet_entry)){
2494 gtk_widget_destroy (sheet->sheet_entry);
2495 sheet->sheet_entry = NULL;
2498 /* destroy the global selection button */
2499 if(sheet->button && GTK_IS_WIDGET(sheet->button)){
2500 gtk_widget_destroy (sheet->button);
2501 sheet->button = NULL;
2505 gtk_timeout_remove(sheet->timer);
2509 if(sheet->clip_timer){
2510 gtk_timeout_remove(sheet->clip_timer);
2511 sheet->clip_timer = 0;
2514 /* unref adjustments */
2515 if (sheet->hadjustment)
2517 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2518 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2519 sheet->hadjustment = NULL;
2521 if (sheet->vadjustment)
2523 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2524 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2525 sheet->vadjustment = NULL;
2528 children = sheet->children;
2530 GtkSheetChild *child = (GtkSheetChild *)children->data;
2531 if(child && child->widget)
2532 gtk_sheet_remove(GTK_CONTAINER(sheet), child->widget);
2533 children = sheet->children;
2535 sheet->children = NULL;
2537 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2538 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2542 gtk_sheet_style_set (GtkWidget *widget,
2543 GtkStyle *previous_style)
2547 g_return_if_fail (widget != NULL);
2548 g_return_if_fail (GTK_IS_SHEET (widget));
2550 if (GTK_WIDGET_CLASS (parent_class)->style_set)
2551 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
2553 sheet = GTK_SHEET (widget);
2555 if(GTK_WIDGET_REALIZED(widget))
2557 gtk_style_set_background (widget->style, widget->window, widget->state);
2563 gtk_sheet_realize (GtkWidget * widget)
2566 GdkWindowAttr attributes;
2567 gint attributes_mask;
2568 GdkGCValues values, auxvalues;
2569 GdkColormap *colormap;
2571 GtkSheetChild *child;
2574 g_return_if_fail (widget != NULL);
2575 g_return_if_fail (GTK_IS_SHEET (widget));
2577 sheet = GTK_SHEET (widget);
2579 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2581 attributes.window_type = GDK_WINDOW_CHILD;
2582 attributes.x = widget->allocation.x;
2583 attributes.y = widget->allocation.y;
2584 attributes.width = widget->allocation.width;
2585 attributes.height = widget->allocation.height;
2586 attributes.wclass = GDK_INPUT_OUTPUT;
2588 attributes.visual = gtk_widget_get_visual (widget);
2589 attributes.colormap = gtk_widget_get_colormap (widget);
2591 attributes.event_mask = gtk_widget_get_events (widget);
2592 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2593 GDK_BUTTON_PRESS_MASK |
2594 GDK_BUTTON_RELEASE_MASK |
2595 GDK_KEY_PRESS_MASK |
2596 GDK_POINTER_MOTION_MASK |
2597 GDK_POINTER_MOTION_HINT_MASK);
2598 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
2601 attributes.cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
2604 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2606 gdk_window_set_user_data (widget->window, sheet);
2608 widget->style = gtk_style_attach (widget->style, widget->window);
2610 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2613 if(sheet->row_titles_visible)
2614 attributes.x = sheet->row_title_area.width;
2616 attributes.width = sheet->column_title_area.width;
2617 attributes.height = sheet->column_title_area.height;
2619 /* column-title window */
2620 sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2621 gdk_window_set_user_data (sheet->column_title_window, sheet);
2622 gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL);
2626 if(sheet->column_titles_visible)
2627 attributes.y = sheet->column_title_area.height;
2628 attributes.width = sheet->row_title_area.width;
2629 attributes.height = sheet->row_title_area.height;
2631 /* row-title window */
2632 sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2633 gdk_window_set_user_data (sheet->row_title_window, sheet);
2634 gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL);
2637 attributes.cursor = gdk_cursor_new(GDK_PLUS);
2641 attributes.width = sheet->sheet_window_width,
2642 attributes.height = sheet->sheet_window_height;
2644 sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2645 gdk_window_set_user_data (sheet->sheet_window, sheet);
2647 gdk_cursor_unref(attributes.cursor);
2649 gdk_window_set_background (sheet->sheet_window, &widget->style->white);
2650 gdk_window_show (sheet->sheet_window);
2652 /* backing_pixmap */
2653 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
2657 gdk_gc_unref(sheet->fg_gc);
2659 gdk_gc_unref(sheet->bg_gc);
2660 sheet->fg_gc = gdk_gc_new (widget->window);
2661 sheet->bg_gc = gdk_gc_new (widget->window);
2663 colormap = gtk_widget_get_colormap(widget);
2665 gdk_color_white(colormap, &widget->style->white);
2666 gdk_color_black(colormap, &widget->style->black);
2668 gdk_gc_get_values(sheet->fg_gc, &auxvalues);
2670 values.foreground = widget->style->white;
2671 values.function = GDK_INVERT;
2672 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2674 gdk_gc_unref(sheet->xor_gc);
2675 sheet->xor_gc = gdk_gc_new_with_values (widget->window,
2681 if(sheet->sheet_entry->parent){
2682 gtk_widget_ref(sheet->sheet_entry);
2683 gtk_widget_unparent(sheet->sheet_entry);
2685 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
2686 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
2688 if(sheet->button && sheet->button->parent){
2689 gtk_widget_ref(sheet->button);
2690 gtk_widget_unparent(sheet->button);
2692 gtk_widget_set_parent_window(sheet->button, sheet->sheet_window);
2693 gtk_widget_set_parent(sheet->button, GTK_WIDGET(sheet));
2696 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
2698 if(!sheet->cursor_drag)
2699 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
2701 if(sheet->column_titles_visible)
2702 gdk_window_show(sheet->column_title_window);
2703 if(sheet->row_titles_visible)
2704 gdk_window_show(sheet->row_title_window);
2706 size_allocate_row_title_buttons(sheet);
2707 size_allocate_column_title_buttons(sheet);
2709 name = g_strdup(sheet->name);
2710 gtk_sheet_set_title(sheet, name);
2714 children = sheet->children;
2717 child = children->data;
2718 children = children->next;
2720 gtk_sheet_realize_child(sheet, child);
2725 create_global_button(GtkSheet *sheet)
2727 sheet->button = gtk_button_new_with_label(" ");
2729 gtk_signal_connect (GTK_OBJECT (sheet->button),
2731 (GtkSignalFunc) global_button_clicked,
2736 size_allocate_global_button(GtkSheet *sheet)
2738 GtkAllocation allocation;
2740 if(!sheet->column_titles_visible) return;
2741 if(!sheet->row_titles_visible) return;
2743 gtk_widget_size_request(sheet->button, NULL);
2747 allocation.width=sheet->row_title_area.width;
2748 allocation.height=sheet->column_title_area.height;
2750 gtk_widget_size_allocate(sheet->button, &allocation);
2751 gtk_widget_show(sheet->button);
2755 global_button_clicked(GtkWidget *widget, gpointer data)
2759 gtk_sheet_click_cell(GTK_SHEET(data), -1, -1, &veto);
2760 gtk_widget_grab_focus(GTK_WIDGET(data));
2765 gtk_sheet_unrealize (GtkWidget * widget)
2769 g_return_if_fail (widget != NULL);
2770 g_return_if_fail (GTK_IS_SHEET (widget));
2772 sheet = GTK_SHEET (widget);
2774 gdk_cursor_destroy (sheet->cursor_drag);
2776 gdk_gc_destroy (sheet->xor_gc);
2777 gdk_gc_destroy (sheet->fg_gc);
2778 gdk_gc_destroy (sheet->bg_gc);
2780 gdk_window_destroy (sheet->sheet_window);
2781 gdk_window_destroy (sheet->column_title_window);
2782 gdk_window_destroy (sheet->row_title_window);
2785 g_free (sheet->pixmap);
2786 sheet->pixmap = NULL;
2789 sheet->column_title_window=NULL;
2790 sheet->sheet_window = NULL;
2791 sheet->cursor_drag = NULL;
2792 sheet->xor_gc = NULL;
2793 sheet->fg_gc = NULL;
2794 sheet->bg_gc = NULL;
2796 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2797 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2801 gtk_sheet_map (GtkWidget * widget)
2804 GtkSheetChild *child;
2807 g_return_if_fail (widget != NULL);
2808 g_return_if_fail (GTK_IS_SHEET (widget));
2810 sheet = GTK_SHEET (widget);
2812 if (!GTK_WIDGET_MAPPED (widget))
2814 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2816 if(!sheet->cursor_drag) sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
2818 gdk_window_show (widget->window);
2820 gdk_window_show (sheet->sheet_window);
2822 if(sheet->column_titles_visible){
2823 size_allocate_column_title_buttons(sheet);
2824 gdk_window_show (sheet->column_title_window);
2826 if(sheet->row_titles_visible){
2827 size_allocate_row_title_buttons(sheet);
2828 gdk_window_show (sheet->row_title_window);
2831 if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)){
2832 gtk_widget_show (sheet->sheet_entry);
2833 gtk_widget_map (sheet->sheet_entry);
2836 if (GTK_WIDGET_VISIBLE (sheet->button) &&
2837 !GTK_WIDGET_MAPPED (sheet->button)){
2838 gtk_widget_show(sheet->button);
2839 gtk_widget_map (sheet->button);
2842 if(GTK_BIN(sheet->button)->child)
2843 if (GTK_WIDGET_VISIBLE (GTK_BIN(sheet->button)->child) &&
2844 !GTK_WIDGET_MAPPED (GTK_BIN(sheet->button)->child))
2845 gtk_widget_map (GTK_BIN(sheet->button)->child);
2847 gtk_sheet_range_draw(sheet, NULL);
2848 gtk_sheet_activate_cell(sheet,
2849 sheet->active_cell.row,
2850 sheet->active_cell.col);
2852 children = sheet->children;
2855 child = children->data;
2856 children = children->next;
2858 if (GTK_WIDGET_VISIBLE (child->widget) &&
2859 !GTK_WIDGET_MAPPED (child->widget)){
2860 gtk_widget_map (child->widget);
2861 gtk_sheet_position_child(sheet, child);
2869 gtk_sheet_unmap (GtkWidget * widget)
2872 GtkSheetChild *child;
2875 g_return_if_fail (widget != NULL);
2876 g_return_if_fail (GTK_IS_SHEET (widget));
2878 sheet = GTK_SHEET (widget);
2880 if (GTK_WIDGET_MAPPED (widget))
2882 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2884 gdk_window_hide (sheet->sheet_window);
2885 if(sheet->column_titles_visible)
2886 gdk_window_hide (sheet->column_title_window);
2887 if(sheet->row_titles_visible)
2888 gdk_window_hide (sheet->row_title_window);
2889 gdk_window_hide (widget->window);
2891 if (GTK_WIDGET_MAPPED (sheet->sheet_entry))
2892 gtk_widget_unmap (sheet->sheet_entry);
2894 if (GTK_WIDGET_MAPPED (sheet->button))
2895 gtk_widget_unmap (sheet->button);
2897 children = sheet->children;
2900 child = children->data;
2901 children = children->next;
2903 if (GTK_WIDGET_VISIBLE (child->widget) &&
2904 GTK_WIDGET_MAPPED (child->widget))
2906 gtk_widget_unmap (child->widget);
2915 gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
2918 GdkGC *fg_gc, *bg_gc;
2919 GtkSheetCellAttr attributes;
2922 g_return_if_fail (sheet != NULL);
2924 /* bail now if we arn't drawable yet */
2925 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
2927 if (row < 0 || row >= yyy_row_count(sheet)) return;
2928 if (col < 0 || col >= xxx_column_count(sheet)) return;
2929 if (! xxx_column_is_visible(sheet, col)) return;
2930 if (! yyy_row_is_visible(sheet, row)) return;
2932 widget = GTK_WIDGET (sheet);
2934 gtk_sheet_get_attributes(sheet, row, col, &attributes);
2936 /* select GC for background rectangle */
2937 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
2938 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
2940 fg_gc = sheet->fg_gc;
2941 bg_gc = sheet->bg_gc;
2943 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
2944 area.y=ROW_TOP_YPIXEL(sheet,row);
2945 area.width= xxx_column_width(sheet, col);
2946 area.height=yyy_row_height(sheet, row);
2948 gdk_draw_rectangle (sheet->pixmap,
2956 gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0);
2958 if(sheet->show_grid){
2959 gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color);
2961 gdk_draw_rectangle (sheet->pixmap,
2965 area.width, area.height);
2970 gtk_sheet_cell_draw_border (GtkSheet *sheet, gint row, gint col, gint mask)
2973 GdkGC *fg_gc, *bg_gc;
2974 GtkSheetCellAttr attributes;
2978 g_return_if_fail (sheet != NULL);
2980 /* bail now if we arn't drawable yet */
2981 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
2983 if (row < 0 || row >= yyy_row_count(sheet)) return;
2984 if (col < 0 || col >= xxx_column_count(sheet)) return;
2985 if (!xxx_column_is_visible(sheet, col)) return;
2986 if (!yyy_row_is_visible(sheet, row)) return;
2988 widget = GTK_WIDGET (sheet);
2990 gtk_sheet_get_attributes(sheet, row, col, &attributes);
2992 /* select GC for background rectangle */
2993 gdk_gc_set_foreground (sheet->fg_gc, &attributes.border.color);
2994 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
2996 fg_gc = sheet->fg_gc;
2997 bg_gc = sheet->bg_gc;
2999 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3000 area.y=ROW_TOP_YPIXEL(sheet,row);
3001 area.width=xxx_column_width(sheet, col);
3002 area.height=yyy_row_height(sheet, row);
3004 width = attributes.border.width;
3005 gdk_gc_set_line_attributes(sheet->fg_gc, attributes.border.width,
3006 attributes.border.line_style,
3007 attributes.border.cap_style,
3008 attributes.border.join_style);
3011 if(attributes.border.mask & GTK_SHEET_LEFT_BORDER & mask)
3012 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3013 area.x, area.y-width/2,
3014 area.x, area.y+area.height+width/2+1);
3016 if(attributes.border.mask & GTK_SHEET_RIGHT_BORDER & mask)
3017 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3018 area.x+area.width, area.y-width/2,
3020 area.y+area.height+width/2+1);
3022 if(attributes.border.mask & GTK_SHEET_TOP_BORDER & mask)
3023 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3024 area.x-width/2,area.y,
3025 area.x+area.width+width/2+1,
3028 if(attributes.border.mask & GTK_SHEET_BOTTOM_BORDER & mask)
3029 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3030 area.x-width/2, area.y+area.height,
3031 area.x+area.width+width/2+1,
3032 area.y+area.height);
3039 gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
3042 GdkRectangle area, clip_area;
3044 gint text_width, text_height, y;
3046 gint size, sizel, sizer;
3047 GdkGC *fg_gc, *bg_gc;
3048 GtkSheetCellAttr attributes;
3049 PangoLayout *layout;
3050 PangoRectangle rect;
3051 PangoRectangle logical_rect;
3052 PangoLayoutLine *line;
3053 PangoFontMetrics *metrics;
3054 PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet));
3055 gint ascent, descent, y_pos;
3059 g_return_if_fail (sheet != NULL);
3061 /* bail now if we aren't drawable yet */
3062 if (!GTK_WIDGET_DRAWABLE (sheet))
3065 label = gtk_sheet_cell_get_text(sheet, row, col);
3069 if (row < 0 || row >= yyy_row_count(sheet)) return;
3070 if (col < 0 || col >= xxx_column_count(sheet)) return;
3071 if (! xxx_column_is_visible(sheet, col)) return;
3072 if (!yyy_row_is_visible(sheet, row)) return;
3075 widget = GTK_WIDGET(sheet);
3077 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3079 /* select GC for background rectangle */
3080 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3081 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3083 fg_gc = sheet->fg_gc;
3084 bg_gc = sheet->bg_gc;
3086 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3087 area.y=ROW_TOP_YPIXEL(sheet,row);
3088 area.width = xxx_column_width(sheet, col);
3089 area.height = yyy_row_height(sheet, row);
3093 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label);
3094 pango_layout_set_font_description (layout, attributes.font_desc);
3096 pango_layout_get_pixel_extents (layout, NULL, &rect);
3098 line = pango_layout_get_lines (layout)->data;
3099 pango_layout_line_get_extents (line, NULL, &logical_rect);
3101 metrics = pango_context_get_metrics(context,
3102 attributes.font_desc,
3103 pango_context_get_language(context));
3105 ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
3106 descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
3108 pango_font_metrics_unref(metrics);
3110 /* Align primarily for locale's ascent/descent */
3112 logical_rect.height /= PANGO_SCALE;
3113 logical_rect.y /= PANGO_SCALE;
3114 y_pos = area.height - logical_rect.height;
3116 if (logical_rect.height > area.height)
3117 y_pos = (logical_rect.height - area.height - 2*CELLOFFSET) / 2;
3120 else if (y_pos + logical_rect.height > area.height)
3121 y_pos = area.height - logical_rect.height;
3123 text_width = rect.width;
3124 text_height = rect.height;
3125 y = area.y + y_pos - CELLOFFSET;
3127 switch(attributes.justification){
3128 case GTK_JUSTIFY_RIGHT:
3131 if(!gtk_sheet_clip_text(sheet)){
3132 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3133 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
3134 if(size>=text_width+CELLOFFSET) break;
3135 size+=xxx_column_width(sheet, i);
3136 xxx_column_set_right_column(sheet, i,
3138 xxx_column_right_column(sheet, i)));
3143 xoffset+=area.width-text_width - 2 * CELLOFFSET -
3144 attributes.border.width/2;
3146 case GTK_JUSTIFY_CENTER:
3149 area.x+=area.width/2;
3150 if(!gtk_sheet_clip_text(sheet)){
3151 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3152 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
3153 if(sizer>=text_width/2) break;
3154 sizer+= xxx_column_width(sheet, i);
3155 xxx_column_set_left_column(sheet, i,
3158 xxx_column_left_column(sheet, i)));
3160 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3161 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
3162 if(sizel>=text_width/2) break;
3163 sizel+=xxx_column_width(sheet, i);
3164 xxx_column_set_right_column(sheet, i,
3166 xxx_column_right_column(sheet, i)));
3168 size=MIN(sizel, sizer);
3171 xoffset+= sizel - text_width/2 - CELLOFFSET;
3172 area.width=sizel+sizer;
3174 case GTK_JUSTIFY_LEFT:
3177 if(!gtk_sheet_clip_text(sheet)){
3178 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3179 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
3180 if(size>=text_width+CELLOFFSET) break;
3181 size+=xxx_column_width(sheet, i);
3182 xxx_column_set_left_column(sheet, i,
3185 xxx_column_left_column(sheet, i)));
3190 xoffset += attributes.border.width/2;
3194 if(!gtk_sheet_clip_text(sheet)) clip_area = area;
3195 gdk_gc_set_clip_rectangle(fg_gc, &clip_area);
3198 gdk_draw_layout (sheet->pixmap, fg_gc,
3199 area.x + xoffset + CELLOFFSET,
3203 gdk_gc_set_clip_rectangle(fg_gc, NULL);
3204 g_object_unref(G_OBJECT(layout));
3206 gdk_draw_pixmap(sheet->sheet_window,
3207 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3221 gtk_sheet_range_draw(GtkSheet *sheet, const GtkSheetRange *range)
3224 GtkSheetRange drawing_range;
3227 g_return_if_fail(sheet != NULL);
3228 g_return_if_fail(GTK_SHEET(sheet));
3230 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
3231 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3232 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
3236 drawing_range.row0=MIN_VISIBLE_ROW(sheet);
3237 drawing_range.col0=MIN_VISIBLE_COLUMN(sheet);
3238 drawing_range.rowi=MAX_VISIBLE_ROW(sheet);
3239 drawing_range.coli=MAX_VISIBLE_COLUMN(sheet);
3241 gdk_draw_rectangle (sheet->pixmap,
3242 GTK_WIDGET(sheet)->style->white_gc,
3245 sheet->sheet_window_width,sheet->sheet_window_height);
3250 drawing_range.row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
3251 drawing_range.col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
3252 drawing_range.rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
3253 drawing_range.coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
3257 if(drawing_range.coli == xxx_column_count(sheet) - 1)
3259 area.x=COLUMN_LEFT_XPIXEL(sheet,
3260 xxx_column_count(sheet) - 1) +
3261 xxx_column_width(sheet, xxx_column_count(sheet) - 1) + 1;
3265 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3267 gdk_draw_rectangle (sheet->pixmap,
3271 sheet->sheet_window_width - area.x,
3272 sheet->sheet_window_height);
3274 gdk_draw_pixmap(sheet->sheet_window,
3275 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3281 sheet->sheet_window_width - area.x,
3282 sheet->sheet_window_height);
3285 if(drawing_range.rowi == yyy_row_count(sheet) - 1){
3287 area.y=ROW_TOP_YPIXEL(sheet,
3288 yyy_row_count(sheet) - 1) +
3289 yyy_row_height(sheet, yyy_row_count(sheet) - 1) + 1;
3291 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3293 gdk_draw_rectangle (sheet->pixmap,
3297 sheet->sheet_window_width,
3298 sheet->sheet_window_height - area.y);
3300 gdk_draw_pixmap(sheet->sheet_window,
3301 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3307 sheet->sheet_window_width,
3308 sheet->sheet_window_height - area.y);
3311 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3312 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3313 gtk_sheet_cell_draw_default(sheet, i, j);
3316 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3317 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3318 gtk_sheet_cell_draw_border(sheet, i-1, j, GTK_SHEET_BOTTOM_BORDER);
3319 gtk_sheet_cell_draw_border(sheet, i+1, j, GTK_SHEET_TOP_BORDER);
3320 gtk_sheet_cell_draw_border(sheet, i, j-1, GTK_SHEET_RIGHT_BORDER);
3321 gtk_sheet_cell_draw_border(sheet, i, j+1, GTK_SHEET_LEFT_BORDER);
3322 gtk_sheet_cell_draw_border(sheet, i, j, 15);
3325 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3326 for(j=drawing_range.col0; j<=drawing_range.coli; j++)
3327 gtk_sheet_cell_draw_label (sheet, i, j);
3329 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3330 for(j= xxx_column_left_column(sheet, drawing_range.col0);
3331 j<drawing_range.col0; j++)
3332 gtk_sheet_cell_draw_label (sheet, i, j);
3334 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3335 for(j = drawing_range.coli+1;
3336 j <= xxx_column_right_column(sheet, drawing_range.coli);
3338 gtk_sheet_cell_draw_label (sheet, i, j);
3340 gtk_sheet_draw_backing_pixmap(sheet, drawing_range);
3342 if(sheet->state != GTK_SHEET_NORMAL && gtk_sheet_range_isvisible(sheet, sheet->range))
3343 gtk_sheet_range_draw_selection(sheet, drawing_range);
3345 if(sheet->state == GTK_STATE_NORMAL &&
3346 sheet->active_cell.row >= drawing_range.row0 &&
3347 sheet->active_cell.row <= drawing_range.rowi &&
3348 sheet->active_cell.col >= drawing_range.col0 &&
3349 sheet->active_cell.col <= drawing_range.coli)
3350 gtk_sheet_show_active_cell(sheet);
3355 gtk_sheet_range_draw_selection(GtkSheet *sheet, GtkSheetRange range)
3361 if(range.col0 > sheet->range.coli || range.coli < sheet->range.col0 ||
3362 range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0)
3365 if(!gtk_sheet_range_isvisible(sheet, range)) return;
3366 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3370 range.col0=MAX(sheet->range.col0, range.col0);
3371 range.coli=MIN(sheet->range.coli, range.coli);
3372 range.row0=MAX(sheet->range.row0, range.row0);
3373 range.rowi=MIN(sheet->range.rowi, range.rowi);
3375 range.col0=MAX(range.col0, MIN_VISIBLE_COLUMN(sheet));
3376 range.coli=MIN(range.coli, MAX_VISIBLE_COLUMN(sheet));
3377 range.row0=MAX(range.row0, MIN_VISIBLE_ROW(sheet));
3378 range.rowi=MIN(range.rowi, MAX_VISIBLE_ROW(sheet));
3380 for(i=range.row0; i<=range.rowi; i++){
3381 for(j=range.col0; j<=range.coli; j++){
3383 if(gtk_sheet_cell_get_state(sheet, i, j)==GTK_STATE_SELECTED &&
3384 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
3387 row_button_set(sheet, i);
3388 column_button_set(sheet, j);
3391 area.x=COLUMN_LEFT_XPIXEL(sheet,j);
3392 area.y=ROW_TOP_YPIXEL(sheet,i);
3393 area.width= xxx_column_width(sheet, j);
3394 area.height=yyy_row_height(sheet, i);
3396 if(i==sheet->range.row0){
3398 area.height=area.height-2;
3400 if(i==sheet->range.rowi) area.height=area.height-3;
3401 if(j==sheet->range.col0){
3403 area.width=area.width-2;
3405 if(j==sheet->range.coli) area.width=area.width-3;
3407 if(i!=sheet->active_cell.row || j!=sheet->active_cell.col){
3408 gdk_draw_rectangle (sheet->sheet_window,
3412 area.width,area.height);
3419 gtk_sheet_draw_border(sheet, sheet->range);
3424 gtk_sheet_draw_backing_pixmap(GtkSheet *sheet, GtkSheetRange range)
3426 gint x,y,width,height;
3428 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3430 x = COLUMN_LEFT_XPIXEL(sheet,range.col0);
3431 y = ROW_TOP_YPIXEL(sheet, range.row0);
3432 width = COLUMN_LEFT_XPIXEL(sheet, range.coli) - x +
3433 xxx_column_width(sheet, range.coli);
3435 height=ROW_TOP_YPIXEL(sheet, range.rowi)-y+yyy_row_height(sheet, range.rowi);
3437 if(range.row0==sheet->range.row0){
3441 if(range.rowi==sheet->range.rowi) height=height+5;
3442 if(range.col0==sheet->range.col0){
3446 if(range.coli==sheet->range.coli) width=width+5;
3449 width=MIN(width, sheet->sheet_window_width-x);
3450 height=MIN(height, sheet->sheet_window_height-y);
3457 x = (sheet->row_titles_visible)
3458 ? MAX(x, sheet->row_title_area.width) : MAX(x, 0);
3459 y = (sheet->column_titles_visible)
3460 ? MAX(y, sheet->column_title_area.height) : MAX(y, 0);
3462 if(range.coli == xxx_column_count(sheet) - 1)
3463 width = sheet->sheet_window_width - x;
3464 if(range.rowi == yyy_row_count(sheet) - 1)
3465 height=sheet->sheet_window_height - y;
3467 gdk_draw_pixmap(sheet->sheet_window,
3468 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3480 gtk_sheet_set_cell_text(GtkSheet *sheet, gint row, gint col, const gchar *text)
3482 GtkSheetCellAttr attributes;
3484 g_return_if_fail (sheet != NULL);
3485 g_return_if_fail (GTK_IS_SHEET (sheet));
3486 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3487 if (col < 0 || row < 0) return;
3489 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3490 gtk_sheet_set_cell(sheet, row, col, attributes.justification, text);
3494 safe_strcmp(const gchar *s1, const gchar *s2)
3496 if ( !s1 && !s2) return 0;
3497 if ( !s1) return -1;
3498 if ( !s2) return +1;
3499 return strcmp(s1, s2);
3503 gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col,
3504 GtkJustification justification,
3507 GSheetModel *model ;
3509 const gchar *old_text ;
3511 GtkSheetRange range;
3513 GtkSheetCellAttr attributes;
3515 g_return_if_fail (sheet != NULL);
3516 g_return_if_fail (GTK_IS_SHEET (sheet));
3517 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3518 if (col < 0 || row < 0) return;
3520 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3522 attributes.justification = justification;
3524 model = gtk_sheet_get_model(sheet);
3526 old_text = g_sheet_model_get_string(model, row, col);
3530 if (0 != safe_strcmp(old_text, text))
3531 changed = g_sheet_model_set_string(model, text, row, col);
3533 if(changed && attributes.is_visible)
3535 const gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
3537 if(s && strlen(s) > 0) {
3538 text_width = STRING_WIDTH(GTK_WIDGET(sheet),
3539 attributes.font_desc, text);
3544 range.col0 = sheet->view.col0;
3545 range.coli = sheet->view.coli;
3547 if(gtk_sheet_autoresize(sheet) &&
3548 text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
3549 gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width);
3550 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3553 if(!GTK_SHEET_IS_FROZEN(sheet))
3554 gtk_sheet_range_draw(sheet, &range);
3558 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
3564 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
3566 GtkSheetRange range;
3568 g_return_if_fail (sheet != NULL);
3569 g_return_if_fail (GTK_IS_SHEET (sheet));
3570 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3571 if (column < 0 || row < 0) return;
3575 range.col0 = sheet->view.col0;
3576 range.coli = sheet->view.coli;
3578 gtk_sheet_real_cell_clear(sheet, row, column, FALSE);
3580 if(!GTK_SHEET_IS_FROZEN(sheet)){
3581 gtk_sheet_range_draw(sheet, &range);
3586 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
3588 GtkSheetRange range;
3590 g_return_if_fail (sheet != NULL);
3591 g_return_if_fail (GTK_IS_SHEET (sheet));
3592 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3593 if (column < 0 || row < 0) return;
3597 range.col0 = sheet->view.col0;
3598 range.coli = sheet->view.coli;
3600 gtk_sheet_real_cell_clear(sheet, row, column, TRUE);
3602 if(!GTK_SHEET_IS_FROZEN(sheet)){
3603 gtk_sheet_range_draw(sheet, &range);
3608 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
3610 GSheetModel *model = gtk_sheet_get_model(sheet);
3612 const gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column);
3614 if (old_text && strlen(old_text) > 0 )
3616 g_sheet_model_datum_clear(model, row, column);
3618 if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0)
3619 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL],
3626 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
3628 g_return_if_fail (sheet != NULL);
3629 g_return_if_fail (GTK_IS_SHEET (sheet));
3631 gtk_sheet_real_range_clear(sheet, range, FALSE);
3635 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range)
3637 g_return_if_fail (sheet != NULL);
3638 g_return_if_fail (GTK_IS_SHEET (sheet));
3640 gtk_sheet_real_range_clear(sheet, range, TRUE);
3645 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
3649 GtkSheetRange clear;
3653 clear.rowi = yyy_row_count(sheet) - 1;
3655 clear.coli = xxx_column_count(sheet) - 1;
3659 clear.row0=MAX(clear.row0, 0);
3660 clear.col0=MAX(clear.col0, 0);
3661 clear.rowi=MIN(clear.rowi, yyy_row_count(sheet) - 1 );
3662 clear.coli=MIN(clear.coli, xxx_column_count(sheet) - 1 );
3664 for(i=clear.row0; i<=clear.rowi; i++)
3665 for(j=clear.col0; j<=clear.coli; j++){
3666 gtk_sheet_real_cell_clear(sheet, i, j, delete);
3669 gtk_sheet_range_draw(sheet, NULL);
3674 gtk_sheet_cell_get_text (GtkSheet *sheet, gint row, gint col)
3677 g_return_val_if_fail (sheet != NULL, NULL);
3678 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
3680 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet))
3682 if(col < 0 || row < 0) return NULL;
3684 model = gtk_sheet_get_model(sheet);
3689 return g_sheet_model_get_string(model, row, col);
3694 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
3697 GtkSheetRange *range;
3699 g_return_val_if_fail (sheet != NULL, 0);
3700 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3701 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return 0;
3702 if(col < 0 || row < 0) return 0;
3704 state = sheet->state;
3705 range = &sheet->range;
3709 case GTK_SHEET_NORMAL:
3710 return GTK_STATE_NORMAL;
3712 case GTK_SHEET_ROW_SELECTED:
3713 if(row>=range->row0 && row<=range->rowi)
3714 return GTK_STATE_SELECTED;
3716 case GTK_SHEET_COLUMN_SELECTED:
3717 if(col>=range->col0 && col<=range->coli)
3718 return GTK_STATE_SELECTED;
3720 case GTK_SHEET_RANGE_SELECTED:
3721 if(row >= range->row0 && row <= range->rowi && \
3722 col >= range->col0 && col <= range->coli)
3723 return GTK_STATE_SELECTED;
3726 return GTK_STATE_NORMAL;
3730 gtk_sheet_get_pixel_info (GtkSheet * sheet,
3738 g_return_val_if_fail (sheet != NULL, 0);
3739 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3741 /* bounds checking, return false if the user clicked
3742 * on a blank area */
3743 trow = ROW_FROM_YPIXEL (sheet, y);
3744 if (trow >= yyy_row_count(sheet))
3749 tcol = COLUMN_FROM_XPIXEL (sheet, x);
3750 if (tcol >= xxx_column_count(sheet))
3759 gtk_sheet_get_cell_area (GtkSheet * sheet,
3764 g_return_val_if_fail (sheet != NULL, 0);
3765 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3767 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3770 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) -
3771 (sheet->row_titles_visible
3772 ? sheet->row_title_area.width
3774 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL(sheet, row) -
3775 (sheet->column_titles_visible
3776 ? sheet->column_title_area.height
3778 area->width= (column == -1) ? sheet->row_title_area.width
3779 : xxx_column_width(sheet, column);
3781 area->height= (row == -1) ? sheet->column_title_area.height
3782 : yyy_row_height(sheet, row);
3785 if(row < 0 || column < 0) return FALSE;
3787 area->x = COLUMN_LEFT_XPIXEL(sheet, column);
3788 area->y = ROW_TOP_YPIXEL(sheet, row);
3789 if(sheet->row_titles_visible)
3790 area->x -= sheet->row_title_area.width;
3791 if(sheet->column_titles_visible)
3792 area->y -= sheet->column_title_area.height;
3794 area->width=sheet->column[column].width;
3795 area->height=yyy_row_height(sheet, row);
3801 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
3803 g_return_val_if_fail (sheet != NULL, 0);
3804 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3806 if(row < 0 || column < 0) return FALSE;
3807 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3810 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
3812 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
3815 sheet->active_cell.row=row;
3816 sheet->active_cell.col=column;
3818 if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE;
3820 if(gtk_sheet_autoscroll(sheet))
3821 gtk_sheet_move_query(sheet, row, column);
3827 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column)
3829 g_return_if_fail (sheet != NULL);
3830 g_return_if_fail (GTK_IS_SHEET (sheet));
3832 *row = sheet->active_cell.row;
3833 *column = sheet->active_cell.col;
3837 gtk_sheet_entry_changed(GtkWidget *widget, gpointer data)
3842 GtkJustification justification;
3843 GtkSheetCellAttr attributes;
3845 g_return_if_fail (data != NULL);
3846 g_return_if_fail (GTK_IS_SHEET (data));
3848 sheet=GTK_SHEET(data);
3850 if(!GTK_WIDGET_VISIBLE(widget)) return;
3851 if(sheet->state != GTK_STATE_NORMAL) return;
3853 row=sheet->active_cell.row;
3854 col=sheet->active_cell.col;
3856 if(row<0 || col<0) return;
3858 sheet->active_cell.row=-1;
3859 sheet->active_cell.col=-1;
3861 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3863 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3865 if(text && strlen(text) > 0){
3866 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3867 justification=attributes.justification;
3868 gtk_sheet_set_cell(sheet, row, col, justification, text);
3871 if(sheet->freeze_count == 0)
3872 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3874 sheet->active_cell.row=row;;
3875 sheet->active_cell.col=col;
3880 gtk_sheet_deactivate_cell(GtkSheet *sheet)
3882 gboolean veto = TRUE;
3884 g_return_val_if_fail (sheet != NULL, FALSE);
3885 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
3887 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return FALSE;
3888 if(sheet->state != GTK_SHEET_NORMAL) return FALSE;
3890 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[DEACTIVATE],
3891 sheet->active_cell.row,
3892 sheet->active_cell.col, &veto);
3894 if(!veto) return FALSE;
3896 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
3897 (GtkSignalFunc) gtk_sheet_entry_changed,
3898 GTK_OBJECT(GTK_WIDGET(sheet)));
3900 gtk_sheet_hide_active_cell(sheet);
3901 sheet->active_cell.row=-1;
3902 sheet->active_cell.col=-1;
3904 if(GTK_SHEET_REDRAW_PENDING(sheet)){
3905 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3906 gtk_sheet_range_draw(sheet, NULL);
3913 gtk_sheet_hide_active_cell(GtkSheet *sheet)
3917 GtkJustification justification;
3918 GtkSheetCellAttr attributes;
3920 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3922 row=sheet->active_cell.row;
3923 col=sheet->active_cell.col;
3925 if(row < 0 || col < 0) return;
3927 if(sheet->freeze_count == 0)
3928 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3930 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3932 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3933 justification=attributes.justification;
3935 if(text && strlen(text)!=0){
3936 gtk_sheet_set_cell(sheet, row, col, justification, text);
3937 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col);
3941 gtk_sheet_cell_clear(sheet, row, col);
3944 row=sheet->active_cell.row;
3945 col=sheet->active_cell.col;
3948 column_button_release(sheet, col);
3949 row_button_release(sheet, row);
3952 gtk_widget_unmap(sheet->sheet_entry);
3954 if(row != -1 && col != -1)
3955 gdk_draw_pixmap(sheet->sheet_window,
3956 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3958 COLUMN_LEFT_XPIXEL(sheet,col)-1,
3959 ROW_TOP_YPIXEL(sheet,row)-1,
3960 COLUMN_LEFT_XPIXEL(sheet,col)-1,
3961 ROW_TOP_YPIXEL(sheet,row)-1,
3962 xxx_column_width(sheet, col) + 4,
3963 yyy_row_height(sheet, row)+4);
3965 gtk_widget_grab_focus(GTK_WIDGET(sheet));
3967 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
3972 gtk_sheet_activate_cell(GtkSheet *sheet, gint row, gint col)
3974 gboolean veto = TRUE;
3976 g_return_val_if_fail (sheet != NULL, FALSE);
3977 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
3979 if(row < 0 || col < 0) return FALSE;
3980 if(row >= yyy_row_count(sheet) || col >= xxx_column_count(sheet))
3983 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
3984 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
3987 if(!veto) return FALSE;
3988 if(sheet->state != GTK_SHEET_NORMAL){
3989 sheet->state=GTK_SHEET_NORMAL;
3990 gtk_sheet_real_unselect_range(sheet, NULL);
3993 sheet->range.row0=row;
3994 sheet->range.col0=col;
3995 sheet->range.rowi=row;
3996 sheet->range.coli=col;
3997 sheet->active_cell.row=row;
3998 sheet->active_cell.col=col;
3999 sheet->selection_cell.row=row;
4000 sheet->selection_cell.col=col;
4002 row_button_set(sheet, row);
4003 column_button_set(sheet, col);
4006 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4007 gtk_sheet_show_active_cell(sheet);
4009 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
4011 G_CALLBACK(gtk_sheet_entry_changed),
4014 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4020 gtk_sheet_show_active_cell(GtkSheet *sheet)
4022 GtkEntry *sheet_entry;
4023 GtkSheetCellAttr attributes;
4025 const gchar *old_text;
4026 GtkJustification justification;
4029 g_return_if_fail (sheet != NULL);
4030 g_return_if_fail (GTK_IS_SHEET (sheet));
4032 row = sheet->active_cell.row;
4033 col = sheet->active_cell.col;
4035 /* Don't show the active cell, if there is no active cell: */
4036 if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */
4039 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4040 if(sheet->state != GTK_SHEET_NORMAL) return;
4041 if(GTK_SHEET_IN_SELECTION(sheet)) return;
4043 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4045 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
4047 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4049 justification = GTK_JUSTIFY_LEFT;
4051 if(gtk_sheet_justify_entry(sheet))
4052 justification = attributes.justification;
4054 text = g_strdup(gtk_sheet_cell_get_text(sheet, row, col));
4056 if(!text) text = g_strdup("");
4058 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible);
4060 if(gtk_sheet_locked(sheet) || !attributes.is_editable){
4061 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
4063 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
4066 /*** Added by John Gotts. Mar 25, 2005 *********/
4067 old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
4068 if (strcmp(old_text, text) != 0)
4070 if(!GTK_IS_ITEM_ENTRY(sheet_entry))
4071 gtk_entry_set_text(GTK_ENTRY(sheet_entry), text);
4073 gtk_item_entry_set_text(GTK_ITEM_ENTRY(sheet_entry), text, justification);
4076 gtk_sheet_entry_set_max_size(sheet);
4077 gtk_sheet_size_allocate_entry(sheet);
4079 gtk_widget_map(sheet->sheet_entry);
4080 gtk_sheet_draw_active_cell(sheet);
4082 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
4088 gtk_sheet_draw_active_cell(GtkSheet *sheet)
4092 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
4093 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4095 row = sheet->active_cell.row;
4096 col = sheet->active_cell.col;
4098 if(row<0 || col<0) return;
4100 if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
4102 row_button_set(sheet, row);
4103 column_button_set(sheet, col);
4105 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4106 gtk_sheet_draw_border(sheet, sheet->range);
4111 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
4113 gint pixmap_width, pixmap_height;
4115 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4117 if(width == 0 && height == 0){
4118 width=sheet->sheet_window_width+80;
4119 height=sheet->sheet_window_height+80;
4125 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4128 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4132 /* reallocate if sizes don't match */
4133 gdk_window_get_size (sheet->pixmap,
4134 &pixmap_width, &pixmap_height);
4135 if ((pixmap_width != width) || (pixmap_height != height))
4137 g_free(sheet->pixmap);
4138 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4141 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4147 gtk_sheet_new_selection(GtkSheet *sheet, GtkSheetRange *range)
4149 gint i,j, mask1, mask2;
4150 gint state, selected;
4151 gint x,y,width,height;
4152 GtkSheetRange new_range, aux_range;
4154 g_return_if_fail (sheet != NULL);
4156 if(range==NULL) range=&sheet->range;
4160 range->row0=MIN(range->row0, sheet->range.row0);
4161 range->rowi=MAX(range->rowi, sheet->range.rowi);
4162 range->col0=MIN(range->col0, sheet->range.col0);
4163 range->coli=MAX(range->coli, sheet->range.coli);
4165 range->row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
4166 range->rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
4167 range->col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
4168 range->coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
4170 aux_range.row0=MAX(new_range.row0, MIN_VISIBLE_ROW(sheet));
4171 aux_range.rowi=MIN(new_range.rowi, MAX_VISIBLE_ROW(sheet));
4172 aux_range.col0=MAX(new_range.col0, MIN_VISIBLE_COLUMN(sheet));
4173 aux_range.coli=MIN(new_range.coli, MAX_VISIBLE_COLUMN(sheet));
4175 for(i=range->row0; i<=range->rowi; i++){
4176 for(j=range->col0; j<=range->coli; j++){
4178 state=gtk_sheet_cell_get_state(sheet, i, j);
4179 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4180 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4182 if(state==GTK_STATE_SELECTED && selected &&
4183 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4184 (i==sheet->range.row0 || i==sheet->range.rowi ||
4185 j==sheet->range.col0 || j==sheet->range.coli ||
4186 i==new_range.row0 || i==new_range.rowi ||
4187 j==new_range.col0 || j==new_range.coli)){
4189 mask1 = i==sheet->range.row0 ? 1 : 0;
4190 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4191 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4192 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4194 mask2 = i==new_range.row0 ? 1 : 0;
4195 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4196 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4197 mask2 = j==new_range.coli ? mask2+8 : mask2;
4200 x=COLUMN_LEFT_XPIXEL(sheet,j);
4201 y=ROW_TOP_YPIXEL(sheet, i);
4202 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4203 xxx_column_width(sheet, j);
4204 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4206 if(i==sheet->range.row0){
4210 if(i==sheet->range.rowi) height=height+3;
4211 if(j==sheet->range.col0){
4215 if(j==sheet->range.coli) width=width+3;
4217 gdk_draw_pixmap(sheet->sheet_window,
4218 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4227 if(i != sheet->active_cell.row || j != sheet->active_cell.col){
4228 x=COLUMN_LEFT_XPIXEL(sheet,j);
4229 y=ROW_TOP_YPIXEL(sheet, i);
4230 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4231 xxx_column_width(sheet, j);
4233 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4235 if(i==new_range.row0){
4239 if(i==new_range.rowi) height=height-3;
4240 if(j==new_range.col0){
4244 if(j==new_range.coli) width=width-3;
4246 gdk_draw_rectangle (sheet->sheet_window,
4257 for(i=range->row0; i<=range->rowi; i++){
4258 for(j=range->col0; j<=range->coli; j++){
4260 state=gtk_sheet_cell_get_state(sheet, i, j);
4261 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4262 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4264 if(state==GTK_STATE_SELECTED && !selected &&
4265 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4267 x=COLUMN_LEFT_XPIXEL(sheet,j);
4268 y=ROW_TOP_YPIXEL(sheet, i);
4269 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4270 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4272 if(i==sheet->range.row0){
4276 if(i==sheet->range.rowi) height=height+3;
4277 if(j==sheet->range.col0){
4281 if(j==sheet->range.coli) width=width+3;
4283 gdk_draw_pixmap(sheet->sheet_window,
4284 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4296 for(i=range->row0; i<=range->rowi; i++){
4297 for(j=range->col0; j<=range->coli; j++){
4299 state=gtk_sheet_cell_get_state(sheet, i, j);
4300 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4301 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4303 if(state!=GTK_STATE_SELECTED && selected &&
4304 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4305 (i != sheet->active_cell.row || j != sheet->active_cell.col)){
4307 x=COLUMN_LEFT_XPIXEL(sheet,j);
4308 y=ROW_TOP_YPIXEL(sheet, i);
4309 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4310 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4312 if(i==new_range.row0){
4316 if(i==new_range.rowi) height=height-3;
4317 if(j==new_range.col0){
4321 if(j==new_range.coli) width=width-3;
4323 gdk_draw_rectangle (sheet->sheet_window,
4334 for(i=aux_range.row0; i<=aux_range.rowi; i++){
4335 for(j=aux_range.col0; j<=aux_range.coli; j++){
4337 if(xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4339 state=gtk_sheet_cell_get_state(sheet, i, j);
4341 mask1 = i==sheet->range.row0 ? 1 : 0;
4342 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4343 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4344 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4346 mask2 = i==new_range.row0 ? 1 : 0;
4347 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4348 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4349 mask2 = j==new_range.coli ? mask2+8 : mask2;
4350 if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){
4351 x=COLUMN_LEFT_XPIXEL(sheet,j);
4352 y=ROW_TOP_YPIXEL(sheet, i);
4353 width=xxx_column_width(sheet, j);
4354 height=yyy_row_height(sheet, i);
4356 gdk_draw_rectangle (sheet->sheet_window,
4364 gdk_draw_rectangle (sheet->sheet_window,
4371 gdk_draw_rectangle (sheet->sheet_window,
4379 gdk_draw_rectangle (sheet->sheet_window,
4396 gtk_sheet_draw_corners(sheet, new_range);
4401 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
4406 gint x,y,width,height;
4408 widget = GTK_WIDGET(sheet);
4410 x=COLUMN_LEFT_XPIXEL(sheet,new_range.col0);
4411 y=ROW_TOP_YPIXEL(sheet,new_range.row0);
4412 width=COLUMN_LEFT_XPIXEL(sheet,new_range.coli)-x+
4413 xxx_column_width(sheet, new_range.coli);
4415 height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+
4416 yyy_row_height(sheet, new_range.rowi);
4418 area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
4419 area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
4420 area.width=sheet->sheet_window_width;
4421 area.height=sheet->sheet_window_height;
4427 if(width>area.width) width=area.width+10;
4432 if(height>area.height) height=area.height+10;
4434 gdk_gc_set_clip_rectangle(sheet->xor_gc, &area);
4436 for(i=-1; i<=1; ++i)
4437 gdk_draw_rectangle (sheet->sheet_window,
4441 width-2*i,height-2*i);
4443 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
4445 gtk_sheet_draw_corners(sheet, new_range);
4450 gtk_sheet_draw_corners(GtkSheet *sheet, GtkSheetRange range)
4455 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.col0)){
4456 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4457 y=ROW_TOP_YPIXEL(sheet,range.row0);
4458 gdk_draw_pixmap(sheet->sheet_window,
4459 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4467 gdk_draw_rectangle (sheet->sheet_window,
4474 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) ||
4475 sheet->state == GTK_SHEET_COLUMN_SELECTED){
4476 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4477 xxx_column_width(sheet, range.coli);
4478 y=ROW_TOP_YPIXEL(sheet,range.row0);
4480 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
4482 y = ROW_TOP_YPIXEL(sheet, sheet->view.row0)+3;
4485 gdk_draw_pixmap(sheet->sheet_window,
4486 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4494 gdk_draw_rectangle (sheet->sheet_window,
4497 x-width+width/2,y-width+width/2,
4501 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.col0) ||
4502 sheet->state == GTK_SHEET_ROW_SELECTED){
4503 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4504 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4505 yyy_row_height(sheet, range.rowi);
4507 if(sheet->state == GTK_SHEET_ROW_SELECTED)
4509 x = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0)+3;
4512 gdk_draw_pixmap(sheet->sheet_window,
4513 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4521 gdk_draw_rectangle (sheet->sheet_window,
4524 x-width+width/2,y-width+width/2,
4528 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){
4529 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4530 xxx_column_width(sheet, range.coli);
4531 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4532 yyy_row_height(sheet, range.rowi);
4534 if(sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
4535 if(sheet->state == GTK_SHEET_NORMAL) width = 3;
4536 gdk_draw_pixmap(sheet->sheet_window,
4537 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4545 gdk_draw_rectangle (sheet->sheet_window,
4548 x-width+width/2,y-width+width/2,
4557 gtk_sheet_real_select_range (GtkSheet * sheet,
4558 GtkSheetRange * range)
4562 g_return_if_fail (sheet != NULL);
4564 if(range==NULL) range=&sheet->range;
4566 if(range->row0 < 0 || range->rowi < 0) return;
4567 if(range->col0 < 0 || range->coli < 0) return;
4572 if(state==GTK_SHEET_COLUMN_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4573 for(i=sheet->range.col0; i< range->col0; i++)
4574 column_button_release(sheet, i);
4575 for(i=range->coli+1; i<= sheet->range.coli; i++)
4576 column_button_release(sheet, i);
4577 for(i=range->col0; i<=range->coli; i++){
4578 column_button_set(sheet, i);
4582 if(state==GTK_SHEET_ROW_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4583 for(i=sheet->range.row0; i< range->row0; i++)
4584 row_button_release(sheet, i);
4585 for(i=range->rowi+1; i<= sheet->range.rowi; i++)
4586 row_button_release(sheet, i);
4587 for(i=range->row0; i<=range->rowi; i++){
4588 row_button_set(sheet, i);
4593 if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
4594 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
4597 gtk_sheet_new_selection(sheet, range);
4599 sheet->range.col0=range->col0;
4600 sheet->range.coli=range->coli;
4601 sheet->range.row0=range->row0;
4602 sheet->range.rowi=range->rowi;
4607 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4608 gtk_sheet_range_draw_selection(sheet, sheet->range);
4611 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[SELECT_RANGE], range);
4615 gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range)
4617 g_return_if_fail (sheet != NULL);
4619 if(range==NULL) range=&sheet->range;
4621 if(range->row0 < 0 || range->rowi < 0) return;
4622 if(range->col0 < 0 || range->coli < 0) return;
4624 if(sheet->state != GTK_SHEET_NORMAL)
4625 gtk_sheet_real_unselect_range(sheet, NULL);
4628 gboolean veto = TRUE;
4629 veto = gtk_sheet_deactivate_cell(sheet);
4633 sheet->range.row0=range->row0;
4634 sheet->range.rowi=range->rowi;
4635 sheet->range.col0=range->col0;
4636 sheet->range.coli=range->coli;
4637 sheet->active_cell.row=range->row0;
4638 sheet->active_cell.col=range->col0;
4639 sheet->selection_cell.row=range->rowi;
4640 sheet->selection_cell.col=range->coli;
4642 sheet->state = GTK_SHEET_RANGE_SELECTED;
4643 gtk_sheet_real_select_range(sheet, NULL);
4648 gtk_sheet_unselect_range (GtkSheet * sheet)
4650 gtk_sheet_real_unselect_range(sheet, NULL);
4651 sheet->state = GTK_STATE_NORMAL;
4652 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
4657 gtk_sheet_real_unselect_range (GtkSheet * sheet,
4658 const GtkSheetRange *range)
4660 g_return_if_fail (sheet != NULL);
4661 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)));
4664 range=&sheet->range;
4667 if(range->row0 < 0 || range->rowi < 0) return;
4668 if(range->col0 < 0 || range->coli < 0) return;
4670 if (gtk_sheet_range_isvisible (sheet, *range)){
4671 gtk_sheet_draw_backing_pixmap(sheet, *range);
4675 for(i=range->col0; i<=range->coli; i++){
4676 column_button_release(sheet, i);
4679 for(i=range->row0; i<=range->rowi; i++){
4680 row_button_release(sheet, i);
4684 gtk_sheet_position_children(sheet);
4689 gtk_sheet_expose (GtkWidget * widget,
4690 GdkEventExpose * event)
4693 GtkSheetRange range;
4695 g_return_val_if_fail (widget != NULL, FALSE);
4696 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4697 g_return_val_if_fail (event != NULL, FALSE);
4699 sheet = GTK_SHEET (widget);
4701 if (GTK_WIDGET_DRAWABLE (widget))
4703 range.row0=ROW_FROM_YPIXEL(sheet,event->area.y);
4704 range.col0=COLUMN_FROM_XPIXEL(sheet,event->area.x);
4705 range.rowi=ROW_FROM_YPIXEL(sheet,event->area.y+event->area.height);
4706 range.coli=COLUMN_FROM_XPIXEL(sheet,event->area.x+event->area.width);
4708 /* exposure events on the sheet */
4710 if(event->window == sheet->row_title_window && sheet->row_titles_visible){
4712 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
4713 gtk_sheet_button_draw(sheet,i,-1);
4716 if(event->window == sheet->column_title_window && sheet->column_titles_visible){
4718 for(i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
4719 gtk_sheet_button_draw(sheet,-1,i);
4722 if (event->window == sheet->sheet_window){
4723 gtk_sheet_draw_backing_pixmap(sheet, range);
4725 if(sheet->state != GTK_SHEET_NORMAL){
4726 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4727 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4728 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4729 gtk_sheet_draw_backing_pixmap(sheet, sheet->drag_range);
4731 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4732 gtk_sheet_range_draw_selection(sheet, sheet->range);
4733 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4734 draw_xor_rectangle(sheet, sheet->drag_range);
4737 if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet))){
4738 if(sheet->state == GTK_SHEET_NORMAL){
4739 gtk_sheet_draw_active_cell(sheet);
4740 if(!GTK_SHEET_IN_SELECTION(sheet))
4741 gtk_widget_queue_draw(sheet->sheet_entry);
4750 if(sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet))
4751 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4753 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
4760 gtk_sheet_button_press (GtkWidget * widget,
4761 GdkEventButton * event)
4764 GdkModifierType mods;
4765 gint x, y, row, column;
4768 g_return_val_if_fail (widget != NULL, FALSE);
4769 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4770 g_return_val_if_fail (event != NULL, FALSE);
4772 sheet = GTK_SHEET (widget);
4774 if ( event->type == GDK_2BUTTON_PRESS)
4776 gtk_widget_get_pointer (widget, &x, &y);
4777 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4779 if (event->window == sheet->column_title_window )
4781 gtk_signal_emit (GTK_OBJECT (sheet),
4782 sheet_signals[DOUBLE_CLICK_COLUMN], column);
4784 else if (event->window == sheet->row_title_window )
4786 gtk_signal_emit (GTK_OBJECT (sheet),
4787 sheet_signals[DOUBLE_CLICK_ROW], row);
4793 if(event->type != GDK_BUTTON_PRESS) return TRUE;
4795 gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
4797 if(!(mods & GDK_BUTTON1_MASK)) return TRUE;
4800 /* press on resize windows */
4801 if (event->window == sheet->column_title_window &&
4802 gtk_sheet_columns_resizable(sheet))
4804 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
4805 if(POSSIBLE_XDRAG(sheet, sheet->x_drag, &sheet->drag_cell.col)){
4807 if (event->type == GDK_2BUTTON_PRESS){
4808 gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
4809 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_XDRAG);
4812 gtk_sheet_column_size_request(sheet, sheet->drag_cell.col, &req);
4813 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4814 gdk_pointer_grab (sheet->column_title_window, FALSE,
4815 GDK_POINTER_MOTION_HINT_MASK |
4816 GDK_BUTTON1_MOTION_MASK |
4817 GDK_BUTTON_RELEASE_MASK,
4818 NULL, NULL, event->time);
4820 draw_xor_vline (sheet);
4825 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet))
4827 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
4829 if(POSSIBLE_YDRAG(sheet, sheet->y_drag, &sheet->drag_cell.row)){
4831 gtk_sheet_row_size_request(sheet, sheet->drag_cell.row, &req);
4832 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
4833 gdk_pointer_grab (sheet->row_title_window, FALSE,
4834 GDK_POINTER_MOTION_HINT_MASK |
4835 GDK_BUTTON1_MOTION_MASK |
4836 GDK_BUTTON_RELEASE_MASK,
4837 NULL, NULL, event->time);
4839 draw_xor_hline (sheet);
4844 /* the sheet itself does not handle other than single click events */
4845 if(event->type != GDK_BUTTON_PRESS) return FALSE;
4847 /* selections on the sheet */
4848 if(event->window == sheet->sheet_window){
4849 gtk_widget_get_pointer (widget, &x, &y);
4850 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4851 gdk_pointer_grab (sheet->sheet_window, FALSE,
4852 GDK_POINTER_MOTION_HINT_MASK |
4853 GDK_BUTTON1_MOTION_MASK |
4854 GDK_BUTTON_RELEASE_MASK,
4855 NULL, NULL, event->time);
4856 gtk_grab_add(GTK_WIDGET(sheet));
4857 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4858 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4860 if(sheet->selection_mode != GTK_SELECTION_SINGLE &&
4861 sheet->cursor_drag->type==GDK_SIZING &&
4862 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_RESIZE(sheet)){
4863 if(sheet->state==GTK_STATE_NORMAL) {
4864 row=sheet->active_cell.row;
4865 column=sheet->active_cell.col;
4866 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4867 sheet->active_cell.row=row;
4868 sheet->active_cell.col=column;
4869 sheet->drag_range=sheet->range;
4870 sheet->state=GTK_SHEET_RANGE_SELECTED;
4871 gtk_sheet_select_range(sheet, &sheet->drag_range);
4875 if(row > sheet->range.rowi) row--;
4876 if(column > sheet->range.coli) column--;
4877 sheet->drag_cell.row = row;
4878 sheet->drag_cell.col = column;
4879 sheet->drag_range=sheet->range;
4880 draw_xor_rectangle(sheet, sheet->drag_range);
4881 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
4883 else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW &&
4884 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_DRAG(sheet)) {
4885 if(sheet->state==GTK_STATE_NORMAL) {
4886 row=sheet->active_cell.row;
4887 column=sheet->active_cell.col;
4888 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4889 sheet->active_cell.row=row;
4890 sheet->active_cell.col=column;
4891 sheet->drag_range=sheet->range;
4892 sheet->state=GTK_SHEET_RANGE_SELECTED;
4893 gtk_sheet_select_range(sheet, &sheet->drag_range);
4897 if(row < sheet->range.row0) row++;
4898 if(row > sheet->range.rowi) row--;
4899 if(column < sheet->range.col0) column++;
4900 if(column > sheet->range.coli) column--;
4901 sheet->drag_cell.row=row;
4902 sheet->drag_cell.col=column;
4903 sheet->drag_range=sheet->range;
4904 draw_xor_rectangle(sheet, sheet->drag_range);
4905 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
4909 gtk_sheet_click_cell(sheet, row, column, &veto);
4910 if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4915 if(event->window == sheet->column_title_window){
4916 gtk_widget_get_pointer (widget, &x, &y);
4917 column = COLUMN_FROM_XPIXEL(sheet, x);
4918 if(xxx_column_is_sensitive(sheet, column)){
4919 gtk_sheet_click_cell(sheet, -1, column, &veto);
4920 gtk_grab_add(GTK_WIDGET(sheet));
4921 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4922 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4923 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4927 if(event->window == sheet->row_title_window){
4928 gtk_widget_get_pointer (widget, &x, &y);
4929 row = ROW_FROM_YPIXEL(sheet, y);
4930 if(yyy_row_is_sensitive(sheet, row)){
4931 gtk_sheet_click_cell(sheet, row, -1, &veto);
4932 gtk_grab_add(GTK_WIDGET(sheet));
4933 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4934 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4935 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4943 gtk_sheet_scroll(gpointer data)
4946 gint x,y,row,column;
4949 sheet=GTK_SHEET(data);
4951 GDK_THREADS_ENTER();
4953 gtk_widget_get_pointer (GTK_WIDGET(sheet), &x, &y);
4954 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4958 if(GTK_SHEET_IN_SELECTION(sheet))
4959 gtk_sheet_extend_selection(sheet, row, column);
4961 if(GTK_SHEET_IN_DRAG(sheet) || GTK_SHEET_IN_RESIZE(sheet)){
4962 move=gtk_sheet_move_query(sheet, row, column);
4963 if(move) draw_xor_rectangle(sheet, sheet->drag_range);
4966 GDK_THREADS_LEAVE();
4973 gtk_sheet_click_cell(GtkSheet *sheet, gint row, gint column, gboolean *veto)
4977 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)){
4982 if(column >= 0 && row >= 0)
4983 if(! xxx_column_is_visible(sheet, column) || !yyy_row_is_visible(sheet, row))
4989 _gtkextra_signal_emit(GTK_OBJECT(sheet), sheet_signals[TRAVERSE],
4990 sheet->active_cell.row, sheet->active_cell.col,
4991 &row, &column, veto);
4994 if(sheet->state == GTK_STATE_NORMAL) return;
4996 row = sheet->active_cell.row;
4997 column = sheet->active_cell.col;
4999 gtk_sheet_activate_cell(sheet, row, column);
5003 if(row == -1 && column >= 0){
5004 if(gtk_sheet_autoscroll(sheet))
5005 gtk_sheet_move_query(sheet, row, column);
5006 gtk_sheet_select_column(sheet, column);
5009 if(column == -1 && row >= 0){
5010 if(gtk_sheet_autoscroll(sheet))
5011 gtk_sheet_move_query(sheet, row, column);
5012 gtk_sheet_select_row(sheet, row);
5016 if(row==-1 && column ==-1){
5017 sheet->range.row0=0;
5018 sheet->range.col0=0;
5019 sheet->range.rowi = yyy_row_count(sheet) - 1;
5020 sheet->range.coli = xxx_column_count(sheet) - 1;
5021 sheet->active_cell.row=0;
5022 sheet->active_cell.col=0;
5023 gtk_sheet_select_range(sheet, NULL);
5027 if(row!=-1 && column !=-1){
5028 if(sheet->state != GTK_SHEET_NORMAL){
5029 sheet->state = GTK_SHEET_NORMAL;
5030 gtk_sheet_real_unselect_range(sheet, NULL);
5034 if(!gtk_sheet_deactivate_cell(sheet)){
5040 if(gtk_sheet_autoscroll(sheet))
5041 gtk_sheet_move_query(sheet, row, column);
5042 sheet->active_cell.row=row;
5043 sheet->active_cell.col=column;
5044 sheet->selection_cell.row=row;
5045 sheet->selection_cell.col=column;
5046 sheet->range.row0=row;
5047 sheet->range.col0=column;
5048 sheet->range.rowi=row;
5049 sheet->range.coli=column;
5050 sheet->state=GTK_SHEET_NORMAL;
5051 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5052 gtk_sheet_draw_active_cell(sheet);
5056 g_assert_not_reached();
5057 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5058 sheet->active_cell.col);
5062 gtk_sheet_button_release (GtkWidget * widget,
5063 GdkEventButton * event)
5068 sheet=GTK_SHEET(widget);
5070 /* release on resize windows */
5071 if (GTK_SHEET_IN_XDRAG (sheet)){
5072 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
5073 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5074 gtk_widget_get_pointer (widget, &x, NULL);
5075 gdk_pointer_ungrab (event->time);
5076 draw_xor_vline (sheet);
5078 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col, new_column_width (sheet, sheet->drag_cell.col, &x));
5079 sheet->old_hadjustment = -1.;
5080 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed");
5084 if (GTK_SHEET_IN_YDRAG (sheet)){
5085 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5086 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5087 gtk_widget_get_pointer (widget, NULL, &y);
5088 gdk_pointer_ungrab (event->time);
5089 draw_xor_hline (sheet);
5091 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
5092 sheet->old_vadjustment = -1.;
5093 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed");
5098 if (GTK_SHEET_IN_DRAG(sheet)){
5099 GtkSheetRange old_range;
5100 draw_xor_rectangle(sheet, sheet->drag_range);
5101 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5102 gdk_pointer_ungrab (event->time);
5104 gtk_sheet_real_unselect_range(sheet, NULL);
5106 sheet->active_cell.row = sheet->active_cell.row +
5107 (sheet->drag_range.row0 - sheet->range.row0);
5108 sheet->active_cell.col = sheet->active_cell.col +
5109 (sheet->drag_range.col0 - sheet->range.col0);
5110 sheet->selection_cell.row = sheet->selection_cell.row +
5111 (sheet->drag_range.row0 - sheet->range.row0);
5112 sheet->selection_cell.col = sheet->selection_cell.col +
5113 (sheet->drag_range.col0 - sheet->range.col0);
5114 old_range=sheet->range;
5115 sheet->range=sheet->drag_range;
5116 sheet->drag_range=old_range;
5117 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[MOVE_RANGE],
5118 &sheet->drag_range, &sheet->range);
5119 gtk_sheet_select_range(sheet, &sheet->range);
5122 if (GTK_SHEET_IN_RESIZE(sheet)){
5123 GtkSheetRange old_range;
5124 draw_xor_rectangle(sheet, sheet->drag_range);
5125 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5126 gdk_pointer_ungrab (event->time);
5128 gtk_sheet_real_unselect_range(sheet, NULL);
5130 sheet->active_cell.row = sheet->active_cell.row +
5131 (sheet->drag_range.row0 - sheet->range.row0);
5132 sheet->active_cell.col = sheet->active_cell.col +
5133 (sheet->drag_range.col0 - sheet->range.col0);
5134 if(sheet->drag_range.row0 < sheet->range.row0)
5135 sheet->selection_cell.row = sheet->drag_range.row0;
5136 if(sheet->drag_range.rowi >= sheet->range.rowi)
5137 sheet->selection_cell.row = sheet->drag_range.rowi;
5138 if(sheet->drag_range.col0 < sheet->range.col0)
5139 sheet->selection_cell.col = sheet->drag_range.col0;
5140 if(sheet->drag_range.coli >= sheet->range.coli)
5141 sheet->selection_cell.col = sheet->drag_range.coli;
5142 old_range = sheet->range;
5143 sheet->range = sheet->drag_range;
5144 sheet->drag_range = old_range;
5146 if(sheet->state==GTK_STATE_NORMAL) sheet->state=GTK_SHEET_RANGE_SELECTED;
5147 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[RESIZE_RANGE],
5148 &sheet->drag_range, &sheet->range);
5149 gtk_sheet_select_range(sheet, &sheet->range);
5152 if(sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)){
5153 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5154 gdk_pointer_ungrab (event->time);
5155 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5156 sheet->active_cell.col);
5159 if(GTK_SHEET_IN_SELECTION)
5160 gdk_pointer_ungrab (event->time);
5162 gtk_timeout_remove(sheet->timer);
5163 gtk_grab_remove(GTK_WIDGET(sheet));
5165 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5171 gtk_sheet_motion (GtkWidget * widget,
5172 GdkEventMotion * event)
5175 GdkModifierType mods;
5176 GdkCursorType new_cursor;
5177 gint x, y, row, column;
5179 g_return_val_if_fail (widget != NULL, FALSE);
5180 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
5181 g_return_val_if_fail (event != NULL, FALSE);
5184 sheet = GTK_SHEET (widget);
5186 /* selections on the sheet */
5190 if(event->window == sheet->column_title_window && gtk_sheet_columns_resizable(sheet)){
5191 gtk_widget_get_pointer(widget, &x, &y);
5192 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_XDRAG(sheet, x, &column)){
5193 new_cursor=GDK_SB_H_DOUBLE_ARROW;
5194 if(new_cursor != sheet->cursor_drag->type){
5195 gdk_cursor_destroy(sheet->cursor_drag);
5196 sheet->cursor_drag=gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
5197 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5200 new_cursor=GDK_TOP_LEFT_ARROW;
5201 if(!GTK_SHEET_IN_XDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5202 gdk_cursor_destroy(sheet->cursor_drag);
5203 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5204 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5209 if(event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet)){
5210 gtk_widget_get_pointer(widget, &x, &y);
5211 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_YDRAG(sheet,y, &column)){
5212 new_cursor=GDK_SB_V_DOUBLE_ARROW;
5213 if(new_cursor != sheet->cursor_drag->type){
5214 gdk_cursor_destroy(sheet->cursor_drag);
5215 sheet->cursor_drag=gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
5216 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5219 new_cursor=GDK_TOP_LEFT_ARROW;
5220 if(!GTK_SHEET_IN_YDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5221 gdk_cursor_destroy(sheet->cursor_drag);
5222 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5223 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5228 new_cursor=GDK_PLUS;
5229 if(!POSSIBLE_DRAG(sheet,x,y,&row,&column) && !GTK_SHEET_IN_DRAG(sheet) &&
5230 !POSSIBLE_RESIZE(sheet,x,y,&row,&column) && !GTK_SHEET_IN_RESIZE(sheet) &&
5231 event->window == sheet->sheet_window &&
5232 new_cursor != sheet->cursor_drag->type){
5233 gdk_cursor_destroy(sheet->cursor_drag);
5234 sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
5235 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5238 new_cursor=GDK_TOP_LEFT_ARROW;
5239 if(!(POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5240 (POSSIBLE_DRAG(sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG(sheet)) &&
5241 event->window == sheet->sheet_window &&
5242 new_cursor != sheet->cursor_drag->type){
5243 gdk_cursor_destroy(sheet->cursor_drag);
5244 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5245 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5248 new_cursor=GDK_SIZING;
5249 if(!GTK_SHEET_IN_DRAG(sheet) &&
5250 (POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5251 event->window == sheet->sheet_window &&
5252 new_cursor != sheet->cursor_drag->type){
5253 gdk_cursor_destroy(sheet->cursor_drag);
5254 sheet->cursor_drag=gdk_cursor_new(GDK_SIZING);
5255 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5258 gdk_window_get_pointer (widget->window, &x, &y, &mods);
5259 if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
5261 if (GTK_SHEET_IN_XDRAG (sheet)){
5262 if (event->is_hint || event->window != widget->window)
5263 gtk_widget_get_pointer (widget, &x, NULL);
5267 new_column_width (sheet, sheet->drag_cell.col, &x);
5268 if (x != sheet->x_drag)
5270 draw_xor_vline (sheet);
5272 draw_xor_vline (sheet);
5277 if (GTK_SHEET_IN_YDRAG (sheet)){
5278 if (event->is_hint || event->window != widget->window)
5279 gtk_widget_get_pointer (widget, NULL, &y);
5283 new_row_height (sheet, sheet->drag_cell.row, &y);
5284 if (y != sheet->y_drag)
5286 draw_xor_hline (sheet);
5288 draw_xor_hline (sheet);
5293 if (GTK_SHEET_IN_DRAG(sheet)){
5295 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col;
5296 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row;
5297 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5298 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5302 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5303 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5304 aux=sheet->drag_range;
5305 sheet->drag_range.row0=sheet->range.row0+row;
5306 sheet->drag_range.col0=sheet->range.col0+column;
5307 sheet->drag_range.rowi=sheet->range.rowi+row;
5308 sheet->drag_range.coli=sheet->range.coli+column;
5309 if(aux.row0 != sheet->drag_range.row0 ||
5310 aux.col0 != sheet->drag_range.col0){
5311 draw_xor_rectangle (sheet, aux);
5312 draw_xor_rectangle (sheet, sheet->drag_range);
5318 if (GTK_SHEET_IN_RESIZE(sheet)){
5320 gint v_h, current_col, current_row, col_threshold, row_threshold;
5323 if(abs(x-COLUMN_LEFT_XPIXEL(sheet,sheet->drag_cell.col)) >
5324 abs(y-ROW_TOP_YPIXEL(sheet,sheet->drag_cell.row))) v_h=2;
5326 current_col = COLUMN_FROM_XPIXEL(sheet,x);
5327 current_row = ROW_FROM_YPIXEL(sheet,y);
5328 column = current_col-sheet->drag_cell.col;
5329 row = current_row-sheet->drag_cell.row;
5331 /*use half of column width resp. row height as threshold to expand selection*/
5332 col_threshold = COLUMN_LEFT_XPIXEL(sheet,current_col)+xxx_column_width (sheet,current_col)/2;
5334 if (x < col_threshold)
5337 else if (column < 0){
5338 if (x > col_threshold)
5341 row_threshold = ROW_TOP_YPIXEL(sheet,current_row)+yyy_row_height (sheet, current_row)/2;
5343 if(y < row_threshold)
5347 if(y > row_threshold)
5351 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5352 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5362 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5363 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5365 aux=sheet->drag_range;
5366 sheet->drag_range=sheet->range;
5368 if(row<0) sheet->drag_range.row0=sheet->range.row0+row;
5369 if(row>0) sheet->drag_range.rowi=sheet->range.rowi+row;
5370 if(column<0) sheet->drag_range.col0=sheet->range.col0+column;
5371 if(column>0) sheet->drag_range.coli=sheet->range.coli+column;
5373 if(aux.row0 != sheet->drag_range.row0 ||
5374 aux.rowi != sheet->drag_range.rowi ||
5375 aux.col0 != sheet->drag_range.col0 ||
5376 aux.coli != sheet->drag_range.coli){
5377 draw_xor_rectangle (sheet, aux);
5378 draw_xor_rectangle (sheet, sheet->drag_range);
5386 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5388 if(sheet->state==GTK_SHEET_NORMAL && row==sheet->active_cell.row &&
5389 column==sheet->active_cell.col) return TRUE;
5391 if(GTK_SHEET_IN_SELECTION(sheet) && mods&GDK_BUTTON1_MASK)
5392 gtk_sheet_extend_selection(sheet, row, column);
5398 gtk_sheet_move_query(GtkSheet *sheet, gint row, gint column)
5400 gint row_move, column_move;
5401 gfloat row_align, col_align;
5402 guint height, width;
5404 gint new_col = column;
5411 height = sheet->sheet_window_height;
5412 width = sheet->sheet_window_width;
5414 if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5416 new_row = MIN(yyy_row_count(sheet), row + 1);
5418 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet) - 1 &&
5419 ROW_TOP_YPIXEL(sheet, yyy_row_count(sheet)-1) +
5420 yyy_row_height(sheet, yyy_row_count(sheet)-1) < height){
5425 if(row<MIN_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5429 if(column>=MAX_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5431 new_col = MIN(xxx_column_count(sheet) - 1, column + 1);
5433 if(MAX_VISIBLE_COLUMN(sheet) == (xxx_column_count(sheet) - 1) &&
5434 COLUMN_LEFT_XPIXEL(sheet, xxx_column_count(sheet) - 1) +
5435 xxx_column_width(sheet, xxx_column_count(sheet) - 1) < width)
5437 column_move = FALSE;
5441 if(column<MIN_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5446 if(row_move || column_move){
5447 gtk_sheet_moveto(sheet, new_row, new_col, row_align, col_align);
5450 return(row_move || column_move);
5454 gtk_sheet_extend_selection(GtkSheet *sheet, gint row, gint column)
5456 GtkSheetRange range;
5460 if(row == sheet->selection_cell.row && column == sheet->selection_cell.col)
5463 if(sheet->selection_mode == GTK_SELECTION_SINGLE) return;
5465 gtk_sheet_move_query(sheet, row, column);
5466 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5468 if(GTK_SHEET_IN_DRAG(sheet)) return;
5472 switch(sheet->state){
5473 case GTK_SHEET_ROW_SELECTED:
5474 column = xxx_column_count(sheet) - 1;
5476 case GTK_SHEET_COLUMN_SELECTED:
5477 row = yyy_row_count(sheet) - 1;
5479 case GTK_SHEET_NORMAL:
5480 sheet->state=GTK_SHEET_RANGE_SELECTED;
5481 r=sheet->active_cell.row;
5482 c=sheet->active_cell.col;
5483 sheet->range.col0=c;
5484 sheet->range.row0=r;
5485 sheet->range.coli=c;
5486 sheet->range.rowi=r;
5487 gdk_draw_pixmap(sheet->sheet_window,
5488 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
5490 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5491 ROW_TOP_YPIXEL(sheet,r)-1,
5492 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5493 ROW_TOP_YPIXEL(sheet,r)-1,
5494 xxx_column_width(sheet, c)+4,
5495 yyy_row_height(sheet, r)+4);
5496 gtk_sheet_range_draw_selection(sheet, sheet->range);
5497 case GTK_SHEET_RANGE_SELECTED:
5498 sheet->state=GTK_SHEET_RANGE_SELECTED;
5501 sheet->selection_cell.row = row;
5502 sheet->selection_cell.col = column;
5504 range.col0=MIN(column,sheet->active_cell.col);
5505 range.coli=MAX(column,sheet->active_cell.col);
5506 range.row0=MIN(row,sheet->active_cell.row);
5507 range.rowi=MAX(row,sheet->active_cell.row);
5509 if(range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi ||
5510 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli ||
5511 state==GTK_SHEET_NORMAL)
5512 gtk_sheet_real_select_range(sheet, &range);
5517 gtk_sheet_entry_key_press(GtkWidget *widget,
5521 gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", key, &focus);
5526 gtk_sheet_key_press(GtkWidget *widget,
5532 gboolean extend_selection = FALSE;
5533 gboolean force_move = FALSE;
5534 gboolean in_selection = FALSE;
5535 gboolean veto = TRUE;
5538 sheet = GTK_SHEET(widget);
5540 if(key->state & GDK_CONTROL_MASK || key->keyval==GDK_Control_L ||
5541 key->keyval==GDK_Control_R) return FALSE;
5545 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL)
5546 gtk_sheet_clip_range(sheet, sheet->range);
5547 if(key->keyval=='x' || key->keyval == 'X')
5548 gtk_sheet_unclip_range(sheet);
5553 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval==GDK_Shift_L
5554 || key->keyval==GDK_Shift_R;
5557 in_selection = GTK_SHEET_IN_SELECTION(sheet);
5558 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5560 switch(key->keyval){
5561 case GDK_Return: case GDK_KP_Enter:
5562 if(sheet->state == GTK_SHEET_NORMAL &&
5563 !GTK_SHEET_IN_SELECTION(sheet))
5564 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
5566 row = sheet->active_cell.row;
5567 col = sheet->active_cell.col;
5568 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5569 row = MIN_VISIBLE_ROW(sheet)-1;
5570 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5571 col = MIN_VISIBLE_COLUMN(sheet);
5572 if(row < yyy_row_count(sheet) - 1){
5574 while(!yyy_row_is_visible(sheet, row) && row<yyy_row_count(sheet)-1)
5577 gtk_sheet_click_cell(sheet, row, col, &veto);
5578 extend_selection = FALSE;
5580 case GDK_ISO_Left_Tab:
5581 row = sheet->active_cell.row;
5582 col = sheet->active_cell.col;
5583 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5584 col = MIN_VISIBLE_COLUMN(sheet)-1;
5585 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5586 row = MIN_VISIBLE_ROW(sheet);
5589 while(! xxx_column_is_visible(sheet, col) && col>0) col--;
5592 gtk_sheet_click_cell(sheet, row, col, &veto);
5593 extend_selection = FALSE;
5596 row = sheet->active_cell.row;
5597 col = sheet->active_cell.col;
5598 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5599 col = MIN_VISIBLE_COLUMN(sheet)-1;
5600 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5601 row = MIN_VISIBLE_ROW(sheet);
5602 if(col < xxx_column_count(sheet) - 1)
5605 while(! xxx_column_is_visible(sheet, col) &&
5606 col < xxx_column_count(sheet) - 1)
5609 gtk_sheet_click_cell(sheet, row, col, &veto);
5610 extend_selection = FALSE;
5612 /* case GDK_BackSpace:
5613 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){
5614 if(sheet->active_cell.col > 0){
5615 col = sheet->active_cell.col - scroll;
5616 row = sheet->active_cell.row;
5617 while(!sheet->column[col].is_visible && col > 0) col--;
5620 gtk_sheet_click_cell(sheet, row, col, &veto);
5621 extend_selection = FALSE;
5625 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5627 if(extend_selection){
5628 if(state==GTK_STATE_NORMAL){
5629 row=sheet->active_cell.row;
5630 col=sheet->active_cell.col;
5631 gtk_sheet_click_cell(sheet, row, col, &veto);
5634 if(sheet->selection_cell.row > 0){
5635 row = sheet->selection_cell.row - scroll;
5636 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5638 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5642 col = sheet->active_cell.col;
5643 row = sheet->active_cell.row;
5644 if(state==GTK_SHEET_COLUMN_SELECTED)
5645 row = MIN_VISIBLE_ROW(sheet);
5646 if(state==GTK_SHEET_ROW_SELECTED)
5647 col = MIN_VISIBLE_COLUMN(sheet);
5649 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5651 gtk_sheet_click_cell(sheet, row, col, &veto);
5652 extend_selection = FALSE;
5655 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5657 if(extend_selection){
5658 if(state==GTK_STATE_NORMAL){
5659 row=sheet->active_cell.row;
5660 col=sheet->active_cell.col;
5661 gtk_sheet_click_cell(sheet, row, col, &veto);
5664 if(sheet->selection_cell.row < yyy_row_count(sheet)-1){
5665 row = sheet->selection_cell.row + scroll;
5666 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5667 row = MIN(yyy_row_count(sheet)-1, row);
5668 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5672 col = sheet->active_cell.col;
5673 row = sheet->active_cell.row;
5674 if(sheet->active_cell.row < yyy_row_count(sheet)-1){
5675 if(state==GTK_SHEET_COLUMN_SELECTED)
5676 row = MIN_VISIBLE_ROW(sheet)-1;
5677 if(state==GTK_SHEET_ROW_SELECTED)
5678 col = MIN_VISIBLE_COLUMN(sheet);
5680 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5681 row = MIN(yyy_row_count(sheet)-1, row);
5683 gtk_sheet_click_cell(sheet, row, col, &veto);
5684 extend_selection = FALSE;
5687 if(extend_selection){
5688 if(state==GTK_STATE_NORMAL){
5689 row=sheet->active_cell.row;
5690 col=sheet->active_cell.col;
5691 gtk_sheet_click_cell(sheet, row, col, &veto);
5694 if(sheet->selection_cell.col < xxx_column_count(sheet) - 1)
5696 col = sheet->selection_cell.col + 1;
5697 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1)
5699 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5703 col = sheet->active_cell.col;
5704 row = sheet->active_cell.row;
5705 if(sheet->active_cell.col < xxx_column_count(sheet) - 1){
5707 if(state==GTK_SHEET_ROW_SELECTED)
5708 col = MIN_VISIBLE_COLUMN(sheet)-1;
5709 if(state==GTK_SHEET_COLUMN_SELECTED)
5710 row = MIN_VISIBLE_ROW(sheet);
5711 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1) col++;
5712 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5714 gtk_sheet_click_cell(sheet, row, col, &veto);
5719 extend_selection = FALSE;
5722 if(extend_selection){
5723 if(state==GTK_STATE_NORMAL){
5724 row=sheet->active_cell.row;
5725 col=sheet->active_cell.col;
5726 gtk_sheet_click_cell(sheet, row, col, &veto);
5729 if(sheet->selection_cell.col > 0){
5730 col = sheet->selection_cell.col - 1;
5731 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5732 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5736 col = sheet->active_cell.col - 1;
5737 row = sheet->active_cell.row;
5738 if(state==GTK_SHEET_ROW_SELECTED)
5739 col = MIN_VISIBLE_COLUMN(sheet)-1;
5740 if(state==GTK_SHEET_COLUMN_SELECTED)
5741 row = MIN_VISIBLE_ROW(sheet);
5742 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5745 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5747 gtk_sheet_click_cell(sheet, row, col, &veto);
5751 extend_selection = FALSE;
5755 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5756 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5757 extend_selection = FALSE;
5760 row=yyy_row_count(sheet)-1;
5761 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5762 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5763 extend_selection = FALSE;
5767 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5768 if(extend_selection) return TRUE;
5770 if(state == GTK_SHEET_ROW_SELECTED)
5771 sheet->active_cell.col=MIN_VISIBLE_COLUMN(sheet);
5772 if(state == GTK_SHEET_COLUMN_SELECTED)
5773 sheet->active_cell.row=MIN_VISIBLE_ROW(sheet);
5777 if(extend_selection) return TRUE;
5779 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5780 sheet->active_cell.col);
5786 gtk_sheet_size_request (GtkWidget * widget,
5787 GtkRequisition * requisition)
5791 GtkSheetChild *child;
5792 GtkRequisition child_requisition;
5794 g_return_if_fail (widget != NULL);
5795 g_return_if_fail (GTK_IS_SHEET (widget));
5796 g_return_if_fail (requisition != NULL);
5798 sheet = GTK_SHEET (widget);
5800 requisition->width = 3*DEFAULT_COLUMN_WIDTH;
5801 requisition->height = 3*DEFAULT_ROW_HEIGHT(widget);
5803 /* compute the size of the column title area */
5804 if(sheet->column_titles_visible)
5805 requisition->height += sheet->column_title_area.height;
5807 /* compute the size of the row title area */
5808 if(sheet->row_titles_visible)
5809 requisition->width += sheet->row_title_area.width;
5811 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5812 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5813 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5814 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5816 if(!sheet->column_titles_visible)
5817 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5819 if(!sheet->row_titles_visible)
5820 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5822 children = sheet->children;
5825 child = children->data;
5826 children = children->next;
5828 gtk_widget_size_request(child->widget, &child_requisition);
5834 gtk_sheet_size_allocate (GtkWidget * widget,
5835 GtkAllocation * allocation)
5838 GtkAllocation sheet_allocation;
5841 g_return_if_fail (widget != NULL);
5842 g_return_if_fail (GTK_IS_SHEET (widget));
5843 g_return_if_fail (allocation != NULL);
5845 sheet = GTK_SHEET (widget);
5846 widget->allocation = *allocation;
5847 border_width = GTK_CONTAINER(widget)->border_width;
5849 if (GTK_WIDGET_REALIZED (widget))
5850 gdk_window_move_resize (widget->window,
5851 allocation->x + border_width,
5852 allocation->y + border_width,
5853 allocation->width - 2*border_width,
5854 allocation->height - 2*border_width);
5856 /* use internal allocation structure for all the math
5857 * because it's easier than always subtracting the container
5859 sheet->internal_allocation.x = 0;
5860 sheet->internal_allocation.y = 0;
5861 sheet->internal_allocation.width = allocation->width - 2*border_width;
5862 sheet->internal_allocation.height = allocation->height - 2*border_width;
5864 sheet_allocation.x = 0;
5865 sheet_allocation.y = 0;
5866 sheet_allocation.width = allocation->width - 2*border_width;
5867 sheet_allocation.height = allocation->height - 2*border_width;
5869 sheet->sheet_window_width = sheet_allocation.width;
5870 sheet->sheet_window_height = sheet_allocation.height;
5872 if (GTK_WIDGET_REALIZED (widget))
5873 gdk_window_move_resize (sheet->sheet_window,
5876 sheet_allocation.width,
5877 sheet_allocation.height);
5879 /* position the window which holds the column title buttons */
5880 sheet->column_title_area.x = 0;
5881 sheet->column_title_area.y = 0;
5882 if(sheet->row_titles_visible)
5883 sheet->column_title_area.x = sheet->row_title_area.width;
5884 sheet->column_title_area.width = sheet_allocation.width -
5885 sheet->column_title_area.x;
5886 if(GTK_WIDGET_REALIZED(widget) && sheet->column_titles_visible)
5887 gdk_window_move_resize (sheet->column_title_window,
5888 sheet->column_title_area.x,
5889 sheet->column_title_area.y,
5890 sheet->column_title_area.width,
5891 sheet->column_title_area.height);
5893 sheet->sheet_window_width = sheet_allocation.width;
5894 sheet->sheet_window_height = sheet_allocation.height;
5896 /* column button allocation */
5897 size_allocate_column_title_buttons (sheet);
5899 /* position the window which holds the row title buttons */
5900 sheet->row_title_area.x = 0;
5901 sheet->row_title_area.y = 0;
5902 if(sheet->column_titles_visible)
5903 sheet->row_title_area.y = sheet->column_title_area.height;
5904 sheet->row_title_area.height = sheet_allocation.height -
5905 sheet->row_title_area.y;
5907 if(GTK_WIDGET_REALIZED(widget) && sheet->row_titles_visible)
5908 gdk_window_move_resize (sheet->row_title_window,
5909 sheet->row_title_area.x,
5910 sheet->row_title_area.y,
5911 sheet->row_title_area.width,
5912 sheet->row_title_area.height);
5915 /* row button allocation */
5916 size_allocate_row_title_buttons (sheet);
5918 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5919 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5920 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5921 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5923 if(!sheet->column_titles_visible)
5924 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5926 if(!sheet->row_titles_visible)
5927 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5929 size_allocate_column_title_buttons(sheet);
5930 size_allocate_row_title_buttons(sheet);
5932 /* re-scale backing pixmap */
5933 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
5934 gtk_sheet_position_children(sheet);
5936 /* set the scrollbars adjustments */
5937 adjust_scrollbars (sheet);
5941 size_allocate_column_title_buttons (GtkSheet * sheet)
5946 if (!sheet->column_titles_visible) return;
5947 if (!GTK_WIDGET_REALIZED (sheet))
5950 width = sheet->sheet_window_width;
5953 if(sheet->row_titles_visible)
5955 width -= sheet->row_title_area.width;
5956 x = sheet->row_title_area.width;
5959 if(sheet->column_title_area.width != width || sheet->column_title_area.x != x)
5961 sheet->column_title_area.width = width;
5962 sheet->column_title_area.x = x;
5963 gdk_window_move_resize (sheet->column_title_window,
5964 sheet->column_title_area.x,
5965 sheet->column_title_area.y,
5966 sheet->column_title_area.width,
5967 sheet->column_title_area.height);
5971 if(MAX_VISIBLE_COLUMN(sheet) == xxx_column_count(sheet) - 1)
5972 gdk_window_clear_area (sheet->column_title_window,
5974 sheet->column_title_area.width,
5975 sheet->column_title_area.height);
5977 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
5979 for (i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
5980 gtk_sheet_button_draw(sheet,-1,i);
5984 size_allocate_row_title_buttons (GtkSheet * sheet)
5989 if (!sheet->row_titles_visible) return;
5990 if (!GTK_WIDGET_REALIZED (sheet))
5993 height = sheet->sheet_window_height;
5996 if(sheet->column_titles_visible)
5998 height -= sheet->column_title_area.height;
5999 y = sheet->column_title_area.height;
6002 if(sheet->row_title_area.height != height || sheet->row_title_area.y != y)
6004 sheet->row_title_area.y = y;
6005 sheet->row_title_area.height = height;
6006 gdk_window_move_resize (sheet->row_title_window,
6007 sheet->row_title_area.x,
6008 sheet->row_title_area.y,
6009 sheet->row_title_area.width,
6010 sheet->row_title_area.height);
6012 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet)-1)
6013 gdk_window_clear_area (sheet->row_title_window,
6015 sheet->row_title_area.width,
6016 sheet->row_title_area.height);
6018 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6020 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
6021 gtk_sheet_button_draw(sheet,i,-1);
6026 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
6028 GtkAllocation shentry_allocation;
6029 GtkSheetCellAttr attributes;
6030 GtkEntry *sheet_entry;
6031 GtkStyle *style = NULL, *previous_style = NULL;
6033 gint size, max_size, text_size, column_width;
6036 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6037 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
6039 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
6041 gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes);
6043 if(GTK_WIDGET_REALIZED(sheet->sheet_entry)){
6045 if(!GTK_WIDGET(sheet_entry)->style)
6046 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry));
6048 previous_style = GTK_WIDGET(sheet_entry)->style;
6050 style = gtk_style_copy(previous_style);
6051 style->bg[GTK_STATE_NORMAL] = attributes.background;
6052 style->fg[GTK_STATE_NORMAL] = attributes.foreground;
6053 style->text[GTK_STATE_NORMAL] = attributes.foreground;
6054 style->bg[GTK_STATE_ACTIVE] = attributes.background;
6055 style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
6056 style->text[GTK_STATE_ACTIVE] = attributes.foreground;
6058 pango_font_description_free(style->font_desc);
6059 style->font_desc = pango_font_description_copy(attributes.font_desc);
6061 GTK_WIDGET(sheet_entry)->style = style;
6062 gtk_widget_size_request(sheet->sheet_entry, NULL);
6063 GTK_WIDGET(sheet_entry)->style = previous_style;
6065 if(style != previous_style){
6066 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6067 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
6068 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
6069 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
6070 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
6072 gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
6076 if(GTK_IS_ITEM_ENTRY(sheet_entry))
6077 max_size = GTK_ITEM_ENTRY(sheet_entry)->text_max_size;
6082 text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
6083 if(text && strlen(text) > 0){
6084 text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
6087 column_width=xxx_column_width(sheet, sheet->active_cell.col);
6089 size=MIN(text_size, max_size);
6090 size=MAX(size,column_width-2*CELLOFFSET);
6092 row=sheet->active_cell.row;
6093 col=sheet->active_cell.col;
6095 shentry_allocation.x = COLUMN_LEFT_XPIXEL(sheet,sheet->active_cell.col);
6096 shentry_allocation.y = ROW_TOP_YPIXEL(sheet,sheet->active_cell.row);
6097 shentry_allocation.width = column_width;
6098 shentry_allocation.height = yyy_row_height(sheet, sheet->active_cell.row);
6100 if(GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6102 shentry_allocation.height -= 2*CELLOFFSET;
6103 shentry_allocation.y += CELLOFFSET;
6104 if(gtk_sheet_clip_text(sheet))
6105 shentry_allocation.width = column_width - 2*CELLOFFSET;
6107 shentry_allocation.width = size;
6109 switch(GTK_ITEM_ENTRY(sheet_entry)->justification){
6110 case GTK_JUSTIFY_CENTER:
6111 shentry_allocation.x += (column_width)/2 - size/2;
6113 case GTK_JUSTIFY_RIGHT:
6114 shentry_allocation.x += column_width - size - CELLOFFSET;
6116 case GTK_JUSTIFY_LEFT:
6117 case GTK_JUSTIFY_FILL:
6118 shentry_allocation.x += CELLOFFSET;
6124 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6125 shentry_allocation.x += 2;
6126 shentry_allocation.y += 2;
6127 shentry_allocation.width -= MIN(shentry_allocation.width, 3);
6128 shentry_allocation.height -= MIN(shentry_allocation.height, 3);
6131 gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation);
6133 if(previous_style == style) gtk_style_unref(previous_style);
6137 gtk_sheet_entry_set_max_size(GtkSheet *sheet)
6141 gint sizel=0, sizer=0;
6143 GtkJustification justification;
6145 row=sheet->active_cell.row;
6146 col=sheet->active_cell.col;
6148 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry) || gtk_sheet_clip_text(sheet)) return;
6150 justification = GTK_ITEM_ENTRY(sheet->sheet_entry)->justification;
6152 switch(justification){
6153 case GTK_JUSTIFY_FILL:
6154 case GTK_JUSTIFY_LEFT:
6155 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6156 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6157 size+=xxx_column_width(sheet, i);
6159 size = MIN(size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL(sheet, col));
6161 case GTK_JUSTIFY_RIGHT:
6162 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
6163 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6164 size+=xxx_column_width(sheet, i);
6167 case GTK_JUSTIFY_CENTER:
6168 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6169 /* if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6171 sizer+=xxx_column_width(sheet, i);
6173 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
6174 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6175 sizel+=xxx_column_width(sheet, i);
6177 size=2*MIN(sizel, sizer);
6181 if(size!=0) size+=xxx_column_width(sheet, col);
6182 GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size=size;
6187 create_sheet_entry(GtkSheet *sheet)
6192 gint found_entry = FALSE;
6194 widget = GTK_WIDGET(sheet);
6196 if(sheet->sheet_entry){
6197 /* avoids warnings */
6198 gtk_widget_ref(sheet->sheet_entry);
6199 gtk_widget_unparent(sheet->sheet_entry);
6200 gtk_widget_destroy(sheet->sheet_entry);
6203 if(sheet->entry_type){
6205 if(!g_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY)){
6207 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6209 sheet->sheet_entry = parent;
6211 entry = gtk_sheet_get_entry (sheet);
6212 if(GTK_IS_ENTRY(entry)) found_entry = TRUE;
6216 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6224 g_warning ("Entry type must be GtkEntry subclass, using default");
6225 entry = gtk_item_entry_new();
6226 sheet->sheet_entry = entry;
6230 sheet->sheet_entry = parent;
6237 entry = gtk_item_entry_new();
6238 sheet->sheet_entry = entry;
6242 gtk_widget_size_request(sheet->sheet_entry, NULL);
6244 if(GTK_WIDGET_REALIZED(sheet))
6246 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
6247 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
6248 gtk_widget_realize(sheet->sheet_entry);
6251 gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event",
6252 (GtkSignalFunc) gtk_sheet_entry_key_press,
6255 gtk_widget_show (sheet->sheet_entry);
6259 /* Finds the last child widget that happens to be of type GtkEntry */
6261 find_entry(GtkWidget *w, gpointer user_data)
6263 GtkWidget **entry = user_data;
6264 if ( GTK_IS_ENTRY(w))
6271 gtk_sheet_get_entry(GtkSheet *sheet)
6274 GtkWidget *entry = NULL;
6275 GtkTableChild *table_child;
6276 GtkBoxChild *box_child;
6277 GList *children = NULL;
6279 g_return_val_if_fail (sheet != NULL, NULL);
6280 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6281 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6283 if(GTK_IS_ENTRY(sheet->sheet_entry)) return (sheet->sheet_entry);
6285 parent = GTK_WIDGET(sheet->sheet_entry);
6287 if(GTK_IS_TABLE(parent)) children = GTK_TABLE(parent)->children;
6288 if(GTK_IS_BOX(parent)) children = GTK_BOX(parent)->children;
6290 if(GTK_IS_CONTAINER(parent))
6292 gtk_container_forall(GTK_CONTAINER(parent), find_entry, &entry);
6294 if(GTK_IS_ENTRY(entry))
6298 if(!children) return NULL;
6301 if(GTK_IS_TABLE(parent)) {
6302 table_child = children->data;
6303 entry = table_child->widget;
6305 if(GTK_IS_BOX(parent)){
6306 box_child = children->data;
6307 entry = box_child->widget;
6310 if(GTK_IS_ENTRY(entry))
6312 children = children->next;
6316 if(!GTK_IS_ENTRY(entry)) return NULL;
6323 gtk_sheet_get_entry_widget(GtkSheet *sheet)
6325 g_return_val_if_fail (sheet != NULL, NULL);
6326 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6327 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6329 return (sheet->sheet_entry);
6335 row_button_set (GtkSheet *sheet, gint row)
6337 if(sheet->row[row].button.state == GTK_STATE_ACTIVE) return;
6339 sheet->row[row].button.state = GTK_STATE_ACTIVE;
6340 gtk_sheet_button_draw(sheet, row, -1);
6345 row_button_release (GtkSheet *sheet, gint row)
6347 if(sheet->row[row].button.state == GTK_STATE_NORMAL) return;
6349 sheet->row[row].button.state = GTK_STATE_NORMAL;
6350 gtk_sheet_button_draw(sheet, row, -1);
6355 gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
6357 GdkWindow *window = NULL;
6358 GtkShadowType shadow_type;
6359 guint width = 0, height = 0;
6362 gint text_width = 0, text_height = 0;
6363 const GtkSheetButton *button = NULL;
6364 GtkSheetChild *child = NULL;
6365 GdkRectangle allocation;
6366 gboolean is_sensitive = FALSE;
6371 PangoAlignment align = PANGO_ALIGN_LEFT;
6374 rtl = gtk_widget_get_direction(GTK_WIDGET(sheet)) == GTK_TEXT_DIR_RTL;
6376 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6378 if(row >= 0 && !yyy_row_is_visible(sheet, row)) return;
6379 if(column >= 0 && ! xxx_column_is_visible(sheet, column)) return;
6380 if(row >= 0 && !sheet->row_titles_visible) return;
6381 if(column >= 0 && !sheet->column_titles_visible) return;
6382 if(column>=0 && column < MIN_VISIBLE_COLUMN(sheet)) return;
6383 if(column>=0 && column > MAX_VISIBLE_COLUMN(sheet)) return;
6384 if(row>=0 && row < MIN_VISIBLE_ROW(sheet)) return;
6385 if(row>=0 && row > MAX_VISIBLE_ROW(sheet)) return;
6386 if( (row == -1) && (column == -1) ) return;
6389 window=sheet->column_title_window;
6390 button= xxx_column_button(sheet, column);
6392 x = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING;
6393 if(sheet->row_titles_visible) x -= sheet->row_title_area.width;
6395 width = xxx_column_width(sheet, column);
6396 height = sheet->column_title_area.height;
6397 is_sensitive=xxx_column_is_sensitive(sheet, column);
6400 window=sheet->row_title_window;
6401 button = yyy_row_button(sheet, row);
6404 y = ROW_TOP_YPIXEL(sheet, row)+CELL_SPACING;
6405 if(sheet->column_titles_visible) y-=sheet->column_title_area.height;
6406 width = sheet->row_title_area.width;
6407 height = yyy_row_height(sheet, row);
6408 is_sensitive=yyy_row_is_sensitive(sheet, row);
6413 allocation.width = width;
6414 allocation.height = height;
6416 gdk_window_clear_area (window,
6420 gtk_paint_box (sheet->button->style, window,
6421 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
6422 &allocation, GTK_WIDGET(sheet->button),
6423 "buttondefault", x, y, width, height);
6425 state = button->state;
6426 if(!is_sensitive) state=GTK_STATE_INSENSITIVE;
6428 if (state == GTK_STATE_ACTIVE)
6429 shadow_type = GTK_SHADOW_IN;
6431 shadow_type = GTK_SHADOW_OUT;
6433 if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
6434 gtk_paint_box (sheet->button->style, window,
6435 button->state, shadow_type,
6436 &allocation, GTK_WIDGET(sheet->button),
6437 "button", x, y, width, height);
6439 if(button->label_visible){
6441 text_height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))-2*CELLOFFSET;
6443 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6445 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation);
6447 y += 2*sheet->button->style->ythickness;
6450 if(button->label && strlen(button->label)>0){
6452 PangoLayout *layout = NULL;
6453 gint real_x = x, real_y = y;
6455 words=button->label;
6456 line = g_new(gchar, 1);
6459 while(words && *words != '\0'){
6462 line=g_realloc(line, len+2);
6466 if(*words == '\n' || *(words+1) == '\0'){
6467 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, line);
6469 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), line);
6470 switch(button->justification){
6471 case GTK_JUSTIFY_LEFT:
6472 real_x = x + CELLOFFSET;
6473 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6475 case GTK_JUSTIFY_RIGHT:
6476 real_x = x + width - text_width - CELLOFFSET;
6477 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6479 case GTK_JUSTIFY_CENTER:
6481 real_x = x + (width - text_width)/2;
6482 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6483 pango_layout_set_justify (layout, TRUE);
6485 pango_layout_set_alignment (layout, align);
6486 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6495 g_object_unref(G_OBJECT(layout));
6497 real_y += text_height + 2;
6500 line = g_new(gchar, 1);
6507 if(button->label && strlen(button->label) > 0){
6508 PangoLayout *layout = NULL;
6509 gint real_x = x, real_y = y;
6511 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, button->label);
6513 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), button->label);
6514 switch(button->justification){
6515 case GTK_JUSTIFY_LEFT:
6516 real_x = x + CELLOFFSET;
6517 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6519 case GTK_JUSTIFY_RIGHT:
6520 real_x = x + width - text_width - CELLOFFSET;
6521 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6523 case GTK_JUSTIFY_CENTER:
6525 real_x = x + (width - text_width)/2;
6526 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6527 pango_layout_set_justify (layout, TRUE);
6529 pango_layout_set_alignment (layout, align);
6530 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6539 g_object_unref(G_OBJECT(layout));
6542 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6544 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, NULL);
6548 if((child = button->child) && (child->widget)){
6549 child->x = allocation.x;
6550 child->y = allocation.y;
6552 child->x += (width - child->widget->requisition.width) / 2;
6553 child->y += (height - child->widget->requisition.height) / 2;
6554 allocation.x = child->x;
6555 allocation.y = child->y;
6556 allocation.width = child->widget->requisition.width;
6557 allocation.height = child->widget->requisition.height;
6562 gtk_widget_set_state(child->widget, button->state);
6564 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
6565 GTK_WIDGET_MAPPED(child->widget))
6567 gtk_widget_size_allocate(child->widget,
6569 gtk_widget_queue_draw(child->widget);
6580 * vadjustment_changed
6581 * hadjustment_changed
6582 * vadjustment_value_changed
6583 * hadjustment_value_changed */
6586 adjust_scrollbars (GtkSheet * sheet)
6589 if(sheet->vadjustment){
6590 sheet->vadjustment->page_size = sheet->sheet_window_height;
6591 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
6592 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
6593 sheet->vadjustment->lower = 0;
6594 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
6596 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet))
6598 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) -
6599 sheet->sheet_window_height);
6600 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
6604 gtk_signal_emit_by_name (GTK_OBJECT(sheet->vadjustment), "changed");
6608 if(sheet->hadjustment){
6609 sheet->hadjustment->page_size = sheet->sheet_window_width;
6610 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
6611 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
6612 sheet->hadjustment->lower = 0;
6613 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
6615 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet))
6617 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) -
6618 sheet->sheet_window_width);
6619 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment),
6623 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), "changed");
6627 if(GTK_WIDGET_REALIZED(sheet))
6629 if(sheet->row_titles_visible){
6630 size_allocate_row_title_buttons(sheet);
6631 gdk_window_show(sheet->row_title_window);
6634 if(sheet->column_titles_visible){
6635 size_allocate_column_title_buttons(sheet);
6636 gdk_window_show(sheet->column_title_window);
6639 gtk_sheet_range_draw(sheet, NULL);
6646 vadjustment_changed (GtkAdjustment * adjustment,
6651 g_return_if_fail (adjustment != NULL);
6652 g_return_if_fail (data != NULL);
6654 sheet = GTK_SHEET (data);
6659 hadjustment_changed (GtkAdjustment * adjustment,
6664 g_return_if_fail (adjustment != NULL);
6665 g_return_if_fail (data != NULL);
6667 sheet = GTK_SHEET (data);
6672 vadjustment_value_changed (GtkAdjustment * adjustment,
6676 gint diff, value, old_value;
6680 g_return_if_fail (adjustment != NULL);
6681 g_return_if_fail (data != NULL);
6682 g_return_if_fail (GTK_IS_SHEET (data));
6684 sheet = GTK_SHEET (data);
6686 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6688 row=ROW_FROM_YPIXEL(sheet,sheet->column_title_area.height + CELL_SPACING);
6689 if(!sheet->column_titles_visible)
6690 row=ROW_FROM_YPIXEL(sheet,CELL_SPACING);
6692 old_value = -sheet->voffset;
6694 new_row = g_sheet_row_pixel_to_row(sheet->row_geometry,
6695 adjustment->value,sheet);
6697 y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
6699 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
6700 yyy_row_height(sheet, row) > sheet->vadjustment->step_increment){
6701 /* This avoids embarrassing twitching */
6702 if(row == new_row && row != yyy_row_count(sheet) - 1 &&
6703 adjustment->value - sheet->old_vadjustment >=
6704 sheet->vadjustment->step_increment &&
6705 new_row + 1 != MIN_VISIBLE_ROW(sheet)){
6707 y=y+yyy_row_height(sheet, row);
6711 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6712 if(sheet->old_vadjustment >= 0. && row == new_row){
6713 sheet->old_vadjustment = sheet->vadjustment->value;
6717 sheet->old_vadjustment = sheet->vadjustment->value;
6718 adjustment->value=y;
6722 sheet->vadjustment->step_increment= yyy_row_height(sheet, 0);
6724 sheet->vadjustment->step_increment=
6725 MIN(yyy_row_height(sheet, new_row), yyy_row_height(sheet, new_row-1));
6728 sheet->vadjustment->value=adjustment->value;
6730 value = adjustment->value;
6732 if (value >= -sheet->voffset)
6735 diff = value + sheet->voffset;
6740 diff = -sheet->voffset - value;
6743 sheet->voffset = -value;
6745 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6746 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6747 if(!sheet->column_titles_visible)
6748 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6750 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6751 sheet->state == GTK_SHEET_NORMAL &&
6752 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6753 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6754 sheet->active_cell.col))
6758 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6760 if(!text || strlen(text)==0)
6761 gtk_sheet_cell_clear(sheet,
6762 sheet->active_cell.row,
6763 sheet->active_cell.col);
6764 gtk_widget_unmap(sheet->sheet_entry);
6767 gtk_sheet_position_children(sheet);
6769 gtk_sheet_range_draw(sheet, NULL);
6770 size_allocate_row_title_buttons(sheet);
6771 size_allocate_global_button(sheet);
6775 hadjustment_value_changed (GtkAdjustment * adjustment,
6779 gint i, diff, value, old_value;
6780 gint column, new_column;
6783 g_return_if_fail (adjustment != NULL);
6784 g_return_if_fail (data != NULL);
6785 g_return_if_fail (GTK_IS_SHEET (data));
6787 sheet = GTK_SHEET (data);
6789 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6791 column=COLUMN_FROM_XPIXEL(sheet,sheet->row_title_area.width + CELL_SPACING);
6792 if(!sheet->row_titles_visible)
6793 column=COLUMN_FROM_XPIXEL(sheet, CELL_SPACING);
6795 old_value = -sheet->hoffset;
6797 for(i=0; i < xxx_column_count(sheet); i++)
6799 if(xxx_column_is_visible(sheet, i)) x += xxx_column_width(sheet, i);
6800 if(x > adjustment->value) break;
6802 x-=xxx_column_width(sheet, i);
6805 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
6806 xxx_column_width(sheet, i) > sheet->hadjustment->step_increment){
6807 /* This avoids embarrassing twitching */
6808 if(column == new_column && column != xxx_column_count(sheet) - 1 &&
6809 adjustment->value - sheet->old_hadjustment >=
6810 sheet->hadjustment->step_increment &&
6811 new_column + 1 != MIN_VISIBLE_COLUMN(sheet)){
6813 x=x+xxx_column_width(sheet, column);
6817 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6818 if(sheet->old_hadjustment >= 0. && new_column == column){
6819 sheet->old_hadjustment = sheet->hadjustment->value;
6823 sheet->old_hadjustment = sheet->hadjustment->value;
6824 adjustment->value=x;
6826 if(new_column == 0){
6827 sheet->hadjustment->step_increment=
6828 xxx_column_width(sheet, 0);
6830 sheet->hadjustment->step_increment=
6831 MIN(xxx_column_width(sheet, new_column), xxx_column_width(sheet, new_column-1));
6835 sheet->hadjustment->value=adjustment->value;
6837 value = adjustment->value;
6839 if (value >= -sheet->hoffset)
6842 diff = value + sheet->hoffset;
6847 diff = -sheet->hoffset - value;
6850 sheet->hoffset = -value;
6852 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6853 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6854 if(!sheet->row_titles_visible)
6855 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6857 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6858 sheet->state == GTK_SHEET_NORMAL &&
6859 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6860 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6861 sheet->active_cell.col))
6865 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6866 if(!text || strlen(text)==0)
6867 gtk_sheet_cell_clear(sheet,
6868 sheet->active_cell.row,
6869 sheet->active_cell.col);
6871 gtk_widget_unmap(sheet->sheet_entry);
6874 gtk_sheet_position_children(sheet);
6876 gtk_sheet_range_draw(sheet, NULL);
6877 size_allocate_column_title_buttons(sheet);
6881 /* COLUMN RESIZING */
6883 draw_xor_vline (GtkSheet * sheet)
6887 g_return_if_fail (sheet != NULL);
6889 widget = GTK_WIDGET (sheet);
6891 gdk_draw_line (widget->window, sheet->xor_gc,
6893 sheet->column_title_area.height,
6895 sheet->sheet_window_height + 1);
6900 draw_xor_hline (GtkSheet * sheet)
6904 g_return_if_fail (sheet != NULL);
6906 widget = GTK_WIDGET (sheet);
6908 gdk_draw_line (widget->window, sheet->xor_gc,
6909 sheet->row_title_area.width,
6912 sheet->sheet_window_width + 1,
6916 /* SELECTED RANGE */
6918 draw_xor_rectangle(GtkSheet *sheet, GtkSheetRange range)
6921 GdkRectangle clip_area, area;
6924 area.x=COLUMN_LEFT_XPIXEL(sheet, range.col0);
6925 area.y=ROW_TOP_YPIXEL(sheet, range.row0);
6926 area.width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-area.x+
6927 xxx_column_width(sheet, range.coli);
6928 area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+
6929 yyy_row_height(sheet, range.rowi);
6931 clip_area.x=sheet->row_title_area.width;
6932 clip_area.y=sheet->column_title_area.height;
6933 clip_area.width=sheet->sheet_window_width;
6934 clip_area.height=sheet->sheet_window_height;
6936 if(!sheet->row_titles_visible) clip_area.x = 0;
6937 if(!sheet->column_titles_visible) clip_area.y = 0;
6940 area.width=area.width+area.x;
6943 if(area.width>clip_area.width) area.width=clip_area.width+10;
6945 area.height=area.height+area.y;
6948 if(area.height>clip_area.height) area.height=clip_area.height+10;
6953 clip_area.height+=3;
6955 gdk_gc_get_values(sheet->xor_gc, &values);
6957 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
6960 gdk_draw_rectangle(sheet->sheet_window,
6964 area.width-2*i, area.height-2*i);
6967 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
6969 gdk_gc_set_foreground(sheet->xor_gc, &values.foreground);
6974 /* this function returns the new width of the column being resized given
6975 * the column and x position of the cursor; the x cursor position is passed
6976 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
6978 new_column_width (GtkSheet * sheet,
6987 min_width = sheet->column_requisition;
6989 /* you can't shrink a column to less than its minimum width */
6990 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
6992 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
6995 /* don't grow past the end of the window */
6997 if (cx > sheet->sheet_window_width)
6999 *x = cx = sheet->sheet_window_width;
7002 /* calculate new column width making sure it doesn't end up
7003 * less than the minimum width */
7004 width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
7005 if (width < min_width)
7008 xxx_set_column_width(sheet, column, width);
7009 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7010 size_allocate_column_title_buttons (sheet);
7015 /* this function returns the new height of the row being resized given
7016 * the row and y position of the cursor; the y cursor position is passed
7017 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7019 new_row_height (GtkSheet * sheet,
7027 min_height = sheet->row_requisition;
7029 /* you can't shrink a row to less than its minimum height */
7030 if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
7033 *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
7036 /* don't grow past the end of the window */
7038 if (cy > sheet->sheet_window_height)
7040 *y = cy = sheet->sheet_window_height;
7043 /* calculate new row height making sure it doesn't end up
7044 * less than the minimum height */
7045 height = (cy - ROW_TOP_YPIXEL (sheet, row));
7046 if (height < min_height)
7047 height = min_height;
7049 yyy_set_row_height(sheet, row, height);
7050 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
7051 size_allocate_row_title_buttons (sheet);
7057 gtk_sheet_set_column_width (GtkSheet * sheet,
7063 g_return_if_fail (sheet != NULL);
7064 g_return_if_fail (GTK_IS_SHEET (sheet));
7066 if (column < 0 || column >= xxx_column_count(sheet))
7069 gtk_sheet_column_size_request(sheet, column, &min_width);
7070 if(width < min_width) return;
7072 xxx_set_column_width(sheet, column, width);
7074 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7075 size_allocate_column_title_buttons (sheet);
7076 adjust_scrollbars (sheet);
7077 gtk_sheet_size_allocate_entry(sheet);
7078 gtk_sheet_range_draw (sheet, NULL);
7081 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, column);
7082 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_COL_WIDTH], column, width);
7089 gtk_sheet_set_row_height (GtkSheet * sheet,
7095 g_return_if_fail (sheet != NULL);
7096 g_return_if_fail (GTK_IS_SHEET (sheet));
7098 if (row < 0 || row >= yyy_row_count(sheet))
7101 gtk_sheet_row_size_request(sheet, row, &min_height);
7102 if(height < min_height) return;
7104 yyy_set_row_height(sheet, row, height);
7106 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7107 size_allocate_row_title_buttons (sheet);
7108 adjust_scrollbars (sheet);
7109 gtk_sheet_size_allocate_entry(sheet);
7110 gtk_sheet_range_draw (sheet, NULL);
7113 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], row, -1);
7114 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_ROW_HEIGHT], row, height);
7120 gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr *attributes)
7122 const GdkColor *fg, *bg;
7123 const GtkJustification *j ;
7124 const PangoFontDescription *font_desc ;
7125 const GtkSheetCellBorder *border ;
7127 g_return_val_if_fail (sheet != NULL, FALSE);
7128 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
7130 if(row < 0 || col < 0) return FALSE;
7132 init_attributes(sheet, col, attributes);
7137 attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
7138 attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
7140 fg = g_sheet_model_get_foreground(sheet->model, row, col);
7142 attributes->foreground = *fg;
7144 bg = g_sheet_model_get_background(sheet->model, row, col);
7146 attributes->background = *bg;
7148 j = g_sheet_model_get_justification(sheet->model, row, col);
7149 if (j) attributes->justification = *j;
7151 font_desc = g_sheet_model_get_font_desc(sheet->model, row, col);
7152 if ( font_desc ) attributes->font_desc = font_desc;
7154 border = g_sheet_model_get_cell_border(sheet->model, row, col);
7156 if ( border ) attributes->border = *border;
7162 init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
7164 /* DEFAULT VALUES */
7165 attributes->foreground = GTK_WIDGET(sheet)->style->black;
7166 attributes->background = sheet->bg_color;
7167 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
7168 GdkColormap *colormap;
7169 colormap=gdk_colormap_get_system();
7170 gdk_color_black(colormap, &attributes->foreground);
7171 attributes->background = sheet->bg_color;
7173 attributes->justification = xxx_column_justification(sheet, col);
7174 attributes->border.width = 0;
7175 attributes->border.line_style = GDK_LINE_SOLID;
7176 attributes->border.cap_style = GDK_CAP_NOT_LAST;
7177 attributes->border.join_style = GDK_JOIN_MITER;
7178 attributes->border.mask = 0;
7179 attributes->border.color = GTK_WIDGET(sheet)->style->black;
7180 attributes->is_editable = TRUE;
7181 attributes->is_visible = TRUE;
7182 attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
7188 /********************************************************************
7189 * Container Functions:
7194 * gtk_sheet_move_child
7195 * gtk_sheet_position_child
7196 * gtk_sheet_position_children
7197 * gtk_sheet_realize_child
7198 * gtk_sheet_get_child_at
7199 ********************************************************************/
7202 gtk_sheet_put(GtkSheet *sheet, GtkWidget *child, gint x, gint y)
7204 GtkRequisition child_requisition;
7205 GtkSheetChild *child_info;
7207 g_return_val_if_fail(sheet != NULL, NULL);
7208 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7209 g_return_val_if_fail(child != NULL, NULL);
7210 g_return_val_if_fail(child->parent == NULL, NULL);
7212 child_info = g_new (GtkSheetChild, 1);
7213 child_info->widget = child;
7216 child_info->attached_to_cell = FALSE;
7217 child_info->floating = TRUE;
7218 child_info->xpadding = child_info->ypadding = 0;
7219 child_info->xexpand = child_info->yexpand = FALSE;
7220 child_info->xshrink = child_info->yshrink = FALSE;
7221 child_info->xfill = child_info->yfill = FALSE;
7223 sheet->children = g_list_append(sheet->children, child_info);
7225 gtk_widget_set_parent (child, GTK_WIDGET(sheet));
7227 gtk_widget_size_request(child, &child_requisition);
7229 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7231 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7232 (!GTK_WIDGET_REALIZED(child) || GTK_WIDGET_NO_WINDOW(child)))
7233 gtk_sheet_realize_child(sheet, child_info);
7235 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7236 !GTK_WIDGET_MAPPED(child))
7237 gtk_widget_map(child);
7240 gtk_sheet_position_child(sheet, child_info);
7242 /* This will avoid drawing on the titles */
7244 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7246 if(sheet->row_titles_visible)
7247 gdk_window_show(sheet->row_title_window);
7248 if(sheet->column_titles_visible)
7249 gdk_window_show(sheet->column_title_window);
7252 return (child_info);
7256 gtk_sheet_attach_floating (GtkSheet *sheet,
7261 GtkSheetChild *child;
7263 if(row < 0 || col < 0){
7264 gtk_sheet_button_attach(sheet, widget, row, col);
7268 gtk_sheet_get_cell_area(sheet, row, col, &area);
7269 child = gtk_sheet_put(sheet, widget, area.x, area.y);
7270 child->attached_to_cell = TRUE;
7276 gtk_sheet_attach_default (GtkSheet *sheet,
7280 if(row < 0 || col < 0){
7281 gtk_sheet_button_attach(sheet, widget, row, col);
7285 gtk_sheet_attach(sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
7289 gtk_sheet_attach (GtkSheet *sheet,
7298 GtkSheetChild *child = NULL;
7300 if(row < 0 || col < 0){
7301 gtk_sheet_button_attach(sheet, widget, row, col);
7305 child = g_new0(GtkSheetChild, 1);
7306 child->attached_to_cell = TRUE;
7307 child->floating = FALSE;
7308 child->widget = widget;
7311 child->xpadding = xpadding;
7312 child->ypadding = ypadding;
7313 child->xexpand = (xoptions & GTK_EXPAND) != 0;
7314 child->yexpand = (yoptions & GTK_EXPAND) != 0;
7315 child->xshrink = (xoptions & GTK_SHRINK) != 0;
7316 child->yshrink = (yoptions & GTK_SHRINK) != 0;
7317 child->xfill = (xoptions & GTK_FILL) != 0;
7318 child->yfill = (yoptions & GTK_FILL) != 0;
7320 sheet->children = g_list_append(sheet->children, child);
7322 gtk_sheet_get_cell_area(sheet, row, col, &area);
7324 child->x = area.x + child->xpadding;
7325 child->y = area.y + child->ypadding;
7327 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7329 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7330 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7331 gtk_sheet_realize_child(sheet, child);
7333 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7334 !GTK_WIDGET_MAPPED(widget))
7335 gtk_widget_map(widget);
7338 gtk_sheet_position_child(sheet, child);
7340 /* This will avoid drawing on the titles */
7342 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7344 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
7345 gdk_window_show(sheet->row_title_window);
7346 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
7347 gdk_window_show(sheet->column_title_window);
7353 gtk_sheet_button_attach (GtkSheet *sheet,
7357 GtkSheetButton *button = 0;
7358 GtkSheetChild *child;
7359 GtkRequisition button_requisition;
7361 if(row >= 0 && col >= 0) return;
7362 if(row < 0 && col < 0) return;
7364 child = g_new (GtkSheetChild, 1);
7365 child->widget = widget;
7368 child->attached_to_cell = TRUE;
7369 child->floating = FALSE;
7372 child->xpadding = child->ypadding = 0;
7373 child->xshrink = child->yshrink = FALSE;
7374 child->xfill = child->yfill = FALSE;
7377 sheet->children = g_list_append(sheet->children, child);
7379 gtk_sheet_button_size_request(sheet, button, &button_requisition);
7382 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7384 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7385 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7386 gtk_sheet_realize_child(sheet, child);
7388 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7389 !GTK_WIDGET_MAPPED(widget))
7390 gtk_widget_map(widget);
7393 if(row == -1) size_allocate_column_title_buttons(sheet);
7394 if(col == -1) size_allocate_row_title_buttons(sheet);
7399 label_size_request(GtkSheet *sheet, gchar *label, GtkRequisition *req)
7404 gint row_height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)) - 2*CELLOFFSET + 2;
7410 while(words && *words != '\0'){
7411 if(*words == '\n' || *(words+1) == '\0'){
7412 req->height += row_height;
7415 req->width = MAX(req->width, STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, word));
7423 if(n > 0) req->height -= 2;
7427 gtk_sheet_button_size_request (GtkSheet *sheet,
7428 const GtkSheetButton *button,
7429 GtkRequisition *button_requisition)
7431 GtkRequisition requisition;
7432 GtkRequisition label_requisition;
7434 if(gtk_sheet_autoresize(sheet) && button->label && strlen(button->label) > 0){
7435 label_size_request(sheet, button->label, &label_requisition);
7436 label_requisition.width += 2*CELLOFFSET;
7437 label_requisition.height += 2*CELLOFFSET;
7439 label_requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7440 label_requisition.width = COLUMN_MIN_WIDTH;
7445 gtk_widget_size_request(button->child->widget, &requisition);
7446 requisition.width += 2*button->child->xpadding;
7447 requisition.height += 2*button->child->ypadding;
7448 requisition.width += 2*sheet->button->style->xthickness;
7449 requisition.height += 2*sheet->button->style->ythickness;
7453 requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7454 requisition.width = COLUMN_MIN_WIDTH;
7457 *button_requisition = requisition;
7458 button_requisition->width = MAX(requisition.width, label_requisition.width);
7459 button_requisition->height = MAX(requisition.height, label_requisition.height);
7464 gtk_sheet_row_size_request (GtkSheet *sheet,
7468 GtkRequisition button_requisition;
7471 gtk_sheet_button_size_request(sheet,
7472 yyy_row_button(sheet, row),
7473 &button_requisition);
7475 *requisition = button_requisition.height;
7477 children = sheet->children;
7479 GtkSheetChild *child = (GtkSheetChild *)children->data;
7480 GtkRequisition child_requisition;
7482 if(child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink){
7483 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7485 if(child_requisition.height + 2 * child->ypadding > *requisition)
7486 *requisition = child_requisition.height + 2 * child->ypadding;
7488 children = children->next;
7491 sheet->row_requisition = * requisition;
7495 gtk_sheet_column_size_request (GtkSheet *sheet,
7499 GtkRequisition button_requisition;
7502 gtk_sheet_button_size_request(sheet,
7503 xxx_column_button(sheet, col),
7504 &button_requisition);
7506 *requisition = button_requisition.width;
7508 children = sheet->children;
7510 GtkSheetChild *child = (GtkSheetChild *)children->data;
7511 GtkRequisition child_requisition;
7513 if(child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink){
7514 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7516 if(child_requisition.width + 2 * child->xpadding > *requisition)
7517 *requisition = child_requisition.width + 2 * child->xpadding;
7519 children = children->next;
7522 sheet->column_requisition = *requisition;
7526 gtk_sheet_move_child(GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
7528 GtkSheetChild *child;
7531 g_return_if_fail(sheet != NULL);
7532 g_return_if_fail(GTK_IS_SHEET(sheet));
7534 children = sheet->children;
7537 child = children->data;
7539 if(child->widget == widget){
7542 child->row = ROW_FROM_YPIXEL(sheet, y);
7543 child->col = COLUMN_FROM_XPIXEL(sheet, x);
7544 gtk_sheet_position_child(sheet, child);
7548 children = children->next;
7551 g_warning("Widget must be a GtkSheet child");
7556 gtk_sheet_position_child(GtkSheet *sheet, GtkSheetChild *child)
7558 GtkRequisition child_requisition;
7559 GtkAllocation child_allocation;
7565 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7567 if(sheet->column_titles_visible)
7568 yoffset = sheet->column_title_area.height;
7570 if(sheet->row_titles_visible)
7571 xoffset = sheet->row_title_area.width;
7573 if(child->attached_to_cell){
7575 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col);
7576 child->y = ROW_TOP_YPIXEL(sheet, child->row);
7578 if(sheet->row_titles_visible)
7579 child->x-=sheet->row_title_area.width;
7580 if(sheet->column_titles_visible)
7581 child->y-=sheet->column_title_area.height;
7583 width = xxx_column_width(sheet, child->col);
7584 height = yyy_row_height(sheet, child->row);
7587 gtk_sheet_get_cell_area(sheet, child->row, child->col, &area);
7588 child->x = area.x + child->xpadding;
7589 child->y = area.y + child->ypadding;
7591 if(!child->floating){
7592 if(child_requisition.width + 2*child->xpadding <= xxx_column_width(sheet, child->col)){
7594 child_requisition.width = child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7597 child->x = area.x + xxx_column_width(sheet, child->col) / 2 -
7598 child_requisition.width / 2;
7600 child_allocation.width = child_requisition.width;
7603 if(!child->xshrink){
7604 gtk_sheet_set_column_width(sheet, child->col, child_requisition.width + 2 * child->xpadding);
7606 child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7609 if(child_requisition.height + 2*child->ypadding <= yyy_row_height(sheet, child->row)){
7611 child_requisition.height = child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7614 child->y = area.y + yyy_row_height(sheet, child->row) / 2 -
7615 child_requisition.height / 2;
7617 child_allocation.height = child_requisition.height;
7620 if(!child->yshrink){
7621 gtk_sheet_set_row_height(sheet, child->row, child_requisition.height + 2 * child->ypadding);
7623 child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7626 child_allocation.width = child_requisition.width;
7627 child_allocation.height = child_requisition.height;
7630 x = child_allocation.x = child->x + xoffset;
7631 y = child_allocation.y = child->y + yoffset;
7635 x = child_allocation.x = child->x + sheet->hoffset + xoffset;
7636 x = child_allocation.x = child->x + xoffset;
7637 y = child_allocation.y = child->y + sheet->voffset + yoffset;
7638 y = child_allocation.y = child->y + yoffset;
7639 child_allocation.width = child_requisition.width;
7640 child_allocation.height = child_requisition.height;
7643 gtk_widget_size_allocate(child->widget, &child_allocation);
7644 gtk_widget_queue_draw(child->widget);
7648 gtk_sheet_forall (GtkContainer *container,
7649 gboolean include_internals,
7650 GtkCallback callback,
7651 gpointer callback_data)
7654 GtkSheetChild *child;
7657 g_return_if_fail (GTK_IS_SHEET (container));
7658 g_return_if_fail (callback != NULL);
7660 sheet = GTK_SHEET (container);
7661 children = sheet->children;
7664 child = children->data;
7665 children = children->next;
7667 (* callback) (child->widget, callback_data);
7670 (* callback) (sheet->button, callback_data);
7671 if(sheet->sheet_entry)
7672 (* callback) (sheet->sheet_entry, callback_data);
7677 gtk_sheet_position_children(GtkSheet *sheet)
7680 GtkSheetChild *child;
7682 children = sheet->children;
7686 child = (GtkSheetChild *)children->data;
7688 if(child->col !=-1 && child->row != -1)
7689 gtk_sheet_position_child(sheet, child);
7691 if(child->row == -1){
7692 if(child->col < MIN_VISIBLE_COLUMN(sheet) ||
7693 child->col > MAX_VISIBLE_COLUMN(sheet))
7694 gtk_sheet_child_hide(child);
7696 gtk_sheet_child_show(child);
7698 if(child->col == -1){
7699 if(child->row < MIN_VISIBLE_ROW(sheet) ||
7700 child->row > MAX_VISIBLE_ROW(sheet))
7701 gtk_sheet_child_hide(child);
7703 gtk_sheet_child_show(child);
7706 children = children->next;
7712 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
7716 GtkSheetChild *child = 0;
7718 g_return_if_fail(container != NULL);
7719 g_return_if_fail(GTK_IS_SHEET(container));
7721 sheet = GTK_SHEET(container);
7723 children = sheet->children;
7727 child = (GtkSheetChild *)children->data;
7729 if(child->widget == widget) break;
7731 children = children->next;
7736 gtk_widget_unparent (widget);
7737 child->widget = NULL;
7739 sheet->children = g_list_remove_link (sheet->children, children);
7740 g_list_free_1 (children);
7747 gtk_sheet_realize_child(GtkSheet *sheet, GtkSheetChild *child)
7751 widget = GTK_WIDGET(sheet);
7753 if(GTK_WIDGET_REALIZED(widget)){
7754 if(child->row == -1)
7755 gtk_widget_set_parent_window(child->widget, sheet->column_title_window);
7756 else if(child->col == -1)
7757 gtk_widget_set_parent_window(child->widget, sheet->row_title_window);
7759 gtk_widget_set_parent_window(child->widget, sheet->sheet_window);
7762 gtk_widget_set_parent(child->widget, widget);
7768 gtk_sheet_get_child_at(GtkSheet *sheet, gint row, gint col)
7771 GtkSheetChild *child = 0;
7773 g_return_val_if_fail(sheet != NULL, NULL);
7774 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7776 children = sheet->children;
7780 child = (GtkSheetChild *)children->data;
7782 if(child->attached_to_cell)
7783 if(child->row == row && child->col == col) break;
7785 children = children->next;
7788 if(children) return child;
7794 gtk_sheet_child_hide(GtkSheetChild *child)
7796 g_return_if_fail(child != NULL);
7797 gtk_widget_hide(child->widget);
7801 gtk_sheet_child_show(GtkSheetChild *child)
7803 g_return_if_fail(child != NULL);
7805 gtk_widget_show(child->widget);
7809 gtk_sheet_get_model(const GtkSheet *sheet)
7811 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
7813 return sheet->model;