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
47 #include <gdk/gdkkeysyms.h>
48 #include <gtk/gtksignal.h>
49 #include <gtk/gtklabel.h>
50 #include <gtk/gtkbutton.h>
51 #include <gtk/gtkadjustment.h>
52 #include <gtk/gtktable.h>
53 #include <gtk/gtkbox.h>
54 #include <gtk/gtkmain.h>
55 #include <gtk/gtktypeutils.h>
56 #include <gtk/gtkentry.h>
57 #include <gtk/gtkcontainer.h>
58 #include <gtk/gtkpixmap.h>
59 #include <pango/pango.h>
60 #include "gtkitementry.h"
62 #include "gtkextra-marshal.h"
63 #include "gsheetmodel.h"
68 GTK_SHEET_IS_LOCKED = 1 << 0,
69 GTK_SHEET_IS_FROZEN = 1 << 1,
70 GTK_SHEET_IN_XDRAG = 1 << 2,
71 GTK_SHEET_IN_YDRAG = 1 << 3,
72 GTK_SHEET_IN_DRAG = 1 << 4,
73 GTK_SHEET_IN_SELECTION = 1 << 5,
74 GTK_SHEET_IN_RESIZE = 1 << 6,
75 GTK_SHEET_IN_CLIP = 1 << 7,
76 GTK_SHEET_REDRAW_PENDING = 1 << 8,
79 #define GTK_SHEET_FLAGS(sheet) (GTK_SHEET (sheet)->flags)
80 #define GTK_SHEET_SET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) |= (flag))
81 #define GTK_SHEET_UNSET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) &= ~(flag))
83 #define GTK_SHEET_IS_LOCKED(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_LOCKED)
86 #define GTK_SHEET_IS_FROZEN(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN)
87 #define GTK_SHEET_IN_XDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG)
88 #define GTK_SHEET_IN_YDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG)
89 #define GTK_SHEET_IN_DRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_DRAG)
90 #define GTK_SHEET_IN_SELECTION(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_SELECTION)
91 #define GTK_SHEET_IN_RESIZE(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_RESIZE)
92 #define GTK_SHEET_IN_CLIP(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_CLIP)
93 #define GTK_SHEET_REDRAW_PENDING(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_REDRAW_PENDING)
95 #define CELL_SPACING 1
97 #define TIMEOUT_SCROLL 20
98 #define TIMEOUT_FLASH 200
99 #define TIME_INTERVAL 8
100 #define COLUMN_MIN_WIDTH 10
105 #define DEFAULT_COLUMN_WIDTH 80
108 static void gtk_sheet_column_title_button_draw(GtkSheet *sheet, gint column);
110 static void gtk_sheet_row_title_button_draw(GtkSheet *sheet, gint row);
113 static gboolean gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col);
116 void dispose_string (const GtkSheet *sheet, gchar *text)
118 GSheetModel *model = gtk_sheet_get_model(sheet);
123 if (g_sheet_model_free_strings(model))
128 guint DEFAULT_ROW_HEIGHT(GtkWidget *widget)
130 if(!widget->style->font_desc) return 24;
132 PangoContext *context = gtk_widget_get_pango_context(widget);
133 PangoFontMetrics *metrics = pango_context_get_metrics(context,
134 widget->style->font_desc,
135 pango_context_get_language(context));
136 guint val = pango_font_metrics_get_descent(metrics) +
137 pango_font_metrics_get_ascent(metrics);
138 pango_font_metrics_unref(metrics);
139 return PANGO_PIXELS(val)+2*CELLOFFSET;
142 static inline guint DEFAULT_FONT_ASCENT(GtkWidget *widget)
144 if(!widget->style->font_desc) return 12;
146 PangoContext *context = gtk_widget_get_pango_context(widget);
147 PangoFontMetrics *metrics = pango_context_get_metrics(context,
148 widget->style->font_desc,
149 pango_context_get_language(context));
150 guint val = pango_font_metrics_get_ascent(metrics);
151 pango_font_metrics_unref(metrics);
152 return PANGO_PIXELS(val);
155 static inline guint STRING_WIDTH(GtkWidget *widget,
156 const PangoFontDescription *font, const gchar *text)
161 layout = gtk_widget_create_pango_layout (widget, text);
162 pango_layout_set_font_description (layout, font);
164 pango_layout_get_extents (layout, NULL, &rect);
166 g_object_unref(G_OBJECT(layout));
167 return PANGO_PIXELS(rect.width);
170 static inline guint DEFAULT_FONT_DESCENT(GtkWidget *widget)
172 if(!widget->style->font_desc) return 12;
174 PangoContext *context = gtk_widget_get_pango_context(widget);
175 PangoFontMetrics *metrics = pango_context_get_metrics(context,
176 widget->style->font_desc,
177 pango_context_get_language(context));
178 guint val = pango_font_metrics_get_descent(metrics);
179 pango_font_metrics_unref(metrics);
180 return PANGO_PIXELS(val);
186 yyy_row_is_visible(const GtkSheet *sheet, gint row)
188 GSheetRow *row_geo = sheet->row_geometry;
190 return g_sheet_row_get_visibility(row_geo, row, 0);
195 yyy_row_is_sensitive(const GtkSheet *sheet, gint row)
197 GSheetRow *row_geo = sheet->row_geometry;
199 return g_sheet_row_get_sensitivity(row_geo, row, 0);
205 yyy_row_count(const GtkSheet *sheet)
207 GSheetRow *row_geo = sheet->row_geometry;
209 return g_sheet_row_get_row_count(row_geo, 0);
213 yyy_row_height(const GtkSheet *sheet, gint row)
215 GSheetRow *row_geo = sheet->row_geometry;
217 return g_sheet_row_get_height(row_geo, row, 0);
221 yyy_row_top_ypixel(const GtkSheet *sheet, gint row)
223 GSheetRow *geo = sheet->row_geometry;
225 gint y = g_sheet_row_start_pixel(geo, row, 0);
227 if ( sheet->column_titles_visible )
228 y += sheet->column_title_area.height;
234 /* Return the row containing pixel Y */
236 yyy_row_ypixel_to_row(const GtkSheet *sheet, gint y)
238 GSheetRow *geo = sheet->row_geometry;
240 gint cy = sheet->voffset;
242 if(sheet->column_titles_visible)
243 cy += sheet->column_title_area.height;
247 return g_sheet_row_pixel_to_row(geo, y - cy, 0);
251 /* gives the top pixel of the given row in context of
252 * the sheet's voffset */
254 ROW_TOP_YPIXEL(const GtkSheet *sheet, gint row)
256 return (sheet->voffset + yyy_row_top_ypixel(sheet, row));
260 /* returns the row index from a y pixel location in the
261 * context of the sheet's voffset */
263 ROW_FROM_YPIXEL(const GtkSheet *sheet, gint y)
265 return (yyy_row_ypixel_to_row(sheet, y));
268 static inline GtkSheetButton *
269 xxx_column_button(const GtkSheet *sheet, gint col)
271 GSheetColumn *col_geo = sheet->column_geometry;
272 if ( col < 0 ) return NULL ;
274 return g_sheet_column_get_button(col_geo, col);
279 xxx_column_left_xpixel(const GtkSheet *sheet, gint col)
281 GSheetColumn *geo = sheet->column_geometry;
283 gint x = g_sheet_column_start_pixel(geo, col);
285 if ( sheet->row_titles_visible )
286 x += sheet->row_title_area.width;
292 xxx_column_width(const GtkSheet *sheet, gint col)
294 GSheetColumn *col_geo = sheet->column_geometry;
296 return g_sheet_column_get_width(col_geo, col);
301 xxx_set_column_width(GtkSheet *sheet, gint col, gint width)
303 if ( sheet->column_geometry )
304 g_sheet_column_set_width(sheet->column_geometry, col, width);
308 xxx_column_set_left_column(GtkSheet *sheet, gint col, gint i)
310 GSheetColumn *col_geo = sheet->column_geometry;
312 g_sheet_column_set_left_text_column(col_geo, col, i);
316 xxx_column_left_column(const GtkSheet *sheet, gint col)
318 GSheetColumn *col_geo = sheet->column_geometry;
320 return g_sheet_column_get_left_text_column(col_geo, col);
324 xxx_column_set_right_column(GtkSheet *sheet, gint col, gint i)
326 GSheetColumn *col_geo = sheet->column_geometry;
328 g_sheet_column_set_right_text_column(col_geo, col, i);
332 xxx_column_right_column(const GtkSheet *sheet, gint col)
334 GSheetColumn *col_geo = sheet->column_geometry;
336 return g_sheet_column_get_right_text_column(col_geo, col);
339 static inline GtkJustification
340 xxx_column_justification(const GtkSheet *sheet, gint col)
342 GSheetColumn *col_geo = sheet->column_geometry;
344 return g_sheet_column_get_justification(col_geo, col);
348 xxx_column_is_visible(const GtkSheet *sheet, gint col)
350 GSheetColumn *col_geo = sheet->column_geometry;
352 return g_sheet_column_get_visibility(col_geo, col);
357 xxx_column_is_sensitive(const GtkSheet *sheet, gint col)
359 GSheetColumn *col_geo = sheet->column_geometry;
361 return g_sheet_column_get_sensitivity(col_geo, col);
365 /* gives the left pixel of the given column in context of
366 * the sheet's hoffset */
368 COLUMN_LEFT_XPIXEL(const GtkSheet *sheet, gint ncol)
370 return (sheet->hoffset + xxx_column_left_xpixel(sheet, ncol));
374 xxx_column_count(const GtkSheet *sheet)
376 GSheetColumn *col_geo = sheet->column_geometry;
378 return g_sheet_column_get_column_count(col_geo);
381 /* returns the column index from a x pixel location in the
382 * context of the sheet's hoffset */
384 COLUMN_FROM_XPIXEL (const GtkSheet * sheet,
390 if( sheet->row_titles_visible )
391 cx += sheet->row_title_area.width;
394 for (i = 0; i < xxx_column_count(sheet); i++)
396 if (x >= cx && x <= (cx + xxx_column_width(sheet, i)) &&
397 xxx_column_is_visible(sheet, i))
399 if( xxx_column_is_visible(sheet, i))
400 cx += xxx_column_width(sheet, i);
404 return xxx_column_count(sheet) - 1;
407 /* returns the total height of the sheet */
408 static inline gint SHEET_HEIGHT(GtkSheet *sheet)
410 const gint n_rows = yyy_row_count(sheet);
412 return yyy_row_top_ypixel(sheet, n_rows - 1) +
413 yyy_row_height(sheet, n_rows - 1);
417 static inline GtkSheetButton *
418 yyy_row_button(GtkSheet *sheet, gint row)
420 GSheetRow *row_geo = sheet->row_geometry;
422 return g_sheet_row_get_button(row_geo, row, sheet);
429 yyy_set_row_height(GtkSheet *sheet, gint row, gint height)
431 if ( sheet->row_geometry )
432 g_sheet_row_set_height(sheet->row_geometry, row, height, sheet);
437 /* returns the total width of the sheet */
438 static inline gint SHEET_WIDTH(GtkSheet *sheet)
442 cx = ( sheet->row_titles_visible ? sheet->row_title_area.width : 0);
444 for (i=0; i < xxx_column_count(sheet); i++)
445 if(xxx_column_is_visible(sheet, i)) cx += xxx_column_width(sheet, i);
450 #define MIN_VISIBLE_ROW(sheet) sheet->view.row0
451 #define MAX_VISIBLE_ROW(sheet) sheet->view.rowi
452 #define MIN_VISIBLE_COLUMN(sheet) sheet->view.col0
453 #define MAX_VISIBLE_COLUMN(sheet) sheet->view.coli
456 static inline gboolean
457 POSSIBLE_XDRAG(const GtkSheet *sheet, gint x, gint *drag_column)
461 column=COLUMN_FROM_XPIXEL(sheet, x);
464 xdrag = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING;
465 if(x <= xdrag+DRAG_WIDTH/2 && column != 0){
466 while(! xxx_column_is_visible(sheet, column-1) && column>0) column--;
467 *drag_column=column-1;
468 return xxx_column_is_sensitive(sheet, column-1);
471 xdrag+= xxx_column_width(sheet, column);
472 if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag+DRAG_WIDTH/2)
473 return xxx_column_is_sensitive(sheet, column);
478 static inline gboolean
479 POSSIBLE_YDRAG(const GtkSheet *sheet, gint y, gint *drag_row)
482 row=ROW_FROM_YPIXEL(sheet, y);
485 ydrag=ROW_TOP_YPIXEL(sheet,row)+CELL_SPACING;
486 if(y <= ydrag+DRAG_WIDTH/2 && row != 0){
487 while(!yyy_row_is_visible(sheet, row-1) && row>0) row--;
489 return yyy_row_is_sensitive(sheet, row-1);
492 ydrag+=yyy_row_height(sheet, row);
494 if(y >= ydrag-DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2)
495 return yyy_row_is_sensitive(sheet, row);
501 static inline gboolean
502 POSSIBLE_DRAG(const GtkSheet *sheet, gint x, gint y,
503 gint *drag_row, gint *drag_column)
507 /* Can't drag if nothing is selected */
508 if ( sheet->range.row0 < 0 || sheet->range.rowi < 0 ||
509 sheet->range.col0 < 0 || sheet->range.coli < 0 )
512 *drag_column = COLUMN_FROM_XPIXEL(sheet, x);
513 *drag_row = ROW_FROM_YPIXEL(sheet, y);
515 if(x >= COLUMN_LEFT_XPIXEL(sheet, sheet->range.col0) - DRAG_WIDTH/2 &&
516 x <= COLUMN_LEFT_XPIXEL(sheet, sheet->range.coli) +
517 xxx_column_width(sheet, sheet->range.coli) + DRAG_WIDTH/2)
519 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.row0);
520 if(y >= ydrag - DRAG_WIDTH/2 && y <= ydrag + DRAG_WIDTH/2)
522 *drag_row = sheet->range.row0;
525 ydrag = ROW_TOP_YPIXEL(sheet, sheet->range.rowi) +
526 yyy_row_height(sheet, sheet->range.rowi);
527 if(y >= ydrag - DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2)
529 *drag_row = sheet->range.rowi;
534 if(y >= ROW_TOP_YPIXEL(sheet, sheet->range.row0) - DRAG_WIDTH/2 &&
535 y <= ROW_TOP_YPIXEL(sheet, sheet->range.rowi) +
536 yyy_row_height(sheet, sheet->range.rowi) + DRAG_WIDTH/2)
538 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->range.col0);
539 if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag + DRAG_WIDTH/2)
541 *drag_column = sheet->range.col0;
544 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->range.coli) +
545 xxx_column_width(sheet, sheet->range.coli);
546 if(x >= xdrag - DRAG_WIDTH/2 && x <= xdrag + DRAG_WIDTH/2)
548 *drag_column = sheet->range.coli;
555 static inline gboolean
556 POSSIBLE_RESIZE(const GtkSheet *sheet, gint x, gint y,
557 gint *drag_row, gint *drag_column)
561 /* Can't drag if nothing is selected */
562 if ( sheet->range.row0 < 0 || sheet->range.rowi < 0 ||
563 sheet->range.col0 < 0 || sheet->range.coli < 0 )
566 xdrag = COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
567 xxx_column_width(sheet, sheet->range.coli);
569 ydrag = ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
570 yyy_row_height(sheet, sheet->range.rowi);
572 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
573 ydrag = ROW_TOP_YPIXEL(sheet, sheet->view.row0);
575 if(sheet->state == GTK_SHEET_ROW_SELECTED)
576 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0);
578 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
579 *drag_row=ROW_FROM_YPIXEL(sheet,y);
581 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2 &&
582 y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2) return TRUE;
587 static void gtk_sheet_class_init (GtkSheetClass * klass);
588 static void gtk_sheet_init (GtkSheet * sheet);
589 static void gtk_sheet_destroy (GtkObject * object);
590 static void gtk_sheet_finalize (GObject * object);
591 static void gtk_sheet_style_set (GtkWidget *widget,
592 GtkStyle *previous_style);
593 static void gtk_sheet_realize (GtkWidget * widget);
594 static void gtk_sheet_unrealize (GtkWidget * widget);
595 static void gtk_sheet_map (GtkWidget * widget);
596 static void gtk_sheet_unmap (GtkWidget * widget);
597 static gint gtk_sheet_expose (GtkWidget * widget,
598 GdkEventExpose * event);
599 static void gtk_sheet_forall (GtkContainer *container,
600 gboolean include_internals,
601 GtkCallback callback,
602 gpointer callback_data);
604 static void gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
605 GtkAdjustment *hadjustment,
606 GtkAdjustment *vadjustment);
608 static gint gtk_sheet_button_press (GtkWidget * widget,
609 GdkEventButton * event);
610 static gint gtk_sheet_button_release (GtkWidget * widget,
611 GdkEventButton * event);
612 static gint gtk_sheet_motion (GtkWidget * widget,
613 GdkEventMotion * event);
614 static gint gtk_sheet_entry_key_press (GtkWidget *widget,
616 static gint gtk_sheet_key_press (GtkWidget *widget,
618 static void gtk_sheet_size_request (GtkWidget * widget,
619 GtkRequisition * requisition);
620 static void gtk_sheet_size_allocate (GtkWidget * widget,
621 GtkAllocation * allocation);
625 static gint gtk_sheet_range_isvisible (GtkSheet * sheet,
626 GtkSheetRange range);
627 static gint gtk_sheet_cell_isvisible (GtkSheet * sheet,
628 gint row, gint column);
631 static gint gtk_sheet_scroll (gpointer data);
632 static gint gtk_sheet_flash (gpointer data);
634 /* Drawing Routines */
636 /* draw cell background and frame */
637 static void gtk_sheet_cell_draw_default (GtkSheet *sheet,
638 gint row, gint column);
640 /* draw cell border */
641 static void gtk_sheet_cell_draw_border (GtkSheet *sheet,
642 gint row, gint column,
645 /* draw cell contents */
646 static void gtk_sheet_cell_draw_label (GtkSheet *sheet,
647 gint row, gint column);
649 /* draw visible part of range. If range==NULL then draw the whole screen */
650 static void gtk_sheet_range_draw (GtkSheet *sheet,
651 const GtkSheetRange *range);
653 /* highlight the visible part of the selected range */
654 static void gtk_sheet_range_draw_selection (GtkSheet *sheet,
655 GtkSheetRange range);
659 static gint gtk_sheet_move_query (GtkSheet *sheet,
660 gint row, gint column);
661 static void gtk_sheet_real_select_range (GtkSheet * sheet,
662 const GtkSheetRange * range);
663 static void gtk_sheet_real_unselect_range (GtkSheet * sheet,
664 const GtkSheetRange * range);
665 static void gtk_sheet_extend_selection (GtkSheet *sheet,
666 gint row, gint column);
667 static void gtk_sheet_new_selection (GtkSheet *sheet,
668 GtkSheetRange *range);
669 static void gtk_sheet_draw_border (GtkSheet *sheet,
670 GtkSheetRange range);
671 static void gtk_sheet_draw_corners (GtkSheet *sheet,
672 GtkSheetRange range);
675 /* Active Cell handling */
677 static void gtk_sheet_entry_changed (GtkWidget *widget,
679 static gboolean gtk_sheet_deactivate_cell (GtkSheet *sheet);
680 static void gtk_sheet_hide_active_cell (GtkSheet *sheet);
681 static gboolean gtk_sheet_activate_cell (GtkSheet *sheet,
683 static void gtk_sheet_draw_active_cell (GtkSheet *sheet);
684 static void gtk_sheet_show_active_cell (GtkSheet *sheet);
685 static void gtk_sheet_click_cell (GtkSheet *sheet,
692 static void gtk_sheet_make_backing_pixmap (GtkSheet *sheet,
693 guint width, guint height);
694 static void gtk_sheet_draw_backing_pixmap (GtkSheet *sheet,
695 GtkSheetRange range);
698 static void adjust_scrollbars (GtkSheet * sheet);
699 static void vadjustment_changed (GtkAdjustment * adjustment,
701 static void hadjustment_changed (GtkAdjustment * adjustment,
703 static void vadjustment_value_changed (GtkAdjustment * adjustment,
705 static void hadjustment_value_changed (GtkAdjustment * adjustment,
709 static void draw_xor_vline (GtkSheet * sheet);
710 static void draw_xor_hline (GtkSheet * sheet);
711 static void draw_xor_rectangle (GtkSheet *sheet,
712 GtkSheetRange range);
713 static void gtk_sheet_draw_flashing_range (GtkSheet *sheet,
714 GtkSheetRange range);
715 static guint new_column_width (GtkSheet * sheet,
718 static guint new_row_height (GtkSheet * sheet,
723 static void create_global_button (GtkSheet *sheet);
724 static void global_button_clicked (GtkWidget *widget,
728 static void create_sheet_entry (GtkSheet *sheet);
729 static void gtk_sheet_size_allocate_entry (GtkSheet *sheet);
730 static void gtk_sheet_entry_set_max_size (GtkSheet *sheet);
732 /* Sheet button gadgets */
734 static void size_allocate_column_title_buttons (GtkSheet * sheet);
735 static void size_allocate_row_title_buttons (GtkSheet * sheet);
738 static void size_allocate_global_button (GtkSheet *sheet);
739 static void gtk_sheet_button_size_request (GtkSheet *sheet,
740 const GtkSheetButton *button,
741 GtkRequisition *requisition);
743 /* Attributes routines */
744 static void init_attributes (const GtkSheet *sheet, gint col,
745 GtkSheetCellAttr *attributes);
748 /* Memory allocation routines */
749 static void gtk_sheet_real_range_clear (GtkSheet *sheet,
750 const GtkSheetRange *range,
752 static void gtk_sheet_real_cell_clear (GtkSheet *sheet,
758 /* Container Functions */
759 static void gtk_sheet_remove (GtkContainer *container,
761 static void gtk_sheet_realize_child (GtkSheet *sheet,
762 GtkSheetChild *child);
763 static void gtk_sheet_position_child (GtkSheet *sheet,
764 GtkSheetChild *child);
765 static void gtk_sheet_position_children (GtkSheet *sheet);
766 static void gtk_sheet_child_show (GtkSheetChild *child);
767 static void gtk_sheet_child_hide (GtkSheetChild *child);
768 static void gtk_sheet_column_size_request (GtkSheet *sheet,
771 static void gtk_sheet_row_size_request (GtkSheet *sheet,
779 _gtkextra_signal_emit(GtkObject *object, guint signal_id, ...);
801 static GtkContainerClass *parent_class = NULL;
802 static guint sheet_signals[LAST_SIGNAL] = {0};
806 gtk_sheet_get_type ()
808 static GType sheet_type = 0;
812 static const GTypeInfo sheet_info =
814 sizeof (GtkSheetClass),
817 (GClassInitFunc) gtk_sheet_class_init,
822 (GInstanceInitFunc) gtk_sheet_init,
826 g_type_register_static (GTK_TYPE_CONTAINER, "GtkSheet",
832 static GtkSheetRange*
833 gtk_sheet_range_copy (const GtkSheetRange *range)
835 GtkSheetRange *new_range;
837 g_return_val_if_fail (range != NULL, NULL);
839 new_range = g_new (GtkSheetRange, 1);
847 gtk_sheet_range_free (GtkSheetRange *range)
849 g_return_if_fail (range != NULL);
855 gtk_sheet_range_get_type (void)
857 static GType sheet_range_type=0;
859 if(!sheet_range_type)
861 sheet_range_type = g_boxed_type_register_static("GtkSheetRange", (GBoxedCopyFunc)gtk_sheet_range_copy, (GBoxedFreeFunc)gtk_sheet_range_free);
863 return sheet_range_type;
868 gtk_sheet_class_init (GtkSheetClass * klass)
870 GtkObjectClass *object_class;
871 GtkWidgetClass *widget_class;
872 GtkContainerClass *container_class;
873 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
875 object_class = (GtkObjectClass *) klass;
876 widget_class = (GtkWidgetClass *) klass;
877 container_class = (GtkContainerClass *) klass;
879 parent_class = g_type_class_peek_parent (klass);
882 * GtkSheet::select-row
883 * @sheet: the sheet widget that emitted the signal
884 * @row: the newly selected row index
886 * A row has been selected.
888 sheet_signals[SELECT_ROW] =
889 gtk_signal_new ("select-row",
891 GTK_CLASS_TYPE(object_class),
892 GTK_SIGNAL_OFFSET (GtkSheetClass, select_row),
894 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
897 * GtkSheet::select-column
898 * @sheet: the sheet widget that emitted the signal
899 * @column: the newly selected column index
901 * A column has been selected.
903 sheet_signals[SELECT_COLUMN] =
904 gtk_signal_new ("select-column",
906 GTK_CLASS_TYPE(object_class),
907 GTK_SIGNAL_OFFSET (GtkSheetClass, select_column),
909 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
913 * GtkSheet::double-click-row
914 * @sheet: the sheet widget that emitted the signal
915 * @row: the row that was double clicked.
917 * A row's title button has been double clicked
919 sheet_signals[DOUBLE_CLICK_ROW] =
920 gtk_signal_new ("double-click-row",
922 GTK_CLASS_TYPE(object_class),
925 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
929 * GtkSheet::double-click-column
930 * @sheet: the sheet widget that emitted the signal
931 * @column: the column that was double clicked.
933 * A column's title button has been double clicked
935 sheet_signals[DOUBLE_CLICK_COLUMN] =
936 gtk_signal_new ("double-click-column",
938 GTK_CLASS_TYPE(object_class),
941 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
943 sheet_signals[SELECT_RANGE] =
944 gtk_signal_new ("select-range",
946 GTK_CLASS_TYPE(object_class),
947 GTK_SIGNAL_OFFSET (GtkSheetClass, select_range),
948 gtkextra_VOID__BOXED,
949 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
951 sheet_signals[CLIP_RANGE] =
952 gtk_signal_new ("clip-range",
954 GTK_CLASS_TYPE(object_class),
955 GTK_SIGNAL_OFFSET (GtkSheetClass, clip_range),
956 gtkextra_VOID__BOXED,
957 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
959 sheet_signals[RESIZE_RANGE] =
960 gtk_signal_new ("resize-range",
962 GTK_CLASS_TYPE(object_class),
963 GTK_SIGNAL_OFFSET (GtkSheetClass, resize_range),
964 gtkextra_VOID__BOXED_BOXED,
965 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
966 sheet_signals[MOVE_RANGE] =
967 gtk_signal_new ("move-range",
969 GTK_CLASS_TYPE(object_class),
970 GTK_SIGNAL_OFFSET (GtkSheetClass, move_range),
971 gtkextra_VOID__BOXED_BOXED,
972 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
973 sheet_signals[TRAVERSE] =
974 gtk_signal_new ("traverse",
976 GTK_CLASS_TYPE(object_class),
977 GTK_SIGNAL_OFFSET (GtkSheetClass, traverse),
978 gtkextra_BOOLEAN__INT_INT_POINTER_POINTER,
979 GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT,
980 GTK_TYPE_POINTER, GTK_TYPE_POINTER);
982 sheet_signals[DEACTIVATE] =
983 gtk_signal_new ("deactivate",
985 GTK_CLASS_TYPE(object_class),
986 GTK_SIGNAL_OFFSET (GtkSheetClass, deactivate),
987 gtkextra_BOOLEAN__INT_INT,
988 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
990 sheet_signals[ACTIVATE] =
991 gtk_signal_new ("activate",
993 GTK_CLASS_TYPE(object_class),
994 GTK_SIGNAL_OFFSET (GtkSheetClass, activate),
995 gtkextra_BOOLEAN__INT_INT,
996 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
998 sheet_signals[SET_CELL] =
999 gtk_signal_new ("set-cell",
1001 GTK_CLASS_TYPE(object_class),
1002 GTK_SIGNAL_OFFSET (GtkSheetClass, set_cell),
1003 gtkextra_VOID__INT_INT,
1004 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1006 sheet_signals[CLEAR_CELL] =
1007 gtk_signal_new ("clear-cell",
1009 GTK_CLASS_TYPE(object_class),
1010 GTK_SIGNAL_OFFSET (GtkSheetClass, clear_cell),
1011 gtkextra_VOID__INT_INT,
1012 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1014 sheet_signals[CHANGED] =
1015 gtk_signal_new ("changed",
1017 GTK_CLASS_TYPE(object_class),
1018 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1019 gtkextra_VOID__INT_INT,
1020 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1022 sheet_signals[NEW_COL_WIDTH] =
1023 gtk_signal_new ("new-column-width",
1025 GTK_CLASS_TYPE(object_class),
1026 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1027 gtkextra_VOID__INT_INT,
1028 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1030 sheet_signals[NEW_ROW_HEIGHT] =
1031 gtk_signal_new ("new-row-height",
1033 GTK_CLASS_TYPE(object_class),
1034 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1035 gtkextra_VOID__INT_INT,
1036 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1038 widget_class->set_scroll_adjustments_signal =
1039 gtk_signal_new ("set-scroll-adjustments",
1041 GTK_CLASS_TYPE(object_class),
1042 GTK_SIGNAL_OFFSET (GtkSheetClass, set_scroll_adjustments),
1043 gtkextra_VOID__OBJECT_OBJECT,
1044 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1047 container_class->add = NULL;
1048 container_class->remove = gtk_sheet_remove;
1049 container_class->forall = gtk_sheet_forall;
1051 object_class->destroy = gtk_sheet_destroy;
1052 gobject_class->finalize = gtk_sheet_finalize;
1054 widget_class->realize = gtk_sheet_realize;
1055 widget_class->unrealize = gtk_sheet_unrealize;
1056 widget_class->map = gtk_sheet_map;
1057 widget_class->unmap = gtk_sheet_unmap;
1058 widget_class->style_set = gtk_sheet_style_set;
1059 widget_class->button_press_event = gtk_sheet_button_press;
1060 widget_class->button_release_event = gtk_sheet_button_release;
1061 widget_class->motion_notify_event = gtk_sheet_motion;
1062 widget_class->key_press_event = gtk_sheet_key_press;
1063 widget_class->expose_event = gtk_sheet_expose;
1064 widget_class->size_request = gtk_sheet_size_request;
1065 widget_class->size_allocate = gtk_sheet_size_allocate;
1066 widget_class->focus_in_event = NULL;
1067 widget_class->focus_out_event = NULL;
1069 klass->set_scroll_adjustments = gtk_sheet_set_scroll_adjustments;
1070 klass->select_row = NULL;
1071 klass->select_column = NULL;
1072 klass->select_range = NULL;
1073 klass->clip_range = NULL;
1074 klass->resize_range = NULL;
1075 klass->move_range = NULL;
1076 klass->traverse = NULL;
1077 klass->deactivate = NULL;
1078 klass->activate = NULL;
1079 klass->set_cell = NULL;
1080 klass->clear_cell = NULL;
1081 klass->changed = NULL;
1086 gtk_sheet_init (GtkSheet *sheet)
1088 sheet->column_geometry = NULL;
1089 sheet->row_geometry = NULL;
1091 sheet->children = NULL;
1094 sheet->selection_mode = GTK_SELECTION_BROWSE;
1095 sheet->freeze_count = 0;
1096 sheet->state = GTK_SHEET_NORMAL;
1098 GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW);
1099 GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS);
1101 sheet->view.row0 = 0;
1102 sheet->view.col0 = 0;
1103 sheet->view.rowi = 0;
1104 sheet->view.coli = 0;
1106 sheet->column_title_window=NULL;
1107 sheet->column_title_area.x=0;
1108 sheet->column_title_area.y=0;
1109 sheet->column_title_area.width=0;
1110 sheet->column_title_area.height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
1112 sheet->row_title_window=NULL;
1113 sheet->row_title_area.x=0;
1114 sheet->row_title_area.y=0;
1115 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1116 sheet->row_title_area.height=0;
1119 sheet->active_cell.row=0;
1120 sheet->active_cell.col=0;
1121 sheet->selection_cell.row=0;
1122 sheet->selection_cell.col=0;
1124 sheet->sheet_entry=NULL;
1127 sheet->range.row0 = 0;
1128 sheet->range.rowi = 0;
1129 sheet->range.col0 = 0;
1130 sheet->range.coli = 0;
1132 sheet->state=GTK_SHEET_NORMAL;
1134 sheet->sheet_window = NULL;
1135 sheet->sheet_window_width = 0;
1136 sheet->sheet_window_height = 0;
1137 sheet->sheet_entry = NULL;
1138 sheet->button = NULL;
1143 sheet->hadjustment = NULL;
1144 sheet->vadjustment = NULL;
1146 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
1147 sheet->xor_gc = NULL;
1148 sheet->fg_gc = NULL;
1149 sheet->bg_gc = NULL;
1153 gdk_color_parse("white", &sheet->bg_color);
1154 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1155 gdk_color_parse("gray", &sheet->grid_color);
1156 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1157 sheet->show_grid = TRUE;
1161 /* Callback which occurs whenever columns are inserted/deleted in the model */
1163 columns_inserted_deleted_callback (GSheetModel *model, gint first_column, gint n_columns,
1167 GtkSheet *sheet = GTK_SHEET(data);
1169 GtkSheetRange range;
1170 gint model_columns = g_sheet_model_get_column_count(model);
1173 /* Need to update all the columns starting from the first column and onwards.
1174 * Previous column are unchanged, so don't need to be updated.
1176 range.col0 = first_column;
1178 range.coli = xxx_column_count(sheet) - 1;
1179 range.rowi = yyy_row_count(sheet) - 1;
1182 COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width + 1);
1185 COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
1187 if ( sheet->view.coli > range.coli)
1188 sheet->view.coli = range.coli;
1190 adjust_scrollbars(sheet);
1192 if (sheet->active_cell.col >= model_columns)
1193 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, model_columns - 1);
1195 for(i = first_column; i <= MAX_VISIBLE_COLUMN(sheet); i++)
1196 gtk_sheet_column_title_button_draw(sheet, i);
1198 gtk_sheet_range_draw(sheet, &range);
1202 /* Callback which occurs whenever rows are inserted/deleted in the model */
1204 rows_inserted_deleted_callback (GSheetModel *model, gint first_row, gint n_rows,
1208 GtkSheet *sheet = GTK_SHEET(data);
1210 GtkSheetRange range;
1212 gint model_rows = g_sheet_model_get_row_count(model);
1214 /* Need to update all the rows starting from the first row and onwards.
1215 * Previous rows are unchanged, so don't need to be updated.
1217 range.row0 = first_row;
1219 range.rowi = yyy_row_count(sheet) - 1;
1220 range.coli = xxx_column_count(sheet) - 1;
1223 ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height + 1);
1225 ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height - 1);
1227 if ( sheet->view.rowi > range.rowi)
1228 sheet->view.rowi = range.rowi;
1230 adjust_scrollbars(sheet);
1232 if (sheet->active_cell.row >= model_rows)
1233 gtk_sheet_activate_cell(sheet, model_rows - 1, sheet->active_cell.col);
1235 for(i = first_row; i <= MAX_VISIBLE_ROW(sheet); i++)
1236 gtk_sheet_row_title_button_draw(sheet, i);
1238 gtk_sheet_range_draw(sheet, &range);
1242 If row0 or rowi are negative, then all rows will be updated.
1243 If col0 or coli are negative, then all columns will be updated.
1246 range_update_callback (GSheetModel *m, gint row0, gint col0,
1247 gint rowi, gint coli, gpointer data)
1249 GtkSheet *sheet = GTK_SHEET(data);
1251 GtkSheetRange range;
1258 if( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
1260 gtk_sheet_range_draw(sheet, NULL);
1263 else if ( row0 < 0 || rowi < 0 )
1265 range.row0=MIN_VISIBLE_ROW(sheet);
1266 range.rowi=MAX_VISIBLE_ROW(sheet);
1268 else if ( col0 < 0 || coli < 0 )
1270 range.col0=MIN_VISIBLE_COLUMN(sheet);
1271 range.coli=MAX_VISIBLE_COLUMN(sheet);
1274 gtk_sheet_range_draw(sheet, &range);
1278 static void gtk_sheet_construct (GtkSheet *sheet,
1281 const gchar *title);
1286 * @rows: initial number of rows
1287 * @columns: initial number of columns
1288 * @title: sheet title
1289 * @model: the model to use for the sheet data
1291 * Creates a new sheet widget with the given number of rows and columns.
1293 * Returns: the new sheet widget
1296 gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, const gchar *title,
1301 widget = gtk_type_new (gtk_sheet_get_type ());
1303 gtk_sheet_construct(GTK_SHEET(widget), vgeo, hgeo, title);
1306 gtk_sheet_set_model(GTK_SHEET(widget), model);
1314 * gtk_sheet_set_model
1315 * @sheet: the sheet to set the model for
1316 * @model: the model to use for the sheet data
1318 * Sets the model for a GtkSheet
1322 gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model)
1324 g_return_if_fail (GTK_IS_SHEET (sheet));
1325 g_return_if_fail (G_IS_SHEET_MODEL (model));
1327 sheet->model = model;
1329 g_signal_connect(model, "range_changed",
1330 G_CALLBACK(range_update_callback), sheet);
1332 g_signal_connect(model, "rows_inserted",
1333 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1335 g_signal_connect(model, "rows_deleted",
1336 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1338 g_signal_connect(model, "columns_inserted",
1339 G_CALLBACK(columns_inserted_deleted_callback), sheet);
1341 g_signal_connect(model, "columns_deleted",
1342 G_CALLBACK(columns_inserted_deleted_callback), sheet);
1347 /* Call back for when the column titles have changed.
1348 FIRST is the first column changed.
1349 N_COLUMNS is the number of columns which have changed, or -1, which
1350 indicates that the column has changed to its right-most extremity
1353 column_titles_changed(GtkWidget *w, gint first, gint n_columns, gpointer data)
1355 GtkSheet *sheet = GTK_SHEET(data);
1356 gboolean extremity = FALSE;
1358 if ( n_columns == -1 )
1361 n_columns = xxx_column_count(sheet) - 1 ;
1364 if(!GTK_SHEET_IS_FROZEN(sheet))
1367 for ( i = first ; i <= first + n_columns ; ++i )
1369 gtk_sheet_column_title_button_draw(sheet, i);
1370 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, i);
1374 gtk_sheet_column_title_button_draw(sheet, -1);
1379 gtk_sheet_construct (GtkSheet *sheet,
1384 g_return_if_fail(G_IS_SHEET_COLUMN(hgeo));
1385 g_return_if_fail(G_IS_SHEET_ROW(vgeo));
1387 sheet->column_geometry = hgeo;
1388 sheet->row_geometry = vgeo;
1391 sheet->columns_resizable = TRUE;
1392 sheet->rows_resizable = TRUE;
1394 sheet->row_titles_visible = TRUE;
1395 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1397 sheet->column_titles_visible = TRUE;
1398 sheet->autoscroll = TRUE;
1399 sheet->justify_entry = TRUE;
1402 /* create sheet entry */
1403 sheet->entry_type = 0;
1404 create_sheet_entry (sheet);
1406 /* create global selection button */
1407 create_global_button(sheet);
1410 sheet->name = g_strdup(title);
1412 g_signal_connect(sheet->column_geometry, "columns_changed",
1413 G_CALLBACK(column_titles_changed), sheet);
1419 gtk_sheet_new_with_custom_entry (GSheetRow *rows, GSheetColumn *columns, const gchar *title,
1424 widget = gtk_type_new (gtk_sheet_get_type ());
1426 gtk_sheet_construct_with_custom_entry(GTK_SHEET(widget),
1427 rows, columns, title, entry_type);
1433 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet,
1439 gtk_sheet_construct(sheet, vgeo, hgeo, title);
1441 sheet->entry_type = entry_type;
1442 create_sheet_entry(sheet);
1448 gtk_sheet_change_entry(GtkSheet *sheet, GtkType entry_type)
1452 g_return_if_fail (sheet != NULL);
1453 g_return_if_fail (GTK_IS_SHEET (sheet));
1455 state = sheet->state;
1457 if(sheet->state == GTK_SHEET_NORMAL)
1458 gtk_sheet_hide_active_cell(sheet);
1460 sheet->entry_type = entry_type;
1462 create_sheet_entry(sheet);
1464 if(state == GTK_SHEET_NORMAL)
1466 gtk_sheet_show_active_cell(sheet);
1467 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
1469 G_CALLBACK(gtk_sheet_entry_changed),
1475 gtk_sheet_show_grid(GtkSheet *sheet, gboolean show)
1477 g_return_if_fail (sheet != NULL);
1478 g_return_if_fail (GTK_IS_SHEET (sheet));
1480 if(show == sheet->show_grid) return;
1482 sheet->show_grid = show;
1484 if(!GTK_SHEET_IS_FROZEN(sheet))
1485 gtk_sheet_range_draw(sheet, NULL);
1489 gtk_sheet_grid_visible(GtkSheet *sheet)
1491 g_return_val_if_fail (sheet != NULL, 0);
1492 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1494 return sheet->show_grid;
1498 gtk_sheet_set_background(GtkSheet *sheet, GdkColor *color)
1500 g_return_if_fail (sheet != NULL);
1501 g_return_if_fail (GTK_IS_SHEET (sheet));
1504 gdk_color_parse("white", &sheet->bg_color);
1505 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1507 sheet->bg_color = *color;
1509 if(!GTK_SHEET_IS_FROZEN(sheet))
1510 gtk_sheet_range_draw(sheet, NULL);
1514 gtk_sheet_set_grid(GtkSheet *sheet, GdkColor *color)
1516 g_return_if_fail (sheet != NULL);
1517 g_return_if_fail (GTK_IS_SHEET (sheet));
1520 gdk_color_parse("black", &sheet->grid_color);
1521 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1523 sheet->grid_color = *color;
1525 if(!GTK_SHEET_IS_FROZEN(sheet))
1526 gtk_sheet_range_draw(sheet, NULL);
1530 gtk_sheet_get_columns_count(GtkSheet *sheet)
1532 g_return_val_if_fail (sheet != NULL, 0);
1533 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1535 return xxx_column_count(sheet);
1539 gtk_sheet_get_rows_count(GtkSheet *sheet)
1541 g_return_val_if_fail (sheet != NULL, 0);
1542 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1544 return yyy_row_count(sheet);
1548 gtk_sheet_get_state(GtkSheet *sheet)
1550 g_return_val_if_fail (sheet != NULL, 0);
1551 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1553 return (sheet->state);
1557 gtk_sheet_set_selection_mode(GtkSheet *sheet, gint mode)
1559 g_return_if_fail (sheet != NULL);
1560 g_return_if_fail (GTK_IS_SHEET (sheet));
1562 if(GTK_WIDGET_REALIZED(sheet))
1563 gtk_sheet_real_unselect_range(sheet, NULL);
1565 sheet->selection_mode = mode;
1569 gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize)
1571 g_return_if_fail (sheet != NULL);
1572 g_return_if_fail (GTK_IS_SHEET (sheet));
1574 sheet->autoresize = autoresize;
1578 gtk_sheet_autoresize (GtkSheet *sheet)
1580 g_return_val_if_fail (sheet != NULL, FALSE);
1581 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1583 return sheet->autoresize;
1587 gtk_sheet_set_column_width (GtkSheet * sheet,
1593 gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
1595 gint text_width = 0;
1598 g_return_if_fail (sheet != NULL);
1599 g_return_if_fail (GTK_IS_SHEET (sheet));
1600 if (column >= xxx_column_count(sheet) || column < 0) return;
1602 for (row = 0; row < yyy_row_count(sheet); row++)
1604 gchar *text = gtk_sheet_cell_get_text(sheet, row, column);
1605 if (text && strlen(text) > 0){
1606 GtkSheetCellAttr attributes;
1608 gtk_sheet_get_attributes(sheet, row, column, &attributes);
1609 if(attributes.is_visible){
1610 gint width = STRING_WIDTH(GTK_WIDGET(sheet),
1611 attributes.font_desc,
1613 + 2*CELLOFFSET + attributes.border.width;
1614 text_width = MAX (text_width, width);
1617 dispose_string(sheet, text);
1620 if(text_width > xxx_column_width(sheet, column) )
1622 gtk_sheet_set_column_width(sheet, column, text_width);
1623 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
1629 gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll)
1631 g_return_if_fail (sheet != NULL);
1632 g_return_if_fail (GTK_IS_SHEET (sheet));
1634 sheet->autoscroll = autoscroll;
1638 gtk_sheet_autoscroll (GtkSheet *sheet)
1640 g_return_val_if_fail (sheet != NULL, FALSE);
1641 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1643 return sheet->autoscroll;
1647 gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text)
1649 g_return_if_fail (sheet != NULL);
1650 g_return_if_fail (GTK_IS_SHEET (sheet));
1652 sheet->clip_text = clip_text;
1656 gtk_sheet_clip_text (GtkSheet *sheet)
1658 g_return_val_if_fail (sheet != NULL, FALSE);
1659 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1661 return sheet->clip_text;
1665 gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify)
1667 g_return_if_fail (sheet != NULL);
1668 g_return_if_fail (GTK_IS_SHEET (sheet));
1670 sheet->justify_entry = justify;
1674 gtk_sheet_justify_entry (GtkSheet *sheet)
1676 g_return_val_if_fail (sheet != NULL, FALSE);
1677 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1679 return sheet->justify_entry;
1683 gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked)
1685 g_return_if_fail (sheet != NULL);
1686 g_return_if_fail (GTK_IS_SHEET (sheet));
1690 GTK_SHEET_SET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
1691 gtk_widget_hide(sheet->sheet_entry);
1692 gtk_widget_unmap(sheet->sheet_entry);
1696 GTK_SHEET_UNSET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
1697 if (GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)))
1699 gtk_widget_show (sheet->sheet_entry);
1700 gtk_widget_map (sheet->sheet_entry);
1704 gtk_entry_set_editable(GTK_ENTRY(sheet->sheet_entry), locked);
1709 gtk_sheet_locked (const GtkSheet *sheet)
1711 g_return_val_if_fail (sheet != NULL, FALSE);
1712 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1714 return GTK_SHEET_IS_LOCKED(sheet);
1717 /* This routine has problems with gtk+-1.2 related with the
1718 * label/button drawing - I think it's a bug in gtk+-1.2 */
1721 gtk_sheet_set_title(GtkSheet *sheet, const gchar *title)
1723 /* GtkWidget *old_widget;
1724 */ GtkWidget *label;
1726 g_return_if_fail (sheet != NULL);
1727 g_return_if_fail (title != NULL);
1728 g_return_if_fail (GTK_IS_SHEET (sheet));
1731 g_free (sheet->name);
1733 sheet->name = g_strdup (title);
1735 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) || !title) return;
1737 if(GTK_BIN(sheet->button)->child)
1738 label = GTK_BIN(sheet->button)->child;
1740 gtk_label_set_text(GTK_LABEL(label), title);
1742 size_allocate_global_button(sheet);
1744 /* remove and destroy the old widget */
1746 old_widget = GTK_BIN (sheet->button)->child;
1749 gtk_container_remove (GTK_CONTAINER (sheet->button), old_widget);
1752 label = gtk_label_new (title);
1753 gtk_misc_set_alignment(GTK_MISC(label), 0.5 , 0.5 );
1755 gtk_container_add (GTK_CONTAINER (sheet->button), label);
1756 gtk_widget_show (label);
1758 size_allocate_global_button(sheet);
1760 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, -1);
1763 gtk_widget_destroy (old_widget);
1768 gtk_sheet_freeze (GtkSheet *sheet)
1770 g_return_if_fail (sheet != NULL);
1771 g_return_if_fail (GTK_IS_SHEET (sheet));
1773 sheet->freeze_count++;
1774 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1778 gtk_sheet_thaw(GtkSheet *sheet)
1780 g_return_if_fail (sheet != NULL);
1781 g_return_if_fail (GTK_IS_SHEET (sheet));
1783 if(sheet->freeze_count == 0) return;
1785 sheet->freeze_count--;
1786 if(sheet->freeze_count > 0) return;
1788 adjust_scrollbars(sheet);
1790 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1792 sheet->old_vadjustment = -1.;
1793 sheet->old_hadjustment = -1.;
1795 if(sheet->hadjustment)
1796 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1798 if(sheet->vadjustment)
1799 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1802 if(sheet->state == GTK_STATE_NORMAL)
1803 if(sheet->sheet_entry && GTK_WIDGET_MAPPED(sheet->sheet_entry)){
1804 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
1806 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
1808 (GtkSignalFunc)gtk_sheet_entry_changed,
1809 GTK_OBJECT(GTK_WIDGET(sheet)));
1810 gtk_sheet_show_active_cell(sheet);
1817 gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width)
1819 if(width < COLUMN_MIN_WIDTH) return;
1821 sheet->row_title_area.width = width;
1822 sheet->view.col0 = COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
1823 sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
1826 adjust_scrollbars(sheet);
1828 sheet->old_hadjustment = -1.;
1829 if(sheet->hadjustment)
1830 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1832 size_allocate_global_button(sheet);
1836 gtk_sheet_set_column_titles_height(GtkSheet *sheet, guint height)
1838 if(height < DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))) return;
1840 sheet->column_title_area.height = height;
1841 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
1842 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
1844 adjust_scrollbars(sheet);
1846 sheet->old_vadjustment = -1.;
1847 if(sheet->vadjustment)
1848 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1850 size_allocate_global_button(sheet);
1854 gtk_sheet_show_column_titles(GtkSheet *sheet)
1858 if(sheet->column_titles_visible) return;
1860 sheet->column_titles_visible = TRUE;
1863 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1864 gdk_window_show(sheet->column_title_window);
1865 gdk_window_move_resize (sheet->column_title_window,
1866 sheet->column_title_area.x,
1867 sheet->column_title_area.y,
1868 sheet->column_title_area.width,
1869 sheet->column_title_area.height);
1871 for(col = MIN_VISIBLE_COLUMN(sheet);
1872 col <= MAX_VISIBLE_COLUMN(sheet);
1875 GtkSheetButton *button = xxx_column_button(sheet, col);
1876 GtkSheetChild *child = button->child;
1878 gtk_sheet_child_show(child);
1879 gtk_sheet_button_free(button);
1881 adjust_scrollbars(sheet);
1884 sheet->old_vadjustment = -1.;
1885 if(sheet->vadjustment)
1886 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1888 size_allocate_global_button(sheet);
1893 gtk_sheet_show_row_titles(GtkSheet *sheet)
1897 if(sheet->row_titles_visible) return;
1899 sheet->row_titles_visible = TRUE;
1902 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1903 gdk_window_show(sheet->row_title_window);
1904 gdk_window_move_resize (sheet->row_title_window,
1905 sheet->row_title_area.x,
1906 sheet->row_title_area.y,
1907 sheet->row_title_area.width,
1908 sheet->row_title_area.height);
1910 for(row = MIN_VISIBLE_ROW(sheet);
1911 row <= MAX_VISIBLE_ROW(sheet);
1914 const GtkSheetButton *button = yyy_row_button(sheet, row);
1915 GtkSheetChild *child = button->child;
1918 gtk_sheet_child_show(child);
1921 adjust_scrollbars(sheet);
1924 sheet->old_hadjustment = -1.;
1925 if(sheet->hadjustment)
1926 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1928 size_allocate_global_button(sheet);
1932 gtk_sheet_hide_column_titles(GtkSheet *sheet)
1936 if(!sheet->column_titles_visible) return;
1938 sheet->column_titles_visible = FALSE;
1940 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1941 if(sheet->column_title_window)
1942 gdk_window_hide(sheet->column_title_window);
1943 if(GTK_WIDGET_VISIBLE(sheet->button))
1944 gtk_widget_hide(sheet->button);
1946 for(col = MIN_VISIBLE_COLUMN(sheet);
1947 col <= MAX_VISIBLE_COLUMN(sheet);
1950 GtkSheetButton *button = xxx_column_button(sheet, col);
1951 GtkSheetChild *child = button->child;
1953 gtk_sheet_child_hide(child);
1954 gtk_sheet_button_free(button);
1956 adjust_scrollbars(sheet);
1959 sheet->old_vadjustment = -1.;
1960 if(sheet->vadjustment)
1961 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1966 gtk_sheet_hide_row_titles(GtkSheet *sheet)
1970 if(!sheet->row_titles_visible) return;
1972 sheet->row_titles_visible = FALSE;
1975 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1976 if(sheet->row_title_window)
1977 gdk_window_hide(sheet->row_title_window);
1978 if(GTK_WIDGET_VISIBLE(sheet->button))
1979 gtk_widget_hide(sheet->button);
1980 for(row = MIN_VISIBLE_ROW(sheet);
1981 row <= MAX_VISIBLE_ROW(sheet);
1984 const GtkSheetButton *button = yyy_row_button(sheet, row);
1985 GtkSheetChild *child = button->child;
1988 gtk_sheet_child_hide(child);
1990 adjust_scrollbars(sheet);
1993 sheet->old_hadjustment = -1.;
1994 if(sheet->hadjustment)
1995 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
2000 gtk_sheet_column_titles_visible(GtkSheet *sheet)
2002 g_return_val_if_fail (sheet != NULL, FALSE);
2003 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2004 return sheet->column_titles_visible;
2008 gtk_sheet_row_titles_visible(GtkSheet *sheet)
2010 g_return_val_if_fail (sheet != NULL, FALSE);
2011 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2012 return sheet->row_titles_visible;
2018 gtk_sheet_moveto (GtkSheet * sheet,
2025 guint width, height;
2027 gint min_row, min_col;
2029 g_return_if_fail (sheet != NULL);
2030 g_return_if_fail (GTK_IS_SHEET (sheet));
2031 g_return_if_fail (sheet->hadjustment != NULL);
2032 g_return_if_fail (sheet->vadjustment != NULL);
2034 if (row < 0 || row >= yyy_row_count(sheet))
2036 if (column < 0 || column >= xxx_column_count(sheet))
2039 height = sheet->sheet_window_height;
2040 width = sheet->sheet_window_width;
2042 /* adjust vertical scrollbar */
2044 if (row >= 0 && row_align >=0.)
2047 y = ROW_TOP_YPIXEL(sheet, row) - sheet->voffset -
2049 (1.-row_align)*yyy_row_height(sheet, row);
2051 y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
2052 - (gint) ( row_align*height + (1. - row_align) * yyy_row_height(sheet, row));
2054 /* This forces the sheet to scroll when you don't see the entire cell */
2057 if(row_align == 1.){
2058 while(min_row >= 0 && min_row > MIN_VISIBLE_ROW(sheet)){
2059 if(yyy_row_is_visible(sheet, min_row))
2060 adjust += yyy_row_height(sheet, min_row);
2061 if(adjust >= height){
2066 min_row = MAX(min_row, 0);
2067 y = ROW_TOP_YPIXEL(sheet, min_row) - sheet->voffset +
2068 yyy_row_height(sheet, min_row) - 1;
2072 sheet->vadjustment->value = 0.0;
2074 sheet->vadjustment->value = y;
2076 sheet->old_vadjustment = -1.;
2077 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
2082 /* adjust horizontal scrollbar */
2083 if (column >= 0 && col_align >= 0.)
2086 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset -
2088 (1.-col_align)*sheet->column[column].width;
2090 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
2091 - (gint) ( col_align*width + (1.-col_align)*
2092 xxx_column_width(sheet, column));
2095 /* This forces the sheet to scroll when you don't see the entire cell */
2098 if(col_align == 1.){
2099 while(min_col >= 0 && min_col > MIN_VISIBLE_COLUMN(sheet)){
2100 if(xxx_column_is_visible(sheet, min_col))
2101 adjust += xxx_column_width(sheet, min_col);
2103 if(adjust >= width){
2108 min_col = MAX(min_col, 0);
2109 x = COLUMN_LEFT_XPIXEL(sheet, min_col) - sheet->hoffset +
2110 xxx_column_width(sheet, min_col) - 1;
2114 sheet->hadjustment->value = 0.0;
2116 sheet->hadjustment->value = x;
2118 sheet->old_vadjustment = -1.;
2119 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
2127 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
2129 g_return_if_fail (sheet != NULL);
2130 g_return_if_fail (GTK_IS_SHEET (sheet));
2132 sheet->columns_resizable = resizable;
2136 gtk_sheet_columns_resizable (GtkSheet *sheet)
2138 g_return_val_if_fail (sheet != NULL, FALSE);
2139 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2141 return sheet->columns_resizable;
2146 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
2148 g_return_if_fail (sheet != NULL);
2149 g_return_if_fail (GTK_IS_SHEET (sheet));
2151 sheet->rows_resizable = resizable;
2155 gtk_sheet_rows_resizable (GtkSheet *sheet)
2157 g_return_val_if_fail (sheet != NULL, FALSE);
2158 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2160 return sheet->rows_resizable;
2165 gtk_sheet_select_row (GtkSheet * sheet,
2168 g_return_if_fail (sheet != NULL);
2169 g_return_if_fail (GTK_IS_SHEET (sheet));
2171 if (row < 0 || row >= yyy_row_count(sheet))
2174 if(sheet->state != GTK_SHEET_NORMAL)
2175 gtk_sheet_real_unselect_range(sheet, NULL);
2178 gboolean veto = TRUE;
2179 veto = gtk_sheet_deactivate_cell(sheet);
2183 sheet->state=GTK_SHEET_ROW_SELECTED;
2184 sheet->range.row0 = row;
2185 sheet->range.col0 = 0;
2186 sheet->range.rowi = row;
2187 sheet->range.coli = xxx_column_count(sheet) - 1;
2188 sheet->active_cell.row = row;
2189 sheet->active_cell.col = 0;
2191 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_ROW], row);
2192 gtk_sheet_real_select_range(sheet, NULL);
2197 gtk_sheet_select_column (GtkSheet * sheet, gint column)
2199 g_return_if_fail (sheet != NULL);
2200 g_return_if_fail (GTK_IS_SHEET (sheet));
2202 if (column < 0 || column >= xxx_column_count(sheet))
2205 if(sheet->state != GTK_SHEET_NORMAL)
2206 gtk_sheet_real_unselect_range(sheet, NULL);
2209 gboolean veto = TRUE;
2210 veto = gtk_sheet_deactivate_cell(sheet);
2214 sheet->state=GTK_SHEET_COLUMN_SELECTED;
2215 sheet->range.row0 = 0;
2216 sheet->range.col0 = column;
2217 sheet->range.rowi = yyy_row_count(sheet) - 1;
2218 sheet->range.coli = column;
2219 sheet->active_cell.row = 0;
2220 sheet->active_cell.col = column;
2222 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_COLUMN], column);
2223 gtk_sheet_real_select_range(sheet, NULL);
2227 gtk_sheet_clip_range (GtkSheet *sheet, const GtkSheetRange *range)
2230 g_return_if_fail (sheet != NULL);
2231 g_return_if_fail (GTK_IS_SHEET (sheet));
2233 if(GTK_SHEET_IN_CLIP(sheet)) return;
2235 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2238 sheet->clip_range = sheet->range;
2240 sheet->clip_range=*range;
2243 sheet->clip_timer=gtk_timeout_add(TIMEOUT_FLASH, gtk_sheet_flash, sheet);
2245 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CLIP_RANGE],
2246 &sheet->clip_range);
2251 gtk_sheet_unclip_range(GtkSheet *sheet)
2254 g_return_if_fail (sheet != NULL);
2255 g_return_if_fail (GTK_IS_SHEET (sheet));
2257 if(!GTK_SHEET_IN_CLIP(sheet)) return;
2259 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2260 gtk_timeout_remove(sheet->clip_timer);
2261 gtk_sheet_range_draw(sheet, &sheet->clip_range);
2263 if(gtk_sheet_range_isvisible(sheet, sheet->range))
2264 gtk_sheet_range_draw(sheet, &sheet->range);
2268 gtk_sheet_in_clip (GtkSheet *sheet)
2270 g_return_val_if_fail (sheet != NULL, FALSE);
2271 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2273 return GTK_SHEET_IN_CLIP(sheet);
2277 gtk_sheet_flash(gpointer data)
2280 gint x,y,width,height;
2281 GdkRectangle clip_area;
2283 sheet=GTK_SHEET(data);
2285 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return TRUE;
2286 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return TRUE;
2287 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return TRUE;
2288 if(GTK_SHEET_IN_XDRAG(sheet)) return TRUE;
2289 if(GTK_SHEET_IN_YDRAG(sheet)) return TRUE;
2291 GDK_THREADS_ENTER();
2293 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2294 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2295 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2296 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2297 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2298 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2300 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2301 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2302 clip_area.width=sheet->sheet_window_width;
2303 clip_area.height=sheet->sheet_window_height;
2309 if(width>clip_area.width) width=clip_area.width+10;
2314 if(height>clip_area.height) height=clip_area.height+10;
2316 gdk_draw_pixmap(sheet->sheet_window,
2317 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2323 gdk_draw_pixmap(sheet->sheet_window,
2324 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2330 gdk_draw_pixmap(sheet->sheet_window,
2331 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2337 gdk_draw_pixmap(sheet->sheet_window,
2338 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2345 sheet->interval=sheet->interval+1;
2346 if(sheet->interval==TIME_INTERVAL) sheet->interval=0;
2348 gdk_gc_set_dashes(sheet->xor_gc, sheet->interval, (gint8*)"\4\4", 2);
2349 gtk_sheet_draw_flashing_range(sheet,sheet->clip_range);
2350 gdk_gc_set_dashes(sheet->xor_gc, 0, (gint8*)"\4\4", 2);
2352 GDK_THREADS_LEAVE();
2359 gtk_sheet_draw_flashing_range(GtkSheet *sheet, GtkSheetRange range)
2361 GdkRectangle clip_area;
2362 gint x,y,width,height;
2364 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return;
2366 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2367 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2368 clip_area.width=sheet->sheet_window_width;
2369 clip_area.height=sheet->sheet_window_height;
2371 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
2373 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2374 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2375 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2376 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2377 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2378 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2384 if(width>clip_area.width) width=clip_area.width+10;
2389 if(height>clip_area.height) height=clip_area.height+10;
2391 gdk_gc_set_line_attributes(sheet->xor_gc, 1, 1, 0 ,0 );
2393 gdk_draw_rectangle(sheet->sheet_window, sheet->xor_gc, FALSE,
2397 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 0, 0, 0);
2399 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
2404 gtk_sheet_range_isvisible (GtkSheet * sheet,
2405 GtkSheetRange range)
2407 g_return_val_if_fail (sheet != NULL, FALSE);
2409 if (range.row0 < 0 || range.row0 >= yyy_row_count(sheet))
2412 if (range.rowi < 0 || range.rowi >= yyy_row_count(sheet))
2415 if (range.col0 < 0 || range.col0 >= xxx_column_count(sheet))
2418 if (range.coli < 0 || range.coli >= xxx_column_count(sheet))
2421 if (range.rowi < MIN_VISIBLE_ROW (sheet))
2424 if (range.row0 > MAX_VISIBLE_ROW (sheet))
2427 if (range.coli < MIN_VISIBLE_COLUMN (sheet))
2430 if (range.col0 > MAX_VISIBLE_COLUMN (sheet))
2437 gtk_sheet_cell_isvisible (GtkSheet * sheet,
2438 gint row, gint column)
2440 GtkSheetRange range;
2443 range.col0 = column;
2445 range.coli = column;
2447 return gtk_sheet_range_isvisible(sheet, range);
2451 gtk_sheet_get_visible_range(GtkSheet *sheet, GtkSheetRange *range)
2454 g_return_if_fail (sheet != NULL);
2455 g_return_if_fail (GTK_IS_SHEET (sheet)) ;
2456 g_return_if_fail (range != NULL);
2458 range->row0 = MIN_VISIBLE_ROW(sheet);
2459 range->col0 = MIN_VISIBLE_COLUMN(sheet);
2460 range->rowi = MAX_VISIBLE_ROW(sheet);
2461 range->coli = MAX_VISIBLE_COLUMN(sheet);
2466 gtk_sheet_get_vadjustment (GtkSheet * sheet)
2468 g_return_val_if_fail (sheet != NULL, NULL);
2469 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2471 return sheet->vadjustment;
2475 gtk_sheet_get_hadjustment (GtkSheet * sheet)
2477 g_return_val_if_fail (sheet != NULL, NULL);
2478 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2480 return sheet->hadjustment;
2484 gtk_sheet_set_vadjustment (GtkSheet *sheet,
2485 GtkAdjustment *adjustment)
2487 GtkAdjustment *old_adjustment;
2489 g_return_if_fail (sheet != NULL);
2490 g_return_if_fail (GTK_IS_SHEET (sheet));
2492 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2494 if (sheet->vadjustment == adjustment)
2497 old_adjustment = sheet->vadjustment;
2499 if (sheet->vadjustment)
2501 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2502 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2505 sheet->vadjustment = adjustment;
2507 if (sheet->vadjustment)
2509 gtk_object_ref (GTK_OBJECT (sheet->vadjustment));
2510 gtk_object_sink (GTK_OBJECT (sheet->vadjustment));
2512 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "changed",
2513 (GtkSignalFunc) vadjustment_changed,
2515 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "value_changed",
2516 (GtkSignalFunc) vadjustment_value_changed,
2520 if (!sheet->vadjustment || !old_adjustment)
2522 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2526 sheet->old_vadjustment = sheet->vadjustment->value;
2530 gtk_sheet_set_hadjustment (GtkSheet *sheet,
2531 GtkAdjustment *adjustment)
2533 GtkAdjustment *old_adjustment;
2535 g_return_if_fail (sheet != NULL);
2536 g_return_if_fail (GTK_IS_SHEET (sheet));
2538 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2540 if (sheet->hadjustment == adjustment)
2543 old_adjustment = sheet->hadjustment;
2545 if (sheet->hadjustment)
2547 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2548 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2551 sheet->hadjustment = adjustment;
2553 if (sheet->hadjustment)
2555 gtk_object_ref (GTK_OBJECT (sheet->hadjustment));
2556 gtk_object_sink (GTK_OBJECT (sheet->hadjustment));
2558 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "changed",
2559 (GtkSignalFunc) hadjustment_changed,
2561 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "value_changed",
2562 (GtkSignalFunc) hadjustment_value_changed,
2566 if (!sheet->hadjustment || !old_adjustment)
2568 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2572 sheet->old_hadjustment = sheet->hadjustment->value;
2576 gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
2577 GtkAdjustment *hadjustment,
2578 GtkAdjustment *vadjustment)
2580 if(sheet->hadjustment != hadjustment)
2581 gtk_sheet_set_hadjustment (sheet, hadjustment);
2583 if(sheet->vadjustment != vadjustment)
2584 gtk_sheet_set_vadjustment (sheet, vadjustment);
2588 gtk_sheet_finalize (GObject * object)
2592 g_return_if_fail (object != NULL);
2593 g_return_if_fail (GTK_IS_SHEET (object));
2595 sheet = GTK_SHEET (object);
2597 /* get rid of all the cells */
2598 gtk_sheet_range_clear (sheet, NULL);
2599 gtk_sheet_range_delete(sheet, NULL);
2602 g_free(sheet->name);
2606 if (G_OBJECT_CLASS (parent_class)->finalize)
2607 (*G_OBJECT_CLASS (parent_class)->finalize) (object);
2611 gtk_sheet_destroy (GtkObject * object)
2616 g_return_if_fail (object != NULL);
2617 g_return_if_fail (GTK_IS_SHEET (object));
2619 sheet = GTK_SHEET (object);
2621 /* destroy the entry */
2622 if(sheet->sheet_entry && GTK_IS_WIDGET(sheet->sheet_entry)){
2623 gtk_widget_destroy (sheet->sheet_entry);
2624 sheet->sheet_entry = NULL;
2627 /* destroy the global selection button */
2628 if(sheet->button && GTK_IS_WIDGET(sheet->button)){
2629 gtk_widget_destroy (sheet->button);
2630 sheet->button = NULL;
2634 gtk_timeout_remove(sheet->timer);
2638 if(sheet->clip_timer){
2639 gtk_timeout_remove(sheet->clip_timer);
2640 sheet->clip_timer = 0;
2643 /* unref adjustments */
2644 if (sheet->hadjustment)
2646 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2647 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2648 sheet->hadjustment = NULL;
2650 if (sheet->vadjustment)
2652 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2653 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2654 sheet->vadjustment = NULL;
2657 children = sheet->children;
2659 GtkSheetChild *child = (GtkSheetChild *)children->data;
2660 if(child && child->widget)
2661 gtk_sheet_remove(GTK_CONTAINER(sheet), child->widget);
2662 children = sheet->children;
2664 sheet->children = NULL;
2666 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2667 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2671 gtk_sheet_style_set (GtkWidget *widget,
2672 GtkStyle *previous_style)
2676 g_return_if_fail (widget != NULL);
2677 g_return_if_fail (GTK_IS_SHEET (widget));
2679 if (GTK_WIDGET_CLASS (parent_class)->style_set)
2680 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
2682 sheet = GTK_SHEET (widget);
2684 if(GTK_WIDGET_REALIZED(widget))
2686 gtk_style_set_background (widget->style, widget->window, widget->state);
2692 gtk_sheet_realize (GtkWidget * widget)
2695 GdkWindowAttr attributes;
2696 gint attributes_mask;
2697 GdkGCValues values, auxvalues;
2698 GdkColormap *colormap;
2700 GtkSheetChild *child;
2703 g_return_if_fail (widget != NULL);
2704 g_return_if_fail (GTK_IS_SHEET (widget));
2706 sheet = GTK_SHEET (widget);
2708 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2710 attributes.window_type = GDK_WINDOW_CHILD;
2711 attributes.x = widget->allocation.x;
2712 attributes.y = widget->allocation.y;
2713 attributes.width = widget->allocation.width;
2714 attributes.height = widget->allocation.height;
2715 attributes.wclass = GDK_INPUT_OUTPUT;
2717 attributes.visual = gtk_widget_get_visual (widget);
2718 attributes.colormap = gtk_widget_get_colormap (widget);
2720 attributes.event_mask = gtk_widget_get_events (widget);
2721 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2722 GDK_BUTTON_PRESS_MASK |
2723 GDK_BUTTON_RELEASE_MASK |
2724 GDK_KEY_PRESS_MASK |
2725 GDK_POINTER_MOTION_MASK |
2726 GDK_POINTER_MOTION_HINT_MASK);
2727 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
2730 attributes.cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
2733 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2735 gdk_window_set_user_data (widget->window, sheet);
2737 widget->style = gtk_style_attach (widget->style, widget->window);
2739 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2742 if(sheet->row_titles_visible)
2743 attributes.x = sheet->row_title_area.width;
2745 attributes.width = sheet->column_title_area.width;
2746 attributes.height = sheet->column_title_area.height;
2748 /* column-title window */
2749 sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2750 gdk_window_set_user_data (sheet->column_title_window, sheet);
2751 gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL);
2755 if(sheet->column_titles_visible)
2756 attributes.y = sheet->column_title_area.height;
2757 attributes.width = sheet->row_title_area.width;
2758 attributes.height = sheet->row_title_area.height;
2760 /* row-title window */
2761 sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2762 gdk_window_set_user_data (sheet->row_title_window, sheet);
2763 gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL);
2766 attributes.cursor = gdk_cursor_new(GDK_PLUS);
2770 attributes.width = sheet->sheet_window_width,
2771 attributes.height = sheet->sheet_window_height;
2773 sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2774 gdk_window_set_user_data (sheet->sheet_window, sheet);
2776 gdk_cursor_unref(attributes.cursor);
2778 gdk_window_set_background (sheet->sheet_window, &widget->style->white);
2779 gdk_window_show (sheet->sheet_window);
2781 /* backing_pixmap */
2782 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
2786 gdk_gc_unref(sheet->fg_gc);
2788 gdk_gc_unref(sheet->bg_gc);
2789 sheet->fg_gc = gdk_gc_new (widget->window);
2790 sheet->bg_gc = gdk_gc_new (widget->window);
2792 colormap = gtk_widget_get_colormap(widget);
2794 gdk_color_white(colormap, &widget->style->white);
2795 gdk_color_black(colormap, &widget->style->black);
2797 gdk_gc_get_values(sheet->fg_gc, &auxvalues);
2799 values.foreground = widget->style->white;
2800 values.function = GDK_INVERT;
2801 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2803 gdk_gc_unref(sheet->xor_gc);
2804 sheet->xor_gc = gdk_gc_new_with_values (widget->window,
2810 if(sheet->sheet_entry->parent){
2811 gtk_widget_ref(sheet->sheet_entry);
2812 gtk_widget_unparent(sheet->sheet_entry);
2814 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
2815 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
2817 if(sheet->button && sheet->button->parent){
2818 gtk_widget_ref(sheet->button);
2819 gtk_widget_unparent(sheet->button);
2821 gtk_widget_set_parent_window(sheet->button, sheet->sheet_window);
2822 gtk_widget_set_parent(sheet->button, GTK_WIDGET(sheet));
2825 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
2827 if(!sheet->cursor_drag)
2828 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
2830 if(sheet->column_titles_visible)
2831 gdk_window_show(sheet->column_title_window);
2832 if(sheet->row_titles_visible)
2833 gdk_window_show(sheet->row_title_window);
2835 size_allocate_row_title_buttons(sheet);
2836 size_allocate_column_title_buttons(sheet);
2838 name = g_strdup(sheet->name);
2839 gtk_sheet_set_title(sheet, name);
2843 children = sheet->children;
2846 child = children->data;
2847 children = children->next;
2849 gtk_sheet_realize_child(sheet, child);
2854 create_global_button(GtkSheet *sheet)
2856 sheet->button = gtk_button_new_with_label(" ");
2858 gtk_signal_connect (GTK_OBJECT (sheet->button),
2860 (GtkSignalFunc) global_button_clicked,
2865 size_allocate_global_button(GtkSheet *sheet)
2867 GtkAllocation allocation;
2869 if(!sheet->column_titles_visible) return;
2870 if(!sheet->row_titles_visible) return;
2872 gtk_widget_size_request(sheet->button, NULL);
2876 allocation.width=sheet->row_title_area.width;
2877 allocation.height=sheet->column_title_area.height;
2879 gtk_widget_size_allocate(sheet->button, &allocation);
2880 gtk_widget_show(sheet->button);
2884 global_button_clicked(GtkWidget *widget, gpointer data)
2888 gtk_sheet_click_cell(GTK_SHEET(data), -1, -1, &veto);
2889 gtk_widget_grab_focus(GTK_WIDGET(data));
2894 gtk_sheet_unrealize (GtkWidget * widget)
2898 g_return_if_fail (widget != NULL);
2899 g_return_if_fail (GTK_IS_SHEET (widget));
2901 sheet = GTK_SHEET (widget);
2903 gdk_cursor_destroy (sheet->cursor_drag);
2905 gdk_gc_destroy (sheet->xor_gc);
2906 gdk_gc_destroy (sheet->fg_gc);
2907 gdk_gc_destroy (sheet->bg_gc);
2909 gdk_window_destroy (sheet->sheet_window);
2910 gdk_window_destroy (sheet->column_title_window);
2911 gdk_window_destroy (sheet->row_title_window);
2914 g_object_unref(sheet->pixmap);
2915 sheet->pixmap = NULL;
2918 sheet->column_title_window=NULL;
2919 sheet->sheet_window = NULL;
2920 sheet->cursor_drag = NULL;
2921 sheet->xor_gc = NULL;
2922 sheet->fg_gc = NULL;
2923 sheet->bg_gc = NULL;
2925 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2926 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2930 gtk_sheet_map (GtkWidget * widget)
2933 GtkSheetChild *child;
2936 g_return_if_fail (widget != NULL);
2937 g_return_if_fail (GTK_IS_SHEET (widget));
2939 sheet = GTK_SHEET (widget);
2941 if (!GTK_WIDGET_MAPPED (widget))
2943 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2945 if(!sheet->cursor_drag) sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
2947 gdk_window_show (widget->window);
2949 gdk_window_show (sheet->sheet_window);
2951 if(sheet->column_titles_visible){
2952 size_allocate_column_title_buttons(sheet);
2953 gdk_window_show (sheet->column_title_window);
2955 if(sheet->row_titles_visible){
2956 size_allocate_row_title_buttons(sheet);
2957 gdk_window_show (sheet->row_title_window);
2960 if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)
2961 && ! gtk_sheet_locked(sheet)
2962 && sheet->active_cell.row >=0
2963 && sheet->active_cell.col >=0 )
2965 gtk_widget_show (sheet->sheet_entry);
2966 gtk_widget_map (sheet->sheet_entry);
2969 if (GTK_WIDGET_VISIBLE (sheet->button) &&
2970 !GTK_WIDGET_MAPPED (sheet->button)){
2971 gtk_widget_show(sheet->button);
2972 gtk_widget_map (sheet->button);
2975 if(GTK_BIN(sheet->button)->child)
2976 if (GTK_WIDGET_VISIBLE (GTK_BIN(sheet->button)->child) &&
2977 !GTK_WIDGET_MAPPED (GTK_BIN(sheet->button)->child))
2978 gtk_widget_map (GTK_BIN(sheet->button)->child);
2980 gtk_sheet_range_draw(sheet, NULL);
2981 gtk_sheet_activate_cell(sheet,
2982 sheet->active_cell.row,
2983 sheet->active_cell.col);
2985 children = sheet->children;
2988 child = children->data;
2989 children = children->next;
2991 if (GTK_WIDGET_VISIBLE (child->widget) &&
2992 !GTK_WIDGET_MAPPED (child->widget)){
2993 gtk_widget_map (child->widget);
2994 gtk_sheet_position_child(sheet, child);
3002 gtk_sheet_unmap (GtkWidget * widget)
3005 GtkSheetChild *child;
3008 g_return_if_fail (widget != NULL);
3009 g_return_if_fail (GTK_IS_SHEET (widget));
3011 sheet = GTK_SHEET (widget);
3013 if (GTK_WIDGET_MAPPED (widget))
3015 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3017 gdk_window_hide (sheet->sheet_window);
3018 if(sheet->column_titles_visible)
3019 gdk_window_hide (sheet->column_title_window);
3020 if(sheet->row_titles_visible)
3021 gdk_window_hide (sheet->row_title_window);
3022 gdk_window_hide (widget->window);
3024 if (GTK_WIDGET_MAPPED (sheet->sheet_entry))
3025 gtk_widget_unmap (sheet->sheet_entry);
3027 if (GTK_WIDGET_MAPPED (sheet->button))
3028 gtk_widget_unmap (sheet->button);
3030 children = sheet->children;
3033 child = children->data;
3034 children = children->next;
3036 if (GTK_WIDGET_VISIBLE (child->widget) &&
3037 GTK_WIDGET_MAPPED (child->widget))
3039 gtk_widget_unmap (child->widget);
3048 gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
3051 GdkGC *fg_gc, *bg_gc;
3052 GtkSheetCellAttr attributes;
3055 g_return_if_fail (sheet != NULL);
3057 /* bail now if we arn't drawable yet */
3058 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
3060 if (row < 0 || row >= yyy_row_count(sheet)) return;
3061 if (col < 0 || col >= xxx_column_count(sheet)) return;
3062 if (! xxx_column_is_visible(sheet, col)) return;
3063 if (! yyy_row_is_visible(sheet, row)) return;
3065 widget = GTK_WIDGET (sheet);
3067 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3069 /* select GC for background rectangle */
3070 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3071 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3073 fg_gc = sheet->fg_gc;
3074 bg_gc = sheet->bg_gc;
3076 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3077 area.y=ROW_TOP_YPIXEL(sheet,row);
3078 area.width= xxx_column_width(sheet, col);
3079 area.height=yyy_row_height(sheet, row);
3081 gdk_draw_rectangle (sheet->pixmap,
3089 gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0);
3091 if(sheet->show_grid){
3092 gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color);
3094 gdk_draw_rectangle (sheet->pixmap,
3098 area.width, area.height);
3103 gtk_sheet_cell_draw_border (GtkSheet *sheet, gint row, gint col, gint mask)
3106 GdkGC *fg_gc, *bg_gc;
3107 GtkSheetCellAttr attributes;
3111 g_return_if_fail (sheet != NULL);
3113 /* bail now if we arn't drawable yet */
3114 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
3116 if (row < 0 || row >= yyy_row_count(sheet)) return;
3117 if (col < 0 || col >= xxx_column_count(sheet)) return;
3118 if (!xxx_column_is_visible(sheet, col)) return;
3119 if (!yyy_row_is_visible(sheet, row)) return;
3121 widget = GTK_WIDGET (sheet);
3123 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3125 /* select GC for background rectangle */
3126 gdk_gc_set_foreground (sheet->fg_gc, &attributes.border.color);
3127 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3129 fg_gc = sheet->fg_gc;
3130 bg_gc = sheet->bg_gc;
3132 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3133 area.y=ROW_TOP_YPIXEL(sheet,row);
3134 area.width=xxx_column_width(sheet, col);
3135 area.height=yyy_row_height(sheet, row);
3137 width = attributes.border.width;
3138 gdk_gc_set_line_attributes(sheet->fg_gc, attributes.border.width,
3139 attributes.border.line_style,
3140 attributes.border.cap_style,
3141 attributes.border.join_style);
3144 if(attributes.border.mask & GTK_SHEET_LEFT_BORDER & mask)
3145 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3146 area.x, area.y-width/2,
3147 area.x, area.y+area.height+width/2+1);
3149 if(attributes.border.mask & GTK_SHEET_RIGHT_BORDER & mask)
3150 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3151 area.x+area.width, area.y-width/2,
3153 area.y+area.height+width/2+1);
3155 if(attributes.border.mask & GTK_SHEET_TOP_BORDER & mask)
3156 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3157 area.x-width/2,area.y,
3158 area.x+area.width+width/2+1,
3161 if(attributes.border.mask & GTK_SHEET_BOTTOM_BORDER & mask)
3162 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3163 area.x-width/2, area.y+area.height,
3164 area.x+area.width+width/2+1,
3165 area.y+area.height);
3172 gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
3175 GdkRectangle area, clip_area;
3177 gint text_width, text_height, y;
3179 gint size, sizel, sizer;
3180 GdkGC *fg_gc, *bg_gc;
3181 GtkSheetCellAttr attributes;
3182 PangoLayout *layout;
3183 PangoRectangle rect;
3184 PangoRectangle logical_rect;
3185 PangoLayoutLine *line;
3186 PangoFontMetrics *metrics;
3187 PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet));
3188 gint ascent, descent, y_pos;
3192 g_return_if_fail (sheet != NULL);
3194 /* bail now if we aren't drawable yet */
3195 if (!GTK_WIDGET_DRAWABLE (sheet))
3198 label = gtk_sheet_cell_get_text(sheet, row, col);
3202 if (row < 0 || row >= yyy_row_count(sheet)) return;
3203 if (col < 0 || col >= xxx_column_count(sheet)) return;
3204 if (! xxx_column_is_visible(sheet, col)) return;
3205 if (!yyy_row_is_visible(sheet, row)) return;
3208 widget = GTK_WIDGET(sheet);
3210 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3212 /* select GC for background rectangle */
3213 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3214 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3216 fg_gc = sheet->fg_gc;
3217 bg_gc = sheet->bg_gc;
3219 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3220 area.y=ROW_TOP_YPIXEL(sheet,row);
3221 area.width = xxx_column_width(sheet, col);
3222 area.height = yyy_row_height(sheet, row);
3226 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label);
3227 dispose_string(sheet, label);
3228 pango_layout_set_font_description (layout, attributes.font_desc);
3230 pango_layout_get_pixel_extents (layout, NULL, &rect);
3232 line = pango_layout_get_lines (layout)->data;
3233 pango_layout_line_get_extents (line, NULL, &logical_rect);
3235 metrics = pango_context_get_metrics(context,
3236 attributes.font_desc,
3237 pango_context_get_language(context));
3239 ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
3240 descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
3242 pango_font_metrics_unref(metrics);
3244 /* Align primarily for locale's ascent/descent */
3246 logical_rect.height /= PANGO_SCALE;
3247 logical_rect.y /= PANGO_SCALE;
3248 y_pos = area.height - logical_rect.height;
3250 if (logical_rect.height > area.height)
3251 y_pos = (logical_rect.height - area.height - 2*CELLOFFSET) / 2;
3254 else if (y_pos + logical_rect.height > area.height)
3255 y_pos = area.height - logical_rect.height;
3257 text_width = rect.width;
3258 text_height = rect.height;
3259 y = area.y + y_pos - CELLOFFSET;
3261 switch(attributes.justification){
3262 case GTK_JUSTIFY_RIGHT:
3265 if(!gtk_sheet_clip_text(sheet)){
3266 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3267 if( !gtk_sheet_cell_empty(sheet, row, i)) break;
3268 if(size>=text_width+CELLOFFSET) break;
3269 size+=xxx_column_width(sheet, i);
3270 xxx_column_set_right_column(sheet, i,
3272 xxx_column_right_column(sheet, i)));
3277 xoffset+=area.width-text_width - 2 * CELLOFFSET -
3278 attributes.border.width/2;
3280 case GTK_JUSTIFY_CENTER:
3283 area.x+=area.width/2;
3284 if(!gtk_sheet_clip_text(sheet)){
3285 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3286 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3287 if(sizer>=text_width/2) break;
3288 sizer+= xxx_column_width(sheet, i);
3289 xxx_column_set_left_column(sheet, i,
3292 xxx_column_left_column(sheet, i)));
3294 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3295 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3296 if(sizel>=text_width/2) break;
3297 sizel+=xxx_column_width(sheet, i);
3298 xxx_column_set_right_column(sheet, i,
3300 xxx_column_right_column(sheet, i)));
3302 size=MIN(sizel, sizer);
3305 xoffset+= sizel - text_width/2 - CELLOFFSET;
3306 area.width=sizel+sizer;
3308 case GTK_JUSTIFY_LEFT:
3311 if(!gtk_sheet_clip_text(sheet)){
3312 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3313 if(! gtk_sheet_cell_empty(sheet, row, i)) break;
3314 if(size>=text_width+CELLOFFSET) break;
3315 size+=xxx_column_width(sheet, i);
3316 xxx_column_set_left_column(sheet, i,
3319 xxx_column_left_column(sheet, i)));
3324 xoffset += attributes.border.width/2;
3328 if(!gtk_sheet_clip_text(sheet)) clip_area = area;
3329 gdk_gc_set_clip_rectangle(fg_gc, &clip_area);
3332 gdk_draw_layout (sheet->pixmap, fg_gc,
3333 area.x + xoffset + CELLOFFSET,
3337 gdk_gc_set_clip_rectangle(fg_gc, NULL);
3338 g_object_unref(G_OBJECT(layout));
3340 gdk_draw_pixmap(sheet->sheet_window,
3341 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3355 gtk_sheet_range_draw(GtkSheet *sheet, const GtkSheetRange *range)
3358 GtkSheetRange drawing_range;
3361 g_return_if_fail(sheet != NULL);
3362 g_return_if_fail(GTK_SHEET(sheet));
3364 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
3365 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3366 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
3370 drawing_range.row0=MIN_VISIBLE_ROW(sheet);
3371 drawing_range.col0=MIN_VISIBLE_COLUMN(sheet);
3372 drawing_range.rowi=MIN(MAX_VISIBLE_ROW(sheet), yyy_row_count(sheet) - 1);
3373 drawing_range.coli=MAX_VISIBLE_COLUMN(sheet);
3376 gdk_draw_rectangle (sheet->pixmap,
3377 GTK_WIDGET(sheet)->style->white_gc,
3380 sheet->sheet_window_width,sheet->sheet_window_height);
3385 drawing_range.row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
3386 drawing_range.col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
3387 drawing_range.rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
3388 drawing_range.coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
3392 if(drawing_range.coli == xxx_column_count(sheet) - 1)
3394 area.x=COLUMN_LEFT_XPIXEL(sheet,
3395 xxx_column_count(sheet) - 1) +
3396 xxx_column_width(sheet, xxx_column_count(sheet) - 1) + 1;
3400 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3402 gdk_draw_rectangle (sheet->pixmap,
3406 sheet->sheet_window_width - area.x,
3407 sheet->sheet_window_height);
3409 gdk_draw_pixmap(sheet->sheet_window,
3410 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3416 sheet->sheet_window_width - area.x,
3417 sheet->sheet_window_height);
3420 if(drawing_range.rowi == yyy_row_count(sheet) - 1){
3422 area.y=ROW_TOP_YPIXEL(sheet,
3423 yyy_row_count(sheet) - 1) +
3424 yyy_row_height(sheet, yyy_row_count(sheet) - 1) + 1;
3426 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3428 gdk_draw_rectangle (sheet->pixmap,
3432 sheet->sheet_window_width,
3433 sheet->sheet_window_height - area.y);
3435 gdk_draw_pixmap(sheet->sheet_window,
3436 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3442 sheet->sheet_window_width,
3443 sheet->sheet_window_height - area.y);
3446 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3447 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3448 gtk_sheet_cell_draw_default(sheet, i, j);
3451 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3452 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3453 gtk_sheet_cell_draw_border(sheet, i-1, j, GTK_SHEET_BOTTOM_BORDER);
3454 gtk_sheet_cell_draw_border(sheet, i+1, j, GTK_SHEET_TOP_BORDER);
3455 gtk_sheet_cell_draw_border(sheet, i, j-1, GTK_SHEET_RIGHT_BORDER);
3456 gtk_sheet_cell_draw_border(sheet, i, j+1, GTK_SHEET_LEFT_BORDER);
3457 gtk_sheet_cell_draw_border(sheet, i, j, 15);
3460 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3461 for(j=drawing_range.col0; j<=drawing_range.coli; j++)
3462 gtk_sheet_cell_draw_label (sheet, i, j);
3464 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3465 for(j= xxx_column_left_column(sheet, drawing_range.col0);
3466 j<drawing_range.col0; j++)
3467 gtk_sheet_cell_draw_label (sheet, i, j);
3469 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3470 for(j = drawing_range.coli+1;
3471 j <= xxx_column_right_column(sheet, drawing_range.coli);
3473 gtk_sheet_cell_draw_label (sheet, i, j);
3475 gtk_sheet_draw_backing_pixmap(sheet, drawing_range);
3477 if(sheet->state != GTK_SHEET_NORMAL &&
3478 gtk_sheet_range_isvisible(sheet, sheet->range))
3479 gtk_sheet_range_draw_selection(sheet, drawing_range);
3481 if(sheet->state == GTK_STATE_NORMAL &&
3482 sheet->active_cell.row >= drawing_range.row0 &&
3483 sheet->active_cell.row <= drawing_range.rowi &&
3484 sheet->active_cell.col >= drawing_range.col0 &&
3485 sheet->active_cell.col <= drawing_range.coli)
3486 gtk_sheet_show_active_cell(sheet);
3491 gtk_sheet_range_draw_selection(GtkSheet *sheet, GtkSheetRange range)
3497 if(range.col0 > sheet->range.coli || range.coli < sheet->range.col0 ||
3498 range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0)
3501 if(!gtk_sheet_range_isvisible(sheet, range)) return;
3502 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3506 range.col0=MAX(sheet->range.col0, range.col0);
3507 range.coli=MIN(sheet->range.coli, range.coli);
3508 range.row0=MAX(sheet->range.row0, range.row0);
3509 range.rowi=MIN(sheet->range.rowi, range.rowi);
3511 range.col0=MAX(range.col0, MIN_VISIBLE_COLUMN(sheet));
3512 range.coli=MIN(range.coli, MAX_VISIBLE_COLUMN(sheet));
3513 range.row0=MAX(range.row0, MIN_VISIBLE_ROW(sheet));
3514 range.rowi=MIN(range.rowi, MAX_VISIBLE_ROW(sheet));
3516 for(i=range.row0; i<=range.rowi; i++){
3517 for(j=range.col0; j<=range.coli; j++){
3519 if(gtk_sheet_cell_get_state(sheet, i, j)==GTK_STATE_SELECTED &&
3520 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
3523 row_button_set(sheet, i);
3524 column_button_set(sheet, j);
3527 area.x=COLUMN_LEFT_XPIXEL(sheet,j);
3528 area.y=ROW_TOP_YPIXEL(sheet,i);
3529 area.width= xxx_column_width(sheet, j);
3530 area.height=yyy_row_height(sheet, i);
3532 if(i==sheet->range.row0)
3535 area.height=area.height-2;
3537 if(i==sheet->range.rowi) area.height=area.height-3;
3538 if(j==sheet->range.col0)
3541 area.width=area.width-2;
3543 if(j==sheet->range.coli) area.width=area.width-3;
3545 if(i!=sheet->active_cell.row || j!=sheet->active_cell.col)
3547 gdk_draw_rectangle (sheet->sheet_window,
3551 area.width,area.height);
3558 gtk_sheet_draw_border(sheet, sheet->range);
3562 gtk_sheet_draw_backing_pixmap(GtkSheet *sheet, GtkSheetRange range)
3564 gint x,y,width,height;
3566 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3568 x = COLUMN_LEFT_XPIXEL(sheet,range.col0);
3569 y = ROW_TOP_YPIXEL(sheet, range.row0);
3570 width = COLUMN_LEFT_XPIXEL(sheet, range.coli) - x +
3571 xxx_column_width(sheet, range.coli);
3573 height=ROW_TOP_YPIXEL(sheet, range.rowi)-y+yyy_row_height(sheet, range.rowi);
3575 if(range.row0 == sheet->range.row0)
3580 if(range.rowi==sheet->range.rowi) height = height + 5;
3581 if(range.col0==sheet->range.col0)
3586 if(range.coli == sheet->range.coli) width = width + 5;
3588 width = MIN(width, sheet->sheet_window_width - x);
3589 height = MIN(height, sheet->sheet_window_height - y);
3596 x = (sheet->row_titles_visible)
3597 ? MAX(x, sheet->row_title_area.width) : MAX(x, 0);
3598 y = (sheet->column_titles_visible)
3599 ? MAX(y, sheet->column_title_area.height) : MAX(y, 0);
3601 if(range.coli == xxx_column_count(sheet) - 1)
3602 width = sheet->sheet_window_width - x;
3603 if(range.rowi == yyy_row_count(sheet) - 1)
3604 height=sheet->sheet_window_height - y;
3606 gdk_draw_pixmap(sheet->sheet_window,
3607 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3619 gtk_sheet_set_cell_text(GtkSheet *sheet, gint row, gint col, const gchar *text)
3621 GtkSheetCellAttr attributes;
3623 g_return_if_fail (sheet != NULL);
3624 g_return_if_fail (GTK_IS_SHEET (sheet));
3625 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3626 if (col < 0 || row < 0) return;
3628 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3629 gtk_sheet_set_cell(sheet, row, col, attributes.justification, text);
3633 safe_strcmp(const gchar *s1, const gchar *s2)
3635 if ( !s1 && !s2) return 0;
3636 if ( !s1) return -1;
3637 if ( !s2) return +1;
3638 return strcmp(s1, s2);
3642 gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col,
3643 GtkJustification justification,
3646 GSheetModel *model ;
3650 GtkSheetRange range;
3652 GtkSheetCellAttr attributes;
3654 g_return_if_fail (sheet != NULL);
3655 g_return_if_fail (GTK_IS_SHEET (sheet));
3656 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3657 if (col < 0 || row < 0) return;
3659 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3661 attributes.justification = justification;
3663 model = gtk_sheet_get_model(sheet);
3665 old_text = g_sheet_model_get_string(model, row, col);
3669 if (0 != safe_strcmp(old_text, text))
3670 changed = g_sheet_model_set_string(model, text, row, col);
3672 if ( g_sheet_model_free_strings(model))
3676 if(changed && attributes.is_visible)
3678 gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
3680 if(s && strlen(s) > 0) {
3681 text_width = STRING_WIDTH(GTK_WIDGET(sheet),
3682 attributes.font_desc, text);
3684 dispose_string(sheet, s);
3688 range.col0 = sheet->view.col0;
3689 range.coli = sheet->view.coli;
3691 if(gtk_sheet_autoresize(sheet) &&
3692 text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
3693 gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width);
3694 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3697 if(!GTK_SHEET_IS_FROZEN(sheet))
3698 gtk_sheet_range_draw(sheet, &range);
3702 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
3708 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
3710 GtkSheetRange range;
3712 g_return_if_fail (sheet != NULL);
3713 g_return_if_fail (GTK_IS_SHEET (sheet));
3714 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3715 if (column < 0 || row < 0) return;
3719 range.col0 = sheet->view.col0;
3720 range.coli = sheet->view.coli;
3722 gtk_sheet_real_cell_clear(sheet, row, column, FALSE);
3724 if(!GTK_SHEET_IS_FROZEN(sheet)){
3725 gtk_sheet_range_draw(sheet, &range);
3730 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
3732 GtkSheetRange range;
3734 g_return_if_fail (sheet != NULL);
3735 g_return_if_fail (GTK_IS_SHEET (sheet));
3736 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3737 if (column < 0 || row < 0) return;
3741 range.col0 = sheet->view.col0;
3742 range.coli = sheet->view.coli;
3744 gtk_sheet_real_cell_clear(sheet, row, column, TRUE);
3746 if(!GTK_SHEET_IS_FROZEN(sheet)){
3747 gtk_sheet_range_draw(sheet, &range);
3752 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
3754 GSheetModel *model = gtk_sheet_get_model(sheet);
3756 gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column);
3758 if (old_text && strlen(old_text) > 0 )
3760 g_sheet_model_datum_clear(model, row, column);
3762 if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0)
3763 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL],
3767 dispose_string (sheet, old_text);
3771 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
3773 g_return_if_fail (sheet != NULL);
3774 g_return_if_fail (GTK_IS_SHEET (sheet));
3776 gtk_sheet_real_range_clear(sheet, range, FALSE);
3780 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range)
3782 g_return_if_fail (sheet != NULL);
3783 g_return_if_fail (GTK_IS_SHEET (sheet));
3785 gtk_sheet_real_range_clear(sheet, range, TRUE);
3790 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
3794 GtkSheetRange clear;
3798 clear.rowi = yyy_row_count(sheet) - 1;
3800 clear.coli = xxx_column_count(sheet) - 1;
3804 clear.row0=MAX(clear.row0, 0);
3805 clear.col0=MAX(clear.col0, 0);
3806 clear.rowi=MIN(clear.rowi, yyy_row_count(sheet) - 1 );
3807 clear.coli=MIN(clear.coli, xxx_column_count(sheet) - 1 );
3809 for(i=clear.row0; i<=clear.rowi; i++)
3810 for(j=clear.col0; j<=clear.coli; j++){
3811 gtk_sheet_real_cell_clear(sheet, i, j, delete);
3814 gtk_sheet_range_draw(sheet, NULL);
3819 gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col)
3822 char *text = gtk_sheet_cell_get_text(sheet, row, col);
3823 empty = (text == NULL );
3825 dispose_string(sheet, text);
3832 gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
3835 g_return_val_if_fail (sheet != NULL, NULL);
3836 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
3838 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet))
3840 if(col < 0 || row < 0) return NULL;
3842 model = gtk_sheet_get_model(sheet);
3847 return g_sheet_model_get_string(model, row, col);
3852 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
3855 GtkSheetRange *range;
3857 g_return_val_if_fail (sheet != NULL, 0);
3858 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3859 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return 0;
3860 if(col < 0 || row < 0) return 0;
3862 state = sheet->state;
3863 range = &sheet->range;
3867 case GTK_SHEET_NORMAL:
3868 return GTK_STATE_NORMAL;
3870 case GTK_SHEET_ROW_SELECTED:
3871 if(row>=range->row0 && row<=range->rowi)
3872 return GTK_STATE_SELECTED;
3874 case GTK_SHEET_COLUMN_SELECTED:
3875 if(col>=range->col0 && col<=range->coli)
3876 return GTK_STATE_SELECTED;
3878 case GTK_SHEET_RANGE_SELECTED:
3879 if(row >= range->row0 && row <= range->rowi && \
3880 col >= range->col0 && col <= range->coli)
3881 return GTK_STATE_SELECTED;
3884 return GTK_STATE_NORMAL;
3888 gtk_sheet_get_pixel_info (GtkSheet * sheet,
3896 g_return_val_if_fail (sheet != NULL, 0);
3897 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3899 /* bounds checking, return false if the user clicked
3900 * on a blank area */
3901 trow = ROW_FROM_YPIXEL (sheet, y);
3902 if (trow >= yyy_row_count(sheet))
3907 tcol = COLUMN_FROM_XPIXEL (sheet, x);
3908 if (tcol >= xxx_column_count(sheet))
3917 gtk_sheet_get_cell_area (GtkSheet * sheet,
3922 g_return_val_if_fail (sheet != NULL, 0);
3923 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3925 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3928 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) -
3929 (sheet->row_titles_visible
3930 ? sheet->row_title_area.width
3932 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL(sheet, row) -
3933 (sheet->column_titles_visible
3934 ? sheet->column_title_area.height
3936 area->width= (column == -1) ? sheet->row_title_area.width
3937 : xxx_column_width(sheet, column);
3939 area->height= (row == -1) ? sheet->column_title_area.height
3940 : yyy_row_height(sheet, row);
3943 if(row < 0 || column < 0) return FALSE;
3945 area->x = COLUMN_LEFT_XPIXEL(sheet, column);
3946 area->y = ROW_TOP_YPIXEL(sheet, row);
3947 if(sheet->row_titles_visible)
3948 area->x -= sheet->row_title_area.width;
3949 if(sheet->column_titles_visible)
3950 area->y -= sheet->column_title_area.height;
3952 area->width=sheet->column[column].width;
3953 area->height=yyy_row_height(sheet, row);
3959 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
3961 g_return_val_if_fail (sheet != NULL, 0);
3962 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3964 if(row < -1 || column < -1) return FALSE;
3965 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3968 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
3970 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
3973 sheet->active_cell.row = row;
3974 sheet->active_cell.col = column;
3976 if ( row == -1 || column == -1)
3978 gtk_sheet_hide_active_cell(sheet);
3982 if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE;
3984 if(gtk_sheet_autoscroll(sheet))
3985 gtk_sheet_move_query(sheet, row, column);
3991 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column)
3993 g_return_if_fail (sheet != NULL);
3994 g_return_if_fail (GTK_IS_SHEET (sheet));
3996 *row = sheet->active_cell.row;
3997 *column = sheet->active_cell.col;
4001 gtk_sheet_entry_changed(GtkWidget *widget, gpointer data)
4006 GtkJustification justification;
4007 GtkSheetCellAttr attributes;
4009 g_return_if_fail (data != NULL);
4010 g_return_if_fail (GTK_IS_SHEET (data));
4012 sheet=GTK_SHEET(data);
4014 if(!GTK_WIDGET_VISIBLE(widget)) return;
4015 if(sheet->state != GTK_STATE_NORMAL) return;
4017 row=sheet->active_cell.row;
4018 col=sheet->active_cell.col;
4020 if(row<0 || col<0) return;
4022 sheet->active_cell.row=-1;
4023 sheet->active_cell.col=-1;
4025 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
4027 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
4029 if(text && strlen(text) > 0)
4031 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4032 justification = attributes.justification;
4033 gtk_sheet_set_cell(sheet, row, col, justification, text);
4036 if(sheet->freeze_count == 0)
4037 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
4039 sheet->active_cell.row=row;;
4040 sheet->active_cell.col=col;
4045 gtk_sheet_deactivate_cell(GtkSheet *sheet)
4047 gboolean veto = TRUE;
4049 g_return_val_if_fail (sheet != NULL, FALSE);
4050 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
4052 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return FALSE;
4053 if(sheet->state != GTK_SHEET_NORMAL) return FALSE;
4055 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[DEACTIVATE],
4056 sheet->active_cell.row,
4057 sheet->active_cell.col, &veto);
4059 if(!veto) return FALSE;
4061 if ( sheet->active_cell.row == -1 || sheet->active_cell.col == -1 )
4064 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
4065 (GtkSignalFunc) gtk_sheet_entry_changed,
4066 GTK_OBJECT(GTK_WIDGET(sheet)));
4068 gtk_sheet_hide_active_cell(sheet);
4069 sheet->active_cell.row = -1;
4070 sheet->active_cell.col = -1;
4072 if(GTK_SHEET_REDRAW_PENDING(sheet)){
4073 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
4074 gtk_sheet_range_draw(sheet, NULL);
4081 gtk_sheet_hide_active_cell(GtkSheet *sheet)
4085 GtkJustification justification;
4086 GtkSheetCellAttr attributes;
4088 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4090 row=sheet->active_cell.row;
4091 col=sheet->active_cell.col;
4093 if(row < 0 || col < 0) return;
4095 if(sheet->freeze_count == 0)
4096 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
4098 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
4100 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4101 justification=attributes.justification;
4103 if(text && strlen(text) != 0)
4105 gtk_sheet_set_cell(sheet, row, col, justification, text);
4106 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col);
4110 gtk_sheet_cell_clear(sheet, row, col);
4113 row=sheet->active_cell.row;
4114 col=sheet->active_cell.col;
4117 column_button_release(sheet, col);
4118 row_button_release(sheet, row);
4121 gtk_widget_hide(sheet->sheet_entry);
4122 gtk_widget_unmap(sheet->sheet_entry);
4124 if(row != -1 && col != -1)
4125 gdk_draw_pixmap(sheet->sheet_window,
4126 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4128 COLUMN_LEFT_XPIXEL(sheet,col)-1,
4129 ROW_TOP_YPIXEL(sheet,row)-1,
4130 COLUMN_LEFT_XPIXEL(sheet,col)-1,
4131 ROW_TOP_YPIXEL(sheet,row)-1,
4132 xxx_column_width(sheet, col) + 4,
4133 yyy_row_height(sheet, row)+4);
4135 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4137 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4142 gtk_sheet_activate_cell(GtkSheet *sheet, gint row, gint col)
4144 gboolean veto = TRUE;
4146 g_return_val_if_fail (sheet != NULL, FALSE);
4147 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
4149 if(row < 0 || col < 0) return FALSE;
4150 if(row >= yyy_row_count(sheet) || col >= xxx_column_count(sheet))
4153 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4154 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
4157 if(!veto) return FALSE;
4158 if(sheet->state != GTK_SHEET_NORMAL){
4159 sheet->state=GTK_SHEET_NORMAL;
4160 gtk_sheet_real_unselect_range(sheet, NULL);
4163 sheet->range.row0 = row;
4164 sheet->range.col0 = col;
4165 sheet->range.rowi = row;
4166 sheet->range.coli = col;
4167 sheet->active_cell.row = row;
4168 sheet->active_cell.col = col;
4169 sheet->selection_cell.row = row;
4170 sheet->selection_cell.col = col;
4172 row_button_set(sheet, row);
4173 column_button_set(sheet, col);
4176 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4177 gtk_sheet_show_active_cell(sheet);
4179 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
4181 G_CALLBACK(gtk_sheet_entry_changed),
4184 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4190 gtk_sheet_show_active_cell(GtkSheet *sheet)
4192 GtkEntry *sheet_entry;
4193 GtkSheetCellAttr attributes;
4195 const gchar *old_text;
4196 GtkJustification justification;
4199 g_return_if_fail (sheet != NULL);
4200 g_return_if_fail (GTK_IS_SHEET (sheet));
4202 row = sheet->active_cell.row;
4203 col = sheet->active_cell.col;
4205 /* Don't show the active cell, if there is no active cell: */
4206 if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */
4209 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4210 if(sheet->state != GTK_SHEET_NORMAL) return;
4211 if(GTK_SHEET_IN_SELECTION(sheet)) return;
4213 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4215 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
4217 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4219 justification = GTK_JUSTIFY_LEFT;
4221 if(gtk_sheet_justify_entry(sheet))
4222 justification = attributes.justification;
4224 text = gtk_sheet_cell_get_text(sheet, row, col);
4226 text = g_strdup("");
4228 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible);
4230 if(gtk_sheet_locked(sheet) || !attributes.is_editable)
4231 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
4233 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
4235 /*** Added by John Gotts. Mar 25, 2005 *********/
4236 old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
4237 if (strcmp(old_text, text) != 0)
4239 if(!GTK_IS_ITEM_ENTRY(sheet_entry))
4240 gtk_entry_set_text(GTK_ENTRY(sheet_entry), text);
4242 gtk_item_entry_set_text(GTK_ITEM_ENTRY(sheet_entry), text, justification);
4245 gtk_sheet_entry_set_max_size(sheet);
4246 gtk_sheet_size_allocate_entry(sheet);
4248 gtk_widget_map(sheet->sheet_entry);
4249 gtk_sheet_draw_active_cell(sheet);
4251 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
4253 dispose_string(sheet, text);
4257 gtk_sheet_draw_active_cell(GtkSheet *sheet)
4261 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
4262 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4264 row = sheet->active_cell.row;
4265 col = sheet->active_cell.col;
4267 if(row < 0 || col < 0) return;
4269 if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
4271 row_button_set(sheet, row);
4272 column_button_set(sheet, col);
4274 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4275 gtk_sheet_draw_border(sheet, sheet->range);
4280 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
4282 gint pixmap_width, pixmap_height;
4284 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4286 if(width == 0 && height == 0){
4287 width=sheet->sheet_window_width+80;
4288 height=sheet->sheet_window_height+80;
4294 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4297 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4301 /* reallocate if sizes don't match */
4302 gdk_window_get_size (sheet->pixmap,
4303 &pixmap_width, &pixmap_height);
4304 if ((pixmap_width != width) || (pixmap_height != height))
4306 g_object_unref(sheet->pixmap);
4307 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4310 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4316 gtk_sheet_new_selection(GtkSheet *sheet, GtkSheetRange *range)
4318 gint i,j, mask1, mask2;
4319 gint state, selected;
4320 gint x,y,width,height;
4321 GtkSheetRange new_range, aux_range;
4323 g_return_if_fail (sheet != NULL);
4325 if(range==NULL) range=&sheet->range;
4329 range->row0=MIN(range->row0, sheet->range.row0);
4330 range->rowi=MAX(range->rowi, sheet->range.rowi);
4331 range->col0=MIN(range->col0, sheet->range.col0);
4332 range->coli=MAX(range->coli, sheet->range.coli);
4334 range->row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
4335 range->rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
4336 range->col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
4337 range->coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
4339 aux_range.row0=MAX(new_range.row0, MIN_VISIBLE_ROW(sheet));
4340 aux_range.rowi=MIN(new_range.rowi, MAX_VISIBLE_ROW(sheet));
4341 aux_range.col0=MAX(new_range.col0, MIN_VISIBLE_COLUMN(sheet));
4342 aux_range.coli=MIN(new_range.coli, MAX_VISIBLE_COLUMN(sheet));
4344 for(i=range->row0; i<=range->rowi; i++){
4345 for(j=range->col0; j<=range->coli; j++){
4347 state=gtk_sheet_cell_get_state(sheet, i, j);
4348 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4349 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4351 if(state==GTK_STATE_SELECTED && selected &&
4352 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4353 (i==sheet->range.row0 || i==sheet->range.rowi ||
4354 j==sheet->range.col0 || j==sheet->range.coli ||
4355 i==new_range.row0 || i==new_range.rowi ||
4356 j==new_range.col0 || j==new_range.coli)){
4358 mask1 = i==sheet->range.row0 ? 1 : 0;
4359 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4360 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4361 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4363 mask2 = i==new_range.row0 ? 1 : 0;
4364 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4365 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4366 mask2 = j==new_range.coli ? mask2+8 : mask2;
4369 x=COLUMN_LEFT_XPIXEL(sheet,j);
4370 y=ROW_TOP_YPIXEL(sheet, i);
4371 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4372 xxx_column_width(sheet, j);
4373 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4375 if(i==sheet->range.row0){
4379 if(i==sheet->range.rowi) height=height+3;
4380 if(j==sheet->range.col0){
4384 if(j==sheet->range.coli) width=width+3;
4386 gdk_draw_pixmap(sheet->sheet_window,
4387 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4396 if(i != sheet->active_cell.row || j != sheet->active_cell.col){
4397 x=COLUMN_LEFT_XPIXEL(sheet,j);
4398 y=ROW_TOP_YPIXEL(sheet, i);
4399 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4400 xxx_column_width(sheet, j);
4402 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4404 if(i==new_range.row0){
4408 if(i==new_range.rowi) height=height-3;
4409 if(j==new_range.col0){
4413 if(j==new_range.coli) width=width-3;
4415 gdk_draw_rectangle (sheet->sheet_window,
4426 for(i=range->row0; i<=range->rowi; i++){
4427 for(j=range->col0; j<=range->coli; j++){
4429 state=gtk_sheet_cell_get_state(sheet, i, j);
4430 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4431 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4433 if(state==GTK_STATE_SELECTED && !selected &&
4434 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4436 x=COLUMN_LEFT_XPIXEL(sheet,j);
4437 y=ROW_TOP_YPIXEL(sheet, i);
4438 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4439 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4441 if(i==sheet->range.row0){
4445 if(i==sheet->range.rowi) height=height+3;
4446 if(j==sheet->range.col0){
4450 if(j==sheet->range.coli) width=width+3;
4452 gdk_draw_pixmap(sheet->sheet_window,
4453 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4465 for(i=range->row0; i<=range->rowi; i++){
4466 for(j=range->col0; j<=range->coli; j++){
4468 state=gtk_sheet_cell_get_state(sheet, i, j);
4469 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4470 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4472 if(state!=GTK_STATE_SELECTED && selected &&
4473 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4474 (i != sheet->active_cell.row || j != sheet->active_cell.col)){
4476 x=COLUMN_LEFT_XPIXEL(sheet,j);
4477 y=ROW_TOP_YPIXEL(sheet, i);
4478 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4479 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4481 if(i==new_range.row0){
4485 if(i==new_range.rowi) height=height-3;
4486 if(j==new_range.col0){
4490 if(j==new_range.coli) width=width-3;
4492 gdk_draw_rectangle (sheet->sheet_window,
4503 for(i=aux_range.row0; i<=aux_range.rowi; i++){
4504 for(j=aux_range.col0; j<=aux_range.coli; j++){
4506 if(xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4508 state=gtk_sheet_cell_get_state(sheet, i, j);
4510 mask1 = i==sheet->range.row0 ? 1 : 0;
4511 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4512 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4513 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4515 mask2 = i==new_range.row0 ? 1 : 0;
4516 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4517 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4518 mask2 = j==new_range.coli ? mask2+8 : mask2;
4519 if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){
4520 x=COLUMN_LEFT_XPIXEL(sheet,j);
4521 y=ROW_TOP_YPIXEL(sheet, i);
4522 width=xxx_column_width(sheet, j);
4523 height=yyy_row_height(sheet, i);
4525 gdk_draw_rectangle (sheet->sheet_window,
4533 gdk_draw_rectangle (sheet->sheet_window,
4540 gdk_draw_rectangle (sheet->sheet_window,
4548 gdk_draw_rectangle (sheet->sheet_window,
4565 gtk_sheet_draw_corners(sheet, new_range);
4570 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
4575 gint x,y,width,height;
4577 widget = GTK_WIDGET(sheet);
4579 x=COLUMN_LEFT_XPIXEL(sheet,new_range.col0);
4580 y=ROW_TOP_YPIXEL(sheet,new_range.row0);
4581 width=COLUMN_LEFT_XPIXEL(sheet,new_range.coli)-x+
4582 xxx_column_width(sheet, new_range.coli);
4584 height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+
4585 yyy_row_height(sheet, new_range.rowi);
4587 area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
4588 area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
4589 area.width=sheet->sheet_window_width;
4590 area.height=sheet->sheet_window_height;
4596 if(width>area.width) width=area.width+10;
4601 if(height>area.height) height=area.height+10;
4603 gdk_gc_set_clip_rectangle(sheet->xor_gc, &area);
4605 for(i=-1; i<=1; ++i)
4606 gdk_draw_rectangle (sheet->sheet_window,
4610 width-2*i,height-2*i);
4612 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
4614 gtk_sheet_draw_corners(sheet, new_range);
4619 gtk_sheet_draw_corners(GtkSheet *sheet, GtkSheetRange range)
4624 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.col0)){
4625 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4626 y=ROW_TOP_YPIXEL(sheet,range.row0);
4627 gdk_draw_pixmap(sheet->sheet_window,
4628 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4636 gdk_draw_rectangle (sheet->sheet_window,
4643 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) ||
4644 sheet->state == GTK_SHEET_COLUMN_SELECTED){
4645 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4646 xxx_column_width(sheet, range.coli);
4647 y=ROW_TOP_YPIXEL(sheet,range.row0);
4649 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
4651 y = ROW_TOP_YPIXEL(sheet, sheet->view.row0)+3;
4654 gdk_draw_pixmap(sheet->sheet_window,
4655 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4663 gdk_draw_rectangle (sheet->sheet_window,
4666 x-width+width/2,y-width+width/2,
4670 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.col0) ||
4671 sheet->state == GTK_SHEET_ROW_SELECTED){
4672 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4673 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4674 yyy_row_height(sheet, range.rowi);
4676 if(sheet->state == GTK_SHEET_ROW_SELECTED)
4678 x = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0)+3;
4681 gdk_draw_pixmap(sheet->sheet_window,
4682 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4690 gdk_draw_rectangle (sheet->sheet_window,
4693 x-width+width/2,y-width+width/2,
4697 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){
4698 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4699 xxx_column_width(sheet, range.coli);
4700 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4701 yyy_row_height(sheet, range.rowi);
4703 if(sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
4704 if(sheet->state == GTK_SHEET_NORMAL) width = 3;
4705 gdk_draw_pixmap(sheet->sheet_window,
4706 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4714 gdk_draw_rectangle (sheet->sheet_window,
4717 x-width+width/2,y-width+width/2,
4726 gtk_sheet_real_select_range (GtkSheet * sheet,
4727 const GtkSheetRange * range)
4731 g_return_if_fail (sheet != NULL);
4733 if(range == NULL) range = &sheet->range;
4735 memcpy(&sheet->range, range, sizeof(*range));
4737 if(range->row0 < 0 || range->rowi < 0) return;
4738 if(range->col0 < 0 || range->coli < 0) return;
4740 state = sheet->state;
4742 if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
4743 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
4745 gtk_sheet_new_selection(sheet, &sheet->range);
4749 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4750 gtk_sheet_range_draw_selection(sheet, sheet->range);
4753 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[SELECT_RANGE], &sheet->range);
4757 gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range)
4759 g_return_if_fail (sheet != NULL);
4761 if(range==NULL) range=&sheet->range;
4763 if(range->row0 < 0 || range->rowi < 0) return;
4764 if(range->col0 < 0 || range->coli < 0) return;
4767 if ( gtk_sheet_locked(sheet)) return ;
4769 if(sheet->state != GTK_SHEET_NORMAL)
4770 gtk_sheet_real_unselect_range(sheet, NULL);
4773 gboolean veto = TRUE;
4774 veto = gtk_sheet_deactivate_cell(sheet);
4778 sheet->range.row0=range->row0;
4779 sheet->range.rowi=range->rowi;
4780 sheet->range.col0=range->col0;
4781 sheet->range.coli=range->coli;
4782 sheet->active_cell.row=range->row0;
4783 sheet->active_cell.col=range->col0;
4784 sheet->selection_cell.row=range->rowi;
4785 sheet->selection_cell.col=range->coli;
4787 sheet->state = GTK_SHEET_RANGE_SELECTED;
4788 gtk_sheet_real_select_range(sheet, NULL);
4793 gtk_sheet_unselect_range (GtkSheet * sheet)
4795 gtk_sheet_real_unselect_range(sheet, NULL);
4796 sheet->state = GTK_STATE_NORMAL;
4797 gtk_sheet_activate_cell(sheet,
4798 sheet->active_cell.row, sheet->active_cell.col);
4803 gtk_sheet_real_unselect_range (GtkSheet * sheet,
4804 const GtkSheetRange *range)
4806 g_return_if_fail (sheet != NULL);
4807 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)));
4810 range = &sheet->range;
4812 if(range->row0 < 0 || range->rowi < 0) return;
4813 if(range->col0 < 0 || range->coli < 0) return;
4815 if (gtk_sheet_range_isvisible (sheet, *range))
4816 gtk_sheet_draw_backing_pixmap(sheet, *range);
4819 for(i=range->col0; i<=range->coli; i++){
4820 column_button_release(sheet, i);
4823 for(i=range->row0; i<=range->rowi; i++){
4824 row_button_release(sheet, i);
4828 sheet->range.row0 = -1;
4829 sheet->range.rowi = -1;
4830 sheet->range.col0 = -1;
4831 sheet->range.coli = -1;
4833 gtk_sheet_position_children(sheet);
4838 gtk_sheet_expose (GtkWidget * widget,
4839 GdkEventExpose * event)
4842 GtkSheetRange range;
4844 g_return_val_if_fail (widget != NULL, FALSE);
4845 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4846 g_return_val_if_fail (event != NULL, FALSE);
4848 sheet = GTK_SHEET (widget);
4850 if (GTK_WIDGET_DRAWABLE (widget))
4852 range.row0 = ROW_FROM_YPIXEL(sheet, event->area.y);
4853 range.col0 = COLUMN_FROM_XPIXEL(sheet, event->area.x);
4854 range.rowi = ROW_FROM_YPIXEL(sheet, event->area.y + event->area.height);
4855 range.coli = COLUMN_FROM_XPIXEL(sheet, event->area.x + event->area.width);
4857 /* exposure events on the sheet */
4858 if(event->window == sheet->row_title_window &&
4859 sheet->row_titles_visible)
4862 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
4863 gtk_sheet_row_title_button_draw(sheet, i);
4866 if(event->window == sheet->column_title_window &&
4867 sheet->column_titles_visible)
4870 for(i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
4871 gtk_sheet_column_title_button_draw(sheet, i);
4874 if (event->window == sheet->sheet_window)
4876 gtk_sheet_draw_backing_pixmap(sheet, range);
4878 if(sheet->state != GTK_SHEET_NORMAL)
4880 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4881 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4882 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4883 gtk_sheet_draw_backing_pixmap(sheet, sheet->drag_range);
4885 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4886 gtk_sheet_range_draw_selection(sheet, sheet->range);
4887 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4888 draw_xor_rectangle(sheet, sheet->drag_range);
4891 if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet)))
4893 if(sheet->state == GTK_SHEET_NORMAL){
4894 gtk_sheet_draw_active_cell(sheet);
4895 if(!GTK_SHEET_IN_SELECTION(sheet))
4896 gtk_widget_queue_draw(sheet->sheet_entry);
4902 if(sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet))
4903 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4905 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
4912 gtk_sheet_button_press (GtkWidget * widget,
4913 GdkEventButton * event)
4916 GdkModifierType mods;
4917 gint x, y, row, column;
4920 g_return_val_if_fail (widget != NULL, FALSE);
4921 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4922 g_return_val_if_fail (event != NULL, FALSE);
4924 sheet = GTK_SHEET (widget);
4926 if ( event->type == GDK_2BUTTON_PRESS)
4928 gtk_widget_get_pointer (widget, &x, &y);
4929 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4931 if (event->window == sheet->column_title_window )
4933 gtk_signal_emit (GTK_OBJECT (sheet),
4934 sheet_signals[DOUBLE_CLICK_COLUMN], column);
4936 else if (event->window == sheet->row_title_window )
4938 gtk_signal_emit (GTK_OBJECT (sheet),
4939 sheet_signals[DOUBLE_CLICK_ROW], row);
4945 if(event->type != GDK_BUTTON_PRESS) return TRUE;
4947 gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
4949 if(!(mods & GDK_BUTTON1_MASK)) return TRUE;
4952 /* press on resize windows */
4953 if (event->window == sheet->column_title_window &&
4954 gtk_sheet_columns_resizable(sheet))
4956 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
4957 if(POSSIBLE_XDRAG(sheet, sheet->x_drag, &sheet->drag_cell.col)){
4959 if (event->type == GDK_2BUTTON_PRESS){
4960 gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
4961 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_XDRAG);
4964 gtk_sheet_column_size_request(sheet, sheet->drag_cell.col, &req);
4965 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4966 gdk_pointer_grab (sheet->column_title_window, FALSE,
4967 GDK_POINTER_MOTION_HINT_MASK |
4968 GDK_BUTTON1_MOTION_MASK |
4969 GDK_BUTTON_RELEASE_MASK,
4970 NULL, NULL, event->time);
4972 draw_xor_vline (sheet);
4977 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet))
4979 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
4981 if(POSSIBLE_YDRAG(sheet, sheet->y_drag, &sheet->drag_cell.row)){
4983 gtk_sheet_row_size_request(sheet, sheet->drag_cell.row, &req);
4984 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
4985 gdk_pointer_grab (sheet->row_title_window, FALSE,
4986 GDK_POINTER_MOTION_HINT_MASK |
4987 GDK_BUTTON1_MOTION_MASK |
4988 GDK_BUTTON_RELEASE_MASK,
4989 NULL, NULL, event->time);
4991 draw_xor_hline (sheet);
4996 /* the sheet itself does not handle other than single click events */
4997 if(event->type != GDK_BUTTON_PRESS) return FALSE;
4999 /* selections on the sheet */
5000 if(event->window == sheet->sheet_window){
5001 gtk_widget_get_pointer (widget, &x, &y);
5002 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5003 gdk_pointer_grab (sheet->sheet_window, FALSE,
5004 GDK_POINTER_MOTION_HINT_MASK |
5005 GDK_BUTTON1_MOTION_MASK |
5006 GDK_BUTTON_RELEASE_MASK,
5007 NULL, NULL, event->time);
5008 gtk_grab_add(GTK_WIDGET(sheet));
5009 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5010 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5012 if(sheet->selection_mode != GTK_SELECTION_SINGLE &&
5013 sheet->cursor_drag->type==GDK_SIZING &&
5014 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_RESIZE(sheet)){
5015 if(sheet->state==GTK_STATE_NORMAL) {
5016 row=sheet->active_cell.row;
5017 column=sheet->active_cell.col;
5018 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
5019 sheet->active_cell.row=row;
5020 sheet->active_cell.col=column;
5021 sheet->drag_range=sheet->range;
5022 sheet->state=GTK_SHEET_RANGE_SELECTED;
5023 gtk_sheet_select_range(sheet, &sheet->drag_range);
5027 if(row > sheet->range.rowi) row--;
5028 if(column > sheet->range.coli) column--;
5029 sheet->drag_cell.row = row;
5030 sheet->drag_cell.col = column;
5031 sheet->drag_range=sheet->range;
5032 draw_xor_rectangle(sheet, sheet->drag_range);
5033 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5035 else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW &&
5036 !GTK_SHEET_IN_SELECTION(sheet)
5037 && ! GTK_SHEET_IN_DRAG(sheet)
5038 && ! gtk_sheet_locked(sheet)
5039 && sheet->active_cell.row >= 0
5040 && sheet->active_cell.col >= 0
5043 if(sheet->state==GTK_STATE_NORMAL) {
5044 row=sheet->active_cell.row;
5045 column=sheet->active_cell.col;
5046 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
5047 sheet->active_cell.row=row;
5048 sheet->active_cell.col=column;
5049 sheet->drag_range=sheet->range;
5050 sheet->state=GTK_SHEET_RANGE_SELECTED;
5051 gtk_sheet_select_range(sheet, &sheet->drag_range);
5055 if(row < sheet->range.row0) row++;
5056 if(row > sheet->range.rowi) row--;
5057 if(column < sheet->range.col0) column++;
5058 if(column > sheet->range.coli) column--;
5059 sheet->drag_cell.row=row;
5060 sheet->drag_cell.col=column;
5061 sheet->drag_range=sheet->range;
5062 draw_xor_rectangle(sheet, sheet->drag_range);
5063 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5067 gtk_sheet_click_cell(sheet, row, column, &veto);
5068 if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5072 if(event->window == sheet->column_title_window){
5073 gtk_widget_get_pointer (widget, &x, &y);
5074 column = COLUMN_FROM_XPIXEL(sheet, x);
5075 if(xxx_column_is_sensitive(sheet, column)){
5076 gtk_sheet_click_cell(sheet, -1, column, &veto);
5077 gtk_grab_add(GTK_WIDGET(sheet));
5078 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5079 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5080 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5084 if(event->window == sheet->row_title_window){
5085 gtk_widget_get_pointer (widget, &x, &y);
5086 row = ROW_FROM_YPIXEL(sheet, y);
5087 if(yyy_row_is_sensitive(sheet, row)){
5088 gtk_sheet_click_cell(sheet, row, -1, &veto);
5089 gtk_grab_add(GTK_WIDGET(sheet));
5090 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5091 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5092 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5100 gtk_sheet_scroll(gpointer data)
5103 gint x,y,row,column;
5106 sheet=GTK_SHEET(data);
5108 GDK_THREADS_ENTER();
5110 gtk_widget_get_pointer (GTK_WIDGET(sheet), &x, &y);
5111 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5115 if(GTK_SHEET_IN_SELECTION(sheet))
5116 gtk_sheet_extend_selection(sheet, row, column);
5118 if(GTK_SHEET_IN_DRAG(sheet) || GTK_SHEET_IN_RESIZE(sheet)){
5119 move=gtk_sheet_move_query(sheet, row, column);
5120 if(move) draw_xor_rectangle(sheet, sheet->drag_range);
5123 GDK_THREADS_LEAVE();
5130 gtk_sheet_click_cell(GtkSheet *sheet, gint row, gint column, gboolean *veto)
5134 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)){
5139 if(column >= 0 && row >= 0)
5140 if(! xxx_column_is_visible(sheet, column) || !yyy_row_is_visible(sheet, row))
5146 _gtkextra_signal_emit(GTK_OBJECT(sheet), sheet_signals[TRAVERSE],
5147 sheet->active_cell.row, sheet->active_cell.col,
5148 &row, &column, veto);
5151 if(sheet->state == GTK_STATE_NORMAL) return;
5153 row = sheet->active_cell.row;
5154 column = sheet->active_cell.col;
5156 gtk_sheet_activate_cell(sheet, row, column);
5160 if(row == -1 && column >= 0){
5161 if(gtk_sheet_autoscroll(sheet))
5162 gtk_sheet_move_query(sheet, row, column);
5163 gtk_sheet_select_column(sheet, column);
5166 if(column == -1 && row >= 0){
5167 if(gtk_sheet_autoscroll(sheet))
5168 gtk_sheet_move_query(sheet, row, column);
5169 gtk_sheet_select_row(sheet, row);
5173 if(row==-1 && column ==-1){
5174 sheet->range.row0=0;
5175 sheet->range.col0=0;
5176 sheet->range.rowi = yyy_row_count(sheet) - 1;
5177 sheet->range.coli = xxx_column_count(sheet) - 1;
5178 sheet->active_cell.row=0;
5179 sheet->active_cell.col=0;
5180 gtk_sheet_select_range(sheet, NULL);
5184 if(row!=-1 && column !=-1){
5185 if(sheet->state != GTK_SHEET_NORMAL){
5186 sheet->state = GTK_SHEET_NORMAL;
5187 gtk_sheet_real_unselect_range(sheet, NULL);
5191 if(!gtk_sheet_deactivate_cell(sheet)){
5197 if(gtk_sheet_autoscroll(sheet))
5198 gtk_sheet_move_query(sheet, row, column);
5199 sheet->active_cell.row=row;
5200 sheet->active_cell.col=column;
5201 sheet->selection_cell.row=row;
5202 sheet->selection_cell.col=column;
5203 sheet->range.row0=row;
5204 sheet->range.col0=column;
5205 sheet->range.rowi=row;
5206 sheet->range.coli=column;
5207 sheet->state=GTK_SHEET_NORMAL;
5208 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5209 gtk_sheet_draw_active_cell(sheet);
5213 g_assert_not_reached();
5214 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5215 sheet->active_cell.col);
5219 gtk_sheet_button_release (GtkWidget * widget,
5220 GdkEventButton * event)
5225 sheet=GTK_SHEET(widget);
5227 /* release on resize windows */
5228 if (GTK_SHEET_IN_XDRAG (sheet))
5230 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
5231 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5232 gtk_widget_get_pointer (widget, &x, NULL);
5233 gdk_pointer_ungrab (event->time);
5234 draw_xor_vline (sheet);
5236 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col,
5237 new_column_width (sheet, sheet->drag_cell.col, &x));
5238 sheet->old_hadjustment = -1.;
5239 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed");
5243 if (GTK_SHEET_IN_YDRAG (sheet)){
5244 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5245 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5246 gtk_widget_get_pointer (widget, NULL, &y);
5247 gdk_pointer_ungrab (event->time);
5248 draw_xor_hline (sheet);
5250 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
5251 sheet->old_vadjustment = -1.;
5252 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed");
5257 if (GTK_SHEET_IN_DRAG(sheet)){
5258 GtkSheetRange old_range;
5259 draw_xor_rectangle(sheet, sheet->drag_range);
5260 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5261 gdk_pointer_ungrab (event->time);
5263 gtk_sheet_real_unselect_range(sheet, NULL);
5265 sheet->active_cell.row = sheet->active_cell.row +
5266 (sheet->drag_range.row0 - sheet->range.row0);
5267 sheet->active_cell.col = sheet->active_cell.col +
5268 (sheet->drag_range.col0 - sheet->range.col0);
5269 sheet->selection_cell.row = sheet->selection_cell.row +
5270 (sheet->drag_range.row0 - sheet->range.row0);
5271 sheet->selection_cell.col = sheet->selection_cell.col +
5272 (sheet->drag_range.col0 - sheet->range.col0);
5273 old_range=sheet->range;
5274 sheet->range=sheet->drag_range;
5275 sheet->drag_range=old_range;
5276 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[MOVE_RANGE],
5277 &sheet->drag_range, &sheet->range);
5278 gtk_sheet_select_range(sheet, &sheet->range);
5281 if (GTK_SHEET_IN_RESIZE(sheet)){
5282 GtkSheetRange old_range;
5283 draw_xor_rectangle(sheet, sheet->drag_range);
5284 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5285 gdk_pointer_ungrab (event->time);
5287 gtk_sheet_real_unselect_range(sheet, NULL);
5289 sheet->active_cell.row = sheet->active_cell.row +
5290 (sheet->drag_range.row0 - sheet->range.row0);
5291 sheet->active_cell.col = sheet->active_cell.col +
5292 (sheet->drag_range.col0 - sheet->range.col0);
5293 if(sheet->drag_range.row0 < sheet->range.row0)
5294 sheet->selection_cell.row = sheet->drag_range.row0;
5295 if(sheet->drag_range.rowi >= sheet->range.rowi)
5296 sheet->selection_cell.row = sheet->drag_range.rowi;
5297 if(sheet->drag_range.col0 < sheet->range.col0)
5298 sheet->selection_cell.col = sheet->drag_range.col0;
5299 if(sheet->drag_range.coli >= sheet->range.coli)
5300 sheet->selection_cell.col = sheet->drag_range.coli;
5301 old_range = sheet->range;
5302 sheet->range = sheet->drag_range;
5303 sheet->drag_range = old_range;
5305 if(sheet->state==GTK_STATE_NORMAL) sheet->state=GTK_SHEET_RANGE_SELECTED;
5306 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[RESIZE_RANGE],
5307 &sheet->drag_range, &sheet->range);
5308 gtk_sheet_select_range(sheet, &sheet->range);
5311 if(sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)){
5312 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5313 gdk_pointer_ungrab (event->time);
5314 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5315 sheet->active_cell.col);
5318 if(GTK_SHEET_IN_SELECTION)
5319 gdk_pointer_ungrab (event->time);
5321 gtk_timeout_remove(sheet->timer);
5322 gtk_grab_remove(GTK_WIDGET(sheet));
5324 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5330 gtk_sheet_motion (GtkWidget * widget,
5331 GdkEventMotion * event)
5334 GdkModifierType mods;
5335 GdkCursorType new_cursor;
5339 g_return_val_if_fail (widget != NULL, FALSE);
5340 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
5341 g_return_val_if_fail (event != NULL, FALSE);
5343 sheet = GTK_SHEET (widget);
5345 /* selections on the sheet */
5349 if(event->window == sheet->column_title_window &&
5350 gtk_sheet_columns_resizable(sheet))
5352 gtk_widget_get_pointer(widget, &x, &y);
5353 if(!GTK_SHEET_IN_SELECTION(sheet) &&
5354 POSSIBLE_XDRAG(sheet, x, &column))
5356 new_cursor = GDK_SB_H_DOUBLE_ARROW;
5357 if(new_cursor != sheet->cursor_drag->type)
5359 gdk_cursor_destroy(sheet->cursor_drag);
5360 sheet->cursor_drag = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
5361 gdk_window_set_cursor(sheet->column_title_window,
5362 sheet->cursor_drag);
5367 new_cursor = GDK_TOP_LEFT_ARROW;
5368 if(!GTK_SHEET_IN_XDRAG(sheet) &&
5369 new_cursor != sheet->cursor_drag->type)
5371 gdk_cursor_destroy(sheet->cursor_drag);
5372 sheet->cursor_drag = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5373 gdk_window_set_cursor(sheet->column_title_window,
5374 sheet->cursor_drag);
5379 if(event->window == sheet->row_title_window &&
5380 gtk_sheet_rows_resizable(sheet))
5382 gtk_widget_get_pointer(widget, &x, &y);
5383 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_YDRAG(sheet,y, &column))
5385 new_cursor = GDK_SB_V_DOUBLE_ARROW;
5386 if(new_cursor != sheet->cursor_drag->type){
5387 gdk_cursor_destroy(sheet->cursor_drag);
5388 sheet->cursor_drag = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
5389 gdk_window_set_cursor(sheet->row_title_window, sheet->cursor_drag);
5394 new_cursor = GDK_TOP_LEFT_ARROW;
5395 if(!GTK_SHEET_IN_YDRAG(sheet) &&
5396 new_cursor != sheet->cursor_drag->type)
5398 gdk_cursor_destroy(sheet->cursor_drag);
5399 sheet->cursor_drag = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5400 gdk_window_set_cursor(sheet->row_title_window, sheet->cursor_drag);
5405 new_cursor = GDK_PLUS;
5406 if( event->window == sheet->sheet_window &&
5407 !POSSIBLE_DRAG(sheet, x, y, &row, &column) &&
5408 !GTK_SHEET_IN_DRAG(sheet) &&
5409 !POSSIBLE_RESIZE(sheet, x, y, &row, &column) &&
5410 !GTK_SHEET_IN_RESIZE(sheet) &&
5411 new_cursor != sheet->cursor_drag->type)
5413 gdk_cursor_destroy(sheet->cursor_drag);
5414 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
5415 gdk_window_set_cursor(sheet->sheet_window, sheet->cursor_drag);
5418 new_cursor = GDK_TOP_LEFT_ARROW;
5419 if( event->window == sheet->sheet_window &&
5420 !(POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) && (POSSIBLE_DRAG(sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG(sheet)) &&
5422 new_cursor != sheet->cursor_drag->type)
5424 gdk_cursor_destroy(sheet->cursor_drag);
5425 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5426 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5429 new_cursor=GDK_SIZING;
5430 if( event->window == sheet->sheet_window &&
5431 !GTK_SHEET_IN_DRAG(sheet) &&
5432 (POSSIBLE_RESIZE(sheet, x, y, &row, &column) ||
5433 GTK_SHEET_IN_RESIZE(sheet)) &&
5434 new_cursor != sheet->cursor_drag->type)
5436 gdk_cursor_destroy(sheet->cursor_drag);
5437 sheet->cursor_drag=gdk_cursor_new(GDK_SIZING);
5438 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5441 gdk_window_get_pointer (widget->window, &x, &y, &mods);
5442 if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
5444 if (GTK_SHEET_IN_XDRAG (sheet))
5446 if (event->is_hint || event->window != widget->window)
5447 gtk_widget_get_pointer (widget, &x, NULL);
5451 new_column_width (sheet, sheet->drag_cell.col, &x);
5452 if (x != sheet->x_drag)
5454 draw_xor_vline (sheet);
5456 draw_xor_vline (sheet);
5461 if (GTK_SHEET_IN_YDRAG (sheet))
5463 if (event->is_hint || event->window != widget->window)
5464 gtk_widget_get_pointer (widget, NULL, &y);
5468 new_row_height (sheet, sheet->drag_cell.row, &y);
5469 if (y != sheet->y_drag)
5471 draw_xor_hline (sheet);
5473 draw_xor_hline (sheet);
5478 if (GTK_SHEET_IN_DRAG(sheet))
5481 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col;
5482 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row;
5483 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5484 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5488 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5489 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet))
5491 aux=sheet->drag_range;
5492 sheet->drag_range.row0 = sheet->range.row0 + row;
5493 sheet->drag_range.col0 = sheet->range.col0 + column;
5494 sheet->drag_range.rowi = sheet->range.rowi + row;
5495 sheet->drag_range.coli = sheet->range.coli + column;
5496 if(aux.row0 != sheet->drag_range.row0 ||
5497 aux.col0 != sheet->drag_range.col0)
5499 draw_xor_rectangle (sheet, aux);
5500 draw_xor_rectangle (sheet, sheet->drag_range);
5506 if (GTK_SHEET_IN_RESIZE(sheet))
5509 gint v_h, current_col, current_row, col_threshold, row_threshold;
5512 if(abs(x-COLUMN_LEFT_XPIXEL(sheet,sheet->drag_cell.col)) >
5513 abs(y-ROW_TOP_YPIXEL(sheet,sheet->drag_cell.row))) v_h=2;
5515 current_col = COLUMN_FROM_XPIXEL(sheet,x);
5516 current_row = ROW_FROM_YPIXEL(sheet,y);
5517 column = current_col-sheet->drag_cell.col;
5518 row = current_row-sheet->drag_cell.row;
5520 /*use half of column width resp. row height as threshold to expand selection*/
5521 col_threshold = COLUMN_LEFT_XPIXEL(sheet,current_col)+xxx_column_width (sheet,current_col)/2;
5524 if (x < col_threshold)
5527 else if (column < 0)
5529 if (x > col_threshold)
5532 row_threshold = ROW_TOP_YPIXEL(sheet,current_row) +
5533 yyy_row_height (sheet, current_row)/2;
5536 if(y < row_threshold)
5541 if(y > row_threshold)
5545 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5546 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5556 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5557 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5559 aux=sheet->drag_range;
5560 sheet->drag_range=sheet->range;
5562 if(row<0) sheet->drag_range.row0=sheet->range.row0+row;
5563 if(row>0) sheet->drag_range.rowi=sheet->range.rowi+row;
5564 if(column<0) sheet->drag_range.col0=sheet->range.col0+column;
5565 if(column>0) sheet->drag_range.coli=sheet->range.coli+column;
5567 if(aux.row0 != sheet->drag_range.row0 ||
5568 aux.rowi != sheet->drag_range.rowi ||
5569 aux.col0 != sheet->drag_range.col0 ||
5570 aux.coli != sheet->drag_range.coli){
5571 draw_xor_rectangle (sheet, aux);
5572 draw_xor_rectangle (sheet, sheet->drag_range);
5580 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5582 if(sheet->state==GTK_SHEET_NORMAL && row==sheet->active_cell.row &&
5583 column==sheet->active_cell.col) return TRUE;
5585 if(GTK_SHEET_IN_SELECTION(sheet) && mods&GDK_BUTTON1_MASK)
5586 gtk_sheet_extend_selection(sheet, row, column);
5592 gtk_sheet_move_query(GtkSheet *sheet, gint row, gint column)
5594 gint row_move, column_move;
5595 gfloat row_align, col_align;
5596 guint height, width;
5598 gint new_col = column;
5605 height = sheet->sheet_window_height;
5606 width = sheet->sheet_window_width;
5608 if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5610 new_row = MIN(yyy_row_count(sheet), row + 1);
5612 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet) - 1 &&
5613 ROW_TOP_YPIXEL(sheet, yyy_row_count(sheet)-1) +
5614 yyy_row_height(sheet, yyy_row_count(sheet)-1) < height){
5619 if(row<MIN_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5623 if(column>=MAX_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5625 new_col = MIN(xxx_column_count(sheet) - 1, column + 1);
5627 if(MAX_VISIBLE_COLUMN(sheet) == (xxx_column_count(sheet) - 1) &&
5628 COLUMN_LEFT_XPIXEL(sheet, xxx_column_count(sheet) - 1) +
5629 xxx_column_width(sheet, xxx_column_count(sheet) - 1) < width)
5631 column_move = FALSE;
5635 if(column<MIN_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5640 if(row_move || column_move){
5641 gtk_sheet_moveto(sheet, new_row, new_col, row_align, col_align);
5644 return(row_move || column_move);
5648 gtk_sheet_extend_selection(GtkSheet *sheet, gint row, gint column)
5650 GtkSheetRange range;
5654 if(row == sheet->selection_cell.row && column == sheet->selection_cell.col)
5657 if(sheet->selection_mode == GTK_SELECTION_SINGLE) return;
5659 gtk_sheet_move_query(sheet, row, column);
5660 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5662 if(GTK_SHEET_IN_DRAG(sheet)) return;
5666 switch(sheet->state){
5667 case GTK_SHEET_ROW_SELECTED:
5668 column = xxx_column_count(sheet) - 1;
5670 case GTK_SHEET_COLUMN_SELECTED:
5671 row = yyy_row_count(sheet) - 1;
5673 case GTK_SHEET_NORMAL:
5674 sheet->state=GTK_SHEET_RANGE_SELECTED;
5675 r=sheet->active_cell.row;
5676 c=sheet->active_cell.col;
5677 sheet->range.col0=c;
5678 sheet->range.row0=r;
5679 sheet->range.coli=c;
5680 sheet->range.rowi=r;
5681 gdk_draw_pixmap(sheet->sheet_window,
5682 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
5684 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5685 ROW_TOP_YPIXEL(sheet,r)-1,
5686 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5687 ROW_TOP_YPIXEL(sheet,r)-1,
5688 xxx_column_width(sheet, c)+4,
5689 yyy_row_height(sheet, r)+4);
5690 gtk_sheet_range_draw_selection(sheet, sheet->range);
5691 case GTK_SHEET_RANGE_SELECTED:
5692 sheet->state=GTK_SHEET_RANGE_SELECTED;
5695 sheet->selection_cell.row = row;
5696 sheet->selection_cell.col = column;
5698 range.col0=MIN(column,sheet->active_cell.col);
5699 range.coli=MAX(column,sheet->active_cell.col);
5700 range.row0=MIN(row,sheet->active_cell.row);
5701 range.rowi=MAX(row,sheet->active_cell.row);
5703 if(range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi ||
5704 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli ||
5705 state==GTK_SHEET_NORMAL)
5706 gtk_sheet_real_select_range(sheet, &range);
5711 gtk_sheet_entry_key_press(GtkWidget *widget,
5715 gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", key, &focus);
5720 gtk_sheet_key_press(GtkWidget *widget,
5726 gboolean extend_selection = FALSE;
5727 gboolean force_move = FALSE;
5728 gboolean in_selection = FALSE;
5729 gboolean veto = TRUE;
5732 sheet = GTK_SHEET(widget);
5734 if(key->state & GDK_CONTROL_MASK || key->keyval==GDK_Control_L ||
5735 key->keyval==GDK_Control_R) return FALSE;
5739 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL)
5740 gtk_sheet_clip_range(sheet, sheet->range);
5741 if(key->keyval=='x' || key->keyval == 'X')
5742 gtk_sheet_unclip_range(sheet);
5747 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval==GDK_Shift_L
5748 || key->keyval==GDK_Shift_R;
5751 in_selection = GTK_SHEET_IN_SELECTION(sheet);
5752 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5754 switch(key->keyval){
5755 case GDK_Return: case GDK_KP_Enter:
5756 if(sheet->state == GTK_SHEET_NORMAL &&
5757 !GTK_SHEET_IN_SELECTION(sheet))
5758 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
5760 row = sheet->active_cell.row;
5761 col = sheet->active_cell.col;
5762 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5763 row = MIN_VISIBLE_ROW(sheet)-1;
5764 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5765 col = MIN_VISIBLE_COLUMN(sheet);
5766 if(row < yyy_row_count(sheet) - 1){
5768 while(!yyy_row_is_visible(sheet, row) && row<yyy_row_count(sheet)-1)
5771 gtk_sheet_click_cell(sheet, row, col, &veto);
5772 extend_selection = FALSE;
5774 case GDK_ISO_Left_Tab:
5775 row = sheet->active_cell.row;
5776 col = sheet->active_cell.col;
5777 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5778 col = MIN_VISIBLE_COLUMN(sheet)-1;
5779 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5780 row = MIN_VISIBLE_ROW(sheet);
5783 while(! xxx_column_is_visible(sheet, col) && col>0) col--;
5786 gtk_sheet_click_cell(sheet, row, col, &veto);
5787 extend_selection = FALSE;
5790 row = sheet->active_cell.row;
5791 col = sheet->active_cell.col;
5792 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5793 col = MIN_VISIBLE_COLUMN(sheet)-1;
5794 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5795 row = MIN_VISIBLE_ROW(sheet);
5796 if(col < xxx_column_count(sheet) - 1)
5799 while(! xxx_column_is_visible(sheet, col) &&
5800 col < xxx_column_count(sheet) - 1)
5803 gtk_sheet_click_cell(sheet, row, col, &veto);
5804 extend_selection = FALSE;
5806 /* case GDK_BackSpace:
5807 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){
5808 if(sheet->active_cell.col > 0){
5809 col = sheet->active_cell.col - scroll;
5810 row = sheet->active_cell.row;
5811 while(!sheet->column[col].is_visible && col > 0) col--;
5814 gtk_sheet_click_cell(sheet, row, col, &veto);
5815 extend_selection = FALSE;
5819 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5821 if(extend_selection){
5822 if(state==GTK_STATE_NORMAL){
5823 row=sheet->active_cell.row;
5824 col=sheet->active_cell.col;
5825 gtk_sheet_click_cell(sheet, row, col, &veto);
5828 if(sheet->selection_cell.row > 0){
5829 row = sheet->selection_cell.row - scroll;
5830 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5832 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5836 col = sheet->active_cell.col;
5837 row = sheet->active_cell.row;
5838 if(state==GTK_SHEET_COLUMN_SELECTED)
5839 row = MIN_VISIBLE_ROW(sheet);
5840 if(state==GTK_SHEET_ROW_SELECTED)
5841 col = MIN_VISIBLE_COLUMN(sheet);
5843 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5845 gtk_sheet_click_cell(sheet, row, col, &veto);
5846 extend_selection = FALSE;
5849 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5851 if(extend_selection){
5852 if(state==GTK_STATE_NORMAL){
5853 row=sheet->active_cell.row;
5854 col=sheet->active_cell.col;
5855 gtk_sheet_click_cell(sheet, row, col, &veto);
5858 if(sheet->selection_cell.row < yyy_row_count(sheet)-1){
5859 row = sheet->selection_cell.row + scroll;
5860 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5861 row = MIN(yyy_row_count(sheet)-1, row);
5862 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5866 col = sheet->active_cell.col;
5867 row = sheet->active_cell.row;
5868 if(sheet->active_cell.row < yyy_row_count(sheet)-1){
5869 if(state==GTK_SHEET_COLUMN_SELECTED)
5870 row = MIN_VISIBLE_ROW(sheet)-1;
5871 if(state==GTK_SHEET_ROW_SELECTED)
5872 col = MIN_VISIBLE_COLUMN(sheet);
5874 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5875 row = MIN(yyy_row_count(sheet)-1, row);
5877 gtk_sheet_click_cell(sheet, row, col, &veto);
5878 extend_selection = FALSE;
5881 if(extend_selection){
5882 if(state==GTK_STATE_NORMAL){
5883 row=sheet->active_cell.row;
5884 col=sheet->active_cell.col;
5885 gtk_sheet_click_cell(sheet, row, col, &veto);
5888 if(sheet->selection_cell.col < xxx_column_count(sheet) - 1)
5890 col = sheet->selection_cell.col + 1;
5891 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1)
5893 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5897 col = sheet->active_cell.col;
5898 row = sheet->active_cell.row;
5899 if(sheet->active_cell.col < xxx_column_count(sheet) - 1){
5901 if(state==GTK_SHEET_ROW_SELECTED)
5902 col = MIN_VISIBLE_COLUMN(sheet)-1;
5903 if(state==GTK_SHEET_COLUMN_SELECTED)
5904 row = MIN_VISIBLE_ROW(sheet);
5905 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1) col++;
5906 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5908 gtk_sheet_click_cell(sheet, row, col, &veto);
5913 extend_selection = FALSE;
5916 if(extend_selection){
5917 if(state==GTK_STATE_NORMAL){
5918 row=sheet->active_cell.row;
5919 col=sheet->active_cell.col;
5920 gtk_sheet_click_cell(sheet, row, col, &veto);
5923 if(sheet->selection_cell.col > 0){
5924 col = sheet->selection_cell.col - 1;
5925 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5926 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5930 col = sheet->active_cell.col - 1;
5931 row = sheet->active_cell.row;
5932 if(state==GTK_SHEET_ROW_SELECTED)
5933 col = MIN_VISIBLE_COLUMN(sheet)-1;
5934 if(state==GTK_SHEET_COLUMN_SELECTED)
5935 row = MIN_VISIBLE_ROW(sheet);
5936 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5939 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5941 gtk_sheet_click_cell(sheet, row, col, &veto);
5945 extend_selection = FALSE;
5949 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5950 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5951 extend_selection = FALSE;
5954 row=yyy_row_count(sheet)-1;
5955 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5956 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5957 extend_selection = FALSE;
5961 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5962 if(extend_selection) return TRUE;
5964 if(state == GTK_SHEET_ROW_SELECTED)
5965 sheet->active_cell.col=MIN_VISIBLE_COLUMN(sheet);
5966 if(state == GTK_SHEET_COLUMN_SELECTED)
5967 sheet->active_cell.row=MIN_VISIBLE_ROW(sheet);
5971 if(extend_selection) return TRUE;
5973 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5974 sheet->active_cell.col);
5980 gtk_sheet_size_request (GtkWidget * widget,
5981 GtkRequisition * requisition)
5985 GtkSheetChild *child;
5986 GtkRequisition child_requisition;
5988 g_return_if_fail (widget != NULL);
5989 g_return_if_fail (GTK_IS_SHEET (widget));
5990 g_return_if_fail (requisition != NULL);
5992 sheet = GTK_SHEET (widget);
5994 requisition->width = 3*DEFAULT_COLUMN_WIDTH;
5995 requisition->height = 3*DEFAULT_ROW_HEIGHT(widget);
5997 /* compute the size of the column title area */
5998 if(sheet->column_titles_visible)
5999 requisition->height += sheet->column_title_area.height;
6001 /* compute the size of the row title area */
6002 if(sheet->row_titles_visible)
6003 requisition->width += sheet->row_title_area.width;
6005 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6006 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6007 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6008 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6010 if(!sheet->column_titles_visible)
6011 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6013 if(!sheet->row_titles_visible)
6014 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6016 children = sheet->children;
6019 child = children->data;
6020 children = children->next;
6022 gtk_widget_size_request(child->widget, &child_requisition);
6028 gtk_sheet_size_allocate (GtkWidget * widget,
6029 GtkAllocation * allocation)
6032 GtkAllocation sheet_allocation;
6035 g_return_if_fail (widget != NULL);
6036 g_return_if_fail (GTK_IS_SHEET (widget));
6037 g_return_if_fail (allocation != NULL);
6039 sheet = GTK_SHEET (widget);
6040 widget->allocation = *allocation;
6041 border_width = GTK_CONTAINER(widget)->border_width;
6043 if (GTK_WIDGET_REALIZED (widget))
6044 gdk_window_move_resize (widget->window,
6045 allocation->x + border_width,
6046 allocation->y + border_width,
6047 allocation->width - 2*border_width,
6048 allocation->height - 2*border_width);
6050 /* use internal allocation structure for all the math
6051 * because it's easier than always subtracting the container
6053 sheet->internal_allocation.x = 0;
6054 sheet->internal_allocation.y = 0;
6055 sheet->internal_allocation.width = allocation->width - 2*border_width;
6056 sheet->internal_allocation.height = allocation->height - 2*border_width;
6058 sheet_allocation.x = 0;
6059 sheet_allocation.y = 0;
6060 sheet_allocation.width = allocation->width - 2*border_width;
6061 sheet_allocation.height = allocation->height - 2*border_width;
6063 sheet->sheet_window_width = sheet_allocation.width;
6064 sheet->sheet_window_height = sheet_allocation.height;
6066 if (GTK_WIDGET_REALIZED (widget))
6067 gdk_window_move_resize (sheet->sheet_window,
6070 sheet_allocation.width,
6071 sheet_allocation.height);
6073 /* position the window which holds the column title buttons */
6074 sheet->column_title_area.x = 0;
6075 sheet->column_title_area.y = 0;
6076 if(sheet->row_titles_visible)
6077 sheet->column_title_area.x = sheet->row_title_area.width;
6078 sheet->column_title_area.width = sheet_allocation.width -
6079 sheet->column_title_area.x;
6080 if(GTK_WIDGET_REALIZED(widget) && sheet->column_titles_visible)
6081 gdk_window_move_resize (sheet->column_title_window,
6082 sheet->column_title_area.x,
6083 sheet->column_title_area.y,
6084 sheet->column_title_area.width,
6085 sheet->column_title_area.height);
6087 sheet->sheet_window_width = sheet_allocation.width;
6088 sheet->sheet_window_height = sheet_allocation.height;
6090 /* column button allocation */
6091 size_allocate_column_title_buttons (sheet);
6093 /* position the window which holds the row title buttons */
6094 sheet->row_title_area.x = 0;
6095 sheet->row_title_area.y = 0;
6096 if(sheet->column_titles_visible)
6097 sheet->row_title_area.y = sheet->column_title_area.height;
6098 sheet->row_title_area.height = sheet_allocation.height -
6099 sheet->row_title_area.y;
6101 if(GTK_WIDGET_REALIZED(widget) && sheet->row_titles_visible)
6102 gdk_window_move_resize (sheet->row_title_window,
6103 sheet->row_title_area.x,
6104 sheet->row_title_area.y,
6105 sheet->row_title_area.width,
6106 sheet->row_title_area.height);
6109 /* row button allocation */
6110 size_allocate_row_title_buttons (sheet);
6112 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6113 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6114 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6115 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6117 if(!sheet->column_titles_visible)
6118 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6120 if(!sheet->row_titles_visible)
6121 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6123 size_allocate_column_title_buttons(sheet);
6124 size_allocate_row_title_buttons(sheet);
6126 /* re-scale backing pixmap */
6127 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
6128 gtk_sheet_position_children(sheet);
6130 /* set the scrollbars adjustments */
6131 adjust_scrollbars (sheet);
6135 size_allocate_column_title_buttons (GtkSheet * sheet)
6140 if (!sheet->column_titles_visible) return;
6141 if (!GTK_WIDGET_REALIZED (sheet))
6144 width = sheet->sheet_window_width;
6147 if(sheet->row_titles_visible)
6149 width -= sheet->row_title_area.width;
6150 x = sheet->row_title_area.width;
6153 if(sheet->column_title_area.width != width || sheet->column_title_area.x != x)
6155 sheet->column_title_area.width = width;
6156 sheet->column_title_area.x = x;
6157 gdk_window_move_resize (sheet->column_title_window,
6158 sheet->column_title_area.x,
6159 sheet->column_title_area.y,
6160 sheet->column_title_area.width,
6161 sheet->column_title_area.height);
6165 if(MAX_VISIBLE_COLUMN(sheet) == xxx_column_count(sheet) - 1)
6166 gdk_window_clear_area (sheet->column_title_window,
6168 sheet->column_title_area.width,
6169 sheet->column_title_area.height);
6171 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6173 for (i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
6174 gtk_sheet_column_title_button_draw(sheet, i);
6178 size_allocate_row_title_buttons (GtkSheet * sheet)
6183 if (!sheet->row_titles_visible) return;
6184 if (!GTK_WIDGET_REALIZED (sheet))
6187 height = sheet->sheet_window_height;
6190 if(sheet->column_titles_visible)
6192 height -= sheet->column_title_area.height;
6193 y = sheet->column_title_area.height;
6196 if(sheet->row_title_area.height != height || sheet->row_title_area.y != y)
6198 sheet->row_title_area.y = y;
6199 sheet->row_title_area.height = height;
6200 gdk_window_move_resize (sheet->row_title_window,
6201 sheet->row_title_area.x,
6202 sheet->row_title_area.y,
6203 sheet->row_title_area.width,
6204 sheet->row_title_area.height);
6206 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet)-1)
6207 gdk_window_clear_area (sheet->row_title_window,
6209 sheet->row_title_area.width,
6210 sheet->row_title_area.height);
6212 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6214 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
6216 if ( i >= yyy_row_count(sheet))
6218 gtk_sheet_row_title_button_draw(sheet, i);
6224 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
6226 GtkAllocation shentry_allocation;
6227 GtkSheetCellAttr attributes = { 0 };
6228 GtkEntry *sheet_entry;
6229 GtkStyle *style = NULL, *previous_style = NULL;
6231 gint size, max_size, text_size, column_width;
6234 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6235 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
6237 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
6239 if ( ! gtk_sheet_get_attributes(sheet, sheet->active_cell.row,
6240 sheet->active_cell.col,
6244 if ( GTK_WIDGET_REALIZED(sheet->sheet_entry) )
6246 if(!GTK_WIDGET(sheet_entry)->style)
6247 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry));
6249 previous_style = GTK_WIDGET(sheet_entry)->style;
6251 style = gtk_style_copy(previous_style);
6252 style->bg[GTK_STATE_NORMAL] = attributes.background;
6253 style->fg[GTK_STATE_NORMAL] = attributes.foreground;
6254 style->text[GTK_STATE_NORMAL] = attributes.foreground;
6255 style->bg[GTK_STATE_ACTIVE] = attributes.background;
6256 style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
6257 style->text[GTK_STATE_ACTIVE] = attributes.foreground;
6259 pango_font_description_free(style->font_desc);
6260 g_assert(attributes.font_desc);
6261 style->font_desc = pango_font_description_copy(attributes.font_desc);
6263 GTK_WIDGET(sheet_entry)->style = style;
6264 gtk_widget_size_request(sheet->sheet_entry, NULL);
6265 GTK_WIDGET(sheet_entry)->style = previous_style;
6267 if(style != previous_style){
6268 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6269 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
6270 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
6271 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
6272 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
6274 gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
6278 if(GTK_IS_ITEM_ENTRY(sheet_entry))
6279 max_size = GTK_ITEM_ENTRY(sheet_entry)->text_max_size;
6284 text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
6285 if(text && strlen(text) > 0)
6286 text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
6288 column_width=xxx_column_width(sheet, sheet->active_cell.col);
6290 size=MIN(text_size, max_size);
6291 size=MAX(size,column_width-2*CELLOFFSET);
6293 row=sheet->active_cell.row;
6294 col=sheet->active_cell.col;
6296 shentry_allocation.x = COLUMN_LEFT_XPIXEL(sheet,sheet->active_cell.col);
6297 shentry_allocation.y = ROW_TOP_YPIXEL(sheet,sheet->active_cell.row);
6298 shentry_allocation.width = column_width;
6299 shentry_allocation.height = yyy_row_height(sheet, sheet->active_cell.row);
6301 if(GTK_IS_ITEM_ENTRY(sheet->sheet_entry))
6303 shentry_allocation.height -= 2*CELLOFFSET;
6304 shentry_allocation.y += CELLOFFSET;
6305 if(gtk_sheet_clip_text(sheet))
6306 shentry_allocation.width = column_width - 2*CELLOFFSET;
6308 shentry_allocation.width = size;
6310 switch(GTK_ITEM_ENTRY(sheet_entry)->justification){
6311 case GTK_JUSTIFY_CENTER:
6312 shentry_allocation.x += (column_width)/2 - size/2;
6314 case GTK_JUSTIFY_RIGHT:
6315 shentry_allocation.x += column_width - size - CELLOFFSET;
6317 case GTK_JUSTIFY_LEFT:
6318 case GTK_JUSTIFY_FILL:
6319 shentry_allocation.x += CELLOFFSET;
6324 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry))
6326 shentry_allocation.x += 2;
6327 shentry_allocation.y += 2;
6328 shentry_allocation.width -= MIN(shentry_allocation.width, 3);
6329 shentry_allocation.height -= MIN(shentry_allocation.height, 3);
6332 gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation);
6334 if(previous_style == style) gtk_style_unref(previous_style);
6338 gtk_sheet_entry_set_max_size(GtkSheet *sheet)
6342 gint sizel=0, sizer=0;
6344 GtkJustification justification;
6347 row=sheet->active_cell.row;
6348 col=sheet->active_cell.col;
6350 if( ! GTK_IS_ITEM_ENTRY(sheet->sheet_entry) || gtk_sheet_clip_text(sheet))
6353 justification = GTK_ITEM_ENTRY(sheet->sheet_entry)->justification;
6355 switch(justification){
6356 case GTK_JUSTIFY_FILL:
6357 case GTK_JUSTIFY_LEFT:
6358 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6359 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6364 size+=xxx_column_width(sheet, i);
6366 size = MIN(size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL(sheet, col));
6368 case GTK_JUSTIFY_RIGHT:
6369 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--)
6371 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6376 size+=xxx_column_width(sheet, i);
6379 case GTK_JUSTIFY_CENTER:
6380 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6381 /* if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6387 sizer+=xxx_column_width(sheet, i);
6389 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--)
6391 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6396 sizel+=xxx_column_width(sheet, i);
6398 size=2*MIN(sizel, sizer);
6403 size += xxx_column_width(sheet, col);
6404 GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size = size;
6408 create_sheet_entry(GtkSheet *sheet)
6413 gint found_entry = FALSE;
6415 widget = GTK_WIDGET(sheet);
6417 if(sheet->sheet_entry)
6419 /* avoids warnings */
6420 gtk_widget_ref(sheet->sheet_entry);
6421 gtk_widget_unparent(sheet->sheet_entry);
6422 gtk_widget_destroy(sheet->sheet_entry);
6425 if(sheet->entry_type)
6427 if(!g_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY))
6429 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6431 sheet->sheet_entry = parent;
6433 entry = gtk_sheet_get_entry (sheet);
6434 if(GTK_IS_ENTRY(entry))
6439 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6446 g_warning ("Entry type must be GtkEntry subclass, using default");
6447 entry = gtk_item_entry_new();
6448 sheet->sheet_entry = entry;
6451 sheet->sheet_entry = parent;
6455 entry = gtk_item_entry_new();
6456 sheet->sheet_entry = entry;
6459 gtk_widget_size_request(sheet->sheet_entry, NULL);
6461 if(GTK_WIDGET_REALIZED(sheet))
6463 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
6464 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
6465 gtk_widget_realize(sheet->sheet_entry);
6468 gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event",
6469 (GtkSignalFunc) gtk_sheet_entry_key_press,
6472 gtk_widget_show (sheet->sheet_entry);
6476 /* Finds the last child widget that happens to be of type GtkEntry */
6478 find_entry(GtkWidget *w, gpointer user_data)
6480 GtkWidget **entry = user_data;
6481 if ( GTK_IS_ENTRY(w))
6488 gtk_sheet_get_entry(GtkSheet *sheet)
6491 GtkWidget *entry = NULL;
6492 GtkTableChild *table_child;
6493 GtkBoxChild *box_child;
6494 GList *children = NULL;
6496 g_return_val_if_fail (sheet != NULL, NULL);
6497 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6498 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6500 if(GTK_IS_ENTRY(sheet->sheet_entry)) return (sheet->sheet_entry);
6502 parent = GTK_WIDGET(sheet->sheet_entry);
6504 if(GTK_IS_TABLE(parent)) children = GTK_TABLE(parent)->children;
6505 if(GTK_IS_BOX(parent)) children = GTK_BOX(parent)->children;
6507 if(GTK_IS_CONTAINER(parent))
6509 gtk_container_forall(GTK_CONTAINER(parent), find_entry, &entry);
6511 if(GTK_IS_ENTRY(entry))
6515 if(!children) return NULL;
6518 if(GTK_IS_TABLE(parent)) {
6519 table_child = children->data;
6520 entry = table_child->widget;
6522 if(GTK_IS_BOX(parent)){
6523 box_child = children->data;
6524 entry = box_child->widget;
6527 if(GTK_IS_ENTRY(entry))
6529 children = children->next;
6533 if(!GTK_IS_ENTRY(entry)) return NULL;
6540 gtk_sheet_get_entry_widget(GtkSheet *sheet)
6542 g_return_val_if_fail (sheet != NULL, NULL);
6543 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6544 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6546 return (sheet->sheet_entry);
6551 gtk_sheet_button_draw(GtkSheet *sheet, GdkWindow *window,
6552 GtkSheetButton *button, gboolean is_sensitive,
6553 GdkRectangle allocation)
6555 GtkShadowType shadow_type;
6556 gint text_width = 0, text_height = 0;
6557 GtkSheetChild *child = NULL;
6558 PangoAlignment align = PANGO_ALIGN_LEFT;
6566 g_return_if_fail(sheet != NULL);
6567 g_return_if_fail(button != NULL);
6569 rtl = gtk_widget_get_direction(GTK_WIDGET(sheet)) == GTK_TEXT_DIR_RTL;
6571 gdk_window_clear_area (window,
6572 allocation.x, allocation.y,
6573 allocation.width, allocation.height);
6575 gtk_paint_box (sheet->button->style, window,
6576 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
6577 &allocation, GTK_WIDGET(sheet->button),
6579 allocation.x, allocation.y,
6580 allocation.width, allocation.height);
6582 state = button->state;
6583 if(!is_sensitive) state = GTK_STATE_INSENSITIVE;
6585 if (state == GTK_STATE_ACTIVE)
6586 shadow_type = GTK_SHADOW_IN;
6588 shadow_type = GTK_SHADOW_OUT;
6590 if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
6591 gtk_paint_box (sheet->button->style, window,
6592 button->state, shadow_type,
6593 &allocation, GTK_WIDGET(sheet->button),
6595 allocation.x, allocation.y,
6596 allocation.width, allocation.height);
6598 if(button->label_visible)
6601 text_height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))-2*CELLOFFSET;
6603 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6605 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation);
6607 allocation.y += 2*sheet->button->style->ythickness;
6610 if(button->label && strlen(button->label)>0){
6612 PangoLayout *layout = NULL;
6613 gint real_x = allocation.x, real_y = allocation.y;
6615 words=button->label;
6616 line = g_new(gchar, 1);
6619 while(words && *words != '\0'){
6622 line=g_realloc(line, len+2);
6626 if(*words == '\n' || *(words+1) == '\0'){
6627 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, line);
6629 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), line);
6630 switch(button->justification){
6631 case GTK_JUSTIFY_LEFT:
6632 real_x = allocation.x + CELLOFFSET;
6633 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6635 case GTK_JUSTIFY_RIGHT:
6636 real_x = allocation.x + allocation.width - text_width - CELLOFFSET;
6637 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6639 case GTK_JUSTIFY_CENTER:
6641 real_x = allocation.x + (allocation.width - text_width)/2;
6642 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6643 pango_layout_set_justify (layout, TRUE);
6645 pango_layout_set_alignment (layout, align);
6646 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6655 g_object_unref(G_OBJECT(layout));
6657 real_y += text_height + 2;
6660 line = g_new(gchar, 1);
6668 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6670 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, NULL);
6674 if((child = button->child) && (child->widget))
6676 child->x = allocation.x;
6677 child->y = allocation.y;
6679 child->x += (allocation.width - child->widget->requisition.width) / 2;
6680 child->y += (allocation.height - child->widget->requisition.height) / 2;
6681 allocation.x = child->x;
6682 allocation.y = child->y;
6683 allocation.width = child->widget->requisition.width;
6684 allocation.height = child->widget->requisition.height;
6686 allocation.x = child->x;
6687 allocation.y = child->y;
6689 gtk_widget_set_state(child->widget, button->state);
6691 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
6692 GTK_WIDGET_MAPPED(child->widget))
6694 gtk_widget_size_allocate(child->widget,
6696 gtk_widget_queue_draw(child->widget);
6700 gtk_sheet_button_free(button);
6704 /* COLUMN value of -1 indicates that the area to the right of the rightmost
6705 button should be redrawn */
6707 gtk_sheet_column_title_button_draw(GtkSheet *sheet, gint column)
6709 GdkWindow *window = NULL;
6710 GdkRectangle allocation;
6711 GtkSheetButton *button = NULL;
6712 gboolean is_sensitive = FALSE;
6714 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6716 if(column >= 0 && ! xxx_column_is_visible(sheet, column)) return;
6717 if(column >= 0 && !sheet->column_titles_visible) return;
6718 if(column>=0 && column < MIN_VISIBLE_COLUMN(sheet)) return;
6719 if(column>=0 && column > MAX_VISIBLE_COLUMN(sheet)) return;
6721 window = sheet->column_title_window;
6723 allocation.height = sheet->column_title_area.height;
6727 const gint cols = xxx_column_count(sheet) ;
6728 allocation.x = COLUMN_LEFT_XPIXEL(sheet, cols - 1)
6730 allocation.width = sheet->column_title_area.width
6731 + sheet->column_title_area.x
6734 gdk_window_clear_area (window,
6735 allocation.x, allocation.y,
6736 allocation.width, allocation.height);
6740 button = xxx_column_button(sheet, column);
6741 allocation.x = COLUMN_LEFT_XPIXEL(sheet, column) + CELL_SPACING;
6742 if(sheet->row_titles_visible)
6743 allocation.x -= sheet->row_title_area.width;
6745 allocation.width = xxx_column_width(sheet, column);
6747 is_sensitive = xxx_column_is_sensitive(sheet, column);
6748 gtk_sheet_button_draw(sheet, window, button,
6749 is_sensitive, allocation);
6754 gtk_sheet_row_title_button_draw(GtkSheet *sheet, gint row)
6756 GdkWindow *window = NULL;
6757 GdkRectangle allocation;
6758 GtkSheetButton *button = NULL;
6759 gboolean is_sensitive = FALSE;
6762 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6764 if(row >= 0 && !yyy_row_is_visible(sheet, row)) return;
6765 if(row >= 0 && !sheet->row_titles_visible) return;
6766 if(row>=0 && row < MIN_VISIBLE_ROW(sheet)) return;
6767 if(row>=0 && row > MAX_VISIBLE_ROW(sheet)) return;
6770 window=sheet->row_title_window;
6771 button = yyy_row_button(sheet, row);
6773 allocation.y = ROW_TOP_YPIXEL(sheet, row) + CELL_SPACING;
6774 if(sheet->column_titles_visible)
6775 allocation.y -= sheet->column_title_area.height;
6776 allocation.width = sheet->row_title_area.width;
6777 allocation.height = yyy_row_height(sheet, row);
6778 is_sensitive = yyy_row_is_sensitive(sheet, row);
6780 gtk_sheet_button_draw(sheet, window, button, is_sensitive, allocation);
6787 * vadjustment_changed
6788 * hadjustment_changed
6789 * vadjustment_value_changed
6790 * hadjustment_value_changed */
6793 adjust_scrollbars (GtkSheet * sheet)
6796 if(sheet->vadjustment){
6797 sheet->vadjustment->page_size = sheet->sheet_window_height;
6798 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
6799 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
6800 sheet->vadjustment->lower = 0;
6801 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
6803 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet))
6805 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) -
6806 sheet->sheet_window_height);
6807 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
6811 gtk_signal_emit_by_name (GTK_OBJECT(sheet->vadjustment), "changed");
6815 if(sheet->hadjustment){
6816 sheet->hadjustment->page_size = sheet->sheet_window_width;
6817 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
6818 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
6819 sheet->hadjustment->lower = 0;
6820 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
6822 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet))
6824 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) -
6825 sheet->sheet_window_width);
6826 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment),
6830 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), "changed");
6834 if(GTK_WIDGET_REALIZED(sheet))
6836 if(sheet->row_titles_visible){
6837 size_allocate_row_title_buttons(sheet);
6838 gdk_window_show(sheet->row_title_window);
6841 if(sheet->column_titles_visible){
6842 size_allocate_column_title_buttons(sheet);
6843 gdk_window_show(sheet->column_title_window);
6846 gtk_sheet_range_draw(sheet, NULL);
6853 vadjustment_changed (GtkAdjustment * adjustment,
6858 g_return_if_fail (adjustment != NULL);
6859 g_return_if_fail (data != NULL);
6861 sheet = GTK_SHEET (data);
6866 hadjustment_changed (GtkAdjustment * adjustment,
6871 g_return_if_fail (adjustment != NULL);
6872 g_return_if_fail (data != NULL);
6874 sheet = GTK_SHEET (data);
6879 vadjustment_value_changed (GtkAdjustment * adjustment,
6883 gint diff, value, old_value;
6887 g_return_if_fail (adjustment != NULL);
6888 g_return_if_fail (data != NULL);
6889 g_return_if_fail (GTK_IS_SHEET (data));
6891 sheet = GTK_SHEET (data);
6893 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6895 row = ROW_FROM_YPIXEL(sheet,sheet->column_title_area.height + CELL_SPACING);
6896 if(!sheet->column_titles_visible)
6897 row=ROW_FROM_YPIXEL(sheet, CELL_SPACING);
6899 old_value = -sheet->voffset;
6901 new_row = g_sheet_row_pixel_to_row(sheet->row_geometry,
6902 adjustment->value,sheet);
6904 y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
6906 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
6907 yyy_row_height(sheet, row) > sheet->vadjustment->step_increment)
6909 /* This avoids embarrassing twitching */
6910 if(row == new_row && row != yyy_row_count(sheet) - 1 &&
6911 adjustment->value - sheet->old_vadjustment >=
6912 sheet->vadjustment->step_increment &&
6913 new_row + 1 != MIN_VISIBLE_ROW(sheet)){
6915 y=y+yyy_row_height(sheet, row);
6919 /* Negative old_adjustment enforces the redraw, otherwise avoid
6921 if(sheet->old_vadjustment >= 0. && row == new_row)
6923 sheet->old_vadjustment = sheet->vadjustment->value;
6927 sheet->old_vadjustment = sheet->vadjustment->value;
6928 adjustment->value=y;
6933 sheet->vadjustment->step_increment = yyy_row_height(sheet, 0);
6937 sheet->vadjustment->step_increment =
6938 MIN(yyy_row_height(sheet, new_row), yyy_row_height(sheet, new_row-1));
6941 sheet->vadjustment->value = adjustment->value;
6943 value = adjustment->value;
6945 if (value >= -sheet->voffset)
6948 diff = value + sheet->voffset;
6953 diff = -sheet->voffset - value;
6956 sheet->voffset = -value;
6958 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height + 1);
6959 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height - 1);
6960 if(!sheet->column_titles_visible)
6961 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6963 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6964 sheet->state == GTK_SHEET_NORMAL &&
6965 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6966 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6967 sheet->active_cell.col))
6971 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6973 if(!text || strlen(text)==0)
6974 gtk_sheet_cell_clear(sheet,
6975 sheet->active_cell.row,
6976 sheet->active_cell.col);
6977 gtk_widget_unmap(sheet->sheet_entry);
6980 gtk_sheet_position_children(sheet);
6982 gtk_sheet_range_draw(sheet, NULL);
6983 size_allocate_row_title_buttons(sheet);
6984 size_allocate_global_button(sheet);
6988 hadjustment_value_changed (GtkAdjustment * adjustment,
6992 gint i, diff, value, old_value;
6993 gint column, new_column;
6996 g_return_if_fail (adjustment != NULL);
6997 g_return_if_fail (data != NULL);
6998 g_return_if_fail (GTK_IS_SHEET (data));
7000 sheet = GTK_SHEET (data);
7002 if(GTK_SHEET_IS_FROZEN(sheet)) return;
7004 column=COLUMN_FROM_XPIXEL(sheet,sheet->row_title_area.width + CELL_SPACING);
7005 if(!sheet->row_titles_visible)
7006 column=COLUMN_FROM_XPIXEL(sheet, CELL_SPACING);
7008 old_value = -sheet->hoffset;
7010 for(i=0; i < xxx_column_count(sheet); i++)
7012 if(xxx_column_is_visible(sheet, i)) x += xxx_column_width(sheet, i);
7013 if(x > adjustment->value) break;
7015 x-=xxx_column_width(sheet, i);
7018 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
7019 xxx_column_width(sheet, i) > sheet->hadjustment->step_increment){
7020 /* This avoids embarrassing twitching */
7021 if(column == new_column && column != xxx_column_count(sheet) - 1 &&
7022 adjustment->value - sheet->old_hadjustment >=
7023 sheet->hadjustment->step_increment &&
7024 new_column + 1 != MIN_VISIBLE_COLUMN(sheet)){
7026 x=x+xxx_column_width(sheet, column);
7030 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
7031 if(sheet->old_hadjustment >= 0. && new_column == column){
7032 sheet->old_hadjustment = sheet->hadjustment->value;
7036 sheet->old_hadjustment = sheet->hadjustment->value;
7037 adjustment->value=x;
7039 if(new_column == 0){
7040 sheet->hadjustment->step_increment=
7041 xxx_column_width(sheet, 0);
7043 sheet->hadjustment->step_increment=
7044 MIN(xxx_column_width(sheet, new_column), xxx_column_width(sheet, new_column-1));
7048 sheet->hadjustment->value=adjustment->value;
7050 value = adjustment->value;
7052 if (value >= -sheet->hoffset)
7055 diff = value + sheet->hoffset;
7060 diff = -sheet->hoffset - value;
7063 sheet->hoffset = -value;
7065 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
7066 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7067 if(!sheet->row_titles_visible)
7068 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
7070 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
7071 sheet->state == GTK_SHEET_NORMAL &&
7072 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
7073 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
7074 sheet->active_cell.col))
7078 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
7079 if(!text || strlen(text)==0)
7080 gtk_sheet_cell_clear(sheet,
7081 sheet->active_cell.row,
7082 sheet->active_cell.col);
7084 gtk_widget_unmap(sheet->sheet_entry);
7087 gtk_sheet_position_children(sheet);
7089 gtk_sheet_range_draw(sheet, NULL);
7090 size_allocate_column_title_buttons(sheet);
7094 /* COLUMN RESIZING */
7096 draw_xor_vline (GtkSheet * sheet)
7100 g_return_if_fail (sheet != NULL);
7102 widget = GTK_WIDGET (sheet);
7104 gdk_draw_line (widget->window, sheet->xor_gc,
7106 sheet->column_title_area.height,
7108 sheet->sheet_window_height + 1);
7113 draw_xor_hline (GtkSheet * sheet)
7117 g_return_if_fail (sheet != NULL);
7119 widget = GTK_WIDGET (sheet);
7121 gdk_draw_line (widget->window, sheet->xor_gc,
7122 sheet->row_title_area.width,
7125 sheet->sheet_window_width + 1,
7129 /* SELECTED RANGE */
7131 draw_xor_rectangle(GtkSheet *sheet, GtkSheetRange range)
7134 GdkRectangle clip_area, area;
7137 area.x=COLUMN_LEFT_XPIXEL(sheet, range.col0);
7138 area.y=ROW_TOP_YPIXEL(sheet, range.row0);
7139 area.width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-area.x+
7140 xxx_column_width(sheet, range.coli);
7141 area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+
7142 yyy_row_height(sheet, range.rowi);
7144 clip_area.x=sheet->row_title_area.width;
7145 clip_area.y=sheet->column_title_area.height;
7146 clip_area.width=sheet->sheet_window_width;
7147 clip_area.height=sheet->sheet_window_height;
7149 if(!sheet->row_titles_visible) clip_area.x = 0;
7150 if(!sheet->column_titles_visible) clip_area.y = 0;
7153 area.width=area.width+area.x;
7156 if(area.width>clip_area.width) area.width=clip_area.width+10;
7158 area.height=area.height+area.y;
7161 if(area.height>clip_area.height) area.height=clip_area.height+10;
7166 clip_area.height+=3;
7168 gdk_gc_get_values(sheet->xor_gc, &values);
7170 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
7173 gdk_draw_rectangle(sheet->sheet_window,
7177 area.width-2*i, area.height-2*i);
7180 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
7182 gdk_gc_set_foreground(sheet->xor_gc, &values.foreground);
7187 /* this function returns the new width of the column being resized given
7188 * the column and x position of the cursor; the x cursor position is passed
7189 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7191 new_column_width (GtkSheet * sheet,
7200 min_width = sheet->column_requisition;
7202 /* you can't shrink a column to less than its minimum width */
7203 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
7205 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
7208 /* don't grow past the end of the window */
7210 if (cx > sheet->sheet_window_width)
7212 *x = cx = sheet->sheet_window_width;
7215 /* calculate new column width making sure it doesn't end up
7216 * less than the minimum width */
7217 width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
7218 if (width < min_width)
7221 xxx_set_column_width(sheet, column, width);
7222 sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7223 size_allocate_column_title_buttons (sheet);
7228 /* this function returns the new height of the row being resized given
7229 * the row and y position of the cursor; the y cursor position is passed
7230 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7232 new_row_height (GtkSheet * sheet,
7240 min_height = sheet->row_requisition;
7242 /* you can't shrink a row to less than its minimum height */
7243 if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
7246 *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
7249 /* don't grow past the end of the window */
7251 if (cy > sheet->sheet_window_height)
7253 *y = cy = sheet->sheet_window_height;
7256 /* calculate new row height making sure it doesn't end up
7257 * less than the minimum height */
7258 height = (cy - ROW_TOP_YPIXEL (sheet, row));
7259 if (height < min_height)
7260 height = min_height;
7262 yyy_set_row_height(sheet, row, height);
7263 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
7264 size_allocate_row_title_buttons (sheet);
7270 gtk_sheet_set_column_width (GtkSheet * sheet,
7276 g_return_if_fail (sheet != NULL);
7277 g_return_if_fail (GTK_IS_SHEET (sheet));
7279 if (column < 0 || column >= xxx_column_count(sheet))
7282 gtk_sheet_column_size_request(sheet, column, &min_width);
7283 if(width < min_width) return;
7285 xxx_set_column_width(sheet, column, width);
7287 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet))
7289 size_allocate_column_title_buttons (sheet);
7290 adjust_scrollbars (sheet);
7291 gtk_sheet_size_allocate_entry(sheet);
7292 gtk_sheet_range_draw (sheet, NULL);
7295 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, column);
7296 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_COL_WIDTH],
7303 gtk_sheet_set_row_height (GtkSheet * sheet,
7309 g_return_if_fail (sheet != NULL);
7310 g_return_if_fail (GTK_IS_SHEET (sheet));
7312 if (row < 0 || row >= yyy_row_count(sheet))
7315 gtk_sheet_row_size_request(sheet, row, &min_height);
7316 if(height < min_height) return;
7318 yyy_set_row_height(sheet, row, height);
7320 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7321 size_allocate_row_title_buttons (sheet);
7322 adjust_scrollbars (sheet);
7323 gtk_sheet_size_allocate_entry(sheet);
7324 gtk_sheet_range_draw (sheet, NULL);
7327 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], row, -1);
7328 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_ROW_HEIGHT], row, height);
7334 gtk_sheet_get_attributes(const GtkSheet *sheet, gint row, gint col,
7335 GtkSheetCellAttr *attributes)
7337 const GdkColor *fg, *bg;
7338 const GtkJustification *j ;
7339 const PangoFontDescription *font_desc ;
7340 const GtkSheetCellBorder *border ;
7342 g_return_val_if_fail (sheet != NULL, FALSE);
7343 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
7345 if(row < 0 || col < 0) return FALSE;
7347 init_attributes(sheet, col, attributes);
7352 attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
7353 attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
7355 fg = g_sheet_model_get_foreground(sheet->model, row, col);
7357 attributes->foreground = *fg;
7359 bg = g_sheet_model_get_background(sheet->model, row, col);
7361 attributes->background = *bg;
7363 j = g_sheet_model_get_justification(sheet->model, row, col);
7364 if (j) attributes->justification = *j;
7366 font_desc = g_sheet_model_get_font_desc(sheet->model, row, col);
7367 if ( font_desc ) attributes->font_desc = font_desc;
7369 border = g_sheet_model_get_cell_border(sheet->model, row, col);
7371 if ( border ) attributes->border = *border;
7377 init_attributes(const GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
7379 /* DEFAULT VALUES */
7380 attributes->foreground = GTK_WIDGET(sheet)->style->black;
7381 attributes->background = sheet->bg_color;
7382 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
7383 GdkColormap *colormap;
7384 colormap=gdk_colormap_get_system();
7385 gdk_color_black(colormap, &attributes->foreground);
7386 attributes->background = sheet->bg_color;
7388 attributes->justification = xxx_column_justification(sheet, col);
7389 attributes->border.width = 0;
7390 attributes->border.line_style = GDK_LINE_SOLID;
7391 attributes->border.cap_style = GDK_CAP_NOT_LAST;
7392 attributes->border.join_style = GDK_JOIN_MITER;
7393 attributes->border.mask = 0;
7394 attributes->border.color = GTK_WIDGET(sheet)->style->black;
7395 attributes->is_editable = TRUE;
7396 attributes->is_visible = TRUE;
7397 attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
7401 /********************************************************************
7402 * Container Functions:
7407 * gtk_sheet_move_child
7408 * gtk_sheet_position_child
7409 * gtk_sheet_position_children
7410 * gtk_sheet_realize_child
7411 * gtk_sheet_get_child_at
7412 ********************************************************************/
7415 gtk_sheet_put(GtkSheet *sheet, GtkWidget *child, gint x, gint y)
7417 GtkRequisition child_requisition;
7418 GtkSheetChild *child_info;
7420 g_return_val_if_fail(sheet != NULL, NULL);
7421 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7422 g_return_val_if_fail(child != NULL, NULL);
7423 g_return_val_if_fail(child->parent == NULL, NULL);
7425 child_info = g_new (GtkSheetChild, 1);
7426 child_info->widget = child;
7429 child_info->attached_to_cell = FALSE;
7430 child_info->floating = TRUE;
7431 child_info->xpadding = child_info->ypadding = 0;
7432 child_info->xexpand = child_info->yexpand = FALSE;
7433 child_info->xshrink = child_info->yshrink = FALSE;
7434 child_info->xfill = child_info->yfill = FALSE;
7436 sheet->children = g_list_append(sheet->children, child_info);
7438 gtk_widget_set_parent (child, GTK_WIDGET(sheet));
7440 gtk_widget_size_request(child, &child_requisition);
7442 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7444 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7445 (!GTK_WIDGET_REALIZED(child) || GTK_WIDGET_NO_WINDOW(child)))
7446 gtk_sheet_realize_child(sheet, child_info);
7448 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7449 !GTK_WIDGET_MAPPED(child))
7450 gtk_widget_map(child);
7453 gtk_sheet_position_child(sheet, child_info);
7455 /* This will avoid drawing on the titles */
7457 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7459 if(sheet->row_titles_visible)
7460 gdk_window_show(sheet->row_title_window);
7461 if(sheet->column_titles_visible)
7462 gdk_window_show(sheet->column_title_window);
7465 return (child_info);
7469 gtk_sheet_attach_floating (GtkSheet *sheet,
7474 GtkSheetChild *child;
7476 if(row < 0 || col < 0){
7477 gtk_sheet_button_attach(sheet, widget, row, col);
7481 gtk_sheet_get_cell_area(sheet, row, col, &area);
7482 child = gtk_sheet_put(sheet, widget, area.x, area.y);
7483 child->attached_to_cell = TRUE;
7489 gtk_sheet_attach_default (GtkSheet *sheet,
7493 if(row < 0 || col < 0){
7494 gtk_sheet_button_attach(sheet, widget, row, col);
7498 gtk_sheet_attach(sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
7502 gtk_sheet_attach (GtkSheet *sheet,
7511 GtkSheetChild *child = NULL;
7513 if(row < 0 || col < 0){
7514 gtk_sheet_button_attach(sheet, widget, row, col);
7518 child = g_new0(GtkSheetChild, 1);
7519 child->attached_to_cell = TRUE;
7520 child->floating = FALSE;
7521 child->widget = widget;
7524 child->xpadding = xpadding;
7525 child->ypadding = ypadding;
7526 child->xexpand = (xoptions & GTK_EXPAND) != 0;
7527 child->yexpand = (yoptions & GTK_EXPAND) != 0;
7528 child->xshrink = (xoptions & GTK_SHRINK) != 0;
7529 child->yshrink = (yoptions & GTK_SHRINK) != 0;
7530 child->xfill = (xoptions & GTK_FILL) != 0;
7531 child->yfill = (yoptions & GTK_FILL) != 0;
7533 sheet->children = g_list_append(sheet->children, child);
7535 gtk_sheet_get_cell_area(sheet, row, col, &area);
7537 child->x = area.x + child->xpadding;
7538 child->y = area.y + child->ypadding;
7540 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7542 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7543 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7544 gtk_sheet_realize_child(sheet, child);
7546 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7547 !GTK_WIDGET_MAPPED(widget))
7548 gtk_widget_map(widget);
7551 gtk_sheet_position_child(sheet, child);
7553 /* This will avoid drawing on the titles */
7555 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7557 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
7558 gdk_window_show(sheet->row_title_window);
7559 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
7560 gdk_window_show(sheet->column_title_window);
7566 gtk_sheet_button_attach (GtkSheet *sheet,
7570 GtkSheetButton *button = 0;
7571 GtkSheetChild *child;
7572 GtkRequisition button_requisition;
7574 if(row >= 0 && col >= 0) return;
7575 if(row < 0 && col < 0) return;
7577 child = g_new (GtkSheetChild, 1);
7578 child->widget = widget;
7581 child->attached_to_cell = TRUE;
7582 child->floating = FALSE;
7585 child->xpadding = child->ypadding = 0;
7586 child->xshrink = child->yshrink = FALSE;
7587 child->xfill = child->yfill = FALSE;
7590 sheet->children = g_list_append(sheet->children, child);
7592 gtk_sheet_button_size_request(sheet, button, &button_requisition);
7595 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7597 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7598 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7599 gtk_sheet_realize_child(sheet, child);
7601 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7602 !GTK_WIDGET_MAPPED(widget))
7603 gtk_widget_map(widget);
7606 if(row == -1) size_allocate_column_title_buttons(sheet);
7607 if(col == -1) size_allocate_row_title_buttons(sheet);
7612 label_size_request(GtkSheet *sheet, gchar *label, GtkRequisition *req)
7617 gint row_height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)) - 2*CELLOFFSET + 2;
7623 while(words && *words != '\0'){
7624 if(*words == '\n' || *(words+1) == '\0'){
7625 req->height += row_height;
7628 req->width = MAX(req->width, STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, word));
7636 if(n > 0) req->height -= 2;
7640 gtk_sheet_button_size_request (GtkSheet *sheet,
7641 const GtkSheetButton *button,
7642 GtkRequisition *button_requisition)
7644 GtkRequisition requisition;
7645 GtkRequisition label_requisition;
7647 if(gtk_sheet_autoresize(sheet) && button->label && strlen(button->label) > 0){
7648 label_size_request(sheet, button->label, &label_requisition);
7649 label_requisition.width += 2*CELLOFFSET;
7650 label_requisition.height += 2*CELLOFFSET;
7652 label_requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7653 label_requisition.width = COLUMN_MIN_WIDTH;
7658 gtk_widget_size_request(button->child->widget, &requisition);
7659 requisition.width += 2*button->child->xpadding;
7660 requisition.height += 2*button->child->ypadding;
7661 requisition.width += 2*sheet->button->style->xthickness;
7662 requisition.height += 2*sheet->button->style->ythickness;
7666 requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7667 requisition.width = COLUMN_MIN_WIDTH;
7670 *button_requisition = requisition;
7671 button_requisition->width = MAX(requisition.width, label_requisition.width);
7672 button_requisition->height = MAX(requisition.height, label_requisition.height);
7677 gtk_sheet_row_size_request (GtkSheet *sheet,
7681 GtkRequisition button_requisition;
7684 gtk_sheet_button_size_request(sheet,
7685 yyy_row_button(sheet, row),
7686 &button_requisition);
7688 *requisition = button_requisition.height;
7690 children = sheet->children;
7692 GtkSheetChild *child = (GtkSheetChild *)children->data;
7693 GtkRequisition child_requisition;
7695 if(child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink){
7696 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7698 if(child_requisition.height + 2 * child->ypadding > *requisition)
7699 *requisition = child_requisition.height + 2 * child->ypadding;
7701 children = children->next;
7704 sheet->row_requisition = * requisition;
7708 gtk_sheet_column_size_request (GtkSheet *sheet,
7712 GtkRequisition button_requisition;
7715 gtk_sheet_button_size_request(sheet,
7716 xxx_column_button(sheet, col),
7717 &button_requisition);
7719 *requisition = button_requisition.width;
7721 children = sheet->children;
7723 GtkSheetChild *child = (GtkSheetChild *)children->data;
7724 GtkRequisition child_requisition;
7726 if(child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink){
7727 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7729 if(child_requisition.width + 2 * child->xpadding > *requisition)
7730 *requisition = child_requisition.width + 2 * child->xpadding;
7732 children = children->next;
7735 sheet->column_requisition = *requisition;
7739 gtk_sheet_move_child(GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
7741 GtkSheetChild *child;
7744 g_return_if_fail(sheet != NULL);
7745 g_return_if_fail(GTK_IS_SHEET(sheet));
7747 children = sheet->children;
7750 child = children->data;
7752 if(child->widget == widget){
7755 child->row = ROW_FROM_YPIXEL(sheet, y);
7756 child->col = COLUMN_FROM_XPIXEL(sheet, x);
7757 gtk_sheet_position_child(sheet, child);
7761 children = children->next;
7764 g_warning("Widget must be a GtkSheet child");
7769 gtk_sheet_position_child(GtkSheet *sheet, GtkSheetChild *child)
7771 GtkRequisition child_requisition;
7772 GtkAllocation child_allocation;
7778 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7780 if(sheet->column_titles_visible)
7781 yoffset = sheet->column_title_area.height;
7783 if(sheet->row_titles_visible)
7784 xoffset = sheet->row_title_area.width;
7786 if(child->attached_to_cell){
7788 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col);
7789 child->y = ROW_TOP_YPIXEL(sheet, child->row);
7791 if(sheet->row_titles_visible)
7792 child->x-=sheet->row_title_area.width;
7793 if(sheet->column_titles_visible)
7794 child->y-=sheet->column_title_area.height;
7796 width = xxx_column_width(sheet, child->col);
7797 height = yyy_row_height(sheet, child->row);
7800 gtk_sheet_get_cell_area(sheet, child->row, child->col, &area);
7801 child->x = area.x + child->xpadding;
7802 child->y = area.y + child->ypadding;
7804 if(!child->floating){
7805 if(child_requisition.width + 2*child->xpadding <= xxx_column_width(sheet, child->col)){
7807 child_requisition.width = child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7810 child->x = area.x + xxx_column_width(sheet, child->col) / 2 -
7811 child_requisition.width / 2;
7813 child_allocation.width = child_requisition.width;
7816 if(!child->xshrink){
7817 gtk_sheet_set_column_width(sheet, child->col, child_requisition.width + 2 * child->xpadding);
7819 child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7822 if(child_requisition.height + 2*child->ypadding <= yyy_row_height(sheet, child->row)){
7824 child_requisition.height = child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7827 child->y = area.y + yyy_row_height(sheet, child->row) / 2 -
7828 child_requisition.height / 2;
7830 child_allocation.height = child_requisition.height;
7833 if(!child->yshrink){
7834 gtk_sheet_set_row_height(sheet, child->row, child_requisition.height + 2 * child->ypadding);
7836 child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7839 child_allocation.width = child_requisition.width;
7840 child_allocation.height = child_requisition.height;
7843 x = child_allocation.x = child->x + xoffset;
7844 y = child_allocation.y = child->y + yoffset;
7848 x = child_allocation.x = child->x + sheet->hoffset + xoffset;
7849 x = child_allocation.x = child->x + xoffset;
7850 y = child_allocation.y = child->y + sheet->voffset + yoffset;
7851 y = child_allocation.y = child->y + yoffset;
7852 child_allocation.width = child_requisition.width;
7853 child_allocation.height = child_requisition.height;
7856 gtk_widget_size_allocate(child->widget, &child_allocation);
7857 gtk_widget_queue_draw(child->widget);
7861 gtk_sheet_forall (GtkContainer *container,
7862 gboolean include_internals,
7863 GtkCallback callback,
7864 gpointer callback_data)
7867 GtkSheetChild *child;
7870 g_return_if_fail (GTK_IS_SHEET (container));
7871 g_return_if_fail (callback != NULL);
7873 sheet = GTK_SHEET (container);
7874 children = sheet->children;
7877 child = children->data;
7878 children = children->next;
7880 (* callback) (child->widget, callback_data);
7883 (* callback) (sheet->button, callback_data);
7884 if(sheet->sheet_entry)
7885 (* callback) (sheet->sheet_entry, callback_data);
7890 gtk_sheet_position_children(GtkSheet *sheet)
7893 GtkSheetChild *child;
7895 children = sheet->children;
7899 child = (GtkSheetChild *)children->data;
7901 if(child->col !=-1 && child->row != -1)
7902 gtk_sheet_position_child(sheet, child);
7904 if(child->row == -1){
7905 if(child->col < MIN_VISIBLE_COLUMN(sheet) ||
7906 child->col > MAX_VISIBLE_COLUMN(sheet))
7907 gtk_sheet_child_hide(child);
7909 gtk_sheet_child_show(child);
7911 if(child->col == -1){
7912 if(child->row < MIN_VISIBLE_ROW(sheet) ||
7913 child->row > MAX_VISIBLE_ROW(sheet))
7914 gtk_sheet_child_hide(child);
7916 gtk_sheet_child_show(child);
7919 children = children->next;
7925 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
7929 GtkSheetChild *child = 0;
7931 g_return_if_fail(container != NULL);
7932 g_return_if_fail(GTK_IS_SHEET(container));
7934 sheet = GTK_SHEET(container);
7936 children = sheet->children;
7940 child = (GtkSheetChild *)children->data;
7942 if(child->widget == widget) break;
7944 children = children->next;
7949 gtk_widget_unparent (widget);
7950 child->widget = NULL;
7952 sheet->children = g_list_remove_link (sheet->children, children);
7953 g_list_free_1 (children);
7960 gtk_sheet_realize_child(GtkSheet *sheet, GtkSheetChild *child)
7964 widget = GTK_WIDGET(sheet);
7966 if(GTK_WIDGET_REALIZED(widget)){
7967 if(child->row == -1)
7968 gtk_widget_set_parent_window(child->widget, sheet->column_title_window);
7969 else if(child->col == -1)
7970 gtk_widget_set_parent_window(child->widget, sheet->row_title_window);
7972 gtk_widget_set_parent_window(child->widget, sheet->sheet_window);
7975 gtk_widget_set_parent(child->widget, widget);
7981 gtk_sheet_get_child_at(GtkSheet *sheet, gint row, gint col)
7984 GtkSheetChild *child = 0;
7986 g_return_val_if_fail(sheet != NULL, NULL);
7987 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7989 children = sheet->children;
7993 child = (GtkSheetChild *)children->data;
7995 if(child->attached_to_cell)
7996 if(child->row == row && child->col == col) break;
7998 children = children->next;
8001 if(children) return child;
8007 gtk_sheet_child_hide(GtkSheetChild *child)
8009 g_return_if_fail(child != NULL);
8010 gtk_widget_hide(child->widget);
8014 gtk_sheet_child_show(GtkSheetChild *child)
8016 g_return_if_fail(child != NULL);
8018 gtk_widget_show(child->widget);
8022 gtk_sheet_get_model(const GtkSheet *sheet)
8024 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
8026 return sheet->model;
8031 gtk_sheet_button_new(void)
8033 GtkSheetButton *button = g_malloc(sizeof(GtkSheetButton));
8035 button->state = GTK_STATE_NORMAL;
8036 button->label = NULL;
8037 button->label_visible = TRUE;
8038 button->child = NULL;
8039 button->justification = GTK_JUSTIFY_FILL;
8046 gtk_sheet_button_free(GtkSheetButton *button)
8048 if (!button) return ;
8050 g_free(button->label);