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
104 static gboolean gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col);
107 void dispose_string (const GtkSheet *sheet, gchar *text)
109 GSheetModel *model = gtk_sheet_get_model(sheet);
114 if (g_sheet_model_free_strings(model))
119 guint DEFAULT_ROW_HEIGHT(GtkWidget *widget)
121 if(!widget->style->font_desc) return 24;
123 PangoContext *context = gtk_widget_get_pango_context(widget);
124 PangoFontMetrics *metrics = pango_context_get_metrics(context,
125 widget->style->font_desc,
126 pango_context_get_language(context));
127 guint val = pango_font_metrics_get_descent(metrics) +
128 pango_font_metrics_get_ascent(metrics);
129 pango_font_metrics_unref(metrics);
130 return PANGO_PIXELS(val)+2*CELLOFFSET;
133 static inline guint DEFAULT_FONT_ASCENT(GtkWidget *widget)
135 if(!widget->style->font_desc) return 12;
137 PangoContext *context = gtk_widget_get_pango_context(widget);
138 PangoFontMetrics *metrics = pango_context_get_metrics(context,
139 widget->style->font_desc,
140 pango_context_get_language(context));
141 guint val = pango_font_metrics_get_ascent(metrics);
142 pango_font_metrics_unref(metrics);
143 return PANGO_PIXELS(val);
146 static inline guint STRING_WIDTH(GtkWidget *widget,
147 const PangoFontDescription *font, const gchar *text)
152 layout = gtk_widget_create_pango_layout (widget, text);
153 pango_layout_set_font_description (layout, font);
155 pango_layout_get_extents (layout, NULL, &rect);
157 g_object_unref(G_OBJECT(layout));
158 return PANGO_PIXELS(rect.width);
161 static inline guint DEFAULT_FONT_DESCENT(GtkWidget *widget)
163 if(!widget->style->font_desc) return 12;
165 PangoContext *context = gtk_widget_get_pango_context(widget);
166 PangoFontMetrics *metrics = pango_context_get_metrics(context,
167 widget->style->font_desc,
168 pango_context_get_language(context));
169 guint val = pango_font_metrics_get_descent(metrics);
170 pango_font_metrics_unref(metrics);
171 return PANGO_PIXELS(val);
177 yyy_row_is_visible(GtkSheet *sheet, gint row)
179 GSheetRow *row_geo = sheet->row_geometry;
181 return g_sheet_row_get_visibility(row_geo, row, sheet);
186 yyy_row_is_sensitive(GtkSheet *sheet, gint row)
188 GSheetRow *row_geo = sheet->row_geometry;
190 return g_sheet_row_get_sensitivity(row_geo, row, sheet);
196 yyy_row_count(const GtkSheet *sheet)
198 GSheetRow *row_geo = sheet->row_geometry;
200 return g_sheet_row_get_row_count(row_geo, sheet);
204 yyy_row_height(const GtkSheet *sheet, gint row)
206 GSheetRow *row_geo = sheet->row_geometry;
208 return g_sheet_row_get_height(row_geo, row, sheet);
212 yyy_row_top_ypixel(GtkSheet *sheet, gint row)
214 GSheetRow *geo = sheet->row_geometry;
216 gint y = g_sheet_row_start_pixel(geo, row, sheet);
218 if ( sheet->column_titles_visible )
219 y += sheet->column_title_area.height;
225 /* Return the row containing pixel Y */
227 yyy_row_ypixel_to_row(GtkSheet *sheet, gint y)
229 GSheetRow *geo = sheet->row_geometry;
231 gint cy = sheet->voffset;
233 if(sheet->column_titles_visible)
234 cy += sheet->column_title_area.height;
239 return g_sheet_row_pixel_to_row(geo, y - cy, sheet);
243 /* gives the top pixel of the given row in context of
244 * the sheet's voffset */
246 ROW_TOP_YPIXEL(GtkSheet *sheet, gint row)
248 return (sheet->voffset + yyy_row_top_ypixel(sheet, row));
252 /* returns the row index from a y pixel location in the
253 * context of the sheet's voffset */
255 ROW_FROM_YPIXEL(GtkSheet *sheet, gint y)
257 return (yyy_row_ypixel_to_row(sheet, y));
260 static inline const GtkSheetButton *
261 xxx_column_button(GtkSheet *sheet, gint col)
263 GSheetColumn *col_geo = sheet->column_geometry;
265 return g_sheet_column_get_button(col_geo, col, sheet);
270 xxx_column_left_xpixel(GtkSheet *sheet, gint col)
272 GSheetColumn *geo = sheet->column_geometry;
274 gint x = g_sheet_column_start_pixel(geo, col, sheet);
276 if ( sheet->row_titles_visible )
277 x += sheet->row_title_area.width;
283 xxx_column_width(const GtkSheet *sheet, gint col)
285 GSheetColumn *col_geo = sheet->column_geometry;
287 return g_sheet_column_get_width(col_geo, col, sheet);
292 xxx_set_column_width(GtkSheet *sheet, gint col, gint width)
294 if ( sheet->column_geometry )
295 g_sheet_column_set_width(sheet->column_geometry, col, width, sheet);
299 xxx_column_set_left_column(GtkSheet *sheet, gint col, gint i)
301 GSheetColumn *col_geo = sheet->column_geometry;
303 g_sheet_column_set_left_text_column(col_geo, col, i, sheet);
307 xxx_column_left_column(const GtkSheet *sheet, gint col)
309 GSheetColumn *col_geo = sheet->column_geometry;
311 return g_sheet_column_get_left_text_column(col_geo, col, sheet);
315 xxx_column_set_right_column(GtkSheet *sheet, gint col, gint i)
317 GSheetColumn *col_geo = sheet->column_geometry;
319 g_sheet_column_set_right_text_column(col_geo, col, i, sheet);
323 xxx_column_right_column(const GtkSheet *sheet, gint col)
325 GSheetColumn *col_geo = sheet->column_geometry;
327 return g_sheet_column_get_right_text_column(col_geo, col, sheet);
330 static inline GtkJustification
331 xxx_column_justification(const GtkSheet *sheet, gint col)
333 GSheetColumn *col_geo = sheet->column_geometry;
335 return g_sheet_column_get_justification(col_geo, col, sheet);
339 xxx_column_is_visible(GtkSheet *sheet, gint col)
341 GSheetColumn *col_geo = sheet->column_geometry;
343 return g_sheet_column_get_visibility(col_geo, col, sheet);
348 xxx_column_is_sensitive(GtkSheet *sheet, gint col)
350 GSheetColumn *col_geo = sheet->column_geometry;
352 return g_sheet_column_get_sensitivity(col_geo, col, sheet);
356 /* gives the left pixel of the given column in context of
357 * the sheet's hoffset */
359 COLUMN_LEFT_XPIXEL(GtkSheet *sheet, gint ncol)
361 return (sheet->hoffset + xxx_column_left_xpixel(sheet, ncol));
365 xxx_column_count(const GtkSheet *sheet)
367 GSheetColumn *col_geo = sheet->column_geometry;
369 return g_sheet_column_get_column_count(col_geo, sheet);
372 /* returns the column index from a x pixel location in the
373 * context of the sheet's hoffset */
375 COLUMN_FROM_XPIXEL (GtkSheet * sheet,
381 if( sheet->row_titles_visible )
382 cx += sheet->row_title_area.width;
385 for (i = 0; i < xxx_column_count(sheet); i++)
387 if (x >= cx && x <= (cx + xxx_column_width(sheet, i)) &&
388 xxx_column_is_visible(sheet, i))
390 if( xxx_column_is_visible(sheet, i))
391 cx += xxx_column_width(sheet, i);
395 return xxx_column_count(sheet) - 1;
398 /* returns the total height of the sheet */
399 static inline gint SHEET_HEIGHT(GtkSheet *sheet)
401 const gint n_rows = yyy_row_count(sheet);
403 return yyy_row_top_ypixel(sheet, n_rows - 1) +
404 yyy_row_height(sheet, n_rows - 1);
408 static inline const GtkSheetButton *
409 yyy_row_button(GtkSheet *sheet, gint row)
411 GSheetRow *row_geo = sheet->row_geometry;
413 return g_sheet_row_get_button(row_geo, row, sheet);
420 yyy_set_row_height(GtkSheet *sheet, gint row, gint height)
422 if ( sheet->row_geometry )
423 g_sheet_row_set_height(sheet->row_geometry, row, height, sheet);
428 /* returns the total width of the sheet */
429 static inline gint SHEET_WIDTH(GtkSheet *sheet)
433 cx = ( sheet->row_titles_visible ? sheet->row_title_area.width : 0);
435 for (i=0; i < xxx_column_count(sheet); i++)
436 if(xxx_column_is_visible(sheet, i)) cx += xxx_column_width(sheet, i);
441 #define MIN_VISIBLE_ROW(sheet) sheet->view.row0
442 #define MAX_VISIBLE_ROW(sheet) sheet->view.rowi
443 #define MIN_VISIBLE_COLUMN(sheet) sheet->view.col0
444 #define MAX_VISIBLE_COLUMN(sheet) sheet->view.coli
448 POSSIBLE_XDRAG(GtkSheet *sheet, gint x, gint *drag_column)
452 column=COLUMN_FROM_XPIXEL(sheet, x);
455 xdrag=COLUMN_LEFT_XPIXEL(sheet,column)+CELL_SPACING;
456 if(x <= xdrag+DRAG_WIDTH/2 && column != 0){
457 while(! xxx_column_is_visible(sheet, column-1) && column>0) column--;
458 *drag_column=column-1;
459 return xxx_column_is_sensitive(sheet, column-1);
462 xdrag+= xxx_column_width(sheet, column);
463 if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag+DRAG_WIDTH/2)
464 return xxx_column_is_sensitive(sheet, column);
470 POSSIBLE_YDRAG(GtkSheet *sheet, gint y, gint *drag_row)
474 row=ROW_FROM_YPIXEL(sheet, y);
477 ydrag=ROW_TOP_YPIXEL(sheet,row)+CELL_SPACING;
478 if(y <= ydrag+DRAG_WIDTH/2 && row != 0){
479 while(!yyy_row_is_visible(sheet, row-1) && row>0) row--;
481 return yyy_row_is_sensitive(sheet, row-1);
484 ydrag+=yyy_row_height(sheet, row);
486 if(y >= ydrag-DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2)
487 return yyy_row_is_sensitive(sheet, row);
493 static inline gint POSSIBLE_DRAG(GtkSheet *sheet, gint x, gint y,
494 gint *drag_row, gint *drag_column)
498 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
499 *drag_row=ROW_FROM_YPIXEL(sheet,y);
501 if(x>=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0)-DRAG_WIDTH/2 &&
502 x<=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
503 xxx_column_width(sheet, sheet->range.coli) + DRAG_WIDTH/2){
504 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.row0);
505 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
506 *drag_row=sheet->range.row0;
509 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
510 yyy_row_height(sheet, sheet->range.rowi);
511 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
512 *drag_row=sheet->range.rowi;
517 if(y>=ROW_TOP_YPIXEL(sheet,sheet->range.row0)-DRAG_WIDTH/2 &&
518 y<=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
519 yyy_row_height(sheet, sheet->range.rowi)+DRAG_WIDTH/2){
520 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0);
521 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
522 *drag_column=sheet->range.col0;
525 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
526 xxx_column_width(sheet, sheet->range.coli);
527 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
528 *drag_column=sheet->range.coli;
535 static inline gint POSSIBLE_RESIZE(GtkSheet *sheet, gint x, gint y,
536 gint *drag_row, gint *drag_column)
540 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
541 xxx_column_width(sheet, sheet->range.coli);
543 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
544 yyy_row_height(sheet, sheet->range.rowi);
546 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
547 ydrag = ROW_TOP_YPIXEL(sheet, sheet->view.row0);
549 if(sheet->state == GTK_SHEET_ROW_SELECTED)
550 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0);
552 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
553 *drag_row=ROW_FROM_YPIXEL(sheet,y);
555 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2 &&
556 y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2) return TRUE;
561 static void gtk_sheet_class_init (GtkSheetClass * klass);
562 static void gtk_sheet_init (GtkSheet * sheet);
563 static void gtk_sheet_destroy (GtkObject * object);
564 static void gtk_sheet_finalize (GObject * object);
565 static void gtk_sheet_style_set (GtkWidget *widget,
566 GtkStyle *previous_style);
567 static void gtk_sheet_realize (GtkWidget * widget);
568 static void gtk_sheet_unrealize (GtkWidget * widget);
569 static void gtk_sheet_map (GtkWidget * widget);
570 static void gtk_sheet_unmap (GtkWidget * widget);
571 static gint gtk_sheet_expose (GtkWidget * widget,
572 GdkEventExpose * event);
573 static void gtk_sheet_forall (GtkContainer *container,
574 gboolean include_internals,
575 GtkCallback callback,
576 gpointer callback_data);
578 static void gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
579 GtkAdjustment *hadjustment,
580 GtkAdjustment *vadjustment);
582 static gint gtk_sheet_button_press (GtkWidget * widget,
583 GdkEventButton * event);
584 static gint gtk_sheet_button_release (GtkWidget * widget,
585 GdkEventButton * event);
586 static gint gtk_sheet_motion (GtkWidget * widget,
587 GdkEventMotion * event);
588 static gint gtk_sheet_entry_key_press (GtkWidget *widget,
590 static gint gtk_sheet_key_press (GtkWidget *widget,
592 static void gtk_sheet_size_request (GtkWidget * widget,
593 GtkRequisition * requisition);
594 static void gtk_sheet_size_allocate (GtkWidget * widget,
595 GtkAllocation * allocation);
599 static gint gtk_sheet_range_isvisible (GtkSheet * sheet,
600 GtkSheetRange range);
601 static gint gtk_sheet_cell_isvisible (GtkSheet * sheet,
602 gint row, gint column);
605 static gint gtk_sheet_scroll (gpointer data);
606 static gint gtk_sheet_flash (gpointer data);
608 /* Drawing Routines */
610 /* draw cell background and frame */
611 static void gtk_sheet_cell_draw_default (GtkSheet *sheet,
612 gint row, gint column);
614 /* draw cell border */
615 static void gtk_sheet_cell_draw_border (GtkSheet *sheet,
616 gint row, gint column,
619 /* draw cell contents */
620 static void gtk_sheet_cell_draw_label (GtkSheet *sheet,
621 gint row, gint column);
623 /* draw visible part of range. If range==NULL then draw the whole screen */
624 static void gtk_sheet_range_draw (GtkSheet *sheet,
625 const GtkSheetRange *range);
627 /* highlight the visible part of the selected range */
628 static void gtk_sheet_range_draw_selection (GtkSheet *sheet,
629 GtkSheetRange range);
633 static gint gtk_sheet_move_query (GtkSheet *sheet,
634 gint row, gint column);
635 static void gtk_sheet_real_select_range (GtkSheet * sheet,
636 GtkSheetRange * range);
637 static void gtk_sheet_real_unselect_range (GtkSheet * sheet,
638 const GtkSheetRange * range);
639 static void gtk_sheet_extend_selection (GtkSheet *sheet,
640 gint row, gint column);
641 static void gtk_sheet_new_selection (GtkSheet *sheet,
642 GtkSheetRange *range);
643 static void gtk_sheet_draw_border (GtkSheet *sheet,
644 GtkSheetRange range);
645 static void gtk_sheet_draw_corners (GtkSheet *sheet,
646 GtkSheetRange range);
649 /* Active Cell handling */
651 static void gtk_sheet_entry_changed (GtkWidget *widget,
653 static gboolean gtk_sheet_deactivate_cell (GtkSheet *sheet);
654 static void gtk_sheet_hide_active_cell (GtkSheet *sheet);
655 static gboolean gtk_sheet_activate_cell (GtkSheet *sheet,
657 static void gtk_sheet_draw_active_cell (GtkSheet *sheet);
658 static void gtk_sheet_show_active_cell (GtkSheet *sheet);
659 static void gtk_sheet_click_cell (GtkSheet *sheet,
666 static void gtk_sheet_make_backing_pixmap (GtkSheet *sheet,
667 guint width, guint height);
668 static void gtk_sheet_draw_backing_pixmap (GtkSheet *sheet,
669 GtkSheetRange range);
672 static void adjust_scrollbars (GtkSheet * sheet);
673 static void vadjustment_changed (GtkAdjustment * adjustment,
675 static void hadjustment_changed (GtkAdjustment * adjustment,
677 static void vadjustment_value_changed (GtkAdjustment * adjustment,
679 static void hadjustment_value_changed (GtkAdjustment * adjustment,
683 static void draw_xor_vline (GtkSheet * sheet);
684 static void draw_xor_hline (GtkSheet * sheet);
685 static void draw_xor_rectangle (GtkSheet *sheet,
686 GtkSheetRange range);
687 static void gtk_sheet_draw_flashing_range (GtkSheet *sheet,
688 GtkSheetRange range);
689 static guint new_column_width (GtkSheet * sheet,
692 static guint new_row_height (GtkSheet * sheet,
697 static void create_global_button (GtkSheet *sheet);
698 static void global_button_clicked (GtkWidget *widget,
702 static void create_sheet_entry (GtkSheet *sheet);
703 static void gtk_sheet_size_allocate_entry (GtkSheet *sheet);
704 static void gtk_sheet_entry_set_max_size (GtkSheet *sheet);
706 /* Sheet button gadgets */
708 static void size_allocate_column_title_buttons (GtkSheet * sheet);
709 static void size_allocate_row_title_buttons (GtkSheet * sheet);
712 static void gtk_sheet_button_draw (GtkSheet *sheet,
713 gint row, gint column);
714 static void size_allocate_global_button (GtkSheet *sheet);
715 static void gtk_sheet_button_size_request (GtkSheet *sheet,
716 const GtkSheetButton *button,
717 GtkRequisition *requisition);
719 /* Attributes routines */
720 static void init_attributes (GtkSheet *sheet, gint col,
721 GtkSheetCellAttr *attributes);
724 /* Memory allocation routines */
725 static void gtk_sheet_real_range_clear (GtkSheet *sheet,
726 const GtkSheetRange *range,
728 static void gtk_sheet_real_cell_clear (GtkSheet *sheet,
734 /* Container Functions */
735 static void gtk_sheet_remove (GtkContainer *container,
737 static void gtk_sheet_realize_child (GtkSheet *sheet,
738 GtkSheetChild *child);
739 static void gtk_sheet_position_child (GtkSheet *sheet,
740 GtkSheetChild *child);
741 static void gtk_sheet_position_children (GtkSheet *sheet);
742 static void gtk_sheet_child_show (GtkSheetChild *child);
743 static void gtk_sheet_child_hide (GtkSheetChild *child);
744 static void gtk_sheet_column_size_request (GtkSheet *sheet,
747 static void gtk_sheet_row_size_request (GtkSheet *sheet,
755 _gtkextra_signal_emit(GtkObject *object, guint signal_id, ...);
777 static GtkContainerClass *parent_class = NULL;
778 static guint sheet_signals[LAST_SIGNAL] = {0};
782 gtk_sheet_get_type ()
784 static GType sheet_type = 0;
788 static const GTypeInfo sheet_info =
790 sizeof (GtkSheetClass),
793 (GClassInitFunc) gtk_sheet_class_init,
798 (GInstanceInitFunc) gtk_sheet_init,
802 g_type_register_static (GTK_TYPE_CONTAINER, "GtkSheet",
808 static GtkSheetRange*
809 gtk_sheet_range_copy (const GtkSheetRange *range)
811 GtkSheetRange *new_range;
813 g_return_val_if_fail (range != NULL, NULL);
815 new_range = g_new (GtkSheetRange, 1);
823 gtk_sheet_range_free (GtkSheetRange *range)
825 g_return_if_fail (range != NULL);
831 gtk_sheet_range_get_type (void)
833 static GType sheet_range_type=0;
835 if(!sheet_range_type)
837 sheet_range_type = g_boxed_type_register_static("GtkSheetRange", (GBoxedCopyFunc)gtk_sheet_range_copy, (GBoxedFreeFunc)gtk_sheet_range_free);
839 return sheet_range_type;
844 gtk_sheet_class_init (GtkSheetClass * klass)
846 GtkObjectClass *object_class;
847 GtkWidgetClass *widget_class;
848 GtkContainerClass *container_class;
849 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
851 object_class = (GtkObjectClass *) klass;
852 widget_class = (GtkWidgetClass *) klass;
853 container_class = (GtkContainerClass *) klass;
855 parent_class = g_type_class_peek_parent (klass);
858 * GtkSheet::select-row
859 * @sheet: the sheet widget that emitted the signal
860 * @row: the newly selected row index
862 * A row has been selected.
864 sheet_signals[SELECT_ROW] =
865 gtk_signal_new ("select-row",
867 GTK_CLASS_TYPE(object_class),
868 GTK_SIGNAL_OFFSET (GtkSheetClass, select_row),
870 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
873 * GtkSheet::select-column
874 * @sheet: the sheet widget that emitted the signal
875 * @column: the newly selected column index
877 * A column has been selected.
879 sheet_signals[SELECT_COLUMN] =
880 gtk_signal_new ("select-column",
882 GTK_CLASS_TYPE(object_class),
883 GTK_SIGNAL_OFFSET (GtkSheetClass, select_column),
885 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
889 * GtkSheet::double-click-row
890 * @sheet: the sheet widget that emitted the signal
891 * @row: the row that was double clicked.
893 * A row's title button has been double clicked
895 sheet_signals[DOUBLE_CLICK_ROW] =
896 gtk_signal_new ("double-click-row",
898 GTK_CLASS_TYPE(object_class),
901 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
905 * GtkSheet::double-click-column
906 * @sheet: the sheet widget that emitted the signal
907 * @column: the column that was double clicked.
909 * A column's title button has been double clicked
911 sheet_signals[DOUBLE_CLICK_COLUMN] =
912 gtk_signal_new ("double-click-column",
914 GTK_CLASS_TYPE(object_class),
917 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
919 sheet_signals[SELECT_RANGE] =
920 gtk_signal_new ("select-range",
922 GTK_CLASS_TYPE(object_class),
923 GTK_SIGNAL_OFFSET (GtkSheetClass, select_range),
924 gtkextra_VOID__BOXED,
925 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
927 sheet_signals[CLIP_RANGE] =
928 gtk_signal_new ("clip-range",
930 GTK_CLASS_TYPE(object_class),
931 GTK_SIGNAL_OFFSET (GtkSheetClass, clip_range),
932 gtkextra_VOID__BOXED,
933 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
935 sheet_signals[RESIZE_RANGE] =
936 gtk_signal_new ("resize-range",
938 GTK_CLASS_TYPE(object_class),
939 GTK_SIGNAL_OFFSET (GtkSheetClass, resize_range),
940 gtkextra_VOID__BOXED_BOXED,
941 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
942 sheet_signals[MOVE_RANGE] =
943 gtk_signal_new ("move-range",
945 GTK_CLASS_TYPE(object_class),
946 GTK_SIGNAL_OFFSET (GtkSheetClass, move_range),
947 gtkextra_VOID__BOXED_BOXED,
948 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
949 sheet_signals[TRAVERSE] =
950 gtk_signal_new ("traverse",
952 GTK_CLASS_TYPE(object_class),
953 GTK_SIGNAL_OFFSET (GtkSheetClass, traverse),
954 gtkextra_BOOLEAN__INT_INT_POINTER_POINTER,
955 GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT,
956 GTK_TYPE_POINTER, GTK_TYPE_POINTER);
958 sheet_signals[DEACTIVATE] =
959 gtk_signal_new ("deactivate",
961 GTK_CLASS_TYPE(object_class),
962 GTK_SIGNAL_OFFSET (GtkSheetClass, deactivate),
963 gtkextra_BOOLEAN__INT_INT,
964 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
966 sheet_signals[ACTIVATE] =
967 gtk_signal_new ("activate",
969 GTK_CLASS_TYPE(object_class),
970 GTK_SIGNAL_OFFSET (GtkSheetClass, activate),
971 gtkextra_BOOLEAN__INT_INT,
972 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
974 sheet_signals[SET_CELL] =
975 gtk_signal_new ("set-cell",
977 GTK_CLASS_TYPE(object_class),
978 GTK_SIGNAL_OFFSET (GtkSheetClass, set_cell),
979 gtkextra_VOID__INT_INT,
980 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
982 sheet_signals[CLEAR_CELL] =
983 gtk_signal_new ("clear-cell",
985 GTK_CLASS_TYPE(object_class),
986 GTK_SIGNAL_OFFSET (GtkSheetClass, clear_cell),
987 gtkextra_VOID__INT_INT,
988 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
990 sheet_signals[CHANGED] =
991 gtk_signal_new ("changed",
993 GTK_CLASS_TYPE(object_class),
994 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
995 gtkextra_VOID__INT_INT,
996 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
998 sheet_signals[NEW_COL_WIDTH] =
999 gtk_signal_new ("new-column-width",
1001 GTK_CLASS_TYPE(object_class),
1002 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1003 gtkextra_VOID__INT_INT,
1004 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1006 sheet_signals[NEW_ROW_HEIGHT] =
1007 gtk_signal_new ("new-row-height",
1009 GTK_CLASS_TYPE(object_class),
1010 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1011 gtkextra_VOID__INT_INT,
1012 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1014 widget_class->set_scroll_adjustments_signal =
1015 gtk_signal_new ("set-scroll-adjustments",
1017 GTK_CLASS_TYPE(object_class),
1018 GTK_SIGNAL_OFFSET (GtkSheetClass, set_scroll_adjustments),
1019 gtkextra_VOID__OBJECT_OBJECT,
1020 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1023 container_class->add = NULL;
1024 container_class->remove = gtk_sheet_remove;
1025 container_class->forall = gtk_sheet_forall;
1027 object_class->destroy = gtk_sheet_destroy;
1028 gobject_class->finalize = gtk_sheet_finalize;
1030 widget_class->realize = gtk_sheet_realize;
1031 widget_class->unrealize = gtk_sheet_unrealize;
1032 widget_class->map = gtk_sheet_map;
1033 widget_class->unmap = gtk_sheet_unmap;
1034 widget_class->style_set = gtk_sheet_style_set;
1035 widget_class->button_press_event = gtk_sheet_button_press;
1036 widget_class->button_release_event = gtk_sheet_button_release;
1037 widget_class->motion_notify_event = gtk_sheet_motion;
1038 widget_class->key_press_event = gtk_sheet_key_press;
1039 widget_class->expose_event = gtk_sheet_expose;
1040 widget_class->size_request = gtk_sheet_size_request;
1041 widget_class->size_allocate = gtk_sheet_size_allocate;
1042 widget_class->focus_in_event = NULL;
1043 widget_class->focus_out_event = NULL;
1045 klass->set_scroll_adjustments = gtk_sheet_set_scroll_adjustments;
1046 klass->select_row = NULL;
1047 klass->select_column = NULL;
1048 klass->select_range = NULL;
1049 klass->clip_range = NULL;
1050 klass->resize_range = NULL;
1051 klass->move_range = NULL;
1052 klass->traverse = NULL;
1053 klass->deactivate = NULL;
1054 klass->activate = NULL;
1055 klass->set_cell = NULL;
1056 klass->clear_cell = NULL;
1057 klass->changed = NULL;
1062 gtk_sheet_init (GtkSheet *sheet)
1064 sheet->column_geometry = NULL;
1065 sheet->row_geometry = NULL;
1067 sheet->children = NULL;
1070 sheet->selection_mode = GTK_SELECTION_BROWSE;
1071 sheet->freeze_count = 0;
1072 sheet->state = GTK_SHEET_NORMAL;
1074 GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW);
1075 GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS);
1077 sheet->view.row0 = 0;
1078 sheet->view.col0 = 0;
1079 sheet->view.rowi = 0;
1080 sheet->view.coli = 0;
1082 sheet->column_title_window=NULL;
1083 sheet->column_title_area.x=0;
1084 sheet->column_title_area.y=0;
1085 sheet->column_title_area.width=0;
1086 sheet->column_title_area.height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
1088 sheet->row_title_window=NULL;
1089 sheet->row_title_area.x=0;
1090 sheet->row_title_area.y=0;
1091 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1092 sheet->row_title_area.height=0;
1095 sheet->active_cell.row=0;
1096 sheet->active_cell.col=0;
1097 sheet->selection_cell.row=0;
1098 sheet->selection_cell.col=0;
1100 sheet->sheet_entry=NULL;
1103 sheet->range.row0=0;
1104 sheet->range.rowi=0;
1105 sheet->range.col0=0;
1106 sheet->range.coli=0;
1108 sheet->state=GTK_SHEET_NORMAL;
1110 sheet->sheet_window = NULL;
1111 sheet->sheet_window_width = 0;
1112 sheet->sheet_window_height = 0;
1113 sheet->sheet_entry = NULL;
1114 sheet->button = NULL;
1119 sheet->hadjustment = NULL;
1120 sheet->vadjustment = NULL;
1122 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
1123 sheet->xor_gc = NULL;
1124 sheet->fg_gc = NULL;
1125 sheet->bg_gc = NULL;
1129 gdk_color_parse("white", &sheet->bg_color);
1130 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1131 gdk_color_parse("gray", &sheet->grid_color);
1132 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1133 sheet->show_grid = TRUE;
1137 /* Callback which occurs whenever rows are inserted/deleted in the model */
1139 rows_inserted_deleted_callback (GSheetModel *m, gint first_row, gint n_rows,
1142 GtkSheet *sheet = GTK_SHEET(data);
1144 GtkSheetRange range;
1146 /* Need to update all the rows starting from the first row and onwards.
1147 * Previous rows are unchanged, so don't need to be updated.
1149 range.row0 = first_row;
1151 range.rowi = yyy_row_count(sheet) - 1;
1152 range.coli = xxx_column_count(sheet) - 1;
1154 gtk_sheet_range_draw(sheet, &range);
1158 If row0 or rowi are negative, then all rows will be updated.
1159 If col0 or coli are negative, then all columns will be updated.
1162 range_update_callback (GSheetModel *m, gint row0, gint col0,
1163 gint rowi, gint coli, gpointer data)
1165 GtkSheet *sheet = GTK_SHEET(data);
1167 GtkSheetRange range;
1174 if( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
1176 gtk_sheet_range_draw(sheet, NULL);
1179 else if ( row0 < 0 || rowi < 0 )
1181 range.row0=MIN_VISIBLE_ROW(sheet);
1182 range.rowi=MAX_VISIBLE_ROW(sheet);
1184 else if ( col0 < 0 || coli < 0 )
1186 range.col0=MIN_VISIBLE_COLUMN(sheet);
1187 range.coli=MAX_VISIBLE_COLUMN(sheet);
1190 gtk_sheet_range_draw(sheet, &range);
1194 static void gtk_sheet_construct (GtkSheet *sheet,
1197 const gchar *title);
1202 * @rows: initial number of rows
1203 * @columns: initial number of columns
1204 * @title: sheet title
1205 * @model: the model to use for the sheet data
1207 * Creates a new sheet widget with the given number of rows and columns.
1209 * Returns: the new sheet widget
1212 gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, const gchar *title,
1217 widget = gtk_type_new (gtk_sheet_get_type ());
1219 gtk_sheet_construct(GTK_SHEET(widget), vgeo, hgeo, title);
1222 gtk_sheet_set_model(GTK_SHEET(widget), model);
1230 * gtk_sheet_set_model
1231 * @sheet: the sheet to set the model for
1232 * @model: the model to use for the sheet data
1234 * Sets the model for a GtkSheet
1238 gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model)
1240 g_return_if_fail (GTK_IS_SHEET (sheet));
1241 g_return_if_fail (G_IS_SHEET_MODEL (model));
1243 sheet->model = model;
1245 g_signal_connect(model, "range_changed",
1246 G_CALLBACK(range_update_callback), sheet);
1248 g_signal_connect(model, "rows_inserted",
1249 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1251 g_signal_connect(model, "rows_deleted",
1252 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1259 column_titles_changed(GtkWidget *w, gint first, gint n_columns, gpointer data)
1261 GtkSheet *sheet = GTK_SHEET(data);
1264 if(!GTK_SHEET_IS_FROZEN(sheet)){
1266 for ( i = first ; i <= MAX_VISIBLE_COLUMN(sheet) ; ++i )
1268 gtk_sheet_button_draw(sheet, -1, i);
1269 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, i);
1275 gtk_sheet_construct (GtkSheet *sheet,
1280 g_return_if_fail(G_IS_SHEET_COLUMN(hgeo));
1281 g_return_if_fail(G_IS_SHEET_ROW(vgeo));
1283 sheet->column_geometry = hgeo;
1284 sheet->row_geometry = vgeo;
1287 sheet->columns_resizable = TRUE;
1288 sheet->rows_resizable = TRUE;
1290 sheet->row_titles_visible = TRUE;
1291 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1293 sheet->column_titles_visible = TRUE;
1294 sheet->autoscroll = TRUE;
1295 sheet->justify_entry = TRUE;
1296 sheet->locked = FALSE;
1299 /* create sheet entry */
1300 sheet->entry_type = 0;
1301 create_sheet_entry (sheet);
1303 /* create global selection button */
1304 create_global_button(sheet);
1307 sheet->name = g_strdup(title);
1309 g_signal_connect(sheet->column_geometry, "columns_changed",
1310 G_CALLBACK(column_titles_changed), sheet);
1316 gtk_sheet_new_with_custom_entry (GSheetRow *rows, GSheetColumn *columns, const gchar *title,
1321 widget = gtk_type_new (gtk_sheet_get_type ());
1323 gtk_sheet_construct_with_custom_entry(GTK_SHEET(widget),
1324 rows, columns, title, entry_type);
1330 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet,
1336 gtk_sheet_construct(sheet, vgeo, hgeo, title);
1338 sheet->entry_type = entry_type;
1339 create_sheet_entry(sheet);
1345 gtk_sheet_change_entry(GtkSheet *sheet, GtkType entry_type)
1349 g_return_if_fail (sheet != NULL);
1350 g_return_if_fail (GTK_IS_SHEET (sheet));
1352 state = sheet->state;
1354 if(sheet->state == GTK_SHEET_NORMAL)
1355 gtk_sheet_hide_active_cell(sheet);
1357 sheet->entry_type = entry_type;
1359 create_sheet_entry(sheet);
1361 if(state == GTK_SHEET_NORMAL)
1363 gtk_sheet_show_active_cell(sheet);
1364 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
1366 G_CALLBACK(gtk_sheet_entry_changed),
1375 gtk_sheet_show_grid(GtkSheet *sheet, gboolean show)
1377 g_return_if_fail (sheet != NULL);
1378 g_return_if_fail (GTK_IS_SHEET (sheet));
1380 if(show == sheet->show_grid) return;
1382 sheet->show_grid = show;
1384 if(!GTK_SHEET_IS_FROZEN(sheet))
1385 gtk_sheet_range_draw(sheet, NULL);
1389 gtk_sheet_grid_visible(GtkSheet *sheet)
1391 g_return_val_if_fail (sheet != NULL, 0);
1392 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1394 return sheet->show_grid;
1398 gtk_sheet_set_background(GtkSheet *sheet, GdkColor *color)
1400 g_return_if_fail (sheet != NULL);
1401 g_return_if_fail (GTK_IS_SHEET (sheet));
1404 gdk_color_parse("white", &sheet->bg_color);
1405 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1407 sheet->bg_color = *color;
1409 if(!GTK_SHEET_IS_FROZEN(sheet))
1410 gtk_sheet_range_draw(sheet, NULL);
1414 gtk_sheet_set_grid(GtkSheet *sheet, GdkColor *color)
1416 g_return_if_fail (sheet != NULL);
1417 g_return_if_fail (GTK_IS_SHEET (sheet));
1420 gdk_color_parse("black", &sheet->grid_color);
1421 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1423 sheet->grid_color = *color;
1425 if(!GTK_SHEET_IS_FROZEN(sheet))
1426 gtk_sheet_range_draw(sheet, NULL);
1430 gtk_sheet_get_columns_count(GtkSheet *sheet)
1432 g_return_val_if_fail (sheet != NULL, 0);
1433 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1435 return xxx_column_count(sheet);
1439 gtk_sheet_get_rows_count(GtkSheet *sheet)
1441 g_return_val_if_fail (sheet != NULL, 0);
1442 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1444 return yyy_row_count(sheet);
1448 gtk_sheet_get_state(GtkSheet *sheet)
1450 g_return_val_if_fail (sheet != NULL, 0);
1451 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1453 return (sheet->state);
1457 gtk_sheet_set_selection_mode(GtkSheet *sheet, gint mode)
1459 g_return_if_fail (sheet != NULL);
1460 g_return_if_fail (GTK_IS_SHEET (sheet));
1462 if(GTK_WIDGET_REALIZED(sheet))
1463 gtk_sheet_real_unselect_range(sheet, NULL);
1465 sheet->selection_mode = mode;
1469 gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize)
1471 g_return_if_fail (sheet != NULL);
1472 g_return_if_fail (GTK_IS_SHEET (sheet));
1474 sheet->autoresize = autoresize;
1478 gtk_sheet_autoresize (GtkSheet *sheet)
1480 g_return_val_if_fail (sheet != NULL, FALSE);
1481 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1483 return sheet->autoresize;
1487 gtk_sheet_set_column_width (GtkSheet * sheet,
1493 gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
1495 gint text_width = 0;
1498 g_return_if_fail (sheet != NULL);
1499 g_return_if_fail (GTK_IS_SHEET (sheet));
1500 if (column >= xxx_column_count(sheet) || column < 0) return;
1502 for (row = 0; row < yyy_row_count(sheet); row++)
1504 gchar *text = gtk_sheet_cell_get_text(sheet, row, column);
1505 if (text && strlen(text) > 0){
1506 GtkSheetCellAttr attributes;
1508 gtk_sheet_get_attributes(sheet, row, column, &attributes);
1509 if(attributes.is_visible){
1510 gint width = STRING_WIDTH(GTK_WIDGET(sheet),
1511 attributes.font_desc,
1513 + 2*CELLOFFSET + attributes.border.width;
1514 text_width = MAX (text_width, width);
1517 dispose_string(sheet, text);
1520 if(text_width > xxx_column_width(sheet, column) )
1522 gtk_sheet_set_column_width(sheet, column, text_width);
1523 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
1529 gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll)
1531 g_return_if_fail (sheet != NULL);
1532 g_return_if_fail (GTK_IS_SHEET (sheet));
1534 sheet->autoscroll = autoscroll;
1538 gtk_sheet_autoscroll (GtkSheet *sheet)
1540 g_return_val_if_fail (sheet != NULL, FALSE);
1541 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1543 return sheet->autoscroll;
1547 gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text)
1549 g_return_if_fail (sheet != NULL);
1550 g_return_if_fail (GTK_IS_SHEET (sheet));
1552 sheet->clip_text = clip_text;
1556 gtk_sheet_clip_text (GtkSheet *sheet)
1558 g_return_val_if_fail (sheet != NULL, FALSE);
1559 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1561 return sheet->clip_text;
1565 gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify)
1567 g_return_if_fail (sheet != NULL);
1568 g_return_if_fail (GTK_IS_SHEET (sheet));
1570 sheet->justify_entry = justify;
1574 gtk_sheet_justify_entry (GtkSheet *sheet)
1576 g_return_val_if_fail (sheet != NULL, FALSE);
1577 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1579 return sheet->justify_entry;
1583 gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked)
1585 g_return_if_fail (sheet != NULL);
1586 g_return_if_fail (GTK_IS_SHEET (sheet));
1588 sheet->locked = locked;
1592 gtk_sheet_locked (GtkSheet *sheet)
1594 g_return_val_if_fail (sheet != NULL, FALSE);
1595 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1597 return sheet->locked;
1600 /* This routine has problems with gtk+-1.2 related with the
1601 * label/button drawing - I think it's a bug in gtk+-1.2 */
1604 gtk_sheet_set_title(GtkSheet *sheet, const gchar *title)
1606 /* GtkWidget *old_widget;
1607 */ GtkWidget *label;
1609 g_return_if_fail (sheet != NULL);
1610 g_return_if_fail (title != NULL);
1611 g_return_if_fail (GTK_IS_SHEET (sheet));
1614 g_free (sheet->name);
1616 sheet->name = g_strdup (title);
1618 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) || !title) return;
1620 if(GTK_BIN(sheet->button)->child)
1621 label = GTK_BIN(sheet->button)->child;
1623 gtk_label_set_text(GTK_LABEL(label), title);
1625 size_allocate_global_button(sheet);
1627 /* remove and destroy the old widget */
1629 old_widget = GTK_BIN (sheet->button)->child;
1632 gtk_container_remove (GTK_CONTAINER (sheet->button), old_widget);
1635 label = gtk_label_new (title);
1636 gtk_misc_set_alignment(GTK_MISC(label), 0.5 , 0.5 );
1638 gtk_container_add (GTK_CONTAINER (sheet->button), label);
1639 gtk_widget_show (label);
1641 size_allocate_global_button(sheet);
1643 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, -1);
1646 gtk_widget_destroy (old_widget);
1651 gtk_sheet_freeze (GtkSheet *sheet)
1653 g_return_if_fail (sheet != NULL);
1654 g_return_if_fail (GTK_IS_SHEET (sheet));
1656 sheet->freeze_count++;
1657 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1661 gtk_sheet_thaw(GtkSheet *sheet)
1663 g_return_if_fail (sheet != NULL);
1664 g_return_if_fail (GTK_IS_SHEET (sheet));
1666 if(sheet->freeze_count == 0) return;
1668 sheet->freeze_count--;
1669 if(sheet->freeze_count > 0) return;
1671 adjust_scrollbars(sheet);
1673 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1675 sheet->old_vadjustment = -1.;
1676 sheet->old_hadjustment = -1.;
1678 if(sheet->hadjustment)
1679 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1681 if(sheet->vadjustment)
1682 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1685 if(sheet->state == GTK_STATE_NORMAL)
1686 if(sheet->sheet_entry && GTK_WIDGET_MAPPED(sheet->sheet_entry)){
1687 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
1689 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
1691 (GtkSignalFunc)gtk_sheet_entry_changed,
1692 GTK_OBJECT(GTK_WIDGET(sheet)));
1693 gtk_sheet_show_active_cell(sheet);
1700 gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width)
1702 if(width < COLUMN_MIN_WIDTH) return;
1704 sheet->row_title_area.width = width;
1705 sheet->view.col0 = COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
1706 sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
1709 adjust_scrollbars(sheet);
1711 sheet->old_hadjustment = -1.;
1712 if(sheet->hadjustment)
1713 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1715 size_allocate_global_button(sheet);
1719 gtk_sheet_set_column_titles_height(GtkSheet *sheet, guint height)
1721 if(height < DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))) return;
1723 sheet->column_title_area.height = height;
1724 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
1725 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
1727 adjust_scrollbars(sheet);
1729 sheet->old_vadjustment = -1.;
1730 if(sheet->vadjustment)
1731 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1733 size_allocate_global_button(sheet);
1737 gtk_sheet_show_column_titles(GtkSheet *sheet)
1741 if(sheet->column_titles_visible) return;
1743 sheet->column_titles_visible = TRUE;
1746 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1747 gdk_window_show(sheet->column_title_window);
1748 gdk_window_move_resize (sheet->column_title_window,
1749 sheet->column_title_area.x,
1750 sheet->column_title_area.y,
1751 sheet->column_title_area.width,
1752 sheet->column_title_area.height);
1754 for(col = MIN_VISIBLE_COLUMN(sheet);
1755 col <= MAX_VISIBLE_COLUMN(sheet);
1758 const GtkSheetButton *button = xxx_column_button(sheet, col);
1759 GtkSheetChild *child = button->child;
1761 gtk_sheet_child_show(child);
1763 adjust_scrollbars(sheet);
1766 sheet->old_vadjustment = -1.;
1767 if(sheet->vadjustment)
1768 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1770 size_allocate_global_button(sheet);
1775 gtk_sheet_show_row_titles(GtkSheet *sheet)
1779 if(sheet->row_titles_visible) return;
1781 sheet->row_titles_visible = TRUE;
1784 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1785 gdk_window_show(sheet->row_title_window);
1786 gdk_window_move_resize (sheet->row_title_window,
1787 sheet->row_title_area.x,
1788 sheet->row_title_area.y,
1789 sheet->row_title_area.width,
1790 sheet->row_title_area.height);
1792 for(row = MIN_VISIBLE_ROW(sheet);
1793 row <= MAX_VISIBLE_ROW(sheet);
1796 const GtkSheetButton *button = yyy_row_button(sheet, row);
1797 GtkSheetChild *child = button->child;
1800 gtk_sheet_child_show(child);
1803 adjust_scrollbars(sheet);
1806 sheet->old_hadjustment = -1.;
1807 if(sheet->hadjustment)
1808 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1810 size_allocate_global_button(sheet);
1814 gtk_sheet_hide_column_titles(GtkSheet *sheet)
1818 if(!sheet->column_titles_visible) return;
1820 sheet->column_titles_visible = FALSE;
1822 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1823 if(sheet->column_title_window)
1824 gdk_window_hide(sheet->column_title_window);
1825 if(GTK_WIDGET_VISIBLE(sheet->button))
1826 gtk_widget_hide(sheet->button);
1828 for(col = MIN_VISIBLE_COLUMN(sheet);
1829 col <= MAX_VISIBLE_COLUMN(sheet);
1832 const GtkSheetButton *button = xxx_column_button(sheet, col);
1833 GtkSheetChild *child = button->child;
1835 gtk_sheet_child_hide(child);
1837 adjust_scrollbars(sheet);
1840 sheet->old_vadjustment = -1.;
1841 if(sheet->vadjustment)
1842 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1847 gtk_sheet_hide_row_titles(GtkSheet *sheet)
1851 if(!sheet->row_titles_visible) return;
1853 sheet->row_titles_visible = FALSE;
1856 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1857 if(sheet->row_title_window)
1858 gdk_window_hide(sheet->row_title_window);
1859 if(GTK_WIDGET_VISIBLE(sheet->button))
1860 gtk_widget_hide(sheet->button);
1861 for(row = MIN_VISIBLE_ROW(sheet);
1862 row <= MAX_VISIBLE_ROW(sheet);
1865 const GtkSheetButton *button = yyy_row_button(sheet, row);
1866 GtkSheetChild *child = button->child;
1869 gtk_sheet_child_hide(child);
1871 adjust_scrollbars(sheet);
1874 sheet->old_hadjustment = -1.;
1875 if(sheet->hadjustment)
1876 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1881 gtk_sheet_column_titles_visible(GtkSheet *sheet)
1883 g_return_val_if_fail (sheet != NULL, FALSE);
1884 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1885 return sheet->column_titles_visible;
1889 gtk_sheet_row_titles_visible(GtkSheet *sheet)
1891 g_return_val_if_fail (sheet != NULL, FALSE);
1892 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1893 return sheet->row_titles_visible;
1899 gtk_sheet_moveto (GtkSheet * sheet,
1906 guint width, height;
1908 gint min_row, min_col;
1910 g_return_if_fail (sheet != NULL);
1911 g_return_if_fail (GTK_IS_SHEET (sheet));
1912 g_return_if_fail (sheet->hadjustment != NULL);
1913 g_return_if_fail (sheet->vadjustment != NULL);
1915 if (row < 0 || row >= yyy_row_count(sheet))
1917 if (column < 0 || column >= xxx_column_count(sheet))
1920 height = sheet->sheet_window_height;
1921 width = sheet->sheet_window_width;
1923 /* adjust vertical scrollbar */
1925 if (row >= 0 && row_align >=0.)
1928 y = ROW_TOP_YPIXEL(sheet, row) - sheet->voffset -
1930 (1.-row_align)*yyy_row_height(sheet, row);
1932 y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
1933 - (gint) ( row_align*height + (1. - row_align) * yyy_row_height(sheet, row));
1935 /* This forces the sheet to scroll when you don't see the entire cell */
1938 if(row_align == 1.){
1939 while(min_row >= 0 && min_row > MIN_VISIBLE_ROW(sheet)){
1940 if(yyy_row_is_visible(sheet, min_row))
1941 adjust += yyy_row_height(sheet, min_row);
1942 if(adjust >= height){
1947 min_row = MAX(min_row, 0);
1948 y = ROW_TOP_YPIXEL(sheet, min_row) - sheet->voffset +
1949 yyy_row_height(sheet, min_row) - 1;
1953 sheet->vadjustment->value = 0.0;
1955 sheet->vadjustment->value = y;
1957 sheet->old_vadjustment = -1.;
1958 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1963 /* adjust horizontal scrollbar */
1964 if (column >= 0 && col_align >= 0.)
1967 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset -
1969 (1.-col_align)*sheet->column[column].width;
1971 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
1972 - (gint) ( col_align*width + (1.-col_align)*
1973 xxx_column_width(sheet, column));
1976 /* This forces the sheet to scroll when you don't see the entire cell */
1979 if(col_align == 1.){
1980 while(min_col >= 0 && min_col > MIN_VISIBLE_COLUMN(sheet)){
1981 if(xxx_column_is_visible(sheet, min_col))
1982 adjust += xxx_column_width(sheet, min_col);
1984 if(adjust >= width){
1989 min_col = MAX(min_col, 0);
1990 x = COLUMN_LEFT_XPIXEL(sheet, min_col) - sheet->hoffset +
1991 xxx_column_width(sheet, min_col) - 1;
1995 sheet->hadjustment->value = 0.0;
1997 sheet->hadjustment->value = x;
1999 sheet->old_vadjustment = -1.;
2000 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
2008 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
2010 g_return_if_fail (sheet != NULL);
2011 g_return_if_fail (GTK_IS_SHEET (sheet));
2013 sheet->columns_resizable = resizable;
2017 gtk_sheet_columns_resizable (GtkSheet *sheet)
2019 g_return_val_if_fail (sheet != NULL, FALSE);
2020 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2022 return sheet->columns_resizable;
2027 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
2029 g_return_if_fail (sheet != NULL);
2030 g_return_if_fail (GTK_IS_SHEET (sheet));
2032 sheet->rows_resizable = resizable;
2036 gtk_sheet_rows_resizable (GtkSheet *sheet)
2038 g_return_val_if_fail (sheet != NULL, FALSE);
2039 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2041 return sheet->rows_resizable;
2046 gtk_sheet_select_row (GtkSheet * sheet,
2049 g_return_if_fail (sheet != NULL);
2050 g_return_if_fail (GTK_IS_SHEET (sheet));
2052 if (row < 0 || row >= yyy_row_count(sheet))
2055 if(sheet->state != GTK_SHEET_NORMAL)
2056 gtk_sheet_real_unselect_range(sheet, NULL);
2059 gboolean veto = TRUE;
2060 veto = gtk_sheet_deactivate_cell(sheet);
2064 sheet->state=GTK_SHEET_ROW_SELECTED;
2065 sheet->range.row0=row;
2066 sheet->range.col0=0;
2067 sheet->range.rowi=row;
2068 sheet->range.coli = xxx_column_count(sheet) - 1;
2069 sheet->active_cell.row=row;
2070 sheet->active_cell.col=0;
2072 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_ROW], row);
2073 gtk_sheet_real_select_range(sheet, NULL);
2079 gtk_sheet_select_column (GtkSheet * sheet,
2083 g_return_if_fail (sheet != NULL);
2084 g_return_if_fail (GTK_IS_SHEET (sheet));
2086 if (column < 0 || column >= xxx_column_count(sheet))
2089 if(sheet->state != GTK_SHEET_NORMAL)
2090 gtk_sheet_real_unselect_range(sheet, NULL);
2093 gboolean veto = TRUE;
2094 veto = gtk_sheet_deactivate_cell(sheet);
2098 sheet->state=GTK_SHEET_COLUMN_SELECTED;
2099 sheet->range.row0=0;
2100 sheet->range.col0=column;
2101 sheet->range.rowi= yyy_row_count(sheet) - 1;
2102 sheet->range.coli=column;
2103 sheet->active_cell.row=0;
2104 sheet->active_cell.col=column;
2106 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_COLUMN], column);
2107 gtk_sheet_real_select_range(sheet, NULL);
2112 gtk_sheet_clip_range (GtkSheet *sheet, const GtkSheetRange *range)
2115 g_return_if_fail (sheet != NULL);
2116 g_return_if_fail (GTK_IS_SHEET (sheet));
2118 if(GTK_SHEET_IN_CLIP(sheet)) return;
2120 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2123 sheet->clip_range = sheet->range;
2125 sheet->clip_range=*range;
2128 sheet->clip_timer=gtk_timeout_add(TIMEOUT_FLASH, gtk_sheet_flash, sheet);
2130 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CLIP_RANGE],
2131 &sheet->clip_range);
2136 gtk_sheet_unclip_range(GtkSheet *sheet)
2139 g_return_if_fail (sheet != NULL);
2140 g_return_if_fail (GTK_IS_SHEET (sheet));
2142 if(!GTK_SHEET_IN_CLIP(sheet)) return;
2144 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2145 gtk_timeout_remove(sheet->clip_timer);
2146 gtk_sheet_range_draw(sheet, &sheet->clip_range);
2148 if(gtk_sheet_range_isvisible(sheet, sheet->range))
2149 gtk_sheet_range_draw(sheet, &sheet->range);
2153 gtk_sheet_in_clip (GtkSheet *sheet)
2155 g_return_val_if_fail (sheet != NULL, FALSE);
2156 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2158 return GTK_SHEET_IN_CLIP(sheet);
2162 gtk_sheet_flash(gpointer data)
2165 gint x,y,width,height;
2166 GdkRectangle clip_area;
2168 sheet=GTK_SHEET(data);
2170 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return TRUE;
2171 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return TRUE;
2172 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return TRUE;
2173 if(GTK_SHEET_IN_XDRAG(sheet)) return TRUE;
2174 if(GTK_SHEET_IN_YDRAG(sheet)) return TRUE;
2176 GDK_THREADS_ENTER();
2178 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2179 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2180 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2181 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2182 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2183 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2185 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2186 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2187 clip_area.width=sheet->sheet_window_width;
2188 clip_area.height=sheet->sheet_window_height;
2194 if(width>clip_area.width) width=clip_area.width+10;
2199 if(height>clip_area.height) height=clip_area.height+10;
2201 gdk_draw_pixmap(sheet->sheet_window,
2202 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2208 gdk_draw_pixmap(sheet->sheet_window,
2209 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2215 gdk_draw_pixmap(sheet->sheet_window,
2216 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2222 gdk_draw_pixmap(sheet->sheet_window,
2223 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2230 sheet->interval=sheet->interval+1;
2231 if(sheet->interval==TIME_INTERVAL) sheet->interval=0;
2233 gdk_gc_set_dashes(sheet->xor_gc, sheet->interval, (gint8*)"\4\4", 2);
2234 gtk_sheet_draw_flashing_range(sheet,sheet->clip_range);
2235 gdk_gc_set_dashes(sheet->xor_gc, 0, (gint8*)"\4\4", 2);
2237 GDK_THREADS_LEAVE();
2244 gtk_sheet_draw_flashing_range(GtkSheet *sheet, GtkSheetRange range)
2246 GdkRectangle clip_area;
2247 gint x,y,width,height;
2249 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return;
2251 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2252 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2253 clip_area.width=sheet->sheet_window_width;
2254 clip_area.height=sheet->sheet_window_height;
2256 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
2258 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2259 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2260 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2261 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2262 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2263 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2269 if(width>clip_area.width) width=clip_area.width+10;
2274 if(height>clip_area.height) height=clip_area.height+10;
2276 gdk_gc_set_line_attributes(sheet->xor_gc, 1, 1, 0 ,0 );
2278 gdk_draw_rectangle(sheet->sheet_window, sheet->xor_gc, FALSE,
2282 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 0, 0, 0);
2284 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
2289 gtk_sheet_range_isvisible (GtkSheet * sheet,
2290 GtkSheetRange range)
2292 g_return_val_if_fail (sheet != NULL, FALSE);
2294 if (range.row0 < 0 || range.row0 >= yyy_row_count(sheet))
2297 if (range.rowi < 0 || range.rowi >= yyy_row_count(sheet))
2300 if (range.col0 < 0 || range.col0 >= xxx_column_count(sheet))
2303 if (range.coli < 0 || range.coli >= xxx_column_count(sheet))
2306 if (range.rowi < MIN_VISIBLE_ROW (sheet))
2309 if (range.row0 > MAX_VISIBLE_ROW (sheet))
2312 if (range.coli < MIN_VISIBLE_COLUMN (sheet))
2315 if (range.col0 > MAX_VISIBLE_COLUMN (sheet))
2322 gtk_sheet_cell_isvisible (GtkSheet * sheet,
2323 gint row, gint column)
2325 GtkSheetRange range;
2328 range.col0 = column;
2330 range.coli = column;
2332 return gtk_sheet_range_isvisible(sheet, range);
2336 gtk_sheet_get_visible_range(GtkSheet *sheet, GtkSheetRange *range)
2339 g_return_if_fail (sheet != NULL);
2340 g_return_if_fail (GTK_IS_SHEET (sheet)) ;
2341 g_return_if_fail (range != NULL);
2343 range->row0 = MIN_VISIBLE_ROW(sheet);
2344 range->col0 = MIN_VISIBLE_COLUMN(sheet);
2345 range->rowi = MAX_VISIBLE_ROW(sheet);
2346 range->coli = MAX_VISIBLE_COLUMN(sheet);
2351 gtk_sheet_get_vadjustment (GtkSheet * sheet)
2353 g_return_val_if_fail (sheet != NULL, NULL);
2354 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2356 return sheet->vadjustment;
2360 gtk_sheet_get_hadjustment (GtkSheet * sheet)
2362 g_return_val_if_fail (sheet != NULL, NULL);
2363 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2365 return sheet->hadjustment;
2369 gtk_sheet_set_vadjustment (GtkSheet *sheet,
2370 GtkAdjustment *adjustment)
2372 GtkAdjustment *old_adjustment;
2374 g_return_if_fail (sheet != NULL);
2375 g_return_if_fail (GTK_IS_SHEET (sheet));
2377 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2379 if (sheet->vadjustment == adjustment)
2382 old_adjustment = sheet->vadjustment;
2384 if (sheet->vadjustment)
2386 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2387 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2390 sheet->vadjustment = adjustment;
2392 if (sheet->vadjustment)
2394 gtk_object_ref (GTK_OBJECT (sheet->vadjustment));
2395 gtk_object_sink (GTK_OBJECT (sheet->vadjustment));
2397 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "changed",
2398 (GtkSignalFunc) vadjustment_changed,
2400 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "value_changed",
2401 (GtkSignalFunc) vadjustment_value_changed,
2405 if (!sheet->vadjustment || !old_adjustment)
2407 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2411 sheet->old_vadjustment = sheet->vadjustment->value;
2415 gtk_sheet_set_hadjustment (GtkSheet *sheet,
2416 GtkAdjustment *adjustment)
2418 GtkAdjustment *old_adjustment;
2420 g_return_if_fail (sheet != NULL);
2421 g_return_if_fail (GTK_IS_SHEET (sheet));
2423 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2425 if (sheet->hadjustment == adjustment)
2428 old_adjustment = sheet->hadjustment;
2430 if (sheet->hadjustment)
2432 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2433 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2436 sheet->hadjustment = adjustment;
2438 if (sheet->hadjustment)
2440 gtk_object_ref (GTK_OBJECT (sheet->hadjustment));
2441 gtk_object_sink (GTK_OBJECT (sheet->hadjustment));
2443 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "changed",
2444 (GtkSignalFunc) hadjustment_changed,
2446 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "value_changed",
2447 (GtkSignalFunc) hadjustment_value_changed,
2451 if (!sheet->hadjustment || !old_adjustment)
2453 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2457 sheet->old_hadjustment = sheet->hadjustment->value;
2461 gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
2462 GtkAdjustment *hadjustment,
2463 GtkAdjustment *vadjustment)
2465 if(sheet->hadjustment != hadjustment)
2466 gtk_sheet_set_hadjustment (sheet, hadjustment);
2467 if(sheet->vadjustment != vadjustment)
2468 gtk_sheet_set_vadjustment (sheet, vadjustment);
2472 gtk_sheet_finalize (GObject * object)
2476 g_return_if_fail (object != NULL);
2477 g_return_if_fail (GTK_IS_SHEET (object));
2479 sheet = GTK_SHEET (object);
2481 /* get rid of all the cells */
2482 gtk_sheet_range_clear (sheet, NULL);
2483 gtk_sheet_range_delete(sheet, NULL);
2486 g_free(sheet->name);
2490 if (G_OBJECT_CLASS (parent_class)->finalize)
2491 (*G_OBJECT_CLASS (parent_class)->finalize) (object);
2495 gtk_sheet_destroy (GtkObject * object)
2500 g_return_if_fail (object != NULL);
2501 g_return_if_fail (GTK_IS_SHEET (object));
2503 sheet = GTK_SHEET (object);
2505 /* destroy the entry */
2506 if(sheet->sheet_entry && GTK_IS_WIDGET(sheet->sheet_entry)){
2507 gtk_widget_destroy (sheet->sheet_entry);
2508 sheet->sheet_entry = NULL;
2511 /* destroy the global selection button */
2512 if(sheet->button && GTK_IS_WIDGET(sheet->button)){
2513 gtk_widget_destroy (sheet->button);
2514 sheet->button = NULL;
2518 gtk_timeout_remove(sheet->timer);
2522 if(sheet->clip_timer){
2523 gtk_timeout_remove(sheet->clip_timer);
2524 sheet->clip_timer = 0;
2527 /* unref adjustments */
2528 if (sheet->hadjustment)
2530 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2531 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2532 sheet->hadjustment = NULL;
2534 if (sheet->vadjustment)
2536 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2537 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2538 sheet->vadjustment = NULL;
2541 children = sheet->children;
2543 GtkSheetChild *child = (GtkSheetChild *)children->data;
2544 if(child && child->widget)
2545 gtk_sheet_remove(GTK_CONTAINER(sheet), child->widget);
2546 children = sheet->children;
2548 sheet->children = NULL;
2550 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2551 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2555 gtk_sheet_style_set (GtkWidget *widget,
2556 GtkStyle *previous_style)
2560 g_return_if_fail (widget != NULL);
2561 g_return_if_fail (GTK_IS_SHEET (widget));
2563 if (GTK_WIDGET_CLASS (parent_class)->style_set)
2564 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
2566 sheet = GTK_SHEET (widget);
2568 if(GTK_WIDGET_REALIZED(widget))
2570 gtk_style_set_background (widget->style, widget->window, widget->state);
2576 gtk_sheet_realize (GtkWidget * widget)
2579 GdkWindowAttr attributes;
2580 gint attributes_mask;
2581 GdkGCValues values, auxvalues;
2582 GdkColormap *colormap;
2584 GtkSheetChild *child;
2587 g_return_if_fail (widget != NULL);
2588 g_return_if_fail (GTK_IS_SHEET (widget));
2590 sheet = GTK_SHEET (widget);
2592 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2594 attributes.window_type = GDK_WINDOW_CHILD;
2595 attributes.x = widget->allocation.x;
2596 attributes.y = widget->allocation.y;
2597 attributes.width = widget->allocation.width;
2598 attributes.height = widget->allocation.height;
2599 attributes.wclass = GDK_INPUT_OUTPUT;
2601 attributes.visual = gtk_widget_get_visual (widget);
2602 attributes.colormap = gtk_widget_get_colormap (widget);
2604 attributes.event_mask = gtk_widget_get_events (widget);
2605 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2606 GDK_BUTTON_PRESS_MASK |
2607 GDK_BUTTON_RELEASE_MASK |
2608 GDK_KEY_PRESS_MASK |
2609 GDK_POINTER_MOTION_MASK |
2610 GDK_POINTER_MOTION_HINT_MASK);
2611 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
2614 attributes.cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
2617 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2619 gdk_window_set_user_data (widget->window, sheet);
2621 widget->style = gtk_style_attach (widget->style, widget->window);
2623 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2626 if(sheet->row_titles_visible)
2627 attributes.x = sheet->row_title_area.width;
2629 attributes.width = sheet->column_title_area.width;
2630 attributes.height = sheet->column_title_area.height;
2632 /* column-title window */
2633 sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2634 gdk_window_set_user_data (sheet->column_title_window, sheet);
2635 gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL);
2639 if(sheet->column_titles_visible)
2640 attributes.y = sheet->column_title_area.height;
2641 attributes.width = sheet->row_title_area.width;
2642 attributes.height = sheet->row_title_area.height;
2644 /* row-title window */
2645 sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2646 gdk_window_set_user_data (sheet->row_title_window, sheet);
2647 gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL);
2650 attributes.cursor = gdk_cursor_new(GDK_PLUS);
2654 attributes.width = sheet->sheet_window_width,
2655 attributes.height = sheet->sheet_window_height;
2657 sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2658 gdk_window_set_user_data (sheet->sheet_window, sheet);
2660 gdk_cursor_unref(attributes.cursor);
2662 gdk_window_set_background (sheet->sheet_window, &widget->style->white);
2663 gdk_window_show (sheet->sheet_window);
2665 /* backing_pixmap */
2666 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
2670 gdk_gc_unref(sheet->fg_gc);
2672 gdk_gc_unref(sheet->bg_gc);
2673 sheet->fg_gc = gdk_gc_new (widget->window);
2674 sheet->bg_gc = gdk_gc_new (widget->window);
2676 colormap = gtk_widget_get_colormap(widget);
2678 gdk_color_white(colormap, &widget->style->white);
2679 gdk_color_black(colormap, &widget->style->black);
2681 gdk_gc_get_values(sheet->fg_gc, &auxvalues);
2683 values.foreground = widget->style->white;
2684 values.function = GDK_INVERT;
2685 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2687 gdk_gc_unref(sheet->xor_gc);
2688 sheet->xor_gc = gdk_gc_new_with_values (widget->window,
2694 if(sheet->sheet_entry->parent){
2695 gtk_widget_ref(sheet->sheet_entry);
2696 gtk_widget_unparent(sheet->sheet_entry);
2698 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
2699 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
2701 if(sheet->button && sheet->button->parent){
2702 gtk_widget_ref(sheet->button);
2703 gtk_widget_unparent(sheet->button);
2705 gtk_widget_set_parent_window(sheet->button, sheet->sheet_window);
2706 gtk_widget_set_parent(sheet->button, GTK_WIDGET(sheet));
2709 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
2711 if(!sheet->cursor_drag)
2712 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
2714 if(sheet->column_titles_visible)
2715 gdk_window_show(sheet->column_title_window);
2716 if(sheet->row_titles_visible)
2717 gdk_window_show(sheet->row_title_window);
2719 size_allocate_row_title_buttons(sheet);
2720 size_allocate_column_title_buttons(sheet);
2722 name = g_strdup(sheet->name);
2723 gtk_sheet_set_title(sheet, name);
2727 children = sheet->children;
2730 child = children->data;
2731 children = children->next;
2733 gtk_sheet_realize_child(sheet, child);
2738 create_global_button(GtkSheet *sheet)
2740 sheet->button = gtk_button_new_with_label(" ");
2742 gtk_signal_connect (GTK_OBJECT (sheet->button),
2744 (GtkSignalFunc) global_button_clicked,
2749 size_allocate_global_button(GtkSheet *sheet)
2751 GtkAllocation allocation;
2753 if(!sheet->column_titles_visible) return;
2754 if(!sheet->row_titles_visible) return;
2756 gtk_widget_size_request(sheet->button, NULL);
2760 allocation.width=sheet->row_title_area.width;
2761 allocation.height=sheet->column_title_area.height;
2763 gtk_widget_size_allocate(sheet->button, &allocation);
2764 gtk_widget_show(sheet->button);
2768 global_button_clicked(GtkWidget *widget, gpointer data)
2772 gtk_sheet_click_cell(GTK_SHEET(data), -1, -1, &veto);
2773 gtk_widget_grab_focus(GTK_WIDGET(data));
2778 gtk_sheet_unrealize (GtkWidget * widget)
2782 g_return_if_fail (widget != NULL);
2783 g_return_if_fail (GTK_IS_SHEET (widget));
2785 sheet = GTK_SHEET (widget);
2787 gdk_cursor_destroy (sheet->cursor_drag);
2789 gdk_gc_destroy (sheet->xor_gc);
2790 gdk_gc_destroy (sheet->fg_gc);
2791 gdk_gc_destroy (sheet->bg_gc);
2793 gdk_window_destroy (sheet->sheet_window);
2794 gdk_window_destroy (sheet->column_title_window);
2795 gdk_window_destroy (sheet->row_title_window);
2798 g_object_unref(sheet->pixmap);
2799 sheet->pixmap = NULL;
2802 sheet->column_title_window=NULL;
2803 sheet->sheet_window = NULL;
2804 sheet->cursor_drag = NULL;
2805 sheet->xor_gc = NULL;
2806 sheet->fg_gc = NULL;
2807 sheet->bg_gc = NULL;
2809 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2810 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2814 gtk_sheet_map (GtkWidget * widget)
2817 GtkSheetChild *child;
2820 g_return_if_fail (widget != NULL);
2821 g_return_if_fail (GTK_IS_SHEET (widget));
2823 sheet = GTK_SHEET (widget);
2825 if (!GTK_WIDGET_MAPPED (widget))
2827 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2829 if(!sheet->cursor_drag) sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
2831 gdk_window_show (widget->window);
2833 gdk_window_show (sheet->sheet_window);
2835 if(sheet->column_titles_visible){
2836 size_allocate_column_title_buttons(sheet);
2837 gdk_window_show (sheet->column_title_window);
2839 if(sheet->row_titles_visible){
2840 size_allocate_row_title_buttons(sheet);
2841 gdk_window_show (sheet->row_title_window);
2844 if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)){
2845 gtk_widget_show (sheet->sheet_entry);
2846 gtk_widget_map (sheet->sheet_entry);
2849 if (GTK_WIDGET_VISIBLE (sheet->button) &&
2850 !GTK_WIDGET_MAPPED (sheet->button)){
2851 gtk_widget_show(sheet->button);
2852 gtk_widget_map (sheet->button);
2855 if(GTK_BIN(sheet->button)->child)
2856 if (GTK_WIDGET_VISIBLE (GTK_BIN(sheet->button)->child) &&
2857 !GTK_WIDGET_MAPPED (GTK_BIN(sheet->button)->child))
2858 gtk_widget_map (GTK_BIN(sheet->button)->child);
2860 gtk_sheet_range_draw(sheet, NULL);
2861 gtk_sheet_activate_cell(sheet,
2862 sheet->active_cell.row,
2863 sheet->active_cell.col);
2865 children = sheet->children;
2868 child = children->data;
2869 children = children->next;
2871 if (GTK_WIDGET_VISIBLE (child->widget) &&
2872 !GTK_WIDGET_MAPPED (child->widget)){
2873 gtk_widget_map (child->widget);
2874 gtk_sheet_position_child(sheet, child);
2882 gtk_sheet_unmap (GtkWidget * widget)
2885 GtkSheetChild *child;
2888 g_return_if_fail (widget != NULL);
2889 g_return_if_fail (GTK_IS_SHEET (widget));
2891 sheet = GTK_SHEET (widget);
2893 if (GTK_WIDGET_MAPPED (widget))
2895 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2897 gdk_window_hide (sheet->sheet_window);
2898 if(sheet->column_titles_visible)
2899 gdk_window_hide (sheet->column_title_window);
2900 if(sheet->row_titles_visible)
2901 gdk_window_hide (sheet->row_title_window);
2902 gdk_window_hide (widget->window);
2904 if (GTK_WIDGET_MAPPED (sheet->sheet_entry))
2905 gtk_widget_unmap (sheet->sheet_entry);
2907 if (GTK_WIDGET_MAPPED (sheet->button))
2908 gtk_widget_unmap (sheet->button);
2910 children = sheet->children;
2913 child = children->data;
2914 children = children->next;
2916 if (GTK_WIDGET_VISIBLE (child->widget) &&
2917 GTK_WIDGET_MAPPED (child->widget))
2919 gtk_widget_unmap (child->widget);
2928 gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
2931 GdkGC *fg_gc, *bg_gc;
2932 GtkSheetCellAttr attributes;
2935 g_return_if_fail (sheet != NULL);
2937 /* bail now if we arn't drawable yet */
2938 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
2940 if (row < 0 || row >= yyy_row_count(sheet)) return;
2941 if (col < 0 || col >= xxx_column_count(sheet)) return;
2942 if (! xxx_column_is_visible(sheet, col)) return;
2943 if (! yyy_row_is_visible(sheet, row)) return;
2945 widget = GTK_WIDGET (sheet);
2947 gtk_sheet_get_attributes(sheet, row, col, &attributes);
2949 /* select GC for background rectangle */
2950 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
2951 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
2953 fg_gc = sheet->fg_gc;
2954 bg_gc = sheet->bg_gc;
2956 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
2957 area.y=ROW_TOP_YPIXEL(sheet,row);
2958 area.width= xxx_column_width(sheet, col);
2959 area.height=yyy_row_height(sheet, row);
2961 gdk_draw_rectangle (sheet->pixmap,
2969 gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0);
2971 if(sheet->show_grid){
2972 gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color);
2974 gdk_draw_rectangle (sheet->pixmap,
2978 area.width, area.height);
2983 gtk_sheet_cell_draw_border (GtkSheet *sheet, gint row, gint col, gint mask)
2986 GdkGC *fg_gc, *bg_gc;
2987 GtkSheetCellAttr attributes;
2991 g_return_if_fail (sheet != NULL);
2993 /* bail now if we arn't drawable yet */
2994 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
2996 if (row < 0 || row >= yyy_row_count(sheet)) return;
2997 if (col < 0 || col >= xxx_column_count(sheet)) return;
2998 if (!xxx_column_is_visible(sheet, col)) return;
2999 if (!yyy_row_is_visible(sheet, row)) return;
3001 widget = GTK_WIDGET (sheet);
3003 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3005 /* select GC for background rectangle */
3006 gdk_gc_set_foreground (sheet->fg_gc, &attributes.border.color);
3007 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3009 fg_gc = sheet->fg_gc;
3010 bg_gc = sheet->bg_gc;
3012 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3013 area.y=ROW_TOP_YPIXEL(sheet,row);
3014 area.width=xxx_column_width(sheet, col);
3015 area.height=yyy_row_height(sheet, row);
3017 width = attributes.border.width;
3018 gdk_gc_set_line_attributes(sheet->fg_gc, attributes.border.width,
3019 attributes.border.line_style,
3020 attributes.border.cap_style,
3021 attributes.border.join_style);
3024 if(attributes.border.mask & GTK_SHEET_LEFT_BORDER & mask)
3025 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3026 area.x, area.y-width/2,
3027 area.x, area.y+area.height+width/2+1);
3029 if(attributes.border.mask & GTK_SHEET_RIGHT_BORDER & mask)
3030 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3031 area.x+area.width, area.y-width/2,
3033 area.y+area.height+width/2+1);
3035 if(attributes.border.mask & GTK_SHEET_TOP_BORDER & mask)
3036 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3037 area.x-width/2,area.y,
3038 area.x+area.width+width/2+1,
3041 if(attributes.border.mask & GTK_SHEET_BOTTOM_BORDER & mask)
3042 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3043 area.x-width/2, area.y+area.height,
3044 area.x+area.width+width/2+1,
3045 area.y+area.height);
3052 gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
3055 GdkRectangle area, clip_area;
3057 gint text_width, text_height, y;
3059 gint size, sizel, sizer;
3060 GdkGC *fg_gc, *bg_gc;
3061 GtkSheetCellAttr attributes;
3062 PangoLayout *layout;
3063 PangoRectangle rect;
3064 PangoRectangle logical_rect;
3065 PangoLayoutLine *line;
3066 PangoFontMetrics *metrics;
3067 PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet));
3068 gint ascent, descent, y_pos;
3072 g_return_if_fail (sheet != NULL);
3074 /* bail now if we aren't drawable yet */
3075 if (!GTK_WIDGET_DRAWABLE (sheet))
3078 label = gtk_sheet_cell_get_text(sheet, row, col);
3082 if (row < 0 || row >= yyy_row_count(sheet)) return;
3083 if (col < 0 || col >= xxx_column_count(sheet)) return;
3084 if (! xxx_column_is_visible(sheet, col)) return;
3085 if (!yyy_row_is_visible(sheet, row)) return;
3088 widget = GTK_WIDGET(sheet);
3090 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3092 /* select GC for background rectangle */
3093 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3094 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3096 fg_gc = sheet->fg_gc;
3097 bg_gc = sheet->bg_gc;
3099 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3100 area.y=ROW_TOP_YPIXEL(sheet,row);
3101 area.width = xxx_column_width(sheet, col);
3102 area.height = yyy_row_height(sheet, row);
3106 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label);
3107 dispose_string(sheet, label);
3108 pango_layout_set_font_description (layout, attributes.font_desc);
3110 pango_layout_get_pixel_extents (layout, NULL, &rect);
3112 line = pango_layout_get_lines (layout)->data;
3113 pango_layout_line_get_extents (line, NULL, &logical_rect);
3115 metrics = pango_context_get_metrics(context,
3116 attributes.font_desc,
3117 pango_context_get_language(context));
3119 ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
3120 descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
3122 pango_font_metrics_unref(metrics);
3124 /* Align primarily for locale's ascent/descent */
3126 logical_rect.height /= PANGO_SCALE;
3127 logical_rect.y /= PANGO_SCALE;
3128 y_pos = area.height - logical_rect.height;
3130 if (logical_rect.height > area.height)
3131 y_pos = (logical_rect.height - area.height - 2*CELLOFFSET) / 2;
3134 else if (y_pos + logical_rect.height > area.height)
3135 y_pos = area.height - logical_rect.height;
3137 text_width = rect.width;
3138 text_height = rect.height;
3139 y = area.y + y_pos - CELLOFFSET;
3141 switch(attributes.justification){
3142 case GTK_JUSTIFY_RIGHT:
3145 if(!gtk_sheet_clip_text(sheet)){
3146 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3147 if( !gtk_sheet_cell_empty(sheet, row, i)) break;
3148 if(size>=text_width+CELLOFFSET) break;
3149 size+=xxx_column_width(sheet, i);
3150 xxx_column_set_right_column(sheet, i,
3152 xxx_column_right_column(sheet, i)));
3157 xoffset+=area.width-text_width - 2 * CELLOFFSET -
3158 attributes.border.width/2;
3160 case GTK_JUSTIFY_CENTER:
3163 area.x+=area.width/2;
3164 if(!gtk_sheet_clip_text(sheet)){
3165 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3166 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3167 if(sizer>=text_width/2) break;
3168 sizer+= xxx_column_width(sheet, i);
3169 xxx_column_set_left_column(sheet, i,
3172 xxx_column_left_column(sheet, i)));
3174 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3175 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3176 if(sizel>=text_width/2) break;
3177 sizel+=xxx_column_width(sheet, i);
3178 xxx_column_set_right_column(sheet, i,
3180 xxx_column_right_column(sheet, i)));
3182 size=MIN(sizel, sizer);
3185 xoffset+= sizel - text_width/2 - CELLOFFSET;
3186 area.width=sizel+sizer;
3188 case GTK_JUSTIFY_LEFT:
3191 if(!gtk_sheet_clip_text(sheet)){
3192 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3193 if(! gtk_sheet_cell_empty(sheet, row, i)) break;
3194 if(size>=text_width+CELLOFFSET) break;
3195 size+=xxx_column_width(sheet, i);
3196 xxx_column_set_left_column(sheet, i,
3199 xxx_column_left_column(sheet, i)));
3204 xoffset += attributes.border.width/2;
3208 if(!gtk_sheet_clip_text(sheet)) clip_area = area;
3209 gdk_gc_set_clip_rectangle(fg_gc, &clip_area);
3212 gdk_draw_layout (sheet->pixmap, fg_gc,
3213 area.x + xoffset + CELLOFFSET,
3217 gdk_gc_set_clip_rectangle(fg_gc, NULL);
3218 g_object_unref(G_OBJECT(layout));
3220 gdk_draw_pixmap(sheet->sheet_window,
3221 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3235 gtk_sheet_range_draw(GtkSheet *sheet, const GtkSheetRange *range)
3238 GtkSheetRange drawing_range;
3241 g_return_if_fail(sheet != NULL);
3242 g_return_if_fail(GTK_SHEET(sheet));
3244 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
3245 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3246 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
3250 drawing_range.row0=MIN_VISIBLE_ROW(sheet);
3251 drawing_range.col0=MIN_VISIBLE_COLUMN(sheet);
3252 drawing_range.rowi=MAX_VISIBLE_ROW(sheet);
3253 drawing_range.coli=MAX_VISIBLE_COLUMN(sheet);
3255 gdk_draw_rectangle (sheet->pixmap,
3256 GTK_WIDGET(sheet)->style->white_gc,
3259 sheet->sheet_window_width,sheet->sheet_window_height);
3264 drawing_range.row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
3265 drawing_range.col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
3266 drawing_range.rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
3267 drawing_range.coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
3271 if(drawing_range.coli == xxx_column_count(sheet) - 1)
3273 area.x=COLUMN_LEFT_XPIXEL(sheet,
3274 xxx_column_count(sheet) - 1) +
3275 xxx_column_width(sheet, xxx_column_count(sheet) - 1) + 1;
3279 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3281 gdk_draw_rectangle (sheet->pixmap,
3285 sheet->sheet_window_width - area.x,
3286 sheet->sheet_window_height);
3288 gdk_draw_pixmap(sheet->sheet_window,
3289 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3295 sheet->sheet_window_width - area.x,
3296 sheet->sheet_window_height);
3299 if(drawing_range.rowi == yyy_row_count(sheet) - 1){
3301 area.y=ROW_TOP_YPIXEL(sheet,
3302 yyy_row_count(sheet) - 1) +
3303 yyy_row_height(sheet, yyy_row_count(sheet) - 1) + 1;
3305 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3307 gdk_draw_rectangle (sheet->pixmap,
3311 sheet->sheet_window_width,
3312 sheet->sheet_window_height - area.y);
3314 gdk_draw_pixmap(sheet->sheet_window,
3315 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3321 sheet->sheet_window_width,
3322 sheet->sheet_window_height - area.y);
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_default(sheet, i, j);
3330 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3331 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3332 gtk_sheet_cell_draw_border(sheet, i-1, j, GTK_SHEET_BOTTOM_BORDER);
3333 gtk_sheet_cell_draw_border(sheet, i+1, j, GTK_SHEET_TOP_BORDER);
3334 gtk_sheet_cell_draw_border(sheet, i, j-1, GTK_SHEET_RIGHT_BORDER);
3335 gtk_sheet_cell_draw_border(sheet, i, j+1, GTK_SHEET_LEFT_BORDER);
3336 gtk_sheet_cell_draw_border(sheet, i, j, 15);
3339 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3340 for(j=drawing_range.col0; j<=drawing_range.coli; j++)
3341 gtk_sheet_cell_draw_label (sheet, i, j);
3343 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3344 for(j= xxx_column_left_column(sheet, drawing_range.col0);
3345 j<drawing_range.col0; j++)
3346 gtk_sheet_cell_draw_label (sheet, i, j);
3348 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3349 for(j = drawing_range.coli+1;
3350 j <= xxx_column_right_column(sheet, drawing_range.coli);
3352 gtk_sheet_cell_draw_label (sheet, i, j);
3354 gtk_sheet_draw_backing_pixmap(sheet, drawing_range);
3356 if(sheet->state != GTK_SHEET_NORMAL && gtk_sheet_range_isvisible(sheet, sheet->range))
3357 gtk_sheet_range_draw_selection(sheet, drawing_range);
3359 if(sheet->state == GTK_STATE_NORMAL &&
3360 sheet->active_cell.row >= drawing_range.row0 &&
3361 sheet->active_cell.row <= drawing_range.rowi &&
3362 sheet->active_cell.col >= drawing_range.col0 &&
3363 sheet->active_cell.col <= drawing_range.coli)
3364 gtk_sheet_show_active_cell(sheet);
3369 gtk_sheet_range_draw_selection(GtkSheet *sheet, GtkSheetRange range)
3375 if(range.col0 > sheet->range.coli || range.coli < sheet->range.col0 ||
3376 range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0)
3379 if(!gtk_sheet_range_isvisible(sheet, range)) return;
3380 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3384 range.col0=MAX(sheet->range.col0, range.col0);
3385 range.coli=MIN(sheet->range.coli, range.coli);
3386 range.row0=MAX(sheet->range.row0, range.row0);
3387 range.rowi=MIN(sheet->range.rowi, range.rowi);
3389 range.col0=MAX(range.col0, MIN_VISIBLE_COLUMN(sheet));
3390 range.coli=MIN(range.coli, MAX_VISIBLE_COLUMN(sheet));
3391 range.row0=MAX(range.row0, MIN_VISIBLE_ROW(sheet));
3392 range.rowi=MIN(range.rowi, MAX_VISIBLE_ROW(sheet));
3394 for(i=range.row0; i<=range.rowi; i++){
3395 for(j=range.col0; j<=range.coli; j++){
3397 if(gtk_sheet_cell_get_state(sheet, i, j)==GTK_STATE_SELECTED &&
3398 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
3401 row_button_set(sheet, i);
3402 column_button_set(sheet, j);
3405 area.x=COLUMN_LEFT_XPIXEL(sheet,j);
3406 area.y=ROW_TOP_YPIXEL(sheet,i);
3407 area.width= xxx_column_width(sheet, j);
3408 area.height=yyy_row_height(sheet, i);
3410 if(i==sheet->range.row0){
3412 area.height=area.height-2;
3414 if(i==sheet->range.rowi) area.height=area.height-3;
3415 if(j==sheet->range.col0){
3417 area.width=area.width-2;
3419 if(j==sheet->range.coli) area.width=area.width-3;
3421 if(i!=sheet->active_cell.row || j!=sheet->active_cell.col){
3422 gdk_draw_rectangle (sheet->sheet_window,
3426 area.width,area.height);
3433 gtk_sheet_draw_border(sheet, sheet->range);
3438 gtk_sheet_draw_backing_pixmap(GtkSheet *sheet, GtkSheetRange range)
3440 gint x,y,width,height;
3442 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3444 x = COLUMN_LEFT_XPIXEL(sheet,range.col0);
3445 y = ROW_TOP_YPIXEL(sheet, range.row0);
3446 width = COLUMN_LEFT_XPIXEL(sheet, range.coli) - x +
3447 xxx_column_width(sheet, range.coli);
3449 height=ROW_TOP_YPIXEL(sheet, range.rowi)-y+yyy_row_height(sheet, range.rowi);
3451 if(range.row0==sheet->range.row0){
3455 if(range.rowi==sheet->range.rowi) height=height+5;
3456 if(range.col0==sheet->range.col0){
3460 if(range.coli==sheet->range.coli) width=width+5;
3463 width=MIN(width, sheet->sheet_window_width-x);
3464 height=MIN(height, sheet->sheet_window_height-y);
3471 x = (sheet->row_titles_visible)
3472 ? MAX(x, sheet->row_title_area.width) : MAX(x, 0);
3473 y = (sheet->column_titles_visible)
3474 ? MAX(y, sheet->column_title_area.height) : MAX(y, 0);
3476 if(range.coli == xxx_column_count(sheet) - 1)
3477 width = sheet->sheet_window_width - x;
3478 if(range.rowi == yyy_row_count(sheet) - 1)
3479 height=sheet->sheet_window_height - y;
3481 gdk_draw_pixmap(sheet->sheet_window,
3482 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3494 gtk_sheet_set_cell_text(GtkSheet *sheet, gint row, gint col, const gchar *text)
3496 GtkSheetCellAttr attributes;
3498 g_return_if_fail (sheet != NULL);
3499 g_return_if_fail (GTK_IS_SHEET (sheet));
3500 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3501 if (col < 0 || row < 0) return;
3503 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3504 gtk_sheet_set_cell(sheet, row, col, attributes.justification, text);
3508 safe_strcmp(const gchar *s1, const gchar *s2)
3510 if ( !s1 && !s2) return 0;
3511 if ( !s1) return -1;
3512 if ( !s2) return +1;
3513 return strcmp(s1, s2);
3517 gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col,
3518 GtkJustification justification,
3521 GSheetModel *model ;
3525 GtkSheetRange range;
3527 GtkSheetCellAttr attributes;
3529 g_return_if_fail (sheet != NULL);
3530 g_return_if_fail (GTK_IS_SHEET (sheet));
3531 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3532 if (col < 0 || row < 0) return;
3534 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3536 attributes.justification = justification;
3538 model = gtk_sheet_get_model(sheet);
3540 old_text = g_sheet_model_get_string(model, row, col);
3544 if (0 != safe_strcmp(old_text, text))
3545 changed = g_sheet_model_set_string(model, text, row, col);
3547 if ( g_sheet_model_free_strings(model))
3551 if(changed && attributes.is_visible)
3553 gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
3555 if(s && strlen(s) > 0) {
3556 text_width = STRING_WIDTH(GTK_WIDGET(sheet),
3557 attributes.font_desc, text);
3559 dispose_string(sheet, s);
3563 range.col0 = sheet->view.col0;
3564 range.coli = sheet->view.coli;
3566 if(gtk_sheet_autoresize(sheet) &&
3567 text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
3568 gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width);
3569 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3572 if(!GTK_SHEET_IS_FROZEN(sheet))
3573 gtk_sheet_range_draw(sheet, &range);
3577 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
3583 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
3585 GtkSheetRange range;
3587 g_return_if_fail (sheet != NULL);
3588 g_return_if_fail (GTK_IS_SHEET (sheet));
3589 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3590 if (column < 0 || row < 0) return;
3594 range.col0 = sheet->view.col0;
3595 range.coli = sheet->view.coli;
3597 gtk_sheet_real_cell_clear(sheet, row, column, FALSE);
3599 if(!GTK_SHEET_IS_FROZEN(sheet)){
3600 gtk_sheet_range_draw(sheet, &range);
3605 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
3607 GtkSheetRange range;
3609 g_return_if_fail (sheet != NULL);
3610 g_return_if_fail (GTK_IS_SHEET (sheet));
3611 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3612 if (column < 0 || row < 0) return;
3616 range.col0 = sheet->view.col0;
3617 range.coli = sheet->view.coli;
3619 gtk_sheet_real_cell_clear(sheet, row, column, TRUE);
3621 if(!GTK_SHEET_IS_FROZEN(sheet)){
3622 gtk_sheet_range_draw(sheet, &range);
3627 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
3629 GSheetModel *model = gtk_sheet_get_model(sheet);
3631 gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column);
3633 if (old_text && strlen(old_text) > 0 )
3635 g_sheet_model_datum_clear(model, row, column);
3637 if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0)
3638 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL],
3642 dispose_string (sheet, old_text);
3646 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
3648 g_return_if_fail (sheet != NULL);
3649 g_return_if_fail (GTK_IS_SHEET (sheet));
3651 gtk_sheet_real_range_clear(sheet, range, FALSE);
3655 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range)
3657 g_return_if_fail (sheet != NULL);
3658 g_return_if_fail (GTK_IS_SHEET (sheet));
3660 gtk_sheet_real_range_clear(sheet, range, TRUE);
3665 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
3669 GtkSheetRange clear;
3673 clear.rowi = yyy_row_count(sheet) - 1;
3675 clear.coli = xxx_column_count(sheet) - 1;
3679 clear.row0=MAX(clear.row0, 0);
3680 clear.col0=MAX(clear.col0, 0);
3681 clear.rowi=MIN(clear.rowi, yyy_row_count(sheet) - 1 );
3682 clear.coli=MIN(clear.coli, xxx_column_count(sheet) - 1 );
3684 for(i=clear.row0; i<=clear.rowi; i++)
3685 for(j=clear.col0; j<=clear.coli; j++){
3686 gtk_sheet_real_cell_clear(sheet, i, j, delete);
3689 gtk_sheet_range_draw(sheet, NULL);
3694 gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col)
3697 char *text = gtk_sheet_cell_get_text(sheet, row, col);
3698 empty = (text == NULL );
3700 dispose_string(sheet, text);
3707 gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
3710 g_return_val_if_fail (sheet != NULL, NULL);
3711 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
3713 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet))
3715 if(col < 0 || row < 0) return NULL;
3717 model = gtk_sheet_get_model(sheet);
3722 return g_sheet_model_get_string(model, row, col);
3727 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
3730 GtkSheetRange *range;
3732 g_return_val_if_fail (sheet != NULL, 0);
3733 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3734 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return 0;
3735 if(col < 0 || row < 0) return 0;
3737 state = sheet->state;
3738 range = &sheet->range;
3742 case GTK_SHEET_NORMAL:
3743 return GTK_STATE_NORMAL;
3745 case GTK_SHEET_ROW_SELECTED:
3746 if(row>=range->row0 && row<=range->rowi)
3747 return GTK_STATE_SELECTED;
3749 case GTK_SHEET_COLUMN_SELECTED:
3750 if(col>=range->col0 && col<=range->coli)
3751 return GTK_STATE_SELECTED;
3753 case GTK_SHEET_RANGE_SELECTED:
3754 if(row >= range->row0 && row <= range->rowi && \
3755 col >= range->col0 && col <= range->coli)
3756 return GTK_STATE_SELECTED;
3759 return GTK_STATE_NORMAL;
3763 gtk_sheet_get_pixel_info (GtkSheet * sheet,
3771 g_return_val_if_fail (sheet != NULL, 0);
3772 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3774 /* bounds checking, return false if the user clicked
3775 * on a blank area */
3776 trow = ROW_FROM_YPIXEL (sheet, y);
3777 if (trow >= yyy_row_count(sheet))
3782 tcol = COLUMN_FROM_XPIXEL (sheet, x);
3783 if (tcol >= xxx_column_count(sheet))
3792 gtk_sheet_get_cell_area (GtkSheet * sheet,
3797 g_return_val_if_fail (sheet != NULL, 0);
3798 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3800 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3803 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) -
3804 (sheet->row_titles_visible
3805 ? sheet->row_title_area.width
3807 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL(sheet, row) -
3808 (sheet->column_titles_visible
3809 ? sheet->column_title_area.height
3811 area->width= (column == -1) ? sheet->row_title_area.width
3812 : xxx_column_width(sheet, column);
3814 area->height= (row == -1) ? sheet->column_title_area.height
3815 : yyy_row_height(sheet, row);
3818 if(row < 0 || column < 0) return FALSE;
3820 area->x = COLUMN_LEFT_XPIXEL(sheet, column);
3821 area->y = ROW_TOP_YPIXEL(sheet, row);
3822 if(sheet->row_titles_visible)
3823 area->x -= sheet->row_title_area.width;
3824 if(sheet->column_titles_visible)
3825 area->y -= sheet->column_title_area.height;
3827 area->width=sheet->column[column].width;
3828 area->height=yyy_row_height(sheet, row);
3834 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
3836 g_return_val_if_fail (sheet != NULL, 0);
3837 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3839 if(row < 0 || column < 0) return FALSE;
3840 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3843 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
3845 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
3848 sheet->active_cell.row=row;
3849 sheet->active_cell.col=column;
3851 if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE;
3853 if(gtk_sheet_autoscroll(sheet))
3854 gtk_sheet_move_query(sheet, row, column);
3860 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column)
3862 g_return_if_fail (sheet != NULL);
3863 g_return_if_fail (GTK_IS_SHEET (sheet));
3865 *row = sheet->active_cell.row;
3866 *column = sheet->active_cell.col;
3870 gtk_sheet_entry_changed(GtkWidget *widget, gpointer data)
3875 GtkJustification justification;
3876 GtkSheetCellAttr attributes;
3878 g_return_if_fail (data != NULL);
3879 g_return_if_fail (GTK_IS_SHEET (data));
3881 sheet=GTK_SHEET(data);
3883 if(!GTK_WIDGET_VISIBLE(widget)) return;
3884 if(sheet->state != GTK_STATE_NORMAL) return;
3886 row=sheet->active_cell.row;
3887 col=sheet->active_cell.col;
3889 if(row<0 || col<0) return;
3891 sheet->active_cell.row=-1;
3892 sheet->active_cell.col=-1;
3894 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3896 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3898 if(text && strlen(text) > 0){
3899 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3900 justification=attributes.justification;
3901 gtk_sheet_set_cell(sheet, row, col, justification, text);
3904 if(sheet->freeze_count == 0)
3905 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3907 sheet->active_cell.row=row;;
3908 sheet->active_cell.col=col;
3913 gtk_sheet_deactivate_cell(GtkSheet *sheet)
3915 gboolean veto = TRUE;
3917 g_return_val_if_fail (sheet != NULL, FALSE);
3918 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
3920 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return FALSE;
3921 if(sheet->state != GTK_SHEET_NORMAL) return FALSE;
3923 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[DEACTIVATE],
3924 sheet->active_cell.row,
3925 sheet->active_cell.col, &veto);
3927 if(!veto) return FALSE;
3929 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
3930 (GtkSignalFunc) gtk_sheet_entry_changed,
3931 GTK_OBJECT(GTK_WIDGET(sheet)));
3933 gtk_sheet_hide_active_cell(sheet);
3934 sheet->active_cell.row=-1;
3935 sheet->active_cell.col=-1;
3937 if(GTK_SHEET_REDRAW_PENDING(sheet)){
3938 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3939 gtk_sheet_range_draw(sheet, NULL);
3946 gtk_sheet_hide_active_cell(GtkSheet *sheet)
3950 GtkJustification justification;
3951 GtkSheetCellAttr attributes;
3953 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3955 row=sheet->active_cell.row;
3956 col=sheet->active_cell.col;
3958 if(row < 0 || col < 0) return;
3960 if(sheet->freeze_count == 0)
3961 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3963 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3965 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3966 justification=attributes.justification;
3968 if(text && strlen(text)!=0){
3969 gtk_sheet_set_cell(sheet, row, col, justification, text);
3970 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col);
3974 gtk_sheet_cell_clear(sheet, row, col);
3977 row=sheet->active_cell.row;
3978 col=sheet->active_cell.col;
3981 column_button_release(sheet, col);
3982 row_button_release(sheet, row);
3985 gtk_widget_unmap(sheet->sheet_entry);
3987 if(row != -1 && col != -1)
3988 gdk_draw_pixmap(sheet->sheet_window,
3989 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3991 COLUMN_LEFT_XPIXEL(sheet,col)-1,
3992 ROW_TOP_YPIXEL(sheet,row)-1,
3993 COLUMN_LEFT_XPIXEL(sheet,col)-1,
3994 ROW_TOP_YPIXEL(sheet,row)-1,
3995 xxx_column_width(sheet, col) + 4,
3996 yyy_row_height(sheet, row)+4);
3998 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4000 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4005 gtk_sheet_activate_cell(GtkSheet *sheet, gint row, gint col)
4007 gboolean veto = TRUE;
4009 g_return_val_if_fail (sheet != NULL, FALSE);
4010 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
4012 if(row < 0 || col < 0) return FALSE;
4013 if(row >= yyy_row_count(sheet) || col >= xxx_column_count(sheet))
4016 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4017 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
4020 if(!veto) return FALSE;
4021 if(sheet->state != GTK_SHEET_NORMAL){
4022 sheet->state=GTK_SHEET_NORMAL;
4023 gtk_sheet_real_unselect_range(sheet, NULL);
4026 sheet->range.row0=row;
4027 sheet->range.col0=col;
4028 sheet->range.rowi=row;
4029 sheet->range.coli=col;
4030 sheet->active_cell.row=row;
4031 sheet->active_cell.col=col;
4032 sheet->selection_cell.row=row;
4033 sheet->selection_cell.col=col;
4035 row_button_set(sheet, row);
4036 column_button_set(sheet, col);
4039 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4040 gtk_sheet_show_active_cell(sheet);
4042 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
4044 G_CALLBACK(gtk_sheet_entry_changed),
4047 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4053 gtk_sheet_show_active_cell(GtkSheet *sheet)
4055 GtkEntry *sheet_entry;
4056 GtkSheetCellAttr attributes;
4058 const gchar *old_text;
4059 GtkJustification justification;
4062 g_return_if_fail (sheet != NULL);
4063 g_return_if_fail (GTK_IS_SHEET (sheet));
4065 row = sheet->active_cell.row;
4066 col = sheet->active_cell.col;
4068 /* Don't show the active cell, if there is no active cell: */
4069 if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */
4072 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4073 if(sheet->state != GTK_SHEET_NORMAL) return;
4074 if(GTK_SHEET_IN_SELECTION(sheet)) return;
4076 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4078 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
4080 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4082 justification = GTK_JUSTIFY_LEFT;
4084 if(gtk_sheet_justify_entry(sheet))
4085 justification = attributes.justification;
4087 text = gtk_sheet_cell_get_text(sheet, row, col);
4089 text = g_strdup("");
4091 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible);
4093 if(gtk_sheet_locked(sheet) || !attributes.is_editable){
4094 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
4096 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
4099 /*** Added by John Gotts. Mar 25, 2005 *********/
4100 old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
4101 if (strcmp(old_text, text) != 0)
4103 if(!GTK_IS_ITEM_ENTRY(sheet_entry))
4104 gtk_entry_set_text(GTK_ENTRY(sheet_entry), text);
4106 gtk_item_entry_set_text(GTK_ITEM_ENTRY(sheet_entry), text, justification);
4109 gtk_sheet_entry_set_max_size(sheet);
4110 gtk_sheet_size_allocate_entry(sheet);
4112 gtk_widget_map(sheet->sheet_entry);
4113 gtk_sheet_draw_active_cell(sheet);
4115 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
4117 dispose_string(sheet, text);
4121 gtk_sheet_draw_active_cell(GtkSheet *sheet)
4125 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
4126 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4128 row = sheet->active_cell.row;
4129 col = sheet->active_cell.col;
4131 if(row<0 || col<0) return;
4133 if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
4135 row_button_set(sheet, row);
4136 column_button_set(sheet, col);
4138 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4139 gtk_sheet_draw_border(sheet, sheet->range);
4144 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
4146 gint pixmap_width, pixmap_height;
4148 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4150 if(width == 0 && height == 0){
4151 width=sheet->sheet_window_width+80;
4152 height=sheet->sheet_window_height+80;
4158 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4161 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4165 /* reallocate if sizes don't match */
4166 gdk_window_get_size (sheet->pixmap,
4167 &pixmap_width, &pixmap_height);
4168 if ((pixmap_width != width) || (pixmap_height != height))
4170 g_object_unref(sheet->pixmap);
4171 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4174 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4180 gtk_sheet_new_selection(GtkSheet *sheet, GtkSheetRange *range)
4182 gint i,j, mask1, mask2;
4183 gint state, selected;
4184 gint x,y,width,height;
4185 GtkSheetRange new_range, aux_range;
4187 g_return_if_fail (sheet != NULL);
4189 if(range==NULL) range=&sheet->range;
4193 range->row0=MIN(range->row0, sheet->range.row0);
4194 range->rowi=MAX(range->rowi, sheet->range.rowi);
4195 range->col0=MIN(range->col0, sheet->range.col0);
4196 range->coli=MAX(range->coli, sheet->range.coli);
4198 range->row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
4199 range->rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
4200 range->col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
4201 range->coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
4203 aux_range.row0=MAX(new_range.row0, MIN_VISIBLE_ROW(sheet));
4204 aux_range.rowi=MIN(new_range.rowi, MAX_VISIBLE_ROW(sheet));
4205 aux_range.col0=MAX(new_range.col0, MIN_VISIBLE_COLUMN(sheet));
4206 aux_range.coli=MIN(new_range.coli, MAX_VISIBLE_COLUMN(sheet));
4208 for(i=range->row0; i<=range->rowi; i++){
4209 for(j=range->col0; j<=range->coli; j++){
4211 state=gtk_sheet_cell_get_state(sheet, i, j);
4212 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4213 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4215 if(state==GTK_STATE_SELECTED && selected &&
4216 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4217 (i==sheet->range.row0 || i==sheet->range.rowi ||
4218 j==sheet->range.col0 || j==sheet->range.coli ||
4219 i==new_range.row0 || i==new_range.rowi ||
4220 j==new_range.col0 || j==new_range.coli)){
4222 mask1 = i==sheet->range.row0 ? 1 : 0;
4223 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4224 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4225 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4227 mask2 = i==new_range.row0 ? 1 : 0;
4228 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4229 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4230 mask2 = j==new_range.coli ? mask2+8 : mask2;
4233 x=COLUMN_LEFT_XPIXEL(sheet,j);
4234 y=ROW_TOP_YPIXEL(sheet, i);
4235 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4236 xxx_column_width(sheet, j);
4237 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4239 if(i==sheet->range.row0){
4243 if(i==sheet->range.rowi) height=height+3;
4244 if(j==sheet->range.col0){
4248 if(j==sheet->range.coli) width=width+3;
4250 gdk_draw_pixmap(sheet->sheet_window,
4251 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4260 if(i != sheet->active_cell.row || j != sheet->active_cell.col){
4261 x=COLUMN_LEFT_XPIXEL(sheet,j);
4262 y=ROW_TOP_YPIXEL(sheet, i);
4263 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4264 xxx_column_width(sheet, j);
4266 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4268 if(i==new_range.row0){
4272 if(i==new_range.rowi) height=height-3;
4273 if(j==new_range.col0){
4277 if(j==new_range.coli) width=width-3;
4279 gdk_draw_rectangle (sheet->sheet_window,
4290 for(i=range->row0; i<=range->rowi; i++){
4291 for(j=range->col0; j<=range->coli; j++){
4293 state=gtk_sheet_cell_get_state(sheet, i, j);
4294 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4295 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4297 if(state==GTK_STATE_SELECTED && !selected &&
4298 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4300 x=COLUMN_LEFT_XPIXEL(sheet,j);
4301 y=ROW_TOP_YPIXEL(sheet, i);
4302 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4303 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4305 if(i==sheet->range.row0){
4309 if(i==sheet->range.rowi) height=height+3;
4310 if(j==sheet->range.col0){
4314 if(j==sheet->range.coli) width=width+3;
4316 gdk_draw_pixmap(sheet->sheet_window,
4317 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4329 for(i=range->row0; i<=range->rowi; i++){
4330 for(j=range->col0; j<=range->coli; j++){
4332 state=gtk_sheet_cell_get_state(sheet, i, j);
4333 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4334 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4336 if(state!=GTK_STATE_SELECTED && selected &&
4337 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4338 (i != sheet->active_cell.row || j != sheet->active_cell.col)){
4340 x=COLUMN_LEFT_XPIXEL(sheet,j);
4341 y=ROW_TOP_YPIXEL(sheet, i);
4342 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4343 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4345 if(i==new_range.row0){
4349 if(i==new_range.rowi) height=height-3;
4350 if(j==new_range.col0){
4354 if(j==new_range.coli) width=width-3;
4356 gdk_draw_rectangle (sheet->sheet_window,
4367 for(i=aux_range.row0; i<=aux_range.rowi; i++){
4368 for(j=aux_range.col0; j<=aux_range.coli; j++){
4370 if(xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4372 state=gtk_sheet_cell_get_state(sheet, i, j);
4374 mask1 = i==sheet->range.row0 ? 1 : 0;
4375 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4376 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4377 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4379 mask2 = i==new_range.row0 ? 1 : 0;
4380 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4381 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4382 mask2 = j==new_range.coli ? mask2+8 : mask2;
4383 if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){
4384 x=COLUMN_LEFT_XPIXEL(sheet,j);
4385 y=ROW_TOP_YPIXEL(sheet, i);
4386 width=xxx_column_width(sheet, j);
4387 height=yyy_row_height(sheet, i);
4389 gdk_draw_rectangle (sheet->sheet_window,
4397 gdk_draw_rectangle (sheet->sheet_window,
4404 gdk_draw_rectangle (sheet->sheet_window,
4412 gdk_draw_rectangle (sheet->sheet_window,
4429 gtk_sheet_draw_corners(sheet, new_range);
4434 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
4439 gint x,y,width,height;
4441 widget = GTK_WIDGET(sheet);
4443 x=COLUMN_LEFT_XPIXEL(sheet,new_range.col0);
4444 y=ROW_TOP_YPIXEL(sheet,new_range.row0);
4445 width=COLUMN_LEFT_XPIXEL(sheet,new_range.coli)-x+
4446 xxx_column_width(sheet, new_range.coli);
4448 height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+
4449 yyy_row_height(sheet, new_range.rowi);
4451 area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
4452 area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
4453 area.width=sheet->sheet_window_width;
4454 area.height=sheet->sheet_window_height;
4460 if(width>area.width) width=area.width+10;
4465 if(height>area.height) height=area.height+10;
4467 gdk_gc_set_clip_rectangle(sheet->xor_gc, &area);
4469 for(i=-1; i<=1; ++i)
4470 gdk_draw_rectangle (sheet->sheet_window,
4474 width-2*i,height-2*i);
4476 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
4478 gtk_sheet_draw_corners(sheet, new_range);
4483 gtk_sheet_draw_corners(GtkSheet *sheet, GtkSheetRange range)
4488 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.col0)){
4489 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4490 y=ROW_TOP_YPIXEL(sheet,range.row0);
4491 gdk_draw_pixmap(sheet->sheet_window,
4492 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4500 gdk_draw_rectangle (sheet->sheet_window,
4507 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) ||
4508 sheet->state == GTK_SHEET_COLUMN_SELECTED){
4509 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4510 xxx_column_width(sheet, range.coli);
4511 y=ROW_TOP_YPIXEL(sheet,range.row0);
4513 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
4515 y = ROW_TOP_YPIXEL(sheet, sheet->view.row0)+3;
4518 gdk_draw_pixmap(sheet->sheet_window,
4519 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4527 gdk_draw_rectangle (sheet->sheet_window,
4530 x-width+width/2,y-width+width/2,
4534 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.col0) ||
4535 sheet->state == GTK_SHEET_ROW_SELECTED){
4536 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4537 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4538 yyy_row_height(sheet, range.rowi);
4540 if(sheet->state == GTK_SHEET_ROW_SELECTED)
4542 x = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0)+3;
4545 gdk_draw_pixmap(sheet->sheet_window,
4546 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4554 gdk_draw_rectangle (sheet->sheet_window,
4557 x-width+width/2,y-width+width/2,
4561 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){
4562 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4563 xxx_column_width(sheet, range.coli);
4564 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4565 yyy_row_height(sheet, range.rowi);
4567 if(sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
4568 if(sheet->state == GTK_SHEET_NORMAL) width = 3;
4569 gdk_draw_pixmap(sheet->sheet_window,
4570 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4578 gdk_draw_rectangle (sheet->sheet_window,
4581 x-width+width/2,y-width+width/2,
4590 gtk_sheet_real_select_range (GtkSheet * sheet,
4591 GtkSheetRange * range)
4595 g_return_if_fail (sheet != NULL);
4597 if(range==NULL) range=&sheet->range;
4599 if(range->row0 < 0 || range->rowi < 0) return;
4600 if(range->col0 < 0 || range->coli < 0) return;
4605 if(state==GTK_SHEET_COLUMN_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4606 for(i=sheet->range.col0; i< range->col0; i++)
4607 column_button_release(sheet, i);
4608 for(i=range->coli+1; i<= sheet->range.coli; i++)
4609 column_button_release(sheet, i);
4610 for(i=range->col0; i<=range->coli; i++){
4611 column_button_set(sheet, i);
4615 if(state==GTK_SHEET_ROW_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4616 for(i=sheet->range.row0; i< range->row0; i++)
4617 row_button_release(sheet, i);
4618 for(i=range->rowi+1; i<= sheet->range.rowi; i++)
4619 row_button_release(sheet, i);
4620 for(i=range->row0; i<=range->rowi; i++){
4621 row_button_set(sheet, i);
4626 if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
4627 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
4630 gtk_sheet_new_selection(sheet, range);
4632 sheet->range.col0=range->col0;
4633 sheet->range.coli=range->coli;
4634 sheet->range.row0=range->row0;
4635 sheet->range.rowi=range->rowi;
4640 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4641 gtk_sheet_range_draw_selection(sheet, sheet->range);
4644 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[SELECT_RANGE], range);
4648 gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range)
4650 g_return_if_fail (sheet != NULL);
4652 if(range==NULL) range=&sheet->range;
4654 if(range->row0 < 0 || range->rowi < 0) return;
4655 if(range->col0 < 0 || range->coli < 0) return;
4657 if(sheet->state != GTK_SHEET_NORMAL)
4658 gtk_sheet_real_unselect_range(sheet, NULL);
4661 gboolean veto = TRUE;
4662 veto = gtk_sheet_deactivate_cell(sheet);
4666 sheet->range.row0=range->row0;
4667 sheet->range.rowi=range->rowi;
4668 sheet->range.col0=range->col0;
4669 sheet->range.coli=range->coli;
4670 sheet->active_cell.row=range->row0;
4671 sheet->active_cell.col=range->col0;
4672 sheet->selection_cell.row=range->rowi;
4673 sheet->selection_cell.col=range->coli;
4675 sheet->state = GTK_SHEET_RANGE_SELECTED;
4676 gtk_sheet_real_select_range(sheet, NULL);
4681 gtk_sheet_unselect_range (GtkSheet * sheet)
4683 gtk_sheet_real_unselect_range(sheet, NULL);
4684 sheet->state = GTK_STATE_NORMAL;
4685 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
4690 gtk_sheet_real_unselect_range (GtkSheet * sheet,
4691 const GtkSheetRange *range)
4693 g_return_if_fail (sheet != NULL);
4694 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)));
4697 range=&sheet->range;
4700 if(range->row0 < 0 || range->rowi < 0) return;
4701 if(range->col0 < 0 || range->coli < 0) return;
4703 if (gtk_sheet_range_isvisible (sheet, *range)){
4704 gtk_sheet_draw_backing_pixmap(sheet, *range);
4708 for(i=range->col0; i<=range->coli; i++){
4709 column_button_release(sheet, i);
4712 for(i=range->row0; i<=range->rowi; i++){
4713 row_button_release(sheet, i);
4717 gtk_sheet_position_children(sheet);
4722 gtk_sheet_expose (GtkWidget * widget,
4723 GdkEventExpose * event)
4726 GtkSheetRange range;
4728 g_return_val_if_fail (widget != NULL, FALSE);
4729 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4730 g_return_val_if_fail (event != NULL, FALSE);
4732 sheet = GTK_SHEET (widget);
4734 if (GTK_WIDGET_DRAWABLE (widget))
4736 range.row0=ROW_FROM_YPIXEL(sheet,event->area.y);
4737 range.col0=COLUMN_FROM_XPIXEL(sheet,event->area.x);
4738 range.rowi=ROW_FROM_YPIXEL(sheet,event->area.y+event->area.height);
4739 range.coli=COLUMN_FROM_XPIXEL(sheet,event->area.x+event->area.width);
4741 /* exposure events on the sheet */
4743 if(event->window == sheet->row_title_window && sheet->row_titles_visible){
4745 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
4746 gtk_sheet_button_draw(sheet,i,-1);
4749 if(event->window == sheet->column_title_window && sheet->column_titles_visible){
4751 for(i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
4752 gtk_sheet_button_draw(sheet,-1,i);
4755 if (event->window == sheet->sheet_window){
4756 gtk_sheet_draw_backing_pixmap(sheet, range);
4758 if(sheet->state != GTK_SHEET_NORMAL){
4759 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4760 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4761 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4762 gtk_sheet_draw_backing_pixmap(sheet, sheet->drag_range);
4764 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4765 gtk_sheet_range_draw_selection(sheet, sheet->range);
4766 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4767 draw_xor_rectangle(sheet, sheet->drag_range);
4770 if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet))){
4771 if(sheet->state == GTK_SHEET_NORMAL){
4772 gtk_sheet_draw_active_cell(sheet);
4773 if(!GTK_SHEET_IN_SELECTION(sheet))
4774 gtk_widget_queue_draw(sheet->sheet_entry);
4783 if(sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet))
4784 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4786 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
4793 gtk_sheet_button_press (GtkWidget * widget,
4794 GdkEventButton * event)
4797 GdkModifierType mods;
4798 gint x, y, row, column;
4801 g_return_val_if_fail (widget != NULL, FALSE);
4802 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4803 g_return_val_if_fail (event != NULL, FALSE);
4805 sheet = GTK_SHEET (widget);
4807 if ( event->type == GDK_2BUTTON_PRESS)
4809 gtk_widget_get_pointer (widget, &x, &y);
4810 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4812 if (event->window == sheet->column_title_window )
4814 gtk_signal_emit (GTK_OBJECT (sheet),
4815 sheet_signals[DOUBLE_CLICK_COLUMN], column);
4817 else if (event->window == sheet->row_title_window )
4819 gtk_signal_emit (GTK_OBJECT (sheet),
4820 sheet_signals[DOUBLE_CLICK_ROW], row);
4826 if(event->type != GDK_BUTTON_PRESS) return TRUE;
4828 gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
4830 if(!(mods & GDK_BUTTON1_MASK)) return TRUE;
4833 /* press on resize windows */
4834 if (event->window == sheet->column_title_window &&
4835 gtk_sheet_columns_resizable(sheet))
4837 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
4838 if(POSSIBLE_XDRAG(sheet, sheet->x_drag, &sheet->drag_cell.col)){
4840 if (event->type == GDK_2BUTTON_PRESS){
4841 gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
4842 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_XDRAG);
4845 gtk_sheet_column_size_request(sheet, sheet->drag_cell.col, &req);
4846 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4847 gdk_pointer_grab (sheet->column_title_window, FALSE,
4848 GDK_POINTER_MOTION_HINT_MASK |
4849 GDK_BUTTON1_MOTION_MASK |
4850 GDK_BUTTON_RELEASE_MASK,
4851 NULL, NULL, event->time);
4853 draw_xor_vline (sheet);
4858 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet))
4860 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
4862 if(POSSIBLE_YDRAG(sheet, sheet->y_drag, &sheet->drag_cell.row)){
4864 gtk_sheet_row_size_request(sheet, sheet->drag_cell.row, &req);
4865 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
4866 gdk_pointer_grab (sheet->row_title_window, FALSE,
4867 GDK_POINTER_MOTION_HINT_MASK |
4868 GDK_BUTTON1_MOTION_MASK |
4869 GDK_BUTTON_RELEASE_MASK,
4870 NULL, NULL, event->time);
4872 draw_xor_hline (sheet);
4877 /* the sheet itself does not handle other than single click events */
4878 if(event->type != GDK_BUTTON_PRESS) return FALSE;
4880 /* selections on the sheet */
4881 if(event->window == sheet->sheet_window){
4882 gtk_widget_get_pointer (widget, &x, &y);
4883 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4884 gdk_pointer_grab (sheet->sheet_window, FALSE,
4885 GDK_POINTER_MOTION_HINT_MASK |
4886 GDK_BUTTON1_MOTION_MASK |
4887 GDK_BUTTON_RELEASE_MASK,
4888 NULL, NULL, event->time);
4889 gtk_grab_add(GTK_WIDGET(sheet));
4890 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4891 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4893 if(sheet->selection_mode != GTK_SELECTION_SINGLE &&
4894 sheet->cursor_drag->type==GDK_SIZING &&
4895 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_RESIZE(sheet)){
4896 if(sheet->state==GTK_STATE_NORMAL) {
4897 row=sheet->active_cell.row;
4898 column=sheet->active_cell.col;
4899 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4900 sheet->active_cell.row=row;
4901 sheet->active_cell.col=column;
4902 sheet->drag_range=sheet->range;
4903 sheet->state=GTK_SHEET_RANGE_SELECTED;
4904 gtk_sheet_select_range(sheet, &sheet->drag_range);
4908 if(row > sheet->range.rowi) row--;
4909 if(column > sheet->range.coli) column--;
4910 sheet->drag_cell.row = row;
4911 sheet->drag_cell.col = column;
4912 sheet->drag_range=sheet->range;
4913 draw_xor_rectangle(sheet, sheet->drag_range);
4914 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
4916 else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW &&
4917 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_DRAG(sheet)) {
4918 if(sheet->state==GTK_STATE_NORMAL) {
4919 row=sheet->active_cell.row;
4920 column=sheet->active_cell.col;
4921 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4922 sheet->active_cell.row=row;
4923 sheet->active_cell.col=column;
4924 sheet->drag_range=sheet->range;
4925 sheet->state=GTK_SHEET_RANGE_SELECTED;
4926 gtk_sheet_select_range(sheet, &sheet->drag_range);
4930 if(row < sheet->range.row0) row++;
4931 if(row > sheet->range.rowi) row--;
4932 if(column < sheet->range.col0) column++;
4933 if(column > sheet->range.coli) column--;
4934 sheet->drag_cell.row=row;
4935 sheet->drag_cell.col=column;
4936 sheet->drag_range=sheet->range;
4937 draw_xor_rectangle(sheet, sheet->drag_range);
4938 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
4942 gtk_sheet_click_cell(sheet, row, column, &veto);
4943 if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4948 if(event->window == sheet->column_title_window){
4949 gtk_widget_get_pointer (widget, &x, &y);
4950 column = COLUMN_FROM_XPIXEL(sheet, x);
4951 if(xxx_column_is_sensitive(sheet, column)){
4952 gtk_sheet_click_cell(sheet, -1, column, &veto);
4953 gtk_grab_add(GTK_WIDGET(sheet));
4954 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4955 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4956 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4960 if(event->window == sheet->row_title_window){
4961 gtk_widget_get_pointer (widget, &x, &y);
4962 row = ROW_FROM_YPIXEL(sheet, y);
4963 if(yyy_row_is_sensitive(sheet, row)){
4964 gtk_sheet_click_cell(sheet, row, -1, &veto);
4965 gtk_grab_add(GTK_WIDGET(sheet));
4966 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4967 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4968 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4976 gtk_sheet_scroll(gpointer data)
4979 gint x,y,row,column;
4982 sheet=GTK_SHEET(data);
4984 GDK_THREADS_ENTER();
4986 gtk_widget_get_pointer (GTK_WIDGET(sheet), &x, &y);
4987 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4991 if(GTK_SHEET_IN_SELECTION(sheet))
4992 gtk_sheet_extend_selection(sheet, row, column);
4994 if(GTK_SHEET_IN_DRAG(sheet) || GTK_SHEET_IN_RESIZE(sheet)){
4995 move=gtk_sheet_move_query(sheet, row, column);
4996 if(move) draw_xor_rectangle(sheet, sheet->drag_range);
4999 GDK_THREADS_LEAVE();
5006 gtk_sheet_click_cell(GtkSheet *sheet, gint row, gint column, gboolean *veto)
5010 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)){
5015 if(column >= 0 && row >= 0)
5016 if(! xxx_column_is_visible(sheet, column) || !yyy_row_is_visible(sheet, row))
5022 _gtkextra_signal_emit(GTK_OBJECT(sheet), sheet_signals[TRAVERSE],
5023 sheet->active_cell.row, sheet->active_cell.col,
5024 &row, &column, veto);
5027 if(sheet->state == GTK_STATE_NORMAL) return;
5029 row = sheet->active_cell.row;
5030 column = sheet->active_cell.col;
5032 gtk_sheet_activate_cell(sheet, row, column);
5036 if(row == -1 && column >= 0){
5037 if(gtk_sheet_autoscroll(sheet))
5038 gtk_sheet_move_query(sheet, row, column);
5039 gtk_sheet_select_column(sheet, column);
5042 if(column == -1 && row >= 0){
5043 if(gtk_sheet_autoscroll(sheet))
5044 gtk_sheet_move_query(sheet, row, column);
5045 gtk_sheet_select_row(sheet, row);
5049 if(row==-1 && column ==-1){
5050 sheet->range.row0=0;
5051 sheet->range.col0=0;
5052 sheet->range.rowi = yyy_row_count(sheet) - 1;
5053 sheet->range.coli = xxx_column_count(sheet) - 1;
5054 sheet->active_cell.row=0;
5055 sheet->active_cell.col=0;
5056 gtk_sheet_select_range(sheet, NULL);
5060 if(row!=-1 && column !=-1){
5061 if(sheet->state != GTK_SHEET_NORMAL){
5062 sheet->state = GTK_SHEET_NORMAL;
5063 gtk_sheet_real_unselect_range(sheet, NULL);
5067 if(!gtk_sheet_deactivate_cell(sheet)){
5073 if(gtk_sheet_autoscroll(sheet))
5074 gtk_sheet_move_query(sheet, row, column);
5075 sheet->active_cell.row=row;
5076 sheet->active_cell.col=column;
5077 sheet->selection_cell.row=row;
5078 sheet->selection_cell.col=column;
5079 sheet->range.row0=row;
5080 sheet->range.col0=column;
5081 sheet->range.rowi=row;
5082 sheet->range.coli=column;
5083 sheet->state=GTK_SHEET_NORMAL;
5084 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5085 gtk_sheet_draw_active_cell(sheet);
5089 g_assert_not_reached();
5090 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5091 sheet->active_cell.col);
5095 gtk_sheet_button_release (GtkWidget * widget,
5096 GdkEventButton * event)
5101 sheet=GTK_SHEET(widget);
5103 /* release on resize windows */
5104 if (GTK_SHEET_IN_XDRAG (sheet)){
5105 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
5106 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5107 gtk_widget_get_pointer (widget, &x, NULL);
5108 gdk_pointer_ungrab (event->time);
5109 draw_xor_vline (sheet);
5111 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col, new_column_width (sheet, sheet->drag_cell.col, &x));
5112 sheet->old_hadjustment = -1.;
5113 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed");
5117 if (GTK_SHEET_IN_YDRAG (sheet)){
5118 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5119 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5120 gtk_widget_get_pointer (widget, NULL, &y);
5121 gdk_pointer_ungrab (event->time);
5122 draw_xor_hline (sheet);
5124 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
5125 sheet->old_vadjustment = -1.;
5126 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed");
5131 if (GTK_SHEET_IN_DRAG(sheet)){
5132 GtkSheetRange old_range;
5133 draw_xor_rectangle(sheet, sheet->drag_range);
5134 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5135 gdk_pointer_ungrab (event->time);
5137 gtk_sheet_real_unselect_range(sheet, NULL);
5139 sheet->active_cell.row = sheet->active_cell.row +
5140 (sheet->drag_range.row0 - sheet->range.row0);
5141 sheet->active_cell.col = sheet->active_cell.col +
5142 (sheet->drag_range.col0 - sheet->range.col0);
5143 sheet->selection_cell.row = sheet->selection_cell.row +
5144 (sheet->drag_range.row0 - sheet->range.row0);
5145 sheet->selection_cell.col = sheet->selection_cell.col +
5146 (sheet->drag_range.col0 - sheet->range.col0);
5147 old_range=sheet->range;
5148 sheet->range=sheet->drag_range;
5149 sheet->drag_range=old_range;
5150 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[MOVE_RANGE],
5151 &sheet->drag_range, &sheet->range);
5152 gtk_sheet_select_range(sheet, &sheet->range);
5155 if (GTK_SHEET_IN_RESIZE(sheet)){
5156 GtkSheetRange old_range;
5157 draw_xor_rectangle(sheet, sheet->drag_range);
5158 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5159 gdk_pointer_ungrab (event->time);
5161 gtk_sheet_real_unselect_range(sheet, NULL);
5163 sheet->active_cell.row = sheet->active_cell.row +
5164 (sheet->drag_range.row0 - sheet->range.row0);
5165 sheet->active_cell.col = sheet->active_cell.col +
5166 (sheet->drag_range.col0 - sheet->range.col0);
5167 if(sheet->drag_range.row0 < sheet->range.row0)
5168 sheet->selection_cell.row = sheet->drag_range.row0;
5169 if(sheet->drag_range.rowi >= sheet->range.rowi)
5170 sheet->selection_cell.row = sheet->drag_range.rowi;
5171 if(sheet->drag_range.col0 < sheet->range.col0)
5172 sheet->selection_cell.col = sheet->drag_range.col0;
5173 if(sheet->drag_range.coli >= sheet->range.coli)
5174 sheet->selection_cell.col = sheet->drag_range.coli;
5175 old_range = sheet->range;
5176 sheet->range = sheet->drag_range;
5177 sheet->drag_range = old_range;
5179 if(sheet->state==GTK_STATE_NORMAL) sheet->state=GTK_SHEET_RANGE_SELECTED;
5180 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[RESIZE_RANGE],
5181 &sheet->drag_range, &sheet->range);
5182 gtk_sheet_select_range(sheet, &sheet->range);
5185 if(sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)){
5186 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5187 gdk_pointer_ungrab (event->time);
5188 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5189 sheet->active_cell.col);
5192 if(GTK_SHEET_IN_SELECTION)
5193 gdk_pointer_ungrab (event->time);
5195 gtk_timeout_remove(sheet->timer);
5196 gtk_grab_remove(GTK_WIDGET(sheet));
5198 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5204 gtk_sheet_motion (GtkWidget * widget,
5205 GdkEventMotion * event)
5208 GdkModifierType mods;
5209 GdkCursorType new_cursor;
5210 gint x, y, row, column;
5212 g_return_val_if_fail (widget != NULL, FALSE);
5213 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
5214 g_return_val_if_fail (event != NULL, FALSE);
5217 sheet = GTK_SHEET (widget);
5219 /* selections on the sheet */
5223 if(event->window == sheet->column_title_window && gtk_sheet_columns_resizable(sheet)){
5224 gtk_widget_get_pointer(widget, &x, &y);
5225 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_XDRAG(sheet, x, &column)){
5226 new_cursor=GDK_SB_H_DOUBLE_ARROW;
5227 if(new_cursor != sheet->cursor_drag->type){
5228 gdk_cursor_destroy(sheet->cursor_drag);
5229 sheet->cursor_drag=gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
5230 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5233 new_cursor=GDK_TOP_LEFT_ARROW;
5234 if(!GTK_SHEET_IN_XDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5235 gdk_cursor_destroy(sheet->cursor_drag);
5236 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5237 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5242 if(event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet)){
5243 gtk_widget_get_pointer(widget, &x, &y);
5244 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_YDRAG(sheet,y, &column)){
5245 new_cursor=GDK_SB_V_DOUBLE_ARROW;
5246 if(new_cursor != sheet->cursor_drag->type){
5247 gdk_cursor_destroy(sheet->cursor_drag);
5248 sheet->cursor_drag=gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
5249 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5252 new_cursor=GDK_TOP_LEFT_ARROW;
5253 if(!GTK_SHEET_IN_YDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5254 gdk_cursor_destroy(sheet->cursor_drag);
5255 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5256 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5261 new_cursor=GDK_PLUS;
5262 if(!POSSIBLE_DRAG(sheet,x,y,&row,&column) && !GTK_SHEET_IN_DRAG(sheet) &&
5263 !POSSIBLE_RESIZE(sheet,x,y,&row,&column) && !GTK_SHEET_IN_RESIZE(sheet) &&
5264 event->window == sheet->sheet_window &&
5265 new_cursor != sheet->cursor_drag->type){
5266 gdk_cursor_destroy(sheet->cursor_drag);
5267 sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
5268 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5271 new_cursor=GDK_TOP_LEFT_ARROW;
5272 if(!(POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5273 (POSSIBLE_DRAG(sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG(sheet)) &&
5274 event->window == sheet->sheet_window &&
5275 new_cursor != sheet->cursor_drag->type){
5276 gdk_cursor_destroy(sheet->cursor_drag);
5277 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5278 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5281 new_cursor=GDK_SIZING;
5282 if(!GTK_SHEET_IN_DRAG(sheet) &&
5283 (POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5284 event->window == sheet->sheet_window &&
5285 new_cursor != sheet->cursor_drag->type){
5286 gdk_cursor_destroy(sheet->cursor_drag);
5287 sheet->cursor_drag=gdk_cursor_new(GDK_SIZING);
5288 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5291 gdk_window_get_pointer (widget->window, &x, &y, &mods);
5292 if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
5294 if (GTK_SHEET_IN_XDRAG (sheet)){
5295 if (event->is_hint || event->window != widget->window)
5296 gtk_widget_get_pointer (widget, &x, NULL);
5300 new_column_width (sheet, sheet->drag_cell.col, &x);
5301 if (x != sheet->x_drag)
5303 draw_xor_vline (sheet);
5305 draw_xor_vline (sheet);
5310 if (GTK_SHEET_IN_YDRAG (sheet)){
5311 if (event->is_hint || event->window != widget->window)
5312 gtk_widget_get_pointer (widget, NULL, &y);
5316 new_row_height (sheet, sheet->drag_cell.row, &y);
5317 if (y != sheet->y_drag)
5319 draw_xor_hline (sheet);
5321 draw_xor_hline (sheet);
5326 if (GTK_SHEET_IN_DRAG(sheet)){
5328 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col;
5329 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row;
5330 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5331 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5335 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5336 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5337 aux=sheet->drag_range;
5338 sheet->drag_range.row0=sheet->range.row0+row;
5339 sheet->drag_range.col0=sheet->range.col0+column;
5340 sheet->drag_range.rowi=sheet->range.rowi+row;
5341 sheet->drag_range.coli=sheet->range.coli+column;
5342 if(aux.row0 != sheet->drag_range.row0 ||
5343 aux.col0 != sheet->drag_range.col0){
5344 draw_xor_rectangle (sheet, aux);
5345 draw_xor_rectangle (sheet, sheet->drag_range);
5351 if (GTK_SHEET_IN_RESIZE(sheet)){
5353 gint v_h, current_col, current_row, col_threshold, row_threshold;
5356 if(abs(x-COLUMN_LEFT_XPIXEL(sheet,sheet->drag_cell.col)) >
5357 abs(y-ROW_TOP_YPIXEL(sheet,sheet->drag_cell.row))) v_h=2;
5359 current_col = COLUMN_FROM_XPIXEL(sheet,x);
5360 current_row = ROW_FROM_YPIXEL(sheet,y);
5361 column = current_col-sheet->drag_cell.col;
5362 row = current_row-sheet->drag_cell.row;
5364 /*use half of column width resp. row height as threshold to expand selection*/
5365 col_threshold = COLUMN_LEFT_XPIXEL(sheet,current_col)+xxx_column_width (sheet,current_col)/2;
5367 if (x < col_threshold)
5370 else if (column < 0){
5371 if (x > col_threshold)
5374 row_threshold = ROW_TOP_YPIXEL(sheet,current_row)+yyy_row_height (sheet, current_row)/2;
5376 if(y < row_threshold)
5380 if(y > row_threshold)
5384 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5385 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5395 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5396 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5398 aux=sheet->drag_range;
5399 sheet->drag_range=sheet->range;
5401 if(row<0) sheet->drag_range.row0=sheet->range.row0+row;
5402 if(row>0) sheet->drag_range.rowi=sheet->range.rowi+row;
5403 if(column<0) sheet->drag_range.col0=sheet->range.col0+column;
5404 if(column>0) sheet->drag_range.coli=sheet->range.coli+column;
5406 if(aux.row0 != sheet->drag_range.row0 ||
5407 aux.rowi != sheet->drag_range.rowi ||
5408 aux.col0 != sheet->drag_range.col0 ||
5409 aux.coli != sheet->drag_range.coli){
5410 draw_xor_rectangle (sheet, aux);
5411 draw_xor_rectangle (sheet, sheet->drag_range);
5419 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5421 if(sheet->state==GTK_SHEET_NORMAL && row==sheet->active_cell.row &&
5422 column==sheet->active_cell.col) return TRUE;
5424 if(GTK_SHEET_IN_SELECTION(sheet) && mods&GDK_BUTTON1_MASK)
5425 gtk_sheet_extend_selection(sheet, row, column);
5431 gtk_sheet_move_query(GtkSheet *sheet, gint row, gint column)
5433 gint row_move, column_move;
5434 gfloat row_align, col_align;
5435 guint height, width;
5437 gint new_col = column;
5444 height = sheet->sheet_window_height;
5445 width = sheet->sheet_window_width;
5447 if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5449 new_row = MIN(yyy_row_count(sheet), row + 1);
5451 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet) - 1 &&
5452 ROW_TOP_YPIXEL(sheet, yyy_row_count(sheet)-1) +
5453 yyy_row_height(sheet, yyy_row_count(sheet)-1) < height){
5458 if(row<MIN_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5462 if(column>=MAX_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5464 new_col = MIN(xxx_column_count(sheet) - 1, column + 1);
5466 if(MAX_VISIBLE_COLUMN(sheet) == (xxx_column_count(sheet) - 1) &&
5467 COLUMN_LEFT_XPIXEL(sheet, xxx_column_count(sheet) - 1) +
5468 xxx_column_width(sheet, xxx_column_count(sheet) - 1) < width)
5470 column_move = FALSE;
5474 if(column<MIN_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5479 if(row_move || column_move){
5480 gtk_sheet_moveto(sheet, new_row, new_col, row_align, col_align);
5483 return(row_move || column_move);
5487 gtk_sheet_extend_selection(GtkSheet *sheet, gint row, gint column)
5489 GtkSheetRange range;
5493 if(row == sheet->selection_cell.row && column == sheet->selection_cell.col)
5496 if(sheet->selection_mode == GTK_SELECTION_SINGLE) return;
5498 gtk_sheet_move_query(sheet, row, column);
5499 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5501 if(GTK_SHEET_IN_DRAG(sheet)) return;
5505 switch(sheet->state){
5506 case GTK_SHEET_ROW_SELECTED:
5507 column = xxx_column_count(sheet) - 1;
5509 case GTK_SHEET_COLUMN_SELECTED:
5510 row = yyy_row_count(sheet) - 1;
5512 case GTK_SHEET_NORMAL:
5513 sheet->state=GTK_SHEET_RANGE_SELECTED;
5514 r=sheet->active_cell.row;
5515 c=sheet->active_cell.col;
5516 sheet->range.col0=c;
5517 sheet->range.row0=r;
5518 sheet->range.coli=c;
5519 sheet->range.rowi=r;
5520 gdk_draw_pixmap(sheet->sheet_window,
5521 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
5523 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5524 ROW_TOP_YPIXEL(sheet,r)-1,
5525 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5526 ROW_TOP_YPIXEL(sheet,r)-1,
5527 xxx_column_width(sheet, c)+4,
5528 yyy_row_height(sheet, r)+4);
5529 gtk_sheet_range_draw_selection(sheet, sheet->range);
5530 case GTK_SHEET_RANGE_SELECTED:
5531 sheet->state=GTK_SHEET_RANGE_SELECTED;
5534 sheet->selection_cell.row = row;
5535 sheet->selection_cell.col = column;
5537 range.col0=MIN(column,sheet->active_cell.col);
5538 range.coli=MAX(column,sheet->active_cell.col);
5539 range.row0=MIN(row,sheet->active_cell.row);
5540 range.rowi=MAX(row,sheet->active_cell.row);
5542 if(range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi ||
5543 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli ||
5544 state==GTK_SHEET_NORMAL)
5545 gtk_sheet_real_select_range(sheet, &range);
5550 gtk_sheet_entry_key_press(GtkWidget *widget,
5554 gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", key, &focus);
5559 gtk_sheet_key_press(GtkWidget *widget,
5565 gboolean extend_selection = FALSE;
5566 gboolean force_move = FALSE;
5567 gboolean in_selection = FALSE;
5568 gboolean veto = TRUE;
5571 sheet = GTK_SHEET(widget);
5573 if(key->state & GDK_CONTROL_MASK || key->keyval==GDK_Control_L ||
5574 key->keyval==GDK_Control_R) return FALSE;
5578 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL)
5579 gtk_sheet_clip_range(sheet, sheet->range);
5580 if(key->keyval=='x' || key->keyval == 'X')
5581 gtk_sheet_unclip_range(sheet);
5586 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval==GDK_Shift_L
5587 || key->keyval==GDK_Shift_R;
5590 in_selection = GTK_SHEET_IN_SELECTION(sheet);
5591 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5593 switch(key->keyval){
5594 case GDK_Return: case GDK_KP_Enter:
5595 if(sheet->state == GTK_SHEET_NORMAL &&
5596 !GTK_SHEET_IN_SELECTION(sheet))
5597 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
5599 row = sheet->active_cell.row;
5600 col = sheet->active_cell.col;
5601 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5602 row = MIN_VISIBLE_ROW(sheet)-1;
5603 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5604 col = MIN_VISIBLE_COLUMN(sheet);
5605 if(row < yyy_row_count(sheet) - 1){
5607 while(!yyy_row_is_visible(sheet, row) && row<yyy_row_count(sheet)-1)
5610 gtk_sheet_click_cell(sheet, row, col, &veto);
5611 extend_selection = FALSE;
5613 case GDK_ISO_Left_Tab:
5614 row = sheet->active_cell.row;
5615 col = sheet->active_cell.col;
5616 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5617 col = MIN_VISIBLE_COLUMN(sheet)-1;
5618 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5619 row = MIN_VISIBLE_ROW(sheet);
5622 while(! xxx_column_is_visible(sheet, col) && col>0) col--;
5625 gtk_sheet_click_cell(sheet, row, col, &veto);
5626 extend_selection = FALSE;
5629 row = sheet->active_cell.row;
5630 col = sheet->active_cell.col;
5631 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5632 col = MIN_VISIBLE_COLUMN(sheet)-1;
5633 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5634 row = MIN_VISIBLE_ROW(sheet);
5635 if(col < xxx_column_count(sheet) - 1)
5638 while(! xxx_column_is_visible(sheet, col) &&
5639 col < xxx_column_count(sheet) - 1)
5642 gtk_sheet_click_cell(sheet, row, col, &veto);
5643 extend_selection = FALSE;
5645 /* case GDK_BackSpace:
5646 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){
5647 if(sheet->active_cell.col > 0){
5648 col = sheet->active_cell.col - scroll;
5649 row = sheet->active_cell.row;
5650 while(!sheet->column[col].is_visible && col > 0) col--;
5653 gtk_sheet_click_cell(sheet, row, col, &veto);
5654 extend_selection = FALSE;
5658 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5660 if(extend_selection){
5661 if(state==GTK_STATE_NORMAL){
5662 row=sheet->active_cell.row;
5663 col=sheet->active_cell.col;
5664 gtk_sheet_click_cell(sheet, row, col, &veto);
5667 if(sheet->selection_cell.row > 0){
5668 row = sheet->selection_cell.row - scroll;
5669 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5671 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5675 col = sheet->active_cell.col;
5676 row = sheet->active_cell.row;
5677 if(state==GTK_SHEET_COLUMN_SELECTED)
5678 row = MIN_VISIBLE_ROW(sheet);
5679 if(state==GTK_SHEET_ROW_SELECTED)
5680 col = MIN_VISIBLE_COLUMN(sheet);
5682 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5684 gtk_sheet_click_cell(sheet, row, col, &veto);
5685 extend_selection = FALSE;
5688 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5690 if(extend_selection){
5691 if(state==GTK_STATE_NORMAL){
5692 row=sheet->active_cell.row;
5693 col=sheet->active_cell.col;
5694 gtk_sheet_click_cell(sheet, row, col, &veto);
5697 if(sheet->selection_cell.row < yyy_row_count(sheet)-1){
5698 row = sheet->selection_cell.row + scroll;
5699 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5700 row = MIN(yyy_row_count(sheet)-1, row);
5701 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5705 col = sheet->active_cell.col;
5706 row = sheet->active_cell.row;
5707 if(sheet->active_cell.row < yyy_row_count(sheet)-1){
5708 if(state==GTK_SHEET_COLUMN_SELECTED)
5709 row = MIN_VISIBLE_ROW(sheet)-1;
5710 if(state==GTK_SHEET_ROW_SELECTED)
5711 col = MIN_VISIBLE_COLUMN(sheet);
5713 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5714 row = MIN(yyy_row_count(sheet)-1, row);
5716 gtk_sheet_click_cell(sheet, row, col, &veto);
5717 extend_selection = FALSE;
5720 if(extend_selection){
5721 if(state==GTK_STATE_NORMAL){
5722 row=sheet->active_cell.row;
5723 col=sheet->active_cell.col;
5724 gtk_sheet_click_cell(sheet, row, col, &veto);
5727 if(sheet->selection_cell.col < xxx_column_count(sheet) - 1)
5729 col = sheet->selection_cell.col + 1;
5730 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1)
5732 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5736 col = sheet->active_cell.col;
5737 row = sheet->active_cell.row;
5738 if(sheet->active_cell.col < xxx_column_count(sheet) - 1){
5740 if(state==GTK_SHEET_ROW_SELECTED)
5741 col = MIN_VISIBLE_COLUMN(sheet)-1;
5742 if(state==GTK_SHEET_COLUMN_SELECTED)
5743 row = MIN_VISIBLE_ROW(sheet);
5744 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1) 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);
5752 extend_selection = FALSE;
5755 if(extend_selection){
5756 if(state==GTK_STATE_NORMAL){
5757 row=sheet->active_cell.row;
5758 col=sheet->active_cell.col;
5759 gtk_sheet_click_cell(sheet, row, col, &veto);
5762 if(sheet->selection_cell.col > 0){
5763 col = sheet->selection_cell.col - 1;
5764 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5765 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5769 col = sheet->active_cell.col - 1;
5770 row = sheet->active_cell.row;
5771 if(state==GTK_SHEET_ROW_SELECTED)
5772 col = MIN_VISIBLE_COLUMN(sheet)-1;
5773 if(state==GTK_SHEET_COLUMN_SELECTED)
5774 row = MIN_VISIBLE_ROW(sheet);
5775 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5778 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5780 gtk_sheet_click_cell(sheet, row, col, &veto);
5784 extend_selection = FALSE;
5788 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5789 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5790 extend_selection = FALSE;
5793 row=yyy_row_count(sheet)-1;
5794 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5795 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5796 extend_selection = FALSE;
5800 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5801 if(extend_selection) return TRUE;
5803 if(state == GTK_SHEET_ROW_SELECTED)
5804 sheet->active_cell.col=MIN_VISIBLE_COLUMN(sheet);
5805 if(state == GTK_SHEET_COLUMN_SELECTED)
5806 sheet->active_cell.row=MIN_VISIBLE_ROW(sheet);
5810 if(extend_selection) return TRUE;
5812 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5813 sheet->active_cell.col);
5819 gtk_sheet_size_request (GtkWidget * widget,
5820 GtkRequisition * requisition)
5824 GtkSheetChild *child;
5825 GtkRequisition child_requisition;
5827 g_return_if_fail (widget != NULL);
5828 g_return_if_fail (GTK_IS_SHEET (widget));
5829 g_return_if_fail (requisition != NULL);
5831 sheet = GTK_SHEET (widget);
5833 requisition->width = 3*DEFAULT_COLUMN_WIDTH;
5834 requisition->height = 3*DEFAULT_ROW_HEIGHT(widget);
5836 /* compute the size of the column title area */
5837 if(sheet->column_titles_visible)
5838 requisition->height += sheet->column_title_area.height;
5840 /* compute the size of the row title area */
5841 if(sheet->row_titles_visible)
5842 requisition->width += sheet->row_title_area.width;
5844 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5845 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5846 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5847 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5849 if(!sheet->column_titles_visible)
5850 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5852 if(!sheet->row_titles_visible)
5853 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5855 children = sheet->children;
5858 child = children->data;
5859 children = children->next;
5861 gtk_widget_size_request(child->widget, &child_requisition);
5867 gtk_sheet_size_allocate (GtkWidget * widget,
5868 GtkAllocation * allocation)
5871 GtkAllocation sheet_allocation;
5874 g_return_if_fail (widget != NULL);
5875 g_return_if_fail (GTK_IS_SHEET (widget));
5876 g_return_if_fail (allocation != NULL);
5878 sheet = GTK_SHEET (widget);
5879 widget->allocation = *allocation;
5880 border_width = GTK_CONTAINER(widget)->border_width;
5882 if (GTK_WIDGET_REALIZED (widget))
5883 gdk_window_move_resize (widget->window,
5884 allocation->x + border_width,
5885 allocation->y + border_width,
5886 allocation->width - 2*border_width,
5887 allocation->height - 2*border_width);
5889 /* use internal allocation structure for all the math
5890 * because it's easier than always subtracting the container
5892 sheet->internal_allocation.x = 0;
5893 sheet->internal_allocation.y = 0;
5894 sheet->internal_allocation.width = allocation->width - 2*border_width;
5895 sheet->internal_allocation.height = allocation->height - 2*border_width;
5897 sheet_allocation.x = 0;
5898 sheet_allocation.y = 0;
5899 sheet_allocation.width = allocation->width - 2*border_width;
5900 sheet_allocation.height = allocation->height - 2*border_width;
5902 sheet->sheet_window_width = sheet_allocation.width;
5903 sheet->sheet_window_height = sheet_allocation.height;
5905 if (GTK_WIDGET_REALIZED (widget))
5906 gdk_window_move_resize (sheet->sheet_window,
5909 sheet_allocation.width,
5910 sheet_allocation.height);
5912 /* position the window which holds the column title buttons */
5913 sheet->column_title_area.x = 0;
5914 sheet->column_title_area.y = 0;
5915 if(sheet->row_titles_visible)
5916 sheet->column_title_area.x = sheet->row_title_area.width;
5917 sheet->column_title_area.width = sheet_allocation.width -
5918 sheet->column_title_area.x;
5919 if(GTK_WIDGET_REALIZED(widget) && sheet->column_titles_visible)
5920 gdk_window_move_resize (sheet->column_title_window,
5921 sheet->column_title_area.x,
5922 sheet->column_title_area.y,
5923 sheet->column_title_area.width,
5924 sheet->column_title_area.height);
5926 sheet->sheet_window_width = sheet_allocation.width;
5927 sheet->sheet_window_height = sheet_allocation.height;
5929 /* column button allocation */
5930 size_allocate_column_title_buttons (sheet);
5932 /* position the window which holds the row title buttons */
5933 sheet->row_title_area.x = 0;
5934 sheet->row_title_area.y = 0;
5935 if(sheet->column_titles_visible)
5936 sheet->row_title_area.y = sheet->column_title_area.height;
5937 sheet->row_title_area.height = sheet_allocation.height -
5938 sheet->row_title_area.y;
5940 if(GTK_WIDGET_REALIZED(widget) && sheet->row_titles_visible)
5941 gdk_window_move_resize (sheet->row_title_window,
5942 sheet->row_title_area.x,
5943 sheet->row_title_area.y,
5944 sheet->row_title_area.width,
5945 sheet->row_title_area.height);
5948 /* row button allocation */
5949 size_allocate_row_title_buttons (sheet);
5951 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5952 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5953 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5954 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5956 if(!sheet->column_titles_visible)
5957 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5959 if(!sheet->row_titles_visible)
5960 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5962 size_allocate_column_title_buttons(sheet);
5963 size_allocate_row_title_buttons(sheet);
5965 /* re-scale backing pixmap */
5966 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
5967 gtk_sheet_position_children(sheet);
5969 /* set the scrollbars adjustments */
5970 adjust_scrollbars (sheet);
5974 size_allocate_column_title_buttons (GtkSheet * sheet)
5979 if (!sheet->column_titles_visible) return;
5980 if (!GTK_WIDGET_REALIZED (sheet))
5983 width = sheet->sheet_window_width;
5986 if(sheet->row_titles_visible)
5988 width -= sheet->row_title_area.width;
5989 x = sheet->row_title_area.width;
5992 if(sheet->column_title_area.width != width || sheet->column_title_area.x != x)
5994 sheet->column_title_area.width = width;
5995 sheet->column_title_area.x = x;
5996 gdk_window_move_resize (sheet->column_title_window,
5997 sheet->column_title_area.x,
5998 sheet->column_title_area.y,
5999 sheet->column_title_area.width,
6000 sheet->column_title_area.height);
6004 if(MAX_VISIBLE_COLUMN(sheet) == xxx_column_count(sheet) - 1)
6005 gdk_window_clear_area (sheet->column_title_window,
6007 sheet->column_title_area.width,
6008 sheet->column_title_area.height);
6010 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6012 for (i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
6013 gtk_sheet_button_draw(sheet,-1,i);
6017 size_allocate_row_title_buttons (GtkSheet * sheet)
6022 if (!sheet->row_titles_visible) return;
6023 if (!GTK_WIDGET_REALIZED (sheet))
6026 height = sheet->sheet_window_height;
6029 if(sheet->column_titles_visible)
6031 height -= sheet->column_title_area.height;
6032 y = sheet->column_title_area.height;
6035 if(sheet->row_title_area.height != height || sheet->row_title_area.y != y)
6037 sheet->row_title_area.y = y;
6038 sheet->row_title_area.height = height;
6039 gdk_window_move_resize (sheet->row_title_window,
6040 sheet->row_title_area.x,
6041 sheet->row_title_area.y,
6042 sheet->row_title_area.width,
6043 sheet->row_title_area.height);
6045 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet)-1)
6046 gdk_window_clear_area (sheet->row_title_window,
6048 sheet->row_title_area.width,
6049 sheet->row_title_area.height);
6051 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6053 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
6054 gtk_sheet_button_draw(sheet,i,-1);
6059 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
6061 GtkAllocation shentry_allocation;
6062 GtkSheetCellAttr attributes;
6063 GtkEntry *sheet_entry;
6064 GtkStyle *style = NULL, *previous_style = NULL;
6066 gint size, max_size, text_size, column_width;
6069 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6070 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
6072 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
6074 gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes);
6076 if(GTK_WIDGET_REALIZED(sheet->sheet_entry)){
6078 if(!GTK_WIDGET(sheet_entry)->style)
6079 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry));
6081 previous_style = GTK_WIDGET(sheet_entry)->style;
6083 style = gtk_style_copy(previous_style);
6084 style->bg[GTK_STATE_NORMAL] = attributes.background;
6085 style->fg[GTK_STATE_NORMAL] = attributes.foreground;
6086 style->text[GTK_STATE_NORMAL] = attributes.foreground;
6087 style->bg[GTK_STATE_ACTIVE] = attributes.background;
6088 style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
6089 style->text[GTK_STATE_ACTIVE] = attributes.foreground;
6091 pango_font_description_free(style->font_desc);
6092 style->font_desc = pango_font_description_copy(attributes.font_desc);
6094 GTK_WIDGET(sheet_entry)->style = style;
6095 gtk_widget_size_request(sheet->sheet_entry, NULL);
6096 GTK_WIDGET(sheet_entry)->style = previous_style;
6098 if(style != previous_style){
6099 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6100 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
6101 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
6102 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
6103 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
6105 gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
6109 if(GTK_IS_ITEM_ENTRY(sheet_entry))
6110 max_size = GTK_ITEM_ENTRY(sheet_entry)->text_max_size;
6115 text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
6116 if(text && strlen(text) > 0){
6117 text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
6120 column_width=xxx_column_width(sheet, sheet->active_cell.col);
6122 size=MIN(text_size, max_size);
6123 size=MAX(size,column_width-2*CELLOFFSET);
6125 row=sheet->active_cell.row;
6126 col=sheet->active_cell.col;
6128 shentry_allocation.x = COLUMN_LEFT_XPIXEL(sheet,sheet->active_cell.col);
6129 shentry_allocation.y = ROW_TOP_YPIXEL(sheet,sheet->active_cell.row);
6130 shentry_allocation.width = column_width;
6131 shentry_allocation.height = yyy_row_height(sheet, sheet->active_cell.row);
6133 if(GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6135 shentry_allocation.height -= 2*CELLOFFSET;
6136 shentry_allocation.y += CELLOFFSET;
6137 if(gtk_sheet_clip_text(sheet))
6138 shentry_allocation.width = column_width - 2*CELLOFFSET;
6140 shentry_allocation.width = size;
6142 switch(GTK_ITEM_ENTRY(sheet_entry)->justification){
6143 case GTK_JUSTIFY_CENTER:
6144 shentry_allocation.x += (column_width)/2 - size/2;
6146 case GTK_JUSTIFY_RIGHT:
6147 shentry_allocation.x += column_width - size - CELLOFFSET;
6149 case GTK_JUSTIFY_LEFT:
6150 case GTK_JUSTIFY_FILL:
6151 shentry_allocation.x += CELLOFFSET;
6157 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6158 shentry_allocation.x += 2;
6159 shentry_allocation.y += 2;
6160 shentry_allocation.width -= MIN(shentry_allocation.width, 3);
6161 shentry_allocation.height -= MIN(shentry_allocation.height, 3);
6164 gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation);
6166 if(previous_style == style) gtk_style_unref(previous_style);
6170 gtk_sheet_entry_set_max_size(GtkSheet *sheet)
6174 gint sizel=0, sizer=0;
6176 GtkJustification justification;
6178 row=sheet->active_cell.row;
6179 col=sheet->active_cell.col;
6181 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry) || gtk_sheet_clip_text(sheet)) return;
6183 justification = GTK_ITEM_ENTRY(sheet->sheet_entry)->justification;
6185 switch(justification){
6186 case GTK_JUSTIFY_FILL:
6187 case GTK_JUSTIFY_LEFT:
6188 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6189 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6190 size+=xxx_column_width(sheet, i);
6192 size = MIN(size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL(sheet, col));
6194 case GTK_JUSTIFY_RIGHT:
6195 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
6196 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6197 size+=xxx_column_width(sheet, i);
6200 case GTK_JUSTIFY_CENTER:
6201 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6202 /* if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6204 sizer+=xxx_column_width(sheet, i);
6206 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
6207 if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6208 sizel+=xxx_column_width(sheet, i);
6210 size=2*MIN(sizel, sizer);
6214 if(size!=0) size+=xxx_column_width(sheet, col);
6215 GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size=size;
6220 create_sheet_entry(GtkSheet *sheet)
6225 gint found_entry = FALSE;
6227 widget = GTK_WIDGET(sheet);
6229 if(sheet->sheet_entry){
6230 /* avoids warnings */
6231 gtk_widget_ref(sheet->sheet_entry);
6232 gtk_widget_unparent(sheet->sheet_entry);
6233 gtk_widget_destroy(sheet->sheet_entry);
6236 if(sheet->entry_type){
6238 if(!g_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY)){
6240 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6242 sheet->sheet_entry = parent;
6244 entry = gtk_sheet_get_entry (sheet);
6245 if(GTK_IS_ENTRY(entry)) found_entry = TRUE;
6249 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6257 g_warning ("Entry type must be GtkEntry subclass, using default");
6258 entry = gtk_item_entry_new();
6259 sheet->sheet_entry = entry;
6263 sheet->sheet_entry = parent;
6270 entry = gtk_item_entry_new();
6271 sheet->sheet_entry = entry;
6275 gtk_widget_size_request(sheet->sheet_entry, NULL);
6277 if(GTK_WIDGET_REALIZED(sheet))
6279 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
6280 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
6281 gtk_widget_realize(sheet->sheet_entry);
6284 gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event",
6285 (GtkSignalFunc) gtk_sheet_entry_key_press,
6288 gtk_widget_show (sheet->sheet_entry);
6292 /* Finds the last child widget that happens to be of type GtkEntry */
6294 find_entry(GtkWidget *w, gpointer user_data)
6296 GtkWidget **entry = user_data;
6297 if ( GTK_IS_ENTRY(w))
6304 gtk_sheet_get_entry(GtkSheet *sheet)
6307 GtkWidget *entry = NULL;
6308 GtkTableChild *table_child;
6309 GtkBoxChild *box_child;
6310 GList *children = NULL;
6312 g_return_val_if_fail (sheet != NULL, NULL);
6313 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6314 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6316 if(GTK_IS_ENTRY(sheet->sheet_entry)) return (sheet->sheet_entry);
6318 parent = GTK_WIDGET(sheet->sheet_entry);
6320 if(GTK_IS_TABLE(parent)) children = GTK_TABLE(parent)->children;
6321 if(GTK_IS_BOX(parent)) children = GTK_BOX(parent)->children;
6323 if(GTK_IS_CONTAINER(parent))
6325 gtk_container_forall(GTK_CONTAINER(parent), find_entry, &entry);
6327 if(GTK_IS_ENTRY(entry))
6331 if(!children) return NULL;
6334 if(GTK_IS_TABLE(parent)) {
6335 table_child = children->data;
6336 entry = table_child->widget;
6338 if(GTK_IS_BOX(parent)){
6339 box_child = children->data;
6340 entry = box_child->widget;
6343 if(GTK_IS_ENTRY(entry))
6345 children = children->next;
6349 if(!GTK_IS_ENTRY(entry)) return NULL;
6356 gtk_sheet_get_entry_widget(GtkSheet *sheet)
6358 g_return_val_if_fail (sheet != NULL, NULL);
6359 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6360 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6362 return (sheet->sheet_entry);
6368 row_button_set (GtkSheet *sheet, gint row)
6370 if(sheet->row[row].button.state == GTK_STATE_ACTIVE) return;
6372 sheet->row[row].button.state = GTK_STATE_ACTIVE;
6373 gtk_sheet_button_draw(sheet, row, -1);
6378 row_button_release (GtkSheet *sheet, gint row)
6380 if(sheet->row[row].button.state == GTK_STATE_NORMAL) return;
6382 sheet->row[row].button.state = GTK_STATE_NORMAL;
6383 gtk_sheet_button_draw(sheet, row, -1);
6388 gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
6390 GdkWindow *window = NULL;
6391 GtkShadowType shadow_type;
6392 guint width = 0, height = 0;
6395 gint text_width = 0, text_height = 0;
6396 const GtkSheetButton *button = NULL;
6397 GtkSheetChild *child = NULL;
6398 GdkRectangle allocation;
6399 gboolean is_sensitive = FALSE;
6404 PangoAlignment align = PANGO_ALIGN_LEFT;
6407 rtl = gtk_widget_get_direction(GTK_WIDGET(sheet)) == GTK_TEXT_DIR_RTL;
6409 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6411 if(row >= 0 && !yyy_row_is_visible(sheet, row)) return;
6412 if(column >= 0 && ! xxx_column_is_visible(sheet, column)) return;
6413 if(row >= 0 && !sheet->row_titles_visible) return;
6414 if(column >= 0 && !sheet->column_titles_visible) return;
6415 if(column>=0 && column < MIN_VISIBLE_COLUMN(sheet)) return;
6416 if(column>=0 && column > MAX_VISIBLE_COLUMN(sheet)) return;
6417 if(row>=0 && row < MIN_VISIBLE_ROW(sheet)) return;
6418 if(row>=0 && row > MAX_VISIBLE_ROW(sheet)) return;
6419 if( (row == -1) && (column == -1) ) return;
6422 window=sheet->column_title_window;
6423 button= xxx_column_button(sheet, column);
6425 x = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING;
6426 if(sheet->row_titles_visible) x -= sheet->row_title_area.width;
6428 width = xxx_column_width(sheet, column);
6429 height = sheet->column_title_area.height;
6430 is_sensitive=xxx_column_is_sensitive(sheet, column);
6433 window=sheet->row_title_window;
6434 button = yyy_row_button(sheet, row);
6437 y = ROW_TOP_YPIXEL(sheet, row)+CELL_SPACING;
6438 if(sheet->column_titles_visible) y-=sheet->column_title_area.height;
6439 width = sheet->row_title_area.width;
6440 height = yyy_row_height(sheet, row);
6441 is_sensitive=yyy_row_is_sensitive(sheet, row);
6446 allocation.width = width;
6447 allocation.height = height;
6449 gdk_window_clear_area (window,
6453 gtk_paint_box (sheet->button->style, window,
6454 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
6455 &allocation, GTK_WIDGET(sheet->button),
6456 "buttondefault", x, y, width, height);
6458 state = button->state;
6459 if(!is_sensitive) state=GTK_STATE_INSENSITIVE;
6461 if (state == GTK_STATE_ACTIVE)
6462 shadow_type = GTK_SHADOW_IN;
6464 shadow_type = GTK_SHADOW_OUT;
6466 if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
6467 gtk_paint_box (sheet->button->style, window,
6468 button->state, shadow_type,
6469 &allocation, GTK_WIDGET(sheet->button),
6470 "button", x, y, width, height);
6472 if(button->label_visible){
6474 text_height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))-2*CELLOFFSET;
6476 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6478 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation);
6480 y += 2*sheet->button->style->ythickness;
6483 if(button->label && strlen(button->label)>0){
6485 PangoLayout *layout = NULL;
6486 gint real_x = x, real_y = y;
6488 words=button->label;
6489 line = g_new(gchar, 1);
6492 while(words && *words != '\0'){
6495 line=g_realloc(line, len+2);
6499 if(*words == '\n' || *(words+1) == '\0'){
6500 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, line);
6502 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), line);
6503 switch(button->justification){
6504 case GTK_JUSTIFY_LEFT:
6505 real_x = x + CELLOFFSET;
6506 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6508 case GTK_JUSTIFY_RIGHT:
6509 real_x = x + width - text_width - CELLOFFSET;
6510 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6512 case GTK_JUSTIFY_CENTER:
6514 real_x = x + (width - text_width)/2;
6515 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6516 pango_layout_set_justify (layout, TRUE);
6518 pango_layout_set_alignment (layout, align);
6519 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6528 g_object_unref(G_OBJECT(layout));
6530 real_y += text_height + 2;
6533 line = g_new(gchar, 1);
6540 if(button->label && strlen(button->label) > 0){
6541 PangoLayout *layout = NULL;
6542 gint real_x = x, real_y = y;
6544 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, button->label);
6546 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), button->label);
6547 switch(button->justification){
6548 case GTK_JUSTIFY_LEFT:
6549 real_x = x + CELLOFFSET;
6550 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6552 case GTK_JUSTIFY_RIGHT:
6553 real_x = x + width - text_width - CELLOFFSET;
6554 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6556 case GTK_JUSTIFY_CENTER:
6558 real_x = x + (width - text_width)/2;
6559 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6560 pango_layout_set_justify (layout, TRUE);
6562 pango_layout_set_alignment (layout, align);
6563 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6572 g_object_unref(G_OBJECT(layout));
6575 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6577 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, NULL);
6581 if((child = button->child) && (child->widget)){
6582 child->x = allocation.x;
6583 child->y = allocation.y;
6585 child->x += (width - child->widget->requisition.width) / 2;
6586 child->y += (height - child->widget->requisition.height) / 2;
6587 allocation.x = child->x;
6588 allocation.y = child->y;
6589 allocation.width = child->widget->requisition.width;
6590 allocation.height = child->widget->requisition.height;
6595 gtk_widget_set_state(child->widget, button->state);
6597 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
6598 GTK_WIDGET_MAPPED(child->widget))
6600 gtk_widget_size_allocate(child->widget,
6602 gtk_widget_queue_draw(child->widget);
6613 * vadjustment_changed
6614 * hadjustment_changed
6615 * vadjustment_value_changed
6616 * hadjustment_value_changed */
6619 adjust_scrollbars (GtkSheet * sheet)
6622 if(sheet->vadjustment){
6623 sheet->vadjustment->page_size = sheet->sheet_window_height;
6624 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
6625 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
6626 sheet->vadjustment->lower = 0;
6627 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
6629 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet))
6631 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) -
6632 sheet->sheet_window_height);
6633 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
6637 gtk_signal_emit_by_name (GTK_OBJECT(sheet->vadjustment), "changed");
6641 if(sheet->hadjustment){
6642 sheet->hadjustment->page_size = sheet->sheet_window_width;
6643 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
6644 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
6645 sheet->hadjustment->lower = 0;
6646 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
6648 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet))
6650 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) -
6651 sheet->sheet_window_width);
6652 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment),
6656 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), "changed");
6660 if(GTK_WIDGET_REALIZED(sheet))
6662 if(sheet->row_titles_visible){
6663 size_allocate_row_title_buttons(sheet);
6664 gdk_window_show(sheet->row_title_window);
6667 if(sheet->column_titles_visible){
6668 size_allocate_column_title_buttons(sheet);
6669 gdk_window_show(sheet->column_title_window);
6672 gtk_sheet_range_draw(sheet, NULL);
6679 vadjustment_changed (GtkAdjustment * adjustment,
6684 g_return_if_fail (adjustment != NULL);
6685 g_return_if_fail (data != NULL);
6687 sheet = GTK_SHEET (data);
6692 hadjustment_changed (GtkAdjustment * adjustment,
6697 g_return_if_fail (adjustment != NULL);
6698 g_return_if_fail (data != NULL);
6700 sheet = GTK_SHEET (data);
6705 vadjustment_value_changed (GtkAdjustment * adjustment,
6709 gint diff, value, old_value;
6713 g_return_if_fail (adjustment != NULL);
6714 g_return_if_fail (data != NULL);
6715 g_return_if_fail (GTK_IS_SHEET (data));
6717 sheet = GTK_SHEET (data);
6719 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6721 row=ROW_FROM_YPIXEL(sheet,sheet->column_title_area.height + CELL_SPACING);
6722 if(!sheet->column_titles_visible)
6723 row=ROW_FROM_YPIXEL(sheet,CELL_SPACING);
6725 old_value = -sheet->voffset;
6727 new_row = g_sheet_row_pixel_to_row(sheet->row_geometry,
6728 adjustment->value,sheet);
6730 y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
6732 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
6733 yyy_row_height(sheet, row) > sheet->vadjustment->step_increment){
6734 /* This avoids embarrassing twitching */
6735 if(row == new_row && row != yyy_row_count(sheet) - 1 &&
6736 adjustment->value - sheet->old_vadjustment >=
6737 sheet->vadjustment->step_increment &&
6738 new_row + 1 != MIN_VISIBLE_ROW(sheet)){
6740 y=y+yyy_row_height(sheet, row);
6744 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6745 if(sheet->old_vadjustment >= 0. && row == new_row){
6746 sheet->old_vadjustment = sheet->vadjustment->value;
6750 sheet->old_vadjustment = sheet->vadjustment->value;
6751 adjustment->value=y;
6755 sheet->vadjustment->step_increment= yyy_row_height(sheet, 0);
6757 sheet->vadjustment->step_increment=
6758 MIN(yyy_row_height(sheet, new_row), yyy_row_height(sheet, new_row-1));
6761 sheet->vadjustment->value=adjustment->value;
6763 value = adjustment->value;
6765 if (value >= -sheet->voffset)
6768 diff = value + sheet->voffset;
6773 diff = -sheet->voffset - value;
6776 sheet->voffset = -value;
6778 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6779 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6780 if(!sheet->column_titles_visible)
6781 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6783 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6784 sheet->state == GTK_SHEET_NORMAL &&
6785 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6786 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6787 sheet->active_cell.col))
6791 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6793 if(!text || strlen(text)==0)
6794 gtk_sheet_cell_clear(sheet,
6795 sheet->active_cell.row,
6796 sheet->active_cell.col);
6797 gtk_widget_unmap(sheet->sheet_entry);
6800 gtk_sheet_position_children(sheet);
6802 gtk_sheet_range_draw(sheet, NULL);
6803 size_allocate_row_title_buttons(sheet);
6804 size_allocate_global_button(sheet);
6808 hadjustment_value_changed (GtkAdjustment * adjustment,
6812 gint i, diff, value, old_value;
6813 gint column, new_column;
6816 g_return_if_fail (adjustment != NULL);
6817 g_return_if_fail (data != NULL);
6818 g_return_if_fail (GTK_IS_SHEET (data));
6820 sheet = GTK_SHEET (data);
6822 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6824 column=COLUMN_FROM_XPIXEL(sheet,sheet->row_title_area.width + CELL_SPACING);
6825 if(!sheet->row_titles_visible)
6826 column=COLUMN_FROM_XPIXEL(sheet, CELL_SPACING);
6828 old_value = -sheet->hoffset;
6830 for(i=0; i < xxx_column_count(sheet); i++)
6832 if(xxx_column_is_visible(sheet, i)) x += xxx_column_width(sheet, i);
6833 if(x > adjustment->value) break;
6835 x-=xxx_column_width(sheet, i);
6838 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
6839 xxx_column_width(sheet, i) > sheet->hadjustment->step_increment){
6840 /* This avoids embarrassing twitching */
6841 if(column == new_column && column != xxx_column_count(sheet) - 1 &&
6842 adjustment->value - sheet->old_hadjustment >=
6843 sheet->hadjustment->step_increment &&
6844 new_column + 1 != MIN_VISIBLE_COLUMN(sheet)){
6846 x=x+xxx_column_width(sheet, column);
6850 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6851 if(sheet->old_hadjustment >= 0. && new_column == column){
6852 sheet->old_hadjustment = sheet->hadjustment->value;
6856 sheet->old_hadjustment = sheet->hadjustment->value;
6857 adjustment->value=x;
6859 if(new_column == 0){
6860 sheet->hadjustment->step_increment=
6861 xxx_column_width(sheet, 0);
6863 sheet->hadjustment->step_increment=
6864 MIN(xxx_column_width(sheet, new_column), xxx_column_width(sheet, new_column-1));
6868 sheet->hadjustment->value=adjustment->value;
6870 value = adjustment->value;
6872 if (value >= -sheet->hoffset)
6875 diff = value + sheet->hoffset;
6880 diff = -sheet->hoffset - value;
6883 sheet->hoffset = -value;
6885 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6886 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6887 if(!sheet->row_titles_visible)
6888 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6890 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6891 sheet->state == GTK_SHEET_NORMAL &&
6892 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6893 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6894 sheet->active_cell.col))
6898 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6899 if(!text || strlen(text)==0)
6900 gtk_sheet_cell_clear(sheet,
6901 sheet->active_cell.row,
6902 sheet->active_cell.col);
6904 gtk_widget_unmap(sheet->sheet_entry);
6907 gtk_sheet_position_children(sheet);
6909 gtk_sheet_range_draw(sheet, NULL);
6910 size_allocate_column_title_buttons(sheet);
6914 /* COLUMN RESIZING */
6916 draw_xor_vline (GtkSheet * sheet)
6920 g_return_if_fail (sheet != NULL);
6922 widget = GTK_WIDGET (sheet);
6924 gdk_draw_line (widget->window, sheet->xor_gc,
6926 sheet->column_title_area.height,
6928 sheet->sheet_window_height + 1);
6933 draw_xor_hline (GtkSheet * sheet)
6937 g_return_if_fail (sheet != NULL);
6939 widget = GTK_WIDGET (sheet);
6941 gdk_draw_line (widget->window, sheet->xor_gc,
6942 sheet->row_title_area.width,
6945 sheet->sheet_window_width + 1,
6949 /* SELECTED RANGE */
6951 draw_xor_rectangle(GtkSheet *sheet, GtkSheetRange range)
6954 GdkRectangle clip_area, area;
6957 area.x=COLUMN_LEFT_XPIXEL(sheet, range.col0);
6958 area.y=ROW_TOP_YPIXEL(sheet, range.row0);
6959 area.width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-area.x+
6960 xxx_column_width(sheet, range.coli);
6961 area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+
6962 yyy_row_height(sheet, range.rowi);
6964 clip_area.x=sheet->row_title_area.width;
6965 clip_area.y=sheet->column_title_area.height;
6966 clip_area.width=sheet->sheet_window_width;
6967 clip_area.height=sheet->sheet_window_height;
6969 if(!sheet->row_titles_visible) clip_area.x = 0;
6970 if(!sheet->column_titles_visible) clip_area.y = 0;
6973 area.width=area.width+area.x;
6976 if(area.width>clip_area.width) area.width=clip_area.width+10;
6978 area.height=area.height+area.y;
6981 if(area.height>clip_area.height) area.height=clip_area.height+10;
6986 clip_area.height+=3;
6988 gdk_gc_get_values(sheet->xor_gc, &values);
6990 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
6993 gdk_draw_rectangle(sheet->sheet_window,
6997 area.width-2*i, area.height-2*i);
7000 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
7002 gdk_gc_set_foreground(sheet->xor_gc, &values.foreground);
7007 /* this function returns the new width of the column being resized given
7008 * the column and x position of the cursor; the x cursor position is passed
7009 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7011 new_column_width (GtkSheet * sheet,
7020 min_width = sheet->column_requisition;
7022 /* you can't shrink a column to less than its minimum width */
7023 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
7025 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
7028 /* don't grow past the end of the window */
7030 if (cx > sheet->sheet_window_width)
7032 *x = cx = sheet->sheet_window_width;
7035 /* calculate new column width making sure it doesn't end up
7036 * less than the minimum width */
7037 width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
7038 if (width < min_width)
7041 xxx_set_column_width(sheet, column, width);
7042 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7043 size_allocate_column_title_buttons (sheet);
7048 /* this function returns the new height of the row being resized given
7049 * the row and y position of the cursor; the y cursor position is passed
7050 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7052 new_row_height (GtkSheet * sheet,
7060 min_height = sheet->row_requisition;
7062 /* you can't shrink a row to less than its minimum height */
7063 if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
7066 *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
7069 /* don't grow past the end of the window */
7071 if (cy > sheet->sheet_window_height)
7073 *y = cy = sheet->sheet_window_height;
7076 /* calculate new row height making sure it doesn't end up
7077 * less than the minimum height */
7078 height = (cy - ROW_TOP_YPIXEL (sheet, row));
7079 if (height < min_height)
7080 height = min_height;
7082 yyy_set_row_height(sheet, row, height);
7083 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
7084 size_allocate_row_title_buttons (sheet);
7090 gtk_sheet_set_column_width (GtkSheet * sheet,
7096 g_return_if_fail (sheet != NULL);
7097 g_return_if_fail (GTK_IS_SHEET (sheet));
7099 if (column < 0 || column >= xxx_column_count(sheet))
7102 gtk_sheet_column_size_request(sheet, column, &min_width);
7103 if(width < min_width) return;
7105 xxx_set_column_width(sheet, column, width);
7107 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7108 size_allocate_column_title_buttons (sheet);
7109 adjust_scrollbars (sheet);
7110 gtk_sheet_size_allocate_entry(sheet);
7111 gtk_sheet_range_draw (sheet, NULL);
7114 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, column);
7115 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_COL_WIDTH], column, width);
7122 gtk_sheet_set_row_height (GtkSheet * sheet,
7128 g_return_if_fail (sheet != NULL);
7129 g_return_if_fail (GTK_IS_SHEET (sheet));
7131 if (row < 0 || row >= yyy_row_count(sheet))
7134 gtk_sheet_row_size_request(sheet, row, &min_height);
7135 if(height < min_height) return;
7137 yyy_set_row_height(sheet, row, height);
7139 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7140 size_allocate_row_title_buttons (sheet);
7141 adjust_scrollbars (sheet);
7142 gtk_sheet_size_allocate_entry(sheet);
7143 gtk_sheet_range_draw (sheet, NULL);
7146 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], row, -1);
7147 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_ROW_HEIGHT], row, height);
7153 gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr *attributes)
7155 const GdkColor *fg, *bg;
7156 const GtkJustification *j ;
7157 const PangoFontDescription *font_desc ;
7158 const GtkSheetCellBorder *border ;
7160 g_return_val_if_fail (sheet != NULL, FALSE);
7161 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
7163 if(row < 0 || col < 0) return FALSE;
7165 init_attributes(sheet, col, attributes);
7170 attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
7171 attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
7173 fg = g_sheet_model_get_foreground(sheet->model, row, col);
7175 attributes->foreground = *fg;
7177 bg = g_sheet_model_get_background(sheet->model, row, col);
7179 attributes->background = *bg;
7181 j = g_sheet_model_get_justification(sheet->model, row, col);
7182 if (j) attributes->justification = *j;
7184 font_desc = g_sheet_model_get_font_desc(sheet->model, row, col);
7185 if ( font_desc ) attributes->font_desc = font_desc;
7187 border = g_sheet_model_get_cell_border(sheet->model, row, col);
7189 if ( border ) attributes->border = *border;
7195 init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
7197 /* DEFAULT VALUES */
7198 attributes->foreground = GTK_WIDGET(sheet)->style->black;
7199 attributes->background = sheet->bg_color;
7200 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
7201 GdkColormap *colormap;
7202 colormap=gdk_colormap_get_system();
7203 gdk_color_black(colormap, &attributes->foreground);
7204 attributes->background = sheet->bg_color;
7206 attributes->justification = xxx_column_justification(sheet, col);
7207 attributes->border.width = 0;
7208 attributes->border.line_style = GDK_LINE_SOLID;
7209 attributes->border.cap_style = GDK_CAP_NOT_LAST;
7210 attributes->border.join_style = GDK_JOIN_MITER;
7211 attributes->border.mask = 0;
7212 attributes->border.color = GTK_WIDGET(sheet)->style->black;
7213 attributes->is_editable = TRUE;
7214 attributes->is_visible = TRUE;
7215 attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
7221 /********************************************************************
7222 * Container Functions:
7227 * gtk_sheet_move_child
7228 * gtk_sheet_position_child
7229 * gtk_sheet_position_children
7230 * gtk_sheet_realize_child
7231 * gtk_sheet_get_child_at
7232 ********************************************************************/
7235 gtk_sheet_put(GtkSheet *sheet, GtkWidget *child, gint x, gint y)
7237 GtkRequisition child_requisition;
7238 GtkSheetChild *child_info;
7240 g_return_val_if_fail(sheet != NULL, NULL);
7241 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7242 g_return_val_if_fail(child != NULL, NULL);
7243 g_return_val_if_fail(child->parent == NULL, NULL);
7245 child_info = g_new (GtkSheetChild, 1);
7246 child_info->widget = child;
7249 child_info->attached_to_cell = FALSE;
7250 child_info->floating = TRUE;
7251 child_info->xpadding = child_info->ypadding = 0;
7252 child_info->xexpand = child_info->yexpand = FALSE;
7253 child_info->xshrink = child_info->yshrink = FALSE;
7254 child_info->xfill = child_info->yfill = FALSE;
7256 sheet->children = g_list_append(sheet->children, child_info);
7258 gtk_widget_set_parent (child, GTK_WIDGET(sheet));
7260 gtk_widget_size_request(child, &child_requisition);
7262 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7264 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7265 (!GTK_WIDGET_REALIZED(child) || GTK_WIDGET_NO_WINDOW(child)))
7266 gtk_sheet_realize_child(sheet, child_info);
7268 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7269 !GTK_WIDGET_MAPPED(child))
7270 gtk_widget_map(child);
7273 gtk_sheet_position_child(sheet, child_info);
7275 /* This will avoid drawing on the titles */
7277 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7279 if(sheet->row_titles_visible)
7280 gdk_window_show(sheet->row_title_window);
7281 if(sheet->column_titles_visible)
7282 gdk_window_show(sheet->column_title_window);
7285 return (child_info);
7289 gtk_sheet_attach_floating (GtkSheet *sheet,
7294 GtkSheetChild *child;
7296 if(row < 0 || col < 0){
7297 gtk_sheet_button_attach(sheet, widget, row, col);
7301 gtk_sheet_get_cell_area(sheet, row, col, &area);
7302 child = gtk_sheet_put(sheet, widget, area.x, area.y);
7303 child->attached_to_cell = TRUE;
7309 gtk_sheet_attach_default (GtkSheet *sheet,
7313 if(row < 0 || col < 0){
7314 gtk_sheet_button_attach(sheet, widget, row, col);
7318 gtk_sheet_attach(sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
7322 gtk_sheet_attach (GtkSheet *sheet,
7331 GtkSheetChild *child = NULL;
7333 if(row < 0 || col < 0){
7334 gtk_sheet_button_attach(sheet, widget, row, col);
7338 child = g_new0(GtkSheetChild, 1);
7339 child->attached_to_cell = TRUE;
7340 child->floating = FALSE;
7341 child->widget = widget;
7344 child->xpadding = xpadding;
7345 child->ypadding = ypadding;
7346 child->xexpand = (xoptions & GTK_EXPAND) != 0;
7347 child->yexpand = (yoptions & GTK_EXPAND) != 0;
7348 child->xshrink = (xoptions & GTK_SHRINK) != 0;
7349 child->yshrink = (yoptions & GTK_SHRINK) != 0;
7350 child->xfill = (xoptions & GTK_FILL) != 0;
7351 child->yfill = (yoptions & GTK_FILL) != 0;
7353 sheet->children = g_list_append(sheet->children, child);
7355 gtk_sheet_get_cell_area(sheet, row, col, &area);
7357 child->x = area.x + child->xpadding;
7358 child->y = area.y + child->ypadding;
7360 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7362 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7363 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7364 gtk_sheet_realize_child(sheet, child);
7366 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7367 !GTK_WIDGET_MAPPED(widget))
7368 gtk_widget_map(widget);
7371 gtk_sheet_position_child(sheet, child);
7373 /* This will avoid drawing on the titles */
7375 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7377 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
7378 gdk_window_show(sheet->row_title_window);
7379 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
7380 gdk_window_show(sheet->column_title_window);
7386 gtk_sheet_button_attach (GtkSheet *sheet,
7390 GtkSheetButton *button = 0;
7391 GtkSheetChild *child;
7392 GtkRequisition button_requisition;
7394 if(row >= 0 && col >= 0) return;
7395 if(row < 0 && col < 0) return;
7397 child = g_new (GtkSheetChild, 1);
7398 child->widget = widget;
7401 child->attached_to_cell = TRUE;
7402 child->floating = FALSE;
7405 child->xpadding = child->ypadding = 0;
7406 child->xshrink = child->yshrink = FALSE;
7407 child->xfill = child->yfill = FALSE;
7410 sheet->children = g_list_append(sheet->children, child);
7412 gtk_sheet_button_size_request(sheet, button, &button_requisition);
7415 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7417 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7418 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7419 gtk_sheet_realize_child(sheet, child);
7421 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7422 !GTK_WIDGET_MAPPED(widget))
7423 gtk_widget_map(widget);
7426 if(row == -1) size_allocate_column_title_buttons(sheet);
7427 if(col == -1) size_allocate_row_title_buttons(sheet);
7432 label_size_request(GtkSheet *sheet, gchar *label, GtkRequisition *req)
7437 gint row_height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)) - 2*CELLOFFSET + 2;
7443 while(words && *words != '\0'){
7444 if(*words == '\n' || *(words+1) == '\0'){
7445 req->height += row_height;
7448 req->width = MAX(req->width, STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, word));
7456 if(n > 0) req->height -= 2;
7460 gtk_sheet_button_size_request (GtkSheet *sheet,
7461 const GtkSheetButton *button,
7462 GtkRequisition *button_requisition)
7464 GtkRequisition requisition;
7465 GtkRequisition label_requisition;
7467 if(gtk_sheet_autoresize(sheet) && button->label && strlen(button->label) > 0){
7468 label_size_request(sheet, button->label, &label_requisition);
7469 label_requisition.width += 2*CELLOFFSET;
7470 label_requisition.height += 2*CELLOFFSET;
7472 label_requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7473 label_requisition.width = COLUMN_MIN_WIDTH;
7478 gtk_widget_size_request(button->child->widget, &requisition);
7479 requisition.width += 2*button->child->xpadding;
7480 requisition.height += 2*button->child->ypadding;
7481 requisition.width += 2*sheet->button->style->xthickness;
7482 requisition.height += 2*sheet->button->style->ythickness;
7486 requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7487 requisition.width = COLUMN_MIN_WIDTH;
7490 *button_requisition = requisition;
7491 button_requisition->width = MAX(requisition.width, label_requisition.width);
7492 button_requisition->height = MAX(requisition.height, label_requisition.height);
7497 gtk_sheet_row_size_request (GtkSheet *sheet,
7501 GtkRequisition button_requisition;
7504 gtk_sheet_button_size_request(sheet,
7505 yyy_row_button(sheet, row),
7506 &button_requisition);
7508 *requisition = button_requisition.height;
7510 children = sheet->children;
7512 GtkSheetChild *child = (GtkSheetChild *)children->data;
7513 GtkRequisition child_requisition;
7515 if(child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink){
7516 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7518 if(child_requisition.height + 2 * child->ypadding > *requisition)
7519 *requisition = child_requisition.height + 2 * child->ypadding;
7521 children = children->next;
7524 sheet->row_requisition = * requisition;
7528 gtk_sheet_column_size_request (GtkSheet *sheet,
7532 GtkRequisition button_requisition;
7535 gtk_sheet_button_size_request(sheet,
7536 xxx_column_button(sheet, col),
7537 &button_requisition);
7539 *requisition = button_requisition.width;
7541 children = sheet->children;
7543 GtkSheetChild *child = (GtkSheetChild *)children->data;
7544 GtkRequisition child_requisition;
7546 if(child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink){
7547 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7549 if(child_requisition.width + 2 * child->xpadding > *requisition)
7550 *requisition = child_requisition.width + 2 * child->xpadding;
7552 children = children->next;
7555 sheet->column_requisition = *requisition;
7559 gtk_sheet_move_child(GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
7561 GtkSheetChild *child;
7564 g_return_if_fail(sheet != NULL);
7565 g_return_if_fail(GTK_IS_SHEET(sheet));
7567 children = sheet->children;
7570 child = children->data;
7572 if(child->widget == widget){
7575 child->row = ROW_FROM_YPIXEL(sheet, y);
7576 child->col = COLUMN_FROM_XPIXEL(sheet, x);
7577 gtk_sheet_position_child(sheet, child);
7581 children = children->next;
7584 g_warning("Widget must be a GtkSheet child");
7589 gtk_sheet_position_child(GtkSheet *sheet, GtkSheetChild *child)
7591 GtkRequisition child_requisition;
7592 GtkAllocation child_allocation;
7598 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7600 if(sheet->column_titles_visible)
7601 yoffset = sheet->column_title_area.height;
7603 if(sheet->row_titles_visible)
7604 xoffset = sheet->row_title_area.width;
7606 if(child->attached_to_cell){
7608 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col);
7609 child->y = ROW_TOP_YPIXEL(sheet, child->row);
7611 if(sheet->row_titles_visible)
7612 child->x-=sheet->row_title_area.width;
7613 if(sheet->column_titles_visible)
7614 child->y-=sheet->column_title_area.height;
7616 width = xxx_column_width(sheet, child->col);
7617 height = yyy_row_height(sheet, child->row);
7620 gtk_sheet_get_cell_area(sheet, child->row, child->col, &area);
7621 child->x = area.x + child->xpadding;
7622 child->y = area.y + child->ypadding;
7624 if(!child->floating){
7625 if(child_requisition.width + 2*child->xpadding <= xxx_column_width(sheet, child->col)){
7627 child_requisition.width = child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7630 child->x = area.x + xxx_column_width(sheet, child->col) / 2 -
7631 child_requisition.width / 2;
7633 child_allocation.width = child_requisition.width;
7636 if(!child->xshrink){
7637 gtk_sheet_set_column_width(sheet, child->col, child_requisition.width + 2 * child->xpadding);
7639 child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7642 if(child_requisition.height + 2*child->ypadding <= yyy_row_height(sheet, child->row)){
7644 child_requisition.height = child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7647 child->y = area.y + yyy_row_height(sheet, child->row) / 2 -
7648 child_requisition.height / 2;
7650 child_allocation.height = child_requisition.height;
7653 if(!child->yshrink){
7654 gtk_sheet_set_row_height(sheet, child->row, child_requisition.height + 2 * child->ypadding);
7656 child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7659 child_allocation.width = child_requisition.width;
7660 child_allocation.height = child_requisition.height;
7663 x = child_allocation.x = child->x + xoffset;
7664 y = child_allocation.y = child->y + yoffset;
7668 x = child_allocation.x = child->x + sheet->hoffset + xoffset;
7669 x = child_allocation.x = child->x + xoffset;
7670 y = child_allocation.y = child->y + sheet->voffset + yoffset;
7671 y = child_allocation.y = child->y + yoffset;
7672 child_allocation.width = child_requisition.width;
7673 child_allocation.height = child_requisition.height;
7676 gtk_widget_size_allocate(child->widget, &child_allocation);
7677 gtk_widget_queue_draw(child->widget);
7681 gtk_sheet_forall (GtkContainer *container,
7682 gboolean include_internals,
7683 GtkCallback callback,
7684 gpointer callback_data)
7687 GtkSheetChild *child;
7690 g_return_if_fail (GTK_IS_SHEET (container));
7691 g_return_if_fail (callback != NULL);
7693 sheet = GTK_SHEET (container);
7694 children = sheet->children;
7697 child = children->data;
7698 children = children->next;
7700 (* callback) (child->widget, callback_data);
7703 (* callback) (sheet->button, callback_data);
7704 if(sheet->sheet_entry)
7705 (* callback) (sheet->sheet_entry, callback_data);
7710 gtk_sheet_position_children(GtkSheet *sheet)
7713 GtkSheetChild *child;
7715 children = sheet->children;
7719 child = (GtkSheetChild *)children->data;
7721 if(child->col !=-1 && child->row != -1)
7722 gtk_sheet_position_child(sheet, child);
7724 if(child->row == -1){
7725 if(child->col < MIN_VISIBLE_COLUMN(sheet) ||
7726 child->col > MAX_VISIBLE_COLUMN(sheet))
7727 gtk_sheet_child_hide(child);
7729 gtk_sheet_child_show(child);
7731 if(child->col == -1){
7732 if(child->row < MIN_VISIBLE_ROW(sheet) ||
7733 child->row > MAX_VISIBLE_ROW(sheet))
7734 gtk_sheet_child_hide(child);
7736 gtk_sheet_child_show(child);
7739 children = children->next;
7745 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
7749 GtkSheetChild *child = 0;
7751 g_return_if_fail(container != NULL);
7752 g_return_if_fail(GTK_IS_SHEET(container));
7754 sheet = GTK_SHEET(container);
7756 children = sheet->children;
7760 child = (GtkSheetChild *)children->data;
7762 if(child->widget == widget) break;
7764 children = children->next;
7769 gtk_widget_unparent (widget);
7770 child->widget = NULL;
7772 sheet->children = g_list_remove_link (sheet->children, children);
7773 g_list_free_1 (children);
7780 gtk_sheet_realize_child(GtkSheet *sheet, GtkSheetChild *child)
7784 widget = GTK_WIDGET(sheet);
7786 if(GTK_WIDGET_REALIZED(widget)){
7787 if(child->row == -1)
7788 gtk_widget_set_parent_window(child->widget, sheet->column_title_window);
7789 else if(child->col == -1)
7790 gtk_widget_set_parent_window(child->widget, sheet->row_title_window);
7792 gtk_widget_set_parent_window(child->widget, sheet->sheet_window);
7795 gtk_widget_set_parent(child->widget, widget);
7801 gtk_sheet_get_child_at(GtkSheet *sheet, gint row, gint col)
7804 GtkSheetChild *child = 0;
7806 g_return_val_if_fail(sheet != NULL, NULL);
7807 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7809 children = sheet->children;
7813 child = (GtkSheetChild *)children->data;
7815 if(child->attached_to_cell)
7816 if(child->row == row && child->col == col) break;
7818 children = children->next;
7821 if(children) return child;
7827 gtk_sheet_child_hide(GtkSheetChild *child)
7829 g_return_if_fail(child != NULL);
7830 gtk_widget_hide(child->widget);
7834 gtk_sheet_child_show(GtkSheetChild *child)
7836 g_return_if_fail(child != NULL);
7838 gtk_widget_show(child->widget);
7842 gtk_sheet_get_model(const GtkSheet *sheet)
7844 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
7846 return sheet->model;