1 /* This version of GtkSheet has been *heavily* modified, for the specific
2 requirements of PSPPIRE. */
4 /* GtkSheet widget for Gtk+.
5 * Copyright (C) 1999-2001 Adrian E. Feiguin <adrian@ifir.ifir.edu.ar>
7 * Based on GtkClist widget by Jay Painter, but major changes.
8 * Memory allocation routines inspired on SC (Spreadsheet Calculator)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 * @short_description: spreadsheet widget for gtk2
28 * GtkSheet is a matrix widget for GTK+. It consists of an scrollable grid of
29 * cells where you can allocate text. Cell contents can be edited interactively
30 * through a specially designed entry, GtkItemEntry. It is also a container
31 * subclass, allowing you to display buttons, curves, pixmaps and any other
34 * You can also set many attributes as: border, foreground and background color,
35 * text justification, and more.
37 * The testgtksheet program shows how easy is to create a spreadsheet-like GUI
45 #include <gdk/gdkkeysyms.h>
46 #include <gtk/gtksignal.h>
47 #include <gtk/gtklabel.h>
48 #include <gtk/gtkbutton.h>
49 #include <gtk/gtkadjustment.h>
50 #include <gtk/gtktable.h>
51 #include <gtk/gtkbox.h>
52 #include <gtk/gtkmain.h>
53 #include <gtk/gtktypeutils.h>
54 #include <gtk/gtkentry.h>
55 #include <gtk/gtkcontainer.h>
56 #include <gtk/gtkpixmap.h>
57 #include <pango/pango.h>
58 #include "gtkitementry.h"
60 #include "gtkextra-marshal.h"
61 #include "gsheetmodel.h"
66 GTK_SHEET_IS_LOCKED = 1 << 0,
67 GTK_SHEET_IS_FROZEN = 1 << 1,
68 GTK_SHEET_IN_XDRAG = 1 << 2,
69 GTK_SHEET_IN_YDRAG = 1 << 3,
70 GTK_SHEET_IN_DRAG = 1 << 4,
71 GTK_SHEET_IN_SELECTION = 1 << 5,
72 GTK_SHEET_IN_RESIZE = 1 << 6,
73 GTK_SHEET_IN_CLIP = 1 << 7,
74 GTK_SHEET_REDRAW_PENDING = 1 << 8,
77 #define GTK_SHEET_FLAGS(sheet) (GTK_SHEET (sheet)->flags)
78 #define GTK_SHEET_SET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) |= (flag))
79 #define GTK_SHEET_UNSET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) &= ~(flag))
81 #define GTK_SHEET_IS_LOCKED(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_LOCKED)
84 #define GTK_SHEET_IS_FROZEN(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN)
85 #define GTK_SHEET_IN_XDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG)
86 #define GTK_SHEET_IN_YDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG)
87 #define GTK_SHEET_IN_DRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_DRAG)
88 #define GTK_SHEET_IN_SELECTION(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_SELECTION)
89 #define GTK_SHEET_IN_RESIZE(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_RESIZE)
90 #define GTK_SHEET_IN_CLIP(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_CLIP)
91 #define GTK_SHEET_REDRAW_PENDING(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_REDRAW_PENDING)
93 #define CELL_SPACING 1
95 #define TIMEOUT_SCROLL 20
96 #define TIMEOUT_FLASH 200
97 #define TIME_INTERVAL 8
98 #define COLUMN_MIN_WIDTH 10
103 #define DEFAULT_COLUMN_WIDTH 80
106 static void gtk_sheet_column_title_button_draw(GtkSheet *sheet, gint column);
108 static void gtk_sheet_row_title_button_draw(GtkSheet *sheet, gint row);
111 static gboolean gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col);
114 void dispose_string (const GtkSheet *sheet, gchar *text)
116 GSheetModel *model = gtk_sheet_get_model(sheet);
121 if (g_sheet_model_free_strings(model))
126 guint DEFAULT_ROW_HEIGHT(GtkWidget *widget)
128 if(!widget->style->font_desc) return 24;
130 PangoContext *context = gtk_widget_get_pango_context(widget);
131 PangoFontMetrics *metrics = pango_context_get_metrics(context,
132 widget->style->font_desc,
133 pango_context_get_language(context));
134 guint val = pango_font_metrics_get_descent(metrics) +
135 pango_font_metrics_get_ascent(metrics);
136 pango_font_metrics_unref(metrics);
137 return PANGO_PIXELS(val)+2*CELLOFFSET;
140 static inline guint DEFAULT_FONT_ASCENT(GtkWidget *widget)
142 if(!widget->style->font_desc) return 12;
144 PangoContext *context = gtk_widget_get_pango_context(widget);
145 PangoFontMetrics *metrics = pango_context_get_metrics(context,
146 widget->style->font_desc,
147 pango_context_get_language(context));
148 guint val = pango_font_metrics_get_ascent(metrics);
149 pango_font_metrics_unref(metrics);
150 return PANGO_PIXELS(val);
153 static inline guint STRING_WIDTH(GtkWidget *widget,
154 const PangoFontDescription *font, const gchar *text)
159 layout = gtk_widget_create_pango_layout (widget, text);
160 pango_layout_set_font_description (layout, font);
162 pango_layout_get_extents (layout, NULL, &rect);
164 g_object_unref(G_OBJECT(layout));
165 return PANGO_PIXELS(rect.width);
168 static inline guint DEFAULT_FONT_DESCENT(GtkWidget *widget)
170 if(!widget->style->font_desc) return 12;
172 PangoContext *context = gtk_widget_get_pango_context(widget);
173 PangoFontMetrics *metrics = pango_context_get_metrics(context,
174 widget->style->font_desc,
175 pango_context_get_language(context));
176 guint val = pango_font_metrics_get_descent(metrics);
177 pango_font_metrics_unref(metrics);
178 return PANGO_PIXELS(val);
184 yyy_row_is_visible(const GtkSheet *sheet, gint row)
186 GSheetRow *row_geo = sheet->row_geometry;
188 return g_sheet_row_get_visibility(row_geo, row, 0);
193 yyy_row_is_sensitive(const GtkSheet *sheet, gint row)
195 GSheetRow *row_geo = sheet->row_geometry;
197 return g_sheet_row_get_sensitivity(row_geo, row, 0);
203 yyy_row_count(const GtkSheet *sheet)
205 GSheetRow *row_geo = sheet->row_geometry;
207 return g_sheet_row_get_row_count(row_geo, 0);
211 yyy_row_height(const GtkSheet *sheet, gint row)
213 GSheetRow *row_geo = sheet->row_geometry;
215 return g_sheet_row_get_height(row_geo, row, 0);
219 yyy_row_top_ypixel(const GtkSheet *sheet, gint row)
221 GSheetRow *geo = sheet->row_geometry;
223 gint y = g_sheet_row_start_pixel(geo, row, 0);
225 if ( sheet->column_titles_visible )
226 y += sheet->column_title_area.height;
232 /* Return the row containing pixel Y */
234 yyy_row_ypixel_to_row(const GtkSheet *sheet, gint y)
236 GSheetRow *geo = sheet->row_geometry;
238 gint cy = sheet->voffset;
240 if(sheet->column_titles_visible)
241 cy += sheet->column_title_area.height;
245 return g_sheet_row_pixel_to_row(geo, y - cy, 0);
249 /* gives the top pixel of the given row in context of
250 * the sheet's voffset */
252 ROW_TOP_YPIXEL(const GtkSheet *sheet, gint row)
254 return (sheet->voffset + yyy_row_top_ypixel(sheet, row));
258 /* returns the row index from a y pixel location in the
259 * context of the sheet's voffset */
261 ROW_FROM_YPIXEL(const GtkSheet *sheet, gint y)
263 return (yyy_row_ypixel_to_row(sheet, y));
266 static inline GtkSheetButton *
267 xxx_column_button(const GtkSheet *sheet, gint col)
269 GSheetColumn *col_geo = sheet->column_geometry;
270 if ( col < 0 ) return NULL ;
272 return g_sheet_column_get_button(col_geo, col, 0);
277 xxx_column_left_xpixel(const GtkSheet *sheet, gint col)
279 GSheetColumn *geo = sheet->column_geometry;
281 /* FIXME: Get rid of this nasty cast.
282 In fact, get rid of this entire variable */
283 gint x = g_sheet_column_start_pixel(geo, col, (GtkSheet *) sheet);
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 /* FIXME: Get rid of this nasty cast.
297 In fact, get rid of this entire variable */
298 return g_sheet_column_get_width(col_geo, col, (GtkSheet *)sheet);
303 xxx_set_column_width(GtkSheet *sheet, gint col, gint width)
305 if ( sheet->column_geometry )
306 g_sheet_column_set_width(sheet->column_geometry, col, width, sheet);
310 xxx_column_set_left_column(GtkSheet *sheet, gint col, gint i)
312 GSheetColumn *col_geo = sheet->column_geometry;
314 g_sheet_column_set_left_text_column(col_geo, col, i, sheet);
318 xxx_column_left_column(const GtkSheet *sheet, gint col)
320 GSheetColumn *col_geo = sheet->column_geometry;
322 return g_sheet_column_get_left_text_column(col_geo, col, 0);
326 xxx_column_set_right_column(GtkSheet *sheet, gint col, gint i)
328 GSheetColumn *col_geo = sheet->column_geometry;
330 g_sheet_column_set_right_text_column(col_geo, col, i, 0);
334 xxx_column_right_column(const GtkSheet *sheet, gint col)
336 GSheetColumn *col_geo = sheet->column_geometry;
338 return g_sheet_column_get_right_text_column(col_geo, col, 0);
341 static inline GtkJustification
342 xxx_column_justification(const GtkSheet *sheet, gint col)
344 GSheetColumn *col_geo = sheet->column_geometry;
346 return g_sheet_column_get_justification(col_geo, col, 0);
350 xxx_column_is_visible(const GtkSheet *sheet, gint col)
352 GSheetColumn *col_geo = sheet->column_geometry;
354 return g_sheet_column_get_visibility(col_geo, col, 0);
359 xxx_column_is_sensitive(const GtkSheet *sheet, gint col)
361 GSheetColumn *col_geo = sheet->column_geometry;
363 return g_sheet_column_get_sensitivity(col_geo, col, 0);
367 /* gives the left pixel of the given column in context of
368 * the sheet's hoffset */
370 COLUMN_LEFT_XPIXEL(const GtkSheet *sheet, gint ncol)
372 return (sheet->hoffset + xxx_column_left_xpixel(sheet, ncol));
376 xxx_column_count(const GtkSheet *sheet)
378 GSheetColumn *col_geo = sheet->column_geometry;
380 return g_sheet_column_get_column_count(col_geo, 0);
383 /* returns the column index from a x pixel location in the
384 * context of the sheet's hoffset */
386 COLUMN_FROM_XPIXEL (const GtkSheet * sheet,
392 if( sheet->row_titles_visible )
393 cx += sheet->row_title_area.width;
396 for (i = 0; i < xxx_column_count(sheet); i++)
398 if (x >= cx && x <= (cx + xxx_column_width(sheet, i)) &&
399 xxx_column_is_visible(sheet, i))
401 if( xxx_column_is_visible(sheet, i))
402 cx += xxx_column_width(sheet, i);
406 return xxx_column_count(sheet) - 1;
409 /* returns the total height of the sheet */
410 static inline gint SHEET_HEIGHT(GtkSheet *sheet)
412 const gint n_rows = yyy_row_count(sheet);
414 return yyy_row_top_ypixel(sheet, n_rows - 1) +
415 yyy_row_height(sheet, n_rows - 1);
419 static inline GtkSheetButton *
420 yyy_row_button(GtkSheet *sheet, gint row)
422 GSheetRow *row_geo = sheet->row_geometry;
424 return g_sheet_row_get_button(row_geo, row, sheet);
431 yyy_set_row_height(GtkSheet *sheet, gint row, gint height)
433 if ( sheet->row_geometry )
434 g_sheet_row_set_height(sheet->row_geometry, row, height, sheet);
439 /* returns the total width of the sheet */
440 static inline gint SHEET_WIDTH(GtkSheet *sheet)
444 cx = ( sheet->row_titles_visible ? sheet->row_title_area.width : 0);
446 for (i=0; i < xxx_column_count(sheet); i++)
447 if(xxx_column_is_visible(sheet, i)) cx += xxx_column_width(sheet, i);
452 #define MIN_VISIBLE_ROW(sheet) sheet->view.row0
453 #define MAX_VISIBLE_ROW(sheet) sheet->view.rowi
454 #define MIN_VISIBLE_COLUMN(sheet) sheet->view.col0
455 #define MAX_VISIBLE_COLUMN(sheet) sheet->view.coli
458 static inline gboolean
459 POSSIBLE_XDRAG(const GtkSheet *sheet, gint x, gint *drag_column)
463 column=COLUMN_FROM_XPIXEL(sheet, x);
466 xdrag = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING;
467 if(x <= xdrag+DRAG_WIDTH/2 && column != 0){
468 while(! xxx_column_is_visible(sheet, column-1) && column>0) column--;
469 *drag_column=column-1;
470 return xxx_column_is_sensitive(sheet, column-1);
473 xdrag+= xxx_column_width(sheet, column);
474 if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag+DRAG_WIDTH/2)
475 return xxx_column_is_sensitive(sheet, column);
480 static inline gboolean
481 POSSIBLE_YDRAG(const GtkSheet *sheet, gint y, gint *drag_row)
485 row=ROW_FROM_YPIXEL(sheet, y);
488 ydrag=ROW_TOP_YPIXEL(sheet,row)+CELL_SPACING;
489 if(y <= ydrag+DRAG_WIDTH/2 && row != 0){
490 while(!yyy_row_is_visible(sheet, row-1) && row>0) row--;
492 return yyy_row_is_sensitive(sheet, row-1);
495 ydrag+=yyy_row_height(sheet, row);
497 if(y >= ydrag-DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2)
498 return yyy_row_is_sensitive(sheet, row);
504 static inline gboolean
505 POSSIBLE_DRAG(const GtkSheet *sheet, gint x, gint y,
506 gint *drag_row, gint *drag_column)
510 /* Can't drag if nothing is selected */
511 if ( sheet->range.row0 < 0 || sheet->range.rowi < 0 ||
512 sheet->range.col0 < 0 || sheet->range.coli < 0 )
515 *drag_column = COLUMN_FROM_XPIXEL(sheet, x);
516 *drag_row = ROW_FROM_YPIXEL(sheet, y);
518 if(x >= COLUMN_LEFT_XPIXEL(sheet, sheet->range.col0) - DRAG_WIDTH/2 &&
519 x <= COLUMN_LEFT_XPIXEL(sheet, sheet->range.coli) +
520 xxx_column_width(sheet, sheet->range.coli) + DRAG_WIDTH/2)
522 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.row0);
523 if(y >= ydrag - DRAG_WIDTH/2 && y <= ydrag + DRAG_WIDTH/2)
525 *drag_row = sheet->range.row0;
528 ydrag = ROW_TOP_YPIXEL(sheet, sheet->range.rowi) +
529 yyy_row_height(sheet, sheet->range.rowi);
530 if(y >= ydrag - DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2)
532 *drag_row = sheet->range.rowi;
537 if(y >= ROW_TOP_YPIXEL(sheet, sheet->range.row0) - DRAG_WIDTH/2 &&
538 y <= ROW_TOP_YPIXEL(sheet, sheet->range.rowi) +
539 yyy_row_height(sheet, sheet->range.rowi) + DRAG_WIDTH/2)
541 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->range.col0);
542 if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag + DRAG_WIDTH/2)
544 *drag_column = sheet->range.col0;
547 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->range.coli) +
548 xxx_column_width(sheet, sheet->range.coli);
549 if(x >= xdrag - DRAG_WIDTH/2 && x <= xdrag + DRAG_WIDTH/2)
551 *drag_column = sheet->range.coli;
558 static inline gboolean
559 POSSIBLE_RESIZE(const GtkSheet *sheet, gint x, gint y,
560 gint *drag_row, gint *drag_column)
564 /* Can't drag if nothing is selected */
565 if ( sheet->range.row0 < 0 || sheet->range.rowi < 0 ||
566 sheet->range.col0 < 0 || sheet->range.coli < 0 )
569 xdrag = COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
570 xxx_column_width(sheet, sheet->range.coli);
572 ydrag = ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
573 yyy_row_height(sheet, sheet->range.rowi);
575 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
576 ydrag = ROW_TOP_YPIXEL(sheet, sheet->view.row0);
578 if(sheet->state == GTK_SHEET_ROW_SELECTED)
579 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0);
581 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
582 *drag_row=ROW_FROM_YPIXEL(sheet,y);
584 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2 &&
585 y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2) return TRUE;
590 static void gtk_sheet_class_init (GtkSheetClass * klass);
591 static void gtk_sheet_init (GtkSheet * sheet);
592 static void gtk_sheet_destroy (GtkObject * object);
593 static void gtk_sheet_finalize (GObject * object);
594 static void gtk_sheet_style_set (GtkWidget *widget,
595 GtkStyle *previous_style);
596 static void gtk_sheet_realize (GtkWidget * widget);
597 static void gtk_sheet_unrealize (GtkWidget * widget);
598 static void gtk_sheet_map (GtkWidget * widget);
599 static void gtk_sheet_unmap (GtkWidget * widget);
600 static gint gtk_sheet_expose (GtkWidget * widget,
601 GdkEventExpose * event);
602 static void gtk_sheet_forall (GtkContainer *container,
603 gboolean include_internals,
604 GtkCallback callback,
605 gpointer callback_data);
607 static void gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
608 GtkAdjustment *hadjustment,
609 GtkAdjustment *vadjustment);
611 static gint gtk_sheet_button_press (GtkWidget * widget,
612 GdkEventButton * event);
613 static gint gtk_sheet_button_release (GtkWidget * widget,
614 GdkEventButton * event);
615 static gint gtk_sheet_motion (GtkWidget * widget,
616 GdkEventMotion * event);
617 static gint gtk_sheet_entry_key_press (GtkWidget *widget,
619 static gint gtk_sheet_key_press (GtkWidget *widget,
621 static void gtk_sheet_size_request (GtkWidget * widget,
622 GtkRequisition * requisition);
623 static void gtk_sheet_size_allocate (GtkWidget * widget,
624 GtkAllocation * allocation);
628 static gint gtk_sheet_range_isvisible (GtkSheet * sheet,
629 GtkSheetRange range);
630 static gint gtk_sheet_cell_isvisible (GtkSheet * sheet,
631 gint row, gint column);
634 static gint gtk_sheet_scroll (gpointer data);
635 static gint gtk_sheet_flash (gpointer data);
637 /* Drawing Routines */
639 /* draw cell background and frame */
640 static void gtk_sheet_cell_draw_default (GtkSheet *sheet,
641 gint row, gint column);
643 /* draw cell border */
644 static void gtk_sheet_cell_draw_border (GtkSheet *sheet,
645 gint row, gint column,
648 /* draw cell contents */
649 static void gtk_sheet_cell_draw_label (GtkSheet *sheet,
650 gint row, gint column);
652 /* draw visible part of range. If range==NULL then draw the whole screen */
653 static void gtk_sheet_range_draw (GtkSheet *sheet,
654 const GtkSheetRange *range);
656 /* highlight the visible part of the selected range */
657 static void gtk_sheet_range_draw_selection (GtkSheet *sheet,
658 GtkSheetRange range);
662 static gint gtk_sheet_move_query (GtkSheet *sheet,
663 gint row, gint column);
664 static void gtk_sheet_real_select_range (GtkSheet * sheet,
665 const GtkSheetRange * range);
666 static void gtk_sheet_real_unselect_range (GtkSheet * sheet,
667 const GtkSheetRange * range);
668 static void gtk_sheet_extend_selection (GtkSheet *sheet,
669 gint row, gint column);
670 static void gtk_sheet_new_selection (GtkSheet *sheet,
671 GtkSheetRange *range);
672 static void gtk_sheet_draw_border (GtkSheet *sheet,
673 GtkSheetRange range);
674 static void gtk_sheet_draw_corners (GtkSheet *sheet,
675 GtkSheetRange range);
678 /* Active Cell handling */
680 static void gtk_sheet_entry_changed (GtkWidget *widget,
682 static gboolean gtk_sheet_deactivate_cell (GtkSheet *sheet);
683 static void gtk_sheet_hide_active_cell (GtkSheet *sheet);
684 static gboolean gtk_sheet_activate_cell (GtkSheet *sheet,
686 static void gtk_sheet_draw_active_cell (GtkSheet *sheet);
687 static void gtk_sheet_show_active_cell (GtkSheet *sheet);
688 static void gtk_sheet_click_cell (GtkSheet *sheet,
695 static void gtk_sheet_make_backing_pixmap (GtkSheet *sheet,
696 guint width, guint height);
697 static void gtk_sheet_draw_backing_pixmap (GtkSheet *sheet,
698 GtkSheetRange range);
701 static void adjust_scrollbars (GtkSheet * sheet);
702 static void vadjustment_changed (GtkAdjustment * adjustment,
704 static void hadjustment_changed (GtkAdjustment * adjustment,
706 static void vadjustment_value_changed (GtkAdjustment * adjustment,
708 static void hadjustment_value_changed (GtkAdjustment * adjustment,
712 static void draw_xor_vline (GtkSheet * sheet);
713 static void draw_xor_hline (GtkSheet * sheet);
714 static void draw_xor_rectangle (GtkSheet *sheet,
715 GtkSheetRange range);
716 static void gtk_sheet_draw_flashing_range (GtkSheet *sheet,
717 GtkSheetRange range);
718 static guint new_column_width (GtkSheet * sheet,
721 static guint new_row_height (GtkSheet * sheet,
726 static void create_global_button (GtkSheet *sheet);
727 static void global_button_clicked (GtkWidget *widget,
731 static void create_sheet_entry (GtkSheet *sheet);
732 static void gtk_sheet_size_allocate_entry (GtkSheet *sheet);
733 static void gtk_sheet_entry_set_max_size (GtkSheet *sheet);
735 /* Sheet button gadgets */
737 static void size_allocate_column_title_buttons (GtkSheet * sheet);
738 static void size_allocate_row_title_buttons (GtkSheet * sheet);
741 static void size_allocate_global_button (GtkSheet *sheet);
742 static void gtk_sheet_button_size_request (GtkSheet *sheet,
743 const GtkSheetButton *button,
744 GtkRequisition *requisition);
746 /* Attributes routines */
747 static void init_attributes (const GtkSheet *sheet, gint col,
748 GtkSheetCellAttr *attributes);
751 /* Memory allocation routines */
752 static void gtk_sheet_real_range_clear (GtkSheet *sheet,
753 const GtkSheetRange *range,
755 static void gtk_sheet_real_cell_clear (GtkSheet *sheet,
761 /* Container Functions */
762 static void gtk_sheet_remove (GtkContainer *container,
764 static void gtk_sheet_realize_child (GtkSheet *sheet,
765 GtkSheetChild *child);
766 static void gtk_sheet_position_child (GtkSheet *sheet,
767 GtkSheetChild *child);
768 static void gtk_sheet_position_children (GtkSheet *sheet);
769 static void gtk_sheet_child_show (GtkSheetChild *child);
770 static void gtk_sheet_child_hide (GtkSheetChild *child);
771 static void gtk_sheet_column_size_request (GtkSheet *sheet,
774 static void gtk_sheet_row_size_request (GtkSheet *sheet,
782 _gtkextra_signal_emit(GtkObject *object, guint signal_id, ...);
804 static GtkContainerClass *parent_class = NULL;
805 static guint sheet_signals[LAST_SIGNAL] = {0};
809 gtk_sheet_get_type ()
811 static GType sheet_type = 0;
815 static const GTypeInfo sheet_info =
817 sizeof (GtkSheetClass),
820 (GClassInitFunc) gtk_sheet_class_init,
825 (GInstanceInitFunc) gtk_sheet_init,
829 g_type_register_static (GTK_TYPE_CONTAINER, "GtkSheet",
835 static GtkSheetRange*
836 gtk_sheet_range_copy (const GtkSheetRange *range)
838 GtkSheetRange *new_range;
840 g_return_val_if_fail (range != NULL, NULL);
842 new_range = g_new (GtkSheetRange, 1);
850 gtk_sheet_range_free (GtkSheetRange *range)
852 g_return_if_fail (range != NULL);
858 gtk_sheet_range_get_type (void)
860 static GType sheet_range_type=0;
862 if(!sheet_range_type)
864 sheet_range_type = g_boxed_type_register_static("GtkSheetRange", (GBoxedCopyFunc)gtk_sheet_range_copy, (GBoxedFreeFunc)gtk_sheet_range_free);
866 return sheet_range_type;
871 gtk_sheet_class_init (GtkSheetClass * klass)
873 GtkObjectClass *object_class;
874 GtkWidgetClass *widget_class;
875 GtkContainerClass *container_class;
876 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
878 object_class = (GtkObjectClass *) klass;
879 widget_class = (GtkWidgetClass *) klass;
880 container_class = (GtkContainerClass *) klass;
882 parent_class = g_type_class_peek_parent (klass);
885 * GtkSheet::select-row
886 * @sheet: the sheet widget that emitted the signal
887 * @row: the newly selected row index
889 * A row has been selected.
891 sheet_signals[SELECT_ROW] =
892 gtk_signal_new ("select-row",
894 GTK_CLASS_TYPE(object_class),
895 GTK_SIGNAL_OFFSET (GtkSheetClass, select_row),
897 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
900 * GtkSheet::select-column
901 * @sheet: the sheet widget that emitted the signal
902 * @column: the newly selected column index
904 * A column has been selected.
906 sheet_signals[SELECT_COLUMN] =
907 gtk_signal_new ("select-column",
909 GTK_CLASS_TYPE(object_class),
910 GTK_SIGNAL_OFFSET (GtkSheetClass, select_column),
912 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
916 * GtkSheet::double-click-row
917 * @sheet: the sheet widget that emitted the signal
918 * @row: the row that was double clicked.
920 * A row's title button has been double clicked
922 sheet_signals[DOUBLE_CLICK_ROW] =
923 gtk_signal_new ("double-click-row",
925 GTK_CLASS_TYPE(object_class),
928 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
932 * GtkSheet::double-click-column
933 * @sheet: the sheet widget that emitted the signal
934 * @column: the column that was double clicked.
936 * A column's title button has been double clicked
938 sheet_signals[DOUBLE_CLICK_COLUMN] =
939 gtk_signal_new ("double-click-column",
941 GTK_CLASS_TYPE(object_class),
944 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
946 sheet_signals[SELECT_RANGE] =
947 gtk_signal_new ("select-range",
949 GTK_CLASS_TYPE(object_class),
950 GTK_SIGNAL_OFFSET (GtkSheetClass, select_range),
951 gtkextra_VOID__BOXED,
952 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
954 sheet_signals[CLIP_RANGE] =
955 gtk_signal_new ("clip-range",
957 GTK_CLASS_TYPE(object_class),
958 GTK_SIGNAL_OFFSET (GtkSheetClass, clip_range),
959 gtkextra_VOID__BOXED,
960 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
962 sheet_signals[RESIZE_RANGE] =
963 gtk_signal_new ("resize-range",
965 GTK_CLASS_TYPE(object_class),
966 GTK_SIGNAL_OFFSET (GtkSheetClass, resize_range),
967 gtkextra_VOID__BOXED_BOXED,
968 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
969 sheet_signals[MOVE_RANGE] =
970 gtk_signal_new ("move-range",
972 GTK_CLASS_TYPE(object_class),
973 GTK_SIGNAL_OFFSET (GtkSheetClass, move_range),
974 gtkextra_VOID__BOXED_BOXED,
975 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
976 sheet_signals[TRAVERSE] =
977 gtk_signal_new ("traverse",
979 GTK_CLASS_TYPE(object_class),
980 GTK_SIGNAL_OFFSET (GtkSheetClass, traverse),
981 gtkextra_BOOLEAN__INT_INT_POINTER_POINTER,
982 GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT,
983 GTK_TYPE_POINTER, GTK_TYPE_POINTER);
985 sheet_signals[DEACTIVATE] =
986 gtk_signal_new ("deactivate",
988 GTK_CLASS_TYPE(object_class),
989 GTK_SIGNAL_OFFSET (GtkSheetClass, deactivate),
990 gtkextra_BOOLEAN__INT_INT,
991 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
993 sheet_signals[ACTIVATE] =
994 gtk_signal_new ("activate",
996 GTK_CLASS_TYPE(object_class),
997 GTK_SIGNAL_OFFSET (GtkSheetClass, activate),
998 gtkextra_BOOLEAN__INT_INT,
999 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1001 sheet_signals[SET_CELL] =
1002 gtk_signal_new ("set-cell",
1004 GTK_CLASS_TYPE(object_class),
1005 GTK_SIGNAL_OFFSET (GtkSheetClass, set_cell),
1006 gtkextra_VOID__INT_INT,
1007 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1009 sheet_signals[CLEAR_CELL] =
1010 gtk_signal_new ("clear-cell",
1012 GTK_CLASS_TYPE(object_class),
1013 GTK_SIGNAL_OFFSET (GtkSheetClass, clear_cell),
1014 gtkextra_VOID__INT_INT,
1015 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1017 sheet_signals[CHANGED] =
1018 gtk_signal_new ("changed",
1020 GTK_CLASS_TYPE(object_class),
1021 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1022 gtkextra_VOID__INT_INT,
1023 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1025 sheet_signals[NEW_COL_WIDTH] =
1026 gtk_signal_new ("new-column-width",
1028 GTK_CLASS_TYPE(object_class),
1029 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1030 gtkextra_VOID__INT_INT,
1031 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1033 sheet_signals[NEW_ROW_HEIGHT] =
1034 gtk_signal_new ("new-row-height",
1036 GTK_CLASS_TYPE(object_class),
1037 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1038 gtkextra_VOID__INT_INT,
1039 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1041 widget_class->set_scroll_adjustments_signal =
1042 gtk_signal_new ("set-scroll-adjustments",
1044 GTK_CLASS_TYPE(object_class),
1045 GTK_SIGNAL_OFFSET (GtkSheetClass, set_scroll_adjustments),
1046 gtkextra_VOID__OBJECT_OBJECT,
1047 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1050 container_class->add = NULL;
1051 container_class->remove = gtk_sheet_remove;
1052 container_class->forall = gtk_sheet_forall;
1054 object_class->destroy = gtk_sheet_destroy;
1055 gobject_class->finalize = gtk_sheet_finalize;
1057 widget_class->realize = gtk_sheet_realize;
1058 widget_class->unrealize = gtk_sheet_unrealize;
1059 widget_class->map = gtk_sheet_map;
1060 widget_class->unmap = gtk_sheet_unmap;
1061 widget_class->style_set = gtk_sheet_style_set;
1062 widget_class->button_press_event = gtk_sheet_button_press;
1063 widget_class->button_release_event = gtk_sheet_button_release;
1064 widget_class->motion_notify_event = gtk_sheet_motion;
1065 widget_class->key_press_event = gtk_sheet_key_press;
1066 widget_class->expose_event = gtk_sheet_expose;
1067 widget_class->size_request = gtk_sheet_size_request;
1068 widget_class->size_allocate = gtk_sheet_size_allocate;
1069 widget_class->focus_in_event = NULL;
1070 widget_class->focus_out_event = NULL;
1072 klass->set_scroll_adjustments = gtk_sheet_set_scroll_adjustments;
1073 klass->select_row = NULL;
1074 klass->select_column = NULL;
1075 klass->select_range = NULL;
1076 klass->clip_range = NULL;
1077 klass->resize_range = NULL;
1078 klass->move_range = NULL;
1079 klass->traverse = NULL;
1080 klass->deactivate = NULL;
1081 klass->activate = NULL;
1082 klass->set_cell = NULL;
1083 klass->clear_cell = NULL;
1084 klass->changed = NULL;
1089 gtk_sheet_init (GtkSheet *sheet)
1091 sheet->column_geometry = NULL;
1092 sheet->row_geometry = NULL;
1094 sheet->children = NULL;
1097 sheet->selection_mode = GTK_SELECTION_BROWSE;
1098 sheet->freeze_count = 0;
1099 sheet->state = GTK_SHEET_NORMAL;
1101 GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW);
1102 GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS);
1104 sheet->view.row0 = 0;
1105 sheet->view.col0 = 0;
1106 sheet->view.rowi = 0;
1107 sheet->view.coli = 0;
1109 sheet->column_title_window=NULL;
1110 sheet->column_title_area.x=0;
1111 sheet->column_title_area.y=0;
1112 sheet->column_title_area.width=0;
1113 sheet->column_title_area.height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
1115 sheet->row_title_window=NULL;
1116 sheet->row_title_area.x=0;
1117 sheet->row_title_area.y=0;
1118 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1119 sheet->row_title_area.height=0;
1122 sheet->active_cell.row=0;
1123 sheet->active_cell.col=0;
1124 sheet->selection_cell.row=0;
1125 sheet->selection_cell.col=0;
1127 sheet->sheet_entry=NULL;
1130 sheet->range.row0 = 0;
1131 sheet->range.rowi = 0;
1132 sheet->range.col0 = 0;
1133 sheet->range.coli = 0;
1135 sheet->state=GTK_SHEET_NORMAL;
1137 sheet->sheet_window = NULL;
1138 sheet->sheet_window_width = 0;
1139 sheet->sheet_window_height = 0;
1140 sheet->sheet_entry = NULL;
1141 sheet->button = NULL;
1146 sheet->hadjustment = NULL;
1147 sheet->vadjustment = NULL;
1149 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
1150 sheet->xor_gc = NULL;
1151 sheet->fg_gc = NULL;
1152 sheet->bg_gc = NULL;
1156 gdk_color_parse("white", &sheet->bg_color);
1157 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1158 gdk_color_parse("gray", &sheet->grid_color);
1159 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1160 sheet->show_grid = TRUE;
1164 /* Callback which occurs whenever columns are inserted/deleted in the model */
1166 columns_inserted_deleted_callback (GSheetModel *model, gint first_column, gint n_columns,
1170 GtkSheet *sheet = GTK_SHEET(data);
1172 GtkSheetRange range;
1173 gint model_columns = g_sheet_model_get_column_count(model);
1176 /* Need to update all the columns starting from the first column and onwards.
1177 * Previous column are unchanged, so don't need to be updated.
1179 range.col0 = first_column;
1181 range.coli = xxx_column_count(sheet) - 1;
1182 range.rowi = yyy_row_count(sheet) - 1;
1185 COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width + 1);
1188 COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
1190 if ( sheet->view.coli > range.coli)
1191 sheet->view.coli = range.coli;
1193 adjust_scrollbars(sheet);
1195 if (sheet->active_cell.col >= model_columns)
1196 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, model_columns - 1);
1198 for(i = first_column; i <= MAX_VISIBLE_COLUMN(sheet); i++)
1199 gtk_sheet_column_title_button_draw(sheet, i);
1201 gtk_sheet_range_draw(sheet, &range);
1205 /* Callback which occurs whenever rows are inserted/deleted in the model */
1207 rows_inserted_deleted_callback (GSheetModel *model, gint first_row, gint n_rows,
1211 GtkSheet *sheet = GTK_SHEET(data);
1213 GtkSheetRange range;
1215 gint model_rows = g_sheet_model_get_row_count(model);
1217 /* Need to update all the rows starting from the first row and onwards.
1218 * Previous rows are unchanged, so don't need to be updated.
1220 range.row0 = first_row;
1222 range.rowi = yyy_row_count(sheet) - 1;
1223 range.coli = xxx_column_count(sheet) - 1;
1226 ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height + 1);
1228 ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height - 1);
1230 if ( sheet->view.rowi > range.rowi)
1231 sheet->view.rowi = range.rowi;
1233 adjust_scrollbars(sheet);
1235 if (sheet->active_cell.row >= model_rows)
1236 gtk_sheet_activate_cell(sheet, model_rows - 1, sheet->active_cell.col);
1238 for(i = first_row; i <= MAX_VISIBLE_ROW(sheet); i++)
1239 gtk_sheet_row_title_button_draw(sheet, i);
1241 gtk_sheet_range_draw(sheet, &range);
1245 If row0 or rowi are negative, then all rows will be updated.
1246 If col0 or coli are negative, then all columns will be updated.
1249 range_update_callback (GSheetModel *m, gint row0, gint col0,
1250 gint rowi, gint coli, gpointer data)
1252 GtkSheet *sheet = GTK_SHEET(data);
1254 GtkSheetRange range;
1261 if( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
1263 gtk_sheet_range_draw(sheet, NULL);
1266 else if ( row0 < 0 || rowi < 0 )
1268 range.row0=MIN_VISIBLE_ROW(sheet);
1269 range.rowi=MAX_VISIBLE_ROW(sheet);
1271 else if ( col0 < 0 || coli < 0 )
1273 range.col0=MIN_VISIBLE_COLUMN(sheet);
1274 range.coli=MAX_VISIBLE_COLUMN(sheet);
1277 gtk_sheet_range_draw(sheet, &range);
1281 static void gtk_sheet_construct (GtkSheet *sheet,
1284 const gchar *title);
1289 * @rows: initial number of rows
1290 * @columns: initial number of columns
1291 * @title: sheet title
1292 * @model: the model to use for the sheet data
1294 * Creates a new sheet widget with the given number of rows and columns.
1296 * Returns: the new sheet widget
1299 gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, const gchar *title,
1304 widget = gtk_type_new (gtk_sheet_get_type ());
1306 gtk_sheet_construct(GTK_SHEET(widget), vgeo, hgeo, title);
1309 gtk_sheet_set_model(GTK_SHEET(widget), model);
1317 * gtk_sheet_set_model
1318 * @sheet: the sheet to set the model for
1319 * @model: the model to use for the sheet data
1321 * Sets the model for a GtkSheet
1325 gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model)
1327 g_return_if_fail (GTK_IS_SHEET (sheet));
1328 g_return_if_fail (G_IS_SHEET_MODEL (model));
1330 sheet->model = model;
1332 g_signal_connect(model, "range_changed",
1333 G_CALLBACK(range_update_callback), sheet);
1335 g_signal_connect(model, "rows_inserted",
1336 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1338 g_signal_connect(model, "rows_deleted",
1339 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1341 g_signal_connect(model, "columns_inserted",
1342 G_CALLBACK(columns_inserted_deleted_callback), sheet);
1344 g_signal_connect(model, "columns_deleted",
1345 G_CALLBACK(columns_inserted_deleted_callback), sheet);
1350 /* Call back for when the column titles have changed.
1351 FIRST is the first column changed.
1352 N_COLUMNS is the number of columns which have changed, or -1, which
1353 indicates that the column has changed to its right-most extremity
1356 column_titles_changed(GtkWidget *w, gint first, gint n_columns, gpointer data)
1358 GtkSheet *sheet = GTK_SHEET(data);
1359 gboolean extremity = FALSE;
1361 if ( n_columns == -1 )
1364 n_columns = xxx_column_count(sheet) - 1 ;
1367 if(!GTK_SHEET_IS_FROZEN(sheet))
1370 for ( i = first ; i <= first + n_columns ; ++i )
1372 gtk_sheet_column_title_button_draw(sheet, i);
1373 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, i);
1377 gtk_sheet_column_title_button_draw(sheet, -1);
1382 gtk_sheet_construct (GtkSheet *sheet,
1387 g_return_if_fail(G_IS_SHEET_COLUMN(hgeo));
1388 g_return_if_fail(G_IS_SHEET_ROW(vgeo));
1390 sheet->column_geometry = hgeo;
1391 sheet->row_geometry = vgeo;
1394 sheet->columns_resizable = TRUE;
1395 sheet->rows_resizable = TRUE;
1397 sheet->row_titles_visible = TRUE;
1398 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1400 sheet->column_titles_visible = TRUE;
1401 sheet->autoscroll = TRUE;
1402 sheet->justify_entry = TRUE;
1405 /* create sheet entry */
1406 sheet->entry_type = 0;
1407 create_sheet_entry (sheet);
1409 /* create global selection button */
1410 create_global_button(sheet);
1413 sheet->name = g_strdup(title);
1415 g_signal_connect(sheet->column_geometry, "columns_changed",
1416 G_CALLBACK(column_titles_changed), sheet);
1422 gtk_sheet_new_with_custom_entry (GSheetRow *rows, GSheetColumn *columns, const gchar *title,
1427 widget = gtk_type_new (gtk_sheet_get_type ());
1429 gtk_sheet_construct_with_custom_entry(GTK_SHEET(widget),
1430 rows, columns, title, entry_type);
1436 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet,
1442 gtk_sheet_construct(sheet, vgeo, hgeo, title);
1444 sheet->entry_type = entry_type;
1445 create_sheet_entry(sheet);
1451 gtk_sheet_change_entry(GtkSheet *sheet, GtkType entry_type)
1455 g_return_if_fail (sheet != NULL);
1456 g_return_if_fail (GTK_IS_SHEET (sheet));
1458 state = sheet->state;
1460 if(sheet->state == GTK_SHEET_NORMAL)
1461 gtk_sheet_hide_active_cell(sheet);
1463 sheet->entry_type = entry_type;
1465 create_sheet_entry(sheet);
1467 if(state == GTK_SHEET_NORMAL)
1469 gtk_sheet_show_active_cell(sheet);
1470 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
1472 G_CALLBACK(gtk_sheet_entry_changed),
1478 gtk_sheet_show_grid(GtkSheet *sheet, gboolean show)
1480 g_return_if_fail (sheet != NULL);
1481 g_return_if_fail (GTK_IS_SHEET (sheet));
1483 if(show == sheet->show_grid) return;
1485 sheet->show_grid = show;
1487 if(!GTK_SHEET_IS_FROZEN(sheet))
1488 gtk_sheet_range_draw(sheet, NULL);
1492 gtk_sheet_grid_visible(GtkSheet *sheet)
1494 g_return_val_if_fail (sheet != NULL, 0);
1495 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1497 return sheet->show_grid;
1501 gtk_sheet_set_background(GtkSheet *sheet, GdkColor *color)
1503 g_return_if_fail (sheet != NULL);
1504 g_return_if_fail (GTK_IS_SHEET (sheet));
1507 gdk_color_parse("white", &sheet->bg_color);
1508 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1510 sheet->bg_color = *color;
1512 if(!GTK_SHEET_IS_FROZEN(sheet))
1513 gtk_sheet_range_draw(sheet, NULL);
1517 gtk_sheet_set_grid(GtkSheet *sheet, GdkColor *color)
1519 g_return_if_fail (sheet != NULL);
1520 g_return_if_fail (GTK_IS_SHEET (sheet));
1523 gdk_color_parse("black", &sheet->grid_color);
1524 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1526 sheet->grid_color = *color;
1528 if(!GTK_SHEET_IS_FROZEN(sheet))
1529 gtk_sheet_range_draw(sheet, NULL);
1533 gtk_sheet_get_columns_count(GtkSheet *sheet)
1535 g_return_val_if_fail (sheet != NULL, 0);
1536 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1538 return xxx_column_count(sheet);
1542 gtk_sheet_get_rows_count(GtkSheet *sheet)
1544 g_return_val_if_fail (sheet != NULL, 0);
1545 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1547 return yyy_row_count(sheet);
1551 gtk_sheet_get_state(GtkSheet *sheet)
1553 g_return_val_if_fail (sheet != NULL, 0);
1554 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1556 return (sheet->state);
1560 gtk_sheet_set_selection_mode(GtkSheet *sheet, gint mode)
1562 g_return_if_fail (sheet != NULL);
1563 g_return_if_fail (GTK_IS_SHEET (sheet));
1565 if(GTK_WIDGET_REALIZED(sheet))
1566 gtk_sheet_real_unselect_range(sheet, NULL);
1568 sheet->selection_mode = mode;
1572 gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize)
1574 g_return_if_fail (sheet != NULL);
1575 g_return_if_fail (GTK_IS_SHEET (sheet));
1577 sheet->autoresize = autoresize;
1581 gtk_sheet_autoresize (GtkSheet *sheet)
1583 g_return_val_if_fail (sheet != NULL, FALSE);
1584 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1586 return sheet->autoresize;
1590 gtk_sheet_set_column_width (GtkSheet * sheet,
1596 gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
1598 gint text_width = 0;
1601 g_return_if_fail (sheet != NULL);
1602 g_return_if_fail (GTK_IS_SHEET (sheet));
1603 if (column >= xxx_column_count(sheet) || column < 0) return;
1605 for (row = 0; row < yyy_row_count(sheet); row++)
1607 gchar *text = gtk_sheet_cell_get_text(sheet, row, column);
1608 if (text && strlen(text) > 0){
1609 GtkSheetCellAttr attributes;
1611 gtk_sheet_get_attributes(sheet, row, column, &attributes);
1612 if(attributes.is_visible){
1613 gint width = STRING_WIDTH(GTK_WIDGET(sheet),
1614 attributes.font_desc,
1616 + 2*CELLOFFSET + attributes.border.width;
1617 text_width = MAX (text_width, width);
1620 dispose_string(sheet, text);
1623 if(text_width > xxx_column_width(sheet, column) )
1625 gtk_sheet_set_column_width(sheet, column, text_width);
1626 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
1632 gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll)
1634 g_return_if_fail (sheet != NULL);
1635 g_return_if_fail (GTK_IS_SHEET (sheet));
1637 sheet->autoscroll = autoscroll;
1641 gtk_sheet_autoscroll (GtkSheet *sheet)
1643 g_return_val_if_fail (sheet != NULL, FALSE);
1644 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1646 return sheet->autoscroll;
1650 gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text)
1652 g_return_if_fail (sheet != NULL);
1653 g_return_if_fail (GTK_IS_SHEET (sheet));
1655 sheet->clip_text = clip_text;
1659 gtk_sheet_clip_text (GtkSheet *sheet)
1661 g_return_val_if_fail (sheet != NULL, FALSE);
1662 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1664 return sheet->clip_text;
1668 gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify)
1670 g_return_if_fail (sheet != NULL);
1671 g_return_if_fail (GTK_IS_SHEET (sheet));
1673 sheet->justify_entry = justify;
1677 gtk_sheet_justify_entry (GtkSheet *sheet)
1679 g_return_val_if_fail (sheet != NULL, FALSE);
1680 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1682 return sheet->justify_entry;
1686 gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked)
1688 g_return_if_fail (sheet != NULL);
1689 g_return_if_fail (GTK_IS_SHEET (sheet));
1693 GTK_SHEET_SET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
1694 gtk_widget_hide(sheet->sheet_entry);
1695 gtk_widget_unmap(sheet->sheet_entry);
1699 GTK_SHEET_UNSET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
1700 if (GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)))
1702 gtk_widget_show (sheet->sheet_entry);
1703 gtk_widget_map (sheet->sheet_entry);
1707 gtk_entry_set_editable(GTK_ENTRY(sheet->sheet_entry), locked);
1712 gtk_sheet_locked (const GtkSheet *sheet)
1714 g_return_val_if_fail (sheet != NULL, FALSE);
1715 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1717 return GTK_SHEET_IS_LOCKED(sheet);
1720 /* This routine has problems with gtk+-1.2 related with the
1721 * label/button drawing - I think it's a bug in gtk+-1.2 */
1724 gtk_sheet_set_title(GtkSheet *sheet, const gchar *title)
1726 /* GtkWidget *old_widget;
1727 */ GtkWidget *label;
1729 g_return_if_fail (sheet != NULL);
1730 g_return_if_fail (title != NULL);
1731 g_return_if_fail (GTK_IS_SHEET (sheet));
1734 g_free (sheet->name);
1736 sheet->name = g_strdup (title);
1738 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) || !title) return;
1740 if(GTK_BIN(sheet->button)->child)
1741 label = GTK_BIN(sheet->button)->child;
1743 gtk_label_set_text(GTK_LABEL(label), title);
1745 size_allocate_global_button(sheet);
1747 /* remove and destroy the old widget */
1749 old_widget = GTK_BIN (sheet->button)->child;
1752 gtk_container_remove (GTK_CONTAINER (sheet->button), old_widget);
1755 label = gtk_label_new (title);
1756 gtk_misc_set_alignment(GTK_MISC(label), 0.5 , 0.5 );
1758 gtk_container_add (GTK_CONTAINER (sheet->button), label);
1759 gtk_widget_show (label);
1761 size_allocate_global_button(sheet);
1763 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, -1);
1766 gtk_widget_destroy (old_widget);
1771 gtk_sheet_freeze (GtkSheet *sheet)
1773 g_return_if_fail (sheet != NULL);
1774 g_return_if_fail (GTK_IS_SHEET (sheet));
1776 sheet->freeze_count++;
1777 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1781 gtk_sheet_thaw(GtkSheet *sheet)
1783 g_return_if_fail (sheet != NULL);
1784 g_return_if_fail (GTK_IS_SHEET (sheet));
1786 if(sheet->freeze_count == 0) return;
1788 sheet->freeze_count--;
1789 if(sheet->freeze_count > 0) return;
1791 adjust_scrollbars(sheet);
1793 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1795 sheet->old_vadjustment = -1.;
1796 sheet->old_hadjustment = -1.;
1798 if(sheet->hadjustment)
1799 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1801 if(sheet->vadjustment)
1802 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1805 if(sheet->state == GTK_STATE_NORMAL)
1806 if(sheet->sheet_entry && GTK_WIDGET_MAPPED(sheet->sheet_entry)){
1807 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
1809 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
1811 (GtkSignalFunc)gtk_sheet_entry_changed,
1812 GTK_OBJECT(GTK_WIDGET(sheet)));
1813 gtk_sheet_show_active_cell(sheet);
1820 gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width)
1822 if(width < COLUMN_MIN_WIDTH) return;
1824 sheet->row_title_area.width = width;
1825 sheet->view.col0 = COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
1826 sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
1829 adjust_scrollbars(sheet);
1831 sheet->old_hadjustment = -1.;
1832 if(sheet->hadjustment)
1833 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1835 size_allocate_global_button(sheet);
1839 gtk_sheet_set_column_titles_height(GtkSheet *sheet, guint height)
1841 if(height < DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))) return;
1843 sheet->column_title_area.height = height;
1844 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
1845 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
1847 adjust_scrollbars(sheet);
1849 sheet->old_vadjustment = -1.;
1850 if(sheet->vadjustment)
1851 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1853 size_allocate_global_button(sheet);
1857 gtk_sheet_show_column_titles(GtkSheet *sheet)
1861 if(sheet->column_titles_visible) return;
1863 sheet->column_titles_visible = TRUE;
1866 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1867 gdk_window_show(sheet->column_title_window);
1868 gdk_window_move_resize (sheet->column_title_window,
1869 sheet->column_title_area.x,
1870 sheet->column_title_area.y,
1871 sheet->column_title_area.width,
1872 sheet->column_title_area.height);
1874 for(col = MIN_VISIBLE_COLUMN(sheet);
1875 col <= MAX_VISIBLE_COLUMN(sheet);
1878 GtkSheetButton *button = xxx_column_button(sheet, col);
1879 GtkSheetChild *child = button->child;
1881 gtk_sheet_child_show(child);
1882 gtk_sheet_button_free(button);
1884 adjust_scrollbars(sheet);
1887 sheet->old_vadjustment = -1.;
1888 if(sheet->vadjustment)
1889 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1891 size_allocate_global_button(sheet);
1896 gtk_sheet_show_row_titles(GtkSheet *sheet)
1900 if(sheet->row_titles_visible) return;
1902 sheet->row_titles_visible = TRUE;
1905 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1906 gdk_window_show(sheet->row_title_window);
1907 gdk_window_move_resize (sheet->row_title_window,
1908 sheet->row_title_area.x,
1909 sheet->row_title_area.y,
1910 sheet->row_title_area.width,
1911 sheet->row_title_area.height);
1913 for(row = MIN_VISIBLE_ROW(sheet);
1914 row <= MAX_VISIBLE_ROW(sheet);
1917 const GtkSheetButton *button = yyy_row_button(sheet, row);
1918 GtkSheetChild *child = button->child;
1921 gtk_sheet_child_show(child);
1924 adjust_scrollbars(sheet);
1927 sheet->old_hadjustment = -1.;
1928 if(sheet->hadjustment)
1929 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1931 size_allocate_global_button(sheet);
1935 gtk_sheet_hide_column_titles(GtkSheet *sheet)
1939 if(!sheet->column_titles_visible) return;
1941 sheet->column_titles_visible = FALSE;
1943 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1944 if(sheet->column_title_window)
1945 gdk_window_hide(sheet->column_title_window);
1946 if(GTK_WIDGET_VISIBLE(sheet->button))
1947 gtk_widget_hide(sheet->button);
1949 for(col = MIN_VISIBLE_COLUMN(sheet);
1950 col <= MAX_VISIBLE_COLUMN(sheet);
1953 GtkSheetButton *button = xxx_column_button(sheet, col);
1954 GtkSheetChild *child = button->child;
1956 gtk_sheet_child_hide(child);
1957 gtk_sheet_button_free(button);
1959 adjust_scrollbars(sheet);
1962 sheet->old_vadjustment = -1.;
1963 if(sheet->vadjustment)
1964 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1969 gtk_sheet_hide_row_titles(GtkSheet *sheet)
1973 if(!sheet->row_titles_visible) return;
1975 sheet->row_titles_visible = FALSE;
1978 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1979 if(sheet->row_title_window)
1980 gdk_window_hide(sheet->row_title_window);
1981 if(GTK_WIDGET_VISIBLE(sheet->button))
1982 gtk_widget_hide(sheet->button);
1983 for(row = MIN_VISIBLE_ROW(sheet);
1984 row <= MAX_VISIBLE_ROW(sheet);
1987 const GtkSheetButton *button = yyy_row_button(sheet, row);
1988 GtkSheetChild *child = button->child;
1991 gtk_sheet_child_hide(child);
1993 adjust_scrollbars(sheet);
1996 sheet->old_hadjustment = -1.;
1997 if(sheet->hadjustment)
1998 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
2003 gtk_sheet_column_titles_visible(GtkSheet *sheet)
2005 g_return_val_if_fail (sheet != NULL, FALSE);
2006 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2007 return sheet->column_titles_visible;
2011 gtk_sheet_row_titles_visible(GtkSheet *sheet)
2013 g_return_val_if_fail (sheet != NULL, FALSE);
2014 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2015 return sheet->row_titles_visible;
2021 gtk_sheet_moveto (GtkSheet * sheet,
2028 guint width, height;
2030 gint min_row, min_col;
2032 g_return_if_fail (sheet != NULL);
2033 g_return_if_fail (GTK_IS_SHEET (sheet));
2034 g_return_if_fail (sheet->hadjustment != NULL);
2035 g_return_if_fail (sheet->vadjustment != NULL);
2037 if (row < 0 || row >= yyy_row_count(sheet))
2039 if (column < 0 || column >= xxx_column_count(sheet))
2042 height = sheet->sheet_window_height;
2043 width = sheet->sheet_window_width;
2045 /* adjust vertical scrollbar */
2047 if (row >= 0 && row_align >=0.)
2050 y = ROW_TOP_YPIXEL(sheet, row) - sheet->voffset -
2052 (1.-row_align)*yyy_row_height(sheet, row);
2054 y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
2055 - (gint) ( row_align*height + (1. - row_align) * yyy_row_height(sheet, row));
2057 /* This forces the sheet to scroll when you don't see the entire cell */
2060 if(row_align == 1.){
2061 while(min_row >= 0 && min_row > MIN_VISIBLE_ROW(sheet)){
2062 if(yyy_row_is_visible(sheet, min_row))
2063 adjust += yyy_row_height(sheet, min_row);
2064 if(adjust >= height){
2069 min_row = MAX(min_row, 0);
2070 y = ROW_TOP_YPIXEL(sheet, min_row) - sheet->voffset +
2071 yyy_row_height(sheet, min_row) - 1;
2075 sheet->vadjustment->value = 0.0;
2077 sheet->vadjustment->value = y;
2079 sheet->old_vadjustment = -1.;
2080 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
2085 /* adjust horizontal scrollbar */
2086 if (column >= 0 && col_align >= 0.)
2089 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset -
2091 (1.-col_align)*sheet->column[column].width;
2093 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
2094 - (gint) ( col_align*width + (1.-col_align)*
2095 xxx_column_width(sheet, column));
2098 /* This forces the sheet to scroll when you don't see the entire cell */
2101 if(col_align == 1.){
2102 while(min_col >= 0 && min_col > MIN_VISIBLE_COLUMN(sheet)){
2103 if(xxx_column_is_visible(sheet, min_col))
2104 adjust += xxx_column_width(sheet, min_col);
2106 if(adjust >= width){
2111 min_col = MAX(min_col, 0);
2112 x = COLUMN_LEFT_XPIXEL(sheet, min_col) - sheet->hoffset +
2113 xxx_column_width(sheet, min_col) - 1;
2117 sheet->hadjustment->value = 0.0;
2119 sheet->hadjustment->value = x;
2121 sheet->old_vadjustment = -1.;
2122 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
2130 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
2132 g_return_if_fail (sheet != NULL);
2133 g_return_if_fail (GTK_IS_SHEET (sheet));
2135 sheet->columns_resizable = resizable;
2139 gtk_sheet_columns_resizable (GtkSheet *sheet)
2141 g_return_val_if_fail (sheet != NULL, FALSE);
2142 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2144 return sheet->columns_resizable;
2149 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
2151 g_return_if_fail (sheet != NULL);
2152 g_return_if_fail (GTK_IS_SHEET (sheet));
2154 sheet->rows_resizable = resizable;
2158 gtk_sheet_rows_resizable (GtkSheet *sheet)
2160 g_return_val_if_fail (sheet != NULL, FALSE);
2161 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2163 return sheet->rows_resizable;
2168 gtk_sheet_select_row (GtkSheet * sheet,
2171 g_return_if_fail (sheet != NULL);
2172 g_return_if_fail (GTK_IS_SHEET (sheet));
2174 if (row < 0 || row >= yyy_row_count(sheet))
2177 if(sheet->state != GTK_SHEET_NORMAL)
2178 gtk_sheet_real_unselect_range(sheet, NULL);
2181 gboolean veto = TRUE;
2182 veto = gtk_sheet_deactivate_cell(sheet);
2186 sheet->state=GTK_SHEET_ROW_SELECTED;
2187 sheet->range.row0 = row;
2188 sheet->range.col0 = 0;
2189 sheet->range.rowi = row;
2190 sheet->range.coli = xxx_column_count(sheet) - 1;
2191 sheet->active_cell.row = row;
2192 sheet->active_cell.col = 0;
2194 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_ROW], row);
2195 gtk_sheet_real_select_range(sheet, NULL);
2200 gtk_sheet_select_column (GtkSheet * sheet, gint column)
2202 g_return_if_fail (sheet != NULL);
2203 g_return_if_fail (GTK_IS_SHEET (sheet));
2205 if (column < 0 || column >= xxx_column_count(sheet))
2208 if(sheet->state != GTK_SHEET_NORMAL)
2209 gtk_sheet_real_unselect_range(sheet, NULL);
2212 gboolean veto = TRUE;
2213 veto = gtk_sheet_deactivate_cell(sheet);
2217 sheet->state=GTK_SHEET_COLUMN_SELECTED;
2218 sheet->range.row0 = 0;
2219 sheet->range.col0 = column;
2220 sheet->range.rowi = yyy_row_count(sheet) - 1;
2221 sheet->range.coli = column;
2222 sheet->active_cell.row = 0;
2223 sheet->active_cell.col = column;
2225 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_COLUMN], column);
2226 gtk_sheet_real_select_range(sheet, NULL);
2230 gtk_sheet_clip_range (GtkSheet *sheet, const GtkSheetRange *range)
2233 g_return_if_fail (sheet != NULL);
2234 g_return_if_fail (GTK_IS_SHEET (sheet));
2236 if(GTK_SHEET_IN_CLIP(sheet)) return;
2238 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2241 sheet->clip_range = sheet->range;
2243 sheet->clip_range=*range;
2246 sheet->clip_timer=gtk_timeout_add(TIMEOUT_FLASH, gtk_sheet_flash, sheet);
2248 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CLIP_RANGE],
2249 &sheet->clip_range);
2254 gtk_sheet_unclip_range(GtkSheet *sheet)
2257 g_return_if_fail (sheet != NULL);
2258 g_return_if_fail (GTK_IS_SHEET (sheet));
2260 if(!GTK_SHEET_IN_CLIP(sheet)) return;
2262 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2263 gtk_timeout_remove(sheet->clip_timer);
2264 gtk_sheet_range_draw(sheet, &sheet->clip_range);
2266 if(gtk_sheet_range_isvisible(sheet, sheet->range))
2267 gtk_sheet_range_draw(sheet, &sheet->range);
2271 gtk_sheet_in_clip (GtkSheet *sheet)
2273 g_return_val_if_fail (sheet != NULL, FALSE);
2274 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2276 return GTK_SHEET_IN_CLIP(sheet);
2280 gtk_sheet_flash(gpointer data)
2283 gint x,y,width,height;
2284 GdkRectangle clip_area;
2286 sheet=GTK_SHEET(data);
2288 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return TRUE;
2289 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return TRUE;
2290 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return TRUE;
2291 if(GTK_SHEET_IN_XDRAG(sheet)) return TRUE;
2292 if(GTK_SHEET_IN_YDRAG(sheet)) return TRUE;
2294 GDK_THREADS_ENTER();
2296 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2297 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2298 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2299 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2300 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2301 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2303 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2304 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2305 clip_area.width=sheet->sheet_window_width;
2306 clip_area.height=sheet->sheet_window_height;
2312 if(width>clip_area.width) width=clip_area.width+10;
2317 if(height>clip_area.height) height=clip_area.height+10;
2319 gdk_draw_pixmap(sheet->sheet_window,
2320 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2326 gdk_draw_pixmap(sheet->sheet_window,
2327 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2333 gdk_draw_pixmap(sheet->sheet_window,
2334 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2340 gdk_draw_pixmap(sheet->sheet_window,
2341 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2348 sheet->interval=sheet->interval+1;
2349 if(sheet->interval==TIME_INTERVAL) sheet->interval=0;
2351 gdk_gc_set_dashes(sheet->xor_gc, sheet->interval, (gint8*)"\4\4", 2);
2352 gtk_sheet_draw_flashing_range(sheet,sheet->clip_range);
2353 gdk_gc_set_dashes(sheet->xor_gc, 0, (gint8*)"\4\4", 2);
2355 GDK_THREADS_LEAVE();
2362 gtk_sheet_draw_flashing_range(GtkSheet *sheet, GtkSheetRange range)
2364 GdkRectangle clip_area;
2365 gint x,y,width,height;
2367 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return;
2369 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2370 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2371 clip_area.width=sheet->sheet_window_width;
2372 clip_area.height=sheet->sheet_window_height;
2374 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
2376 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2377 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2378 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2379 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2380 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2381 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2387 if(width>clip_area.width) width=clip_area.width+10;
2392 if(height>clip_area.height) height=clip_area.height+10;
2394 gdk_gc_set_line_attributes(sheet->xor_gc, 1, 1, 0 ,0 );
2396 gdk_draw_rectangle(sheet->sheet_window, sheet->xor_gc, FALSE,
2400 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 0, 0, 0);
2402 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
2407 gtk_sheet_range_isvisible (GtkSheet * sheet,
2408 GtkSheetRange range)
2410 g_return_val_if_fail (sheet != NULL, FALSE);
2412 if (range.row0 < 0 || range.row0 >= yyy_row_count(sheet))
2415 if (range.rowi < 0 || range.rowi >= yyy_row_count(sheet))
2418 if (range.col0 < 0 || range.col0 >= xxx_column_count(sheet))
2421 if (range.coli < 0 || range.coli >= xxx_column_count(sheet))
2424 if (range.rowi < MIN_VISIBLE_ROW (sheet))
2427 if (range.row0 > MAX_VISIBLE_ROW (sheet))
2430 if (range.coli < MIN_VISIBLE_COLUMN (sheet))
2433 if (range.col0 > MAX_VISIBLE_COLUMN (sheet))
2440 gtk_sheet_cell_isvisible (GtkSheet * sheet,
2441 gint row, gint column)
2443 GtkSheetRange range;
2446 range.col0 = column;
2448 range.coli = column;
2450 return gtk_sheet_range_isvisible(sheet, range);
2454 gtk_sheet_get_visible_range(GtkSheet *sheet, GtkSheetRange *range)
2457 g_return_if_fail (sheet != NULL);
2458 g_return_if_fail (GTK_IS_SHEET (sheet)) ;
2459 g_return_if_fail (range != NULL);
2461 range->row0 = MIN_VISIBLE_ROW(sheet);
2462 range->col0 = MIN_VISIBLE_COLUMN(sheet);
2463 range->rowi = MAX_VISIBLE_ROW(sheet);
2464 range->coli = MAX_VISIBLE_COLUMN(sheet);
2469 gtk_sheet_get_vadjustment (GtkSheet * sheet)
2471 g_return_val_if_fail (sheet != NULL, NULL);
2472 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2474 return sheet->vadjustment;
2478 gtk_sheet_get_hadjustment (GtkSheet * sheet)
2480 g_return_val_if_fail (sheet != NULL, NULL);
2481 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2483 return sheet->hadjustment;
2487 gtk_sheet_set_vadjustment (GtkSheet *sheet,
2488 GtkAdjustment *adjustment)
2490 GtkAdjustment *old_adjustment;
2492 g_return_if_fail (sheet != NULL);
2493 g_return_if_fail (GTK_IS_SHEET (sheet));
2495 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2497 if (sheet->vadjustment == adjustment)
2500 old_adjustment = sheet->vadjustment;
2502 if (sheet->vadjustment)
2504 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2505 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2508 sheet->vadjustment = adjustment;
2510 if (sheet->vadjustment)
2512 gtk_object_ref (GTK_OBJECT (sheet->vadjustment));
2513 gtk_object_sink (GTK_OBJECT (sheet->vadjustment));
2515 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "changed",
2516 (GtkSignalFunc) vadjustment_changed,
2518 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "value_changed",
2519 (GtkSignalFunc) vadjustment_value_changed,
2523 if (!sheet->vadjustment || !old_adjustment)
2525 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2529 sheet->old_vadjustment = sheet->vadjustment->value;
2533 gtk_sheet_set_hadjustment (GtkSheet *sheet,
2534 GtkAdjustment *adjustment)
2536 GtkAdjustment *old_adjustment;
2538 g_return_if_fail (sheet != NULL);
2539 g_return_if_fail (GTK_IS_SHEET (sheet));
2541 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2543 if (sheet->hadjustment == adjustment)
2546 old_adjustment = sheet->hadjustment;
2548 if (sheet->hadjustment)
2550 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2551 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2554 sheet->hadjustment = adjustment;
2556 if (sheet->hadjustment)
2558 gtk_object_ref (GTK_OBJECT (sheet->hadjustment));
2559 gtk_object_sink (GTK_OBJECT (sheet->hadjustment));
2561 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "changed",
2562 (GtkSignalFunc) hadjustment_changed,
2564 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "value_changed",
2565 (GtkSignalFunc) hadjustment_value_changed,
2569 if (!sheet->hadjustment || !old_adjustment)
2571 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2575 sheet->old_hadjustment = sheet->hadjustment->value;
2579 gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
2580 GtkAdjustment *hadjustment,
2581 GtkAdjustment *vadjustment)
2583 if(sheet->hadjustment != hadjustment)
2584 gtk_sheet_set_hadjustment (sheet, hadjustment);
2586 if(sheet->vadjustment != vadjustment)
2587 gtk_sheet_set_vadjustment (sheet, vadjustment);
2591 gtk_sheet_finalize (GObject * object)
2595 g_return_if_fail (object != NULL);
2596 g_return_if_fail (GTK_IS_SHEET (object));
2598 sheet = GTK_SHEET (object);
2600 /* get rid of all the cells */
2601 gtk_sheet_range_clear (sheet, NULL);
2602 gtk_sheet_range_delete(sheet, NULL);
2605 g_free(sheet->name);
2609 if (G_OBJECT_CLASS (parent_class)->finalize)
2610 (*G_OBJECT_CLASS (parent_class)->finalize) (object);
2614 gtk_sheet_destroy (GtkObject * object)
2619 g_return_if_fail (object != NULL);
2620 g_return_if_fail (GTK_IS_SHEET (object));
2622 sheet = GTK_SHEET (object);
2624 /* destroy the entry */
2625 if(sheet->sheet_entry && GTK_IS_WIDGET(sheet->sheet_entry)){
2626 gtk_widget_destroy (sheet->sheet_entry);
2627 sheet->sheet_entry = NULL;
2630 /* destroy the global selection button */
2631 if(sheet->button && GTK_IS_WIDGET(sheet->button)){
2632 gtk_widget_destroy (sheet->button);
2633 sheet->button = NULL;
2637 gtk_timeout_remove(sheet->timer);
2641 if(sheet->clip_timer){
2642 gtk_timeout_remove(sheet->clip_timer);
2643 sheet->clip_timer = 0;
2646 /* unref adjustments */
2647 if (sheet->hadjustment)
2649 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2650 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2651 sheet->hadjustment = NULL;
2653 if (sheet->vadjustment)
2655 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2656 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2657 sheet->vadjustment = NULL;
2660 children = sheet->children;
2662 GtkSheetChild *child = (GtkSheetChild *)children->data;
2663 if(child && child->widget)
2664 gtk_sheet_remove(GTK_CONTAINER(sheet), child->widget);
2665 children = sheet->children;
2667 sheet->children = NULL;
2669 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2670 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2674 gtk_sheet_style_set (GtkWidget *widget,
2675 GtkStyle *previous_style)
2679 g_return_if_fail (widget != NULL);
2680 g_return_if_fail (GTK_IS_SHEET (widget));
2682 if (GTK_WIDGET_CLASS (parent_class)->style_set)
2683 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
2685 sheet = GTK_SHEET (widget);
2687 if(GTK_WIDGET_REALIZED(widget))
2689 gtk_style_set_background (widget->style, widget->window, widget->state);
2695 gtk_sheet_realize (GtkWidget * widget)
2698 GdkWindowAttr attributes;
2699 gint attributes_mask;
2700 GdkGCValues values, auxvalues;
2701 GdkColormap *colormap;
2703 GtkSheetChild *child;
2706 g_return_if_fail (widget != NULL);
2707 g_return_if_fail (GTK_IS_SHEET (widget));
2709 sheet = GTK_SHEET (widget);
2711 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2713 attributes.window_type = GDK_WINDOW_CHILD;
2714 attributes.x = widget->allocation.x;
2715 attributes.y = widget->allocation.y;
2716 attributes.width = widget->allocation.width;
2717 attributes.height = widget->allocation.height;
2718 attributes.wclass = GDK_INPUT_OUTPUT;
2720 attributes.visual = gtk_widget_get_visual (widget);
2721 attributes.colormap = gtk_widget_get_colormap (widget);
2723 attributes.event_mask = gtk_widget_get_events (widget);
2724 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2725 GDK_BUTTON_PRESS_MASK |
2726 GDK_BUTTON_RELEASE_MASK |
2727 GDK_KEY_PRESS_MASK |
2728 GDK_POINTER_MOTION_MASK |
2729 GDK_POINTER_MOTION_HINT_MASK);
2730 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
2733 attributes.cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
2736 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2738 gdk_window_set_user_data (widget->window, sheet);
2740 widget->style = gtk_style_attach (widget->style, widget->window);
2742 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2745 if(sheet->row_titles_visible)
2746 attributes.x = sheet->row_title_area.width;
2748 attributes.width = sheet->column_title_area.width;
2749 attributes.height = sheet->column_title_area.height;
2751 /* column-title window */
2752 sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2753 gdk_window_set_user_data (sheet->column_title_window, sheet);
2754 gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL);
2758 if(sheet->column_titles_visible)
2759 attributes.y = sheet->column_title_area.height;
2760 attributes.width = sheet->row_title_area.width;
2761 attributes.height = sheet->row_title_area.height;
2763 /* row-title window */
2764 sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2765 gdk_window_set_user_data (sheet->row_title_window, sheet);
2766 gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL);
2769 attributes.cursor = gdk_cursor_new(GDK_PLUS);
2773 attributes.width = sheet->sheet_window_width,
2774 attributes.height = sheet->sheet_window_height;
2776 sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2777 gdk_window_set_user_data (sheet->sheet_window, sheet);
2779 gdk_cursor_unref(attributes.cursor);
2781 gdk_window_set_background (sheet->sheet_window, &widget->style->white);
2782 gdk_window_show (sheet->sheet_window);
2784 /* backing_pixmap */
2785 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
2789 gdk_gc_unref(sheet->fg_gc);
2791 gdk_gc_unref(sheet->bg_gc);
2792 sheet->fg_gc = gdk_gc_new (widget->window);
2793 sheet->bg_gc = gdk_gc_new (widget->window);
2795 colormap = gtk_widget_get_colormap(widget);
2797 gdk_color_white(colormap, &widget->style->white);
2798 gdk_color_black(colormap, &widget->style->black);
2800 gdk_gc_get_values(sheet->fg_gc, &auxvalues);
2802 values.foreground = widget->style->white;
2803 values.function = GDK_INVERT;
2804 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2806 gdk_gc_unref(sheet->xor_gc);
2807 sheet->xor_gc = gdk_gc_new_with_values (widget->window,
2813 if(sheet->sheet_entry->parent){
2814 gtk_widget_ref(sheet->sheet_entry);
2815 gtk_widget_unparent(sheet->sheet_entry);
2817 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
2818 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
2820 if(sheet->button && sheet->button->parent){
2821 gtk_widget_ref(sheet->button);
2822 gtk_widget_unparent(sheet->button);
2824 gtk_widget_set_parent_window(sheet->button, sheet->sheet_window);
2825 gtk_widget_set_parent(sheet->button, GTK_WIDGET(sheet));
2828 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
2830 if(!sheet->cursor_drag)
2831 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
2833 if(sheet->column_titles_visible)
2834 gdk_window_show(sheet->column_title_window);
2835 if(sheet->row_titles_visible)
2836 gdk_window_show(sheet->row_title_window);
2838 size_allocate_row_title_buttons(sheet);
2839 size_allocate_column_title_buttons(sheet);
2841 name = g_strdup(sheet->name);
2842 gtk_sheet_set_title(sheet, name);
2846 children = sheet->children;
2849 child = children->data;
2850 children = children->next;
2852 gtk_sheet_realize_child(sheet, child);
2857 create_global_button(GtkSheet *sheet)
2859 sheet->button = gtk_button_new_with_label(" ");
2861 gtk_signal_connect (GTK_OBJECT (sheet->button),
2863 (GtkSignalFunc) global_button_clicked,
2868 size_allocate_global_button(GtkSheet *sheet)
2870 GtkAllocation allocation;
2872 if(!sheet->column_titles_visible) return;
2873 if(!sheet->row_titles_visible) return;
2875 gtk_widget_size_request(sheet->button, NULL);
2879 allocation.width=sheet->row_title_area.width;
2880 allocation.height=sheet->column_title_area.height;
2882 gtk_widget_size_allocate(sheet->button, &allocation);
2883 gtk_widget_show(sheet->button);
2887 global_button_clicked(GtkWidget *widget, gpointer data)
2891 gtk_sheet_click_cell(GTK_SHEET(data), -1, -1, &veto);
2892 gtk_widget_grab_focus(GTK_WIDGET(data));
2897 gtk_sheet_unrealize (GtkWidget * widget)
2901 g_return_if_fail (widget != NULL);
2902 g_return_if_fail (GTK_IS_SHEET (widget));
2904 sheet = GTK_SHEET (widget);
2906 gdk_cursor_destroy (sheet->cursor_drag);
2908 gdk_gc_destroy (sheet->xor_gc);
2909 gdk_gc_destroy (sheet->fg_gc);
2910 gdk_gc_destroy (sheet->bg_gc);
2912 gdk_window_destroy (sheet->sheet_window);
2913 gdk_window_destroy (sheet->column_title_window);
2914 gdk_window_destroy (sheet->row_title_window);
2917 g_object_unref(sheet->pixmap);
2918 sheet->pixmap = NULL;
2921 sheet->column_title_window=NULL;
2922 sheet->sheet_window = NULL;
2923 sheet->cursor_drag = NULL;
2924 sheet->xor_gc = NULL;
2925 sheet->fg_gc = NULL;
2926 sheet->bg_gc = NULL;
2928 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2929 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2933 gtk_sheet_map (GtkWidget * widget)
2936 GtkSheetChild *child;
2939 g_return_if_fail (widget != NULL);
2940 g_return_if_fail (GTK_IS_SHEET (widget));
2942 sheet = GTK_SHEET (widget);
2944 if (!GTK_WIDGET_MAPPED (widget))
2946 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2948 if(!sheet->cursor_drag) sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
2950 gdk_window_show (widget->window);
2952 gdk_window_show (sheet->sheet_window);
2954 if(sheet->column_titles_visible){
2955 size_allocate_column_title_buttons(sheet);
2956 gdk_window_show (sheet->column_title_window);
2958 if(sheet->row_titles_visible){
2959 size_allocate_row_title_buttons(sheet);
2960 gdk_window_show (sheet->row_title_window);
2963 if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)
2964 && ! gtk_sheet_locked(sheet)
2965 && sheet->active_cell.row >=0
2966 && sheet->active_cell.col >=0 )
2968 gtk_widget_show (sheet->sheet_entry);
2969 gtk_widget_map (sheet->sheet_entry);
2972 if (GTK_WIDGET_VISIBLE (sheet->button) &&
2973 !GTK_WIDGET_MAPPED (sheet->button)){
2974 gtk_widget_show(sheet->button);
2975 gtk_widget_map (sheet->button);
2978 if(GTK_BIN(sheet->button)->child)
2979 if (GTK_WIDGET_VISIBLE (GTK_BIN(sheet->button)->child) &&
2980 !GTK_WIDGET_MAPPED (GTK_BIN(sheet->button)->child))
2981 gtk_widget_map (GTK_BIN(sheet->button)->child);
2983 gtk_sheet_range_draw(sheet, NULL);
2984 gtk_sheet_activate_cell(sheet,
2985 sheet->active_cell.row,
2986 sheet->active_cell.col);
2988 children = sheet->children;
2991 child = children->data;
2992 children = children->next;
2994 if (GTK_WIDGET_VISIBLE (child->widget) &&
2995 !GTK_WIDGET_MAPPED (child->widget)){
2996 gtk_widget_map (child->widget);
2997 gtk_sheet_position_child(sheet, child);
3005 gtk_sheet_unmap (GtkWidget * widget)
3008 GtkSheetChild *child;
3011 g_return_if_fail (widget != NULL);
3012 g_return_if_fail (GTK_IS_SHEET (widget));
3014 sheet = GTK_SHEET (widget);
3016 if (GTK_WIDGET_MAPPED (widget))
3018 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
3020 gdk_window_hide (sheet->sheet_window);
3021 if(sheet->column_titles_visible)
3022 gdk_window_hide (sheet->column_title_window);
3023 if(sheet->row_titles_visible)
3024 gdk_window_hide (sheet->row_title_window);
3025 gdk_window_hide (widget->window);
3027 if (GTK_WIDGET_MAPPED (sheet->sheet_entry))
3028 gtk_widget_unmap (sheet->sheet_entry);
3030 if (GTK_WIDGET_MAPPED (sheet->button))
3031 gtk_widget_unmap (sheet->button);
3033 children = sheet->children;
3036 child = children->data;
3037 children = children->next;
3039 if (GTK_WIDGET_VISIBLE (child->widget) &&
3040 GTK_WIDGET_MAPPED (child->widget))
3042 gtk_widget_unmap (child->widget);
3051 gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
3054 GdkGC *fg_gc, *bg_gc;
3055 GtkSheetCellAttr attributes;
3058 g_return_if_fail (sheet != NULL);
3060 /* bail now if we arn't drawable yet */
3061 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
3063 if (row < 0 || row >= yyy_row_count(sheet)) return;
3064 if (col < 0 || col >= xxx_column_count(sheet)) return;
3065 if (! xxx_column_is_visible(sheet, col)) return;
3066 if (! yyy_row_is_visible(sheet, row)) return;
3068 widget = GTK_WIDGET (sheet);
3070 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3072 /* select GC for background rectangle */
3073 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3074 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3076 fg_gc = sheet->fg_gc;
3077 bg_gc = sheet->bg_gc;
3079 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3080 area.y=ROW_TOP_YPIXEL(sheet,row);
3081 area.width= xxx_column_width(sheet, col);
3082 area.height=yyy_row_height(sheet, row);
3084 gdk_draw_rectangle (sheet->pixmap,
3092 gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0);
3094 if(sheet->show_grid){
3095 gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color);
3097 gdk_draw_rectangle (sheet->pixmap,
3101 area.width, area.height);
3106 gtk_sheet_cell_draw_border (GtkSheet *sheet, gint row, gint col, gint mask)
3109 GdkGC *fg_gc, *bg_gc;
3110 GtkSheetCellAttr attributes;
3114 g_return_if_fail (sheet != NULL);
3116 /* bail now if we arn't drawable yet */
3117 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
3119 if (row < 0 || row >= yyy_row_count(sheet)) return;
3120 if (col < 0 || col >= xxx_column_count(sheet)) return;
3121 if (!xxx_column_is_visible(sheet, col)) return;
3122 if (!yyy_row_is_visible(sheet, row)) return;
3124 widget = GTK_WIDGET (sheet);
3126 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3128 /* select GC for background rectangle */
3129 gdk_gc_set_foreground (sheet->fg_gc, &attributes.border.color);
3130 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3132 fg_gc = sheet->fg_gc;
3133 bg_gc = sheet->bg_gc;
3135 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3136 area.y=ROW_TOP_YPIXEL(sheet,row);
3137 area.width=xxx_column_width(sheet, col);
3138 area.height=yyy_row_height(sheet, row);
3140 width = attributes.border.width;
3141 gdk_gc_set_line_attributes(sheet->fg_gc, attributes.border.width,
3142 attributes.border.line_style,
3143 attributes.border.cap_style,
3144 attributes.border.join_style);
3147 if(attributes.border.mask & GTK_SHEET_LEFT_BORDER & mask)
3148 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3149 area.x, area.y-width/2,
3150 area.x, area.y+area.height+width/2+1);
3152 if(attributes.border.mask & GTK_SHEET_RIGHT_BORDER & mask)
3153 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3154 area.x+area.width, area.y-width/2,
3156 area.y+area.height+width/2+1);
3158 if(attributes.border.mask & GTK_SHEET_TOP_BORDER & mask)
3159 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3160 area.x-width/2,area.y,
3161 area.x+area.width+width/2+1,
3164 if(attributes.border.mask & GTK_SHEET_BOTTOM_BORDER & mask)
3165 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3166 area.x-width/2, area.y+area.height,
3167 area.x+area.width+width/2+1,
3168 area.y+area.height);
3175 gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
3178 GdkRectangle area, clip_area;
3180 gint text_width, text_height, y;
3182 gint size, sizel, sizer;
3183 GdkGC *fg_gc, *bg_gc;
3184 GtkSheetCellAttr attributes;
3185 PangoLayout *layout;
3186 PangoRectangle rect;
3187 PangoRectangle logical_rect;
3188 PangoLayoutLine *line;
3189 PangoFontMetrics *metrics;
3190 PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet));
3191 gint ascent, descent, y_pos;
3195 g_return_if_fail (sheet != NULL);
3197 /* bail now if we aren't drawable yet */
3198 if (!GTK_WIDGET_DRAWABLE (sheet))
3201 label = gtk_sheet_cell_get_text(sheet, row, col);
3205 if (row < 0 || row >= yyy_row_count(sheet)) return;
3206 if (col < 0 || col >= xxx_column_count(sheet)) return;
3207 if (! xxx_column_is_visible(sheet, col)) return;
3208 if (!yyy_row_is_visible(sheet, row)) return;
3211 widget = GTK_WIDGET(sheet);
3213 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3215 /* select GC for background rectangle */
3216 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3217 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3219 fg_gc = sheet->fg_gc;
3220 bg_gc = sheet->bg_gc;
3222 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3223 area.y=ROW_TOP_YPIXEL(sheet,row);
3224 area.width = xxx_column_width(sheet, col);
3225 area.height = yyy_row_height(sheet, row);
3229 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label);
3230 dispose_string(sheet, label);
3231 pango_layout_set_font_description (layout, attributes.font_desc);
3233 pango_layout_get_pixel_extents (layout, NULL, &rect);
3235 line = pango_layout_get_lines (layout)->data;
3236 pango_layout_line_get_extents (line, NULL, &logical_rect);
3238 metrics = pango_context_get_metrics(context,
3239 attributes.font_desc,
3240 pango_context_get_language(context));
3242 ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
3243 descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
3245 pango_font_metrics_unref(metrics);
3247 /* Align primarily for locale's ascent/descent */
3249 logical_rect.height /= PANGO_SCALE;
3250 logical_rect.y /= PANGO_SCALE;
3251 y_pos = area.height - logical_rect.height;
3253 if (logical_rect.height > area.height)
3254 y_pos = (logical_rect.height - area.height - 2*CELLOFFSET) / 2;
3257 else if (y_pos + logical_rect.height > area.height)
3258 y_pos = area.height - logical_rect.height;
3260 text_width = rect.width;
3261 text_height = rect.height;
3262 y = area.y + y_pos - CELLOFFSET;
3264 switch(attributes.justification){
3265 case GTK_JUSTIFY_RIGHT:
3268 if(!gtk_sheet_clip_text(sheet)){
3269 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3270 if( !gtk_sheet_cell_empty(sheet, row, i)) break;
3271 if(size>=text_width+CELLOFFSET) break;
3272 size+=xxx_column_width(sheet, i);
3273 xxx_column_set_right_column(sheet, i,
3275 xxx_column_right_column(sheet, i)));
3280 xoffset+=area.width-text_width - 2 * CELLOFFSET -
3281 attributes.border.width/2;
3283 case GTK_JUSTIFY_CENTER:
3286 area.x+=area.width/2;
3287 if(!gtk_sheet_clip_text(sheet)){
3288 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3289 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3290 if(sizer>=text_width/2) break;
3291 sizer+= xxx_column_width(sheet, i);
3292 xxx_column_set_left_column(sheet, i,
3295 xxx_column_left_column(sheet, i)));
3297 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3298 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3299 if(sizel>=text_width/2) break;
3300 sizel+=xxx_column_width(sheet, i);
3301 xxx_column_set_right_column(sheet, i,
3303 xxx_column_right_column(sheet, i)));
3305 size=MIN(sizel, sizer);
3308 xoffset+= sizel - text_width/2 - CELLOFFSET;
3309 area.width=sizel+sizer;
3311 case GTK_JUSTIFY_LEFT:
3314 if(!gtk_sheet_clip_text(sheet)){
3315 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3316 if(! gtk_sheet_cell_empty(sheet, row, i)) break;
3317 if(size>=text_width+CELLOFFSET) break;
3318 size+=xxx_column_width(sheet, i);
3319 xxx_column_set_left_column(sheet, i,
3322 xxx_column_left_column(sheet, i)));
3327 xoffset += attributes.border.width/2;
3331 if(!gtk_sheet_clip_text(sheet)) clip_area = area;
3332 gdk_gc_set_clip_rectangle(fg_gc, &clip_area);
3335 gdk_draw_layout (sheet->pixmap, fg_gc,
3336 area.x + xoffset + CELLOFFSET,
3340 gdk_gc_set_clip_rectangle(fg_gc, NULL);
3341 g_object_unref(G_OBJECT(layout));
3343 gdk_draw_pixmap(sheet->sheet_window,
3344 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3358 gtk_sheet_range_draw(GtkSheet *sheet, const GtkSheetRange *range)
3361 GtkSheetRange drawing_range;
3364 g_return_if_fail(sheet != NULL);
3365 g_return_if_fail(GTK_SHEET(sheet));
3367 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
3368 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3369 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
3373 drawing_range.row0=MIN_VISIBLE_ROW(sheet);
3374 drawing_range.col0=MIN_VISIBLE_COLUMN(sheet);
3375 drawing_range.rowi=MIN(MAX_VISIBLE_ROW(sheet), yyy_row_count(sheet) - 1);
3376 drawing_range.coli=MAX_VISIBLE_COLUMN(sheet);
3379 gdk_draw_rectangle (sheet->pixmap,
3380 GTK_WIDGET(sheet)->style->white_gc,
3383 sheet->sheet_window_width,sheet->sheet_window_height);
3388 drawing_range.row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
3389 drawing_range.col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
3390 drawing_range.rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
3391 drawing_range.coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
3395 if(drawing_range.coli == xxx_column_count(sheet) - 1)
3397 area.x=COLUMN_LEFT_XPIXEL(sheet,
3398 xxx_column_count(sheet) - 1) +
3399 xxx_column_width(sheet, xxx_column_count(sheet) - 1) + 1;
3403 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3405 gdk_draw_rectangle (sheet->pixmap,
3409 sheet->sheet_window_width - area.x,
3410 sheet->sheet_window_height);
3412 gdk_draw_pixmap(sheet->sheet_window,
3413 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3419 sheet->sheet_window_width - area.x,
3420 sheet->sheet_window_height);
3423 if(drawing_range.rowi == yyy_row_count(sheet) - 1){
3425 area.y=ROW_TOP_YPIXEL(sheet,
3426 yyy_row_count(sheet) - 1) +
3427 yyy_row_height(sheet, yyy_row_count(sheet) - 1) + 1;
3429 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3431 gdk_draw_rectangle (sheet->pixmap,
3435 sheet->sheet_window_width,
3436 sheet->sheet_window_height - area.y);
3438 gdk_draw_pixmap(sheet->sheet_window,
3439 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3445 sheet->sheet_window_width,
3446 sheet->sheet_window_height - area.y);
3449 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3450 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3451 gtk_sheet_cell_draw_default(sheet, i, j);
3454 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3455 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3456 gtk_sheet_cell_draw_border(sheet, i-1, j, GTK_SHEET_BOTTOM_BORDER);
3457 gtk_sheet_cell_draw_border(sheet, i+1, j, GTK_SHEET_TOP_BORDER);
3458 gtk_sheet_cell_draw_border(sheet, i, j-1, GTK_SHEET_RIGHT_BORDER);
3459 gtk_sheet_cell_draw_border(sheet, i, j+1, GTK_SHEET_LEFT_BORDER);
3460 gtk_sheet_cell_draw_border(sheet, i, j, 15);
3463 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3464 for(j=drawing_range.col0; j<=drawing_range.coli; j++)
3465 gtk_sheet_cell_draw_label (sheet, i, j);
3467 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3468 for(j= xxx_column_left_column(sheet, drawing_range.col0);
3469 j<drawing_range.col0; j++)
3470 gtk_sheet_cell_draw_label (sheet, i, j);
3472 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3473 for(j = drawing_range.coli+1;
3474 j <= xxx_column_right_column(sheet, drawing_range.coli);
3476 gtk_sheet_cell_draw_label (sheet, i, j);
3478 gtk_sheet_draw_backing_pixmap(sheet, drawing_range);
3480 if(sheet->state != GTK_SHEET_NORMAL &&
3481 gtk_sheet_range_isvisible(sheet, sheet->range))
3482 gtk_sheet_range_draw_selection(sheet, drawing_range);
3484 if(sheet->state == GTK_STATE_NORMAL &&
3485 sheet->active_cell.row >= drawing_range.row0 &&
3486 sheet->active_cell.row <= drawing_range.rowi &&
3487 sheet->active_cell.col >= drawing_range.col0 &&
3488 sheet->active_cell.col <= drawing_range.coli)
3489 gtk_sheet_show_active_cell(sheet);
3494 gtk_sheet_range_draw_selection(GtkSheet *sheet, GtkSheetRange range)
3500 if(range.col0 > sheet->range.coli || range.coli < sheet->range.col0 ||
3501 range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0)
3504 if(!gtk_sheet_range_isvisible(sheet, range)) return;
3505 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3509 range.col0=MAX(sheet->range.col0, range.col0);
3510 range.coli=MIN(sheet->range.coli, range.coli);
3511 range.row0=MAX(sheet->range.row0, range.row0);
3512 range.rowi=MIN(sheet->range.rowi, range.rowi);
3514 range.col0=MAX(range.col0, MIN_VISIBLE_COLUMN(sheet));
3515 range.coli=MIN(range.coli, MAX_VISIBLE_COLUMN(sheet));
3516 range.row0=MAX(range.row0, MIN_VISIBLE_ROW(sheet));
3517 range.rowi=MIN(range.rowi, MAX_VISIBLE_ROW(sheet));
3519 for(i=range.row0; i<=range.rowi; i++){
3520 for(j=range.col0; j<=range.coli; j++){
3522 if(gtk_sheet_cell_get_state(sheet, i, j)==GTK_STATE_SELECTED &&
3523 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
3526 row_button_set(sheet, i);
3527 column_button_set(sheet, j);
3530 area.x=COLUMN_LEFT_XPIXEL(sheet,j);
3531 area.y=ROW_TOP_YPIXEL(sheet,i);
3532 area.width= xxx_column_width(sheet, j);
3533 area.height=yyy_row_height(sheet, i);
3535 if(i==sheet->range.row0)
3538 area.height=area.height-2;
3540 if(i==sheet->range.rowi) area.height=area.height-3;
3541 if(j==sheet->range.col0)
3544 area.width=area.width-2;
3546 if(j==sheet->range.coli) area.width=area.width-3;
3548 if(i!=sheet->active_cell.row || j!=sheet->active_cell.col)
3550 gdk_draw_rectangle (sheet->sheet_window,
3554 area.width,area.height);
3561 gtk_sheet_draw_border(sheet, sheet->range);
3565 gtk_sheet_draw_backing_pixmap(GtkSheet *sheet, GtkSheetRange range)
3567 gint x,y,width,height;
3569 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3571 x = COLUMN_LEFT_XPIXEL(sheet,range.col0);
3572 y = ROW_TOP_YPIXEL(sheet, range.row0);
3573 width = COLUMN_LEFT_XPIXEL(sheet, range.coli) - x +
3574 xxx_column_width(sheet, range.coli);
3576 height=ROW_TOP_YPIXEL(sheet, range.rowi)-y+yyy_row_height(sheet, range.rowi);
3578 if(range.row0 == sheet->range.row0)
3583 if(range.rowi==sheet->range.rowi) height = height + 5;
3584 if(range.col0==sheet->range.col0)
3589 if(range.coli == sheet->range.coli) width = width + 5;
3591 width = MIN(width, sheet->sheet_window_width - x);
3592 height = MIN(height, sheet->sheet_window_height - y);
3599 x = (sheet->row_titles_visible)
3600 ? MAX(x, sheet->row_title_area.width) : MAX(x, 0);
3601 y = (sheet->column_titles_visible)
3602 ? MAX(y, sheet->column_title_area.height) : MAX(y, 0);
3604 if(range.coli == xxx_column_count(sheet) - 1)
3605 width = sheet->sheet_window_width - x;
3606 if(range.rowi == yyy_row_count(sheet) - 1)
3607 height=sheet->sheet_window_height - y;
3609 gdk_draw_pixmap(sheet->sheet_window,
3610 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3622 gtk_sheet_set_cell_text(GtkSheet *sheet, gint row, gint col, const gchar *text)
3624 GtkSheetCellAttr attributes;
3626 g_return_if_fail (sheet != NULL);
3627 g_return_if_fail (GTK_IS_SHEET (sheet));
3628 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3629 if (col < 0 || row < 0) return;
3631 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3632 gtk_sheet_set_cell(sheet, row, col, attributes.justification, text);
3636 safe_strcmp(const gchar *s1, const gchar *s2)
3638 if ( !s1 && !s2) return 0;
3639 if ( !s1) return -1;
3640 if ( !s2) return +1;
3641 return strcmp(s1, s2);
3645 gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col,
3646 GtkJustification justification,
3649 GSheetModel *model ;
3653 GtkSheetRange range;
3655 GtkSheetCellAttr attributes;
3657 g_return_if_fail (sheet != NULL);
3658 g_return_if_fail (GTK_IS_SHEET (sheet));
3659 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3660 if (col < 0 || row < 0) return;
3662 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3664 attributes.justification = justification;
3666 model = gtk_sheet_get_model(sheet);
3668 old_text = g_sheet_model_get_string(model, row, col);
3672 if (0 != safe_strcmp(old_text, text))
3673 changed = g_sheet_model_set_string(model, text, row, col);
3675 if ( g_sheet_model_free_strings(model))
3679 if(changed && attributes.is_visible)
3681 gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
3683 if(s && strlen(s) > 0) {
3684 text_width = STRING_WIDTH(GTK_WIDGET(sheet),
3685 attributes.font_desc, text);
3687 dispose_string(sheet, s);
3691 range.col0 = sheet->view.col0;
3692 range.coli = sheet->view.coli;
3694 if(gtk_sheet_autoresize(sheet) &&
3695 text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
3696 gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width);
3697 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3700 if(!GTK_SHEET_IS_FROZEN(sheet))
3701 gtk_sheet_range_draw(sheet, &range);
3705 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
3711 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
3713 GtkSheetRange range;
3715 g_return_if_fail (sheet != NULL);
3716 g_return_if_fail (GTK_IS_SHEET (sheet));
3717 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3718 if (column < 0 || row < 0) return;
3722 range.col0 = sheet->view.col0;
3723 range.coli = sheet->view.coli;
3725 gtk_sheet_real_cell_clear(sheet, row, column, FALSE);
3727 if(!GTK_SHEET_IS_FROZEN(sheet)){
3728 gtk_sheet_range_draw(sheet, &range);
3733 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
3735 GtkSheetRange range;
3737 g_return_if_fail (sheet != NULL);
3738 g_return_if_fail (GTK_IS_SHEET (sheet));
3739 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3740 if (column < 0 || row < 0) return;
3744 range.col0 = sheet->view.col0;
3745 range.coli = sheet->view.coli;
3747 gtk_sheet_real_cell_clear(sheet, row, column, TRUE);
3749 if(!GTK_SHEET_IS_FROZEN(sheet)){
3750 gtk_sheet_range_draw(sheet, &range);
3755 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
3757 GSheetModel *model = gtk_sheet_get_model(sheet);
3759 gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column);
3761 if (old_text && strlen(old_text) > 0 )
3763 g_sheet_model_datum_clear(model, row, column);
3765 if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0)
3766 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL],
3770 dispose_string (sheet, old_text);
3774 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
3776 g_return_if_fail (sheet != NULL);
3777 g_return_if_fail (GTK_IS_SHEET (sheet));
3779 gtk_sheet_real_range_clear(sheet, range, FALSE);
3783 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range)
3785 g_return_if_fail (sheet != NULL);
3786 g_return_if_fail (GTK_IS_SHEET (sheet));
3788 gtk_sheet_real_range_clear(sheet, range, TRUE);
3793 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
3797 GtkSheetRange clear;
3801 clear.rowi = yyy_row_count(sheet) - 1;
3803 clear.coli = xxx_column_count(sheet) - 1;
3807 clear.row0=MAX(clear.row0, 0);
3808 clear.col0=MAX(clear.col0, 0);
3809 clear.rowi=MIN(clear.rowi, yyy_row_count(sheet) - 1 );
3810 clear.coli=MIN(clear.coli, xxx_column_count(sheet) - 1 );
3812 for(i=clear.row0; i<=clear.rowi; i++)
3813 for(j=clear.col0; j<=clear.coli; j++){
3814 gtk_sheet_real_cell_clear(sheet, i, j, delete);
3817 gtk_sheet_range_draw(sheet, NULL);
3822 gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col)
3825 char *text = gtk_sheet_cell_get_text(sheet, row, col);
3826 empty = (text == NULL );
3828 dispose_string(sheet, text);
3835 gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
3838 g_return_val_if_fail (sheet != NULL, NULL);
3839 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
3841 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet))
3843 if(col < 0 || row < 0) return NULL;
3845 model = gtk_sheet_get_model(sheet);
3850 return g_sheet_model_get_string(model, row, col);
3855 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
3858 GtkSheetRange *range;
3860 g_return_val_if_fail (sheet != NULL, 0);
3861 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3862 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return 0;
3863 if(col < 0 || row < 0) return 0;
3865 state = sheet->state;
3866 range = &sheet->range;
3870 case GTK_SHEET_NORMAL:
3871 return GTK_STATE_NORMAL;
3873 case GTK_SHEET_ROW_SELECTED:
3874 if(row>=range->row0 && row<=range->rowi)
3875 return GTK_STATE_SELECTED;
3877 case GTK_SHEET_COLUMN_SELECTED:
3878 if(col>=range->col0 && col<=range->coli)
3879 return GTK_STATE_SELECTED;
3881 case GTK_SHEET_RANGE_SELECTED:
3882 if(row >= range->row0 && row <= range->rowi && \
3883 col >= range->col0 && col <= range->coli)
3884 return GTK_STATE_SELECTED;
3887 return GTK_STATE_NORMAL;
3891 gtk_sheet_get_pixel_info (GtkSheet * sheet,
3899 g_return_val_if_fail (sheet != NULL, 0);
3900 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3902 /* bounds checking, return false if the user clicked
3903 * on a blank area */
3904 trow = ROW_FROM_YPIXEL (sheet, y);
3905 if (trow >= yyy_row_count(sheet))
3910 tcol = COLUMN_FROM_XPIXEL (sheet, x);
3911 if (tcol >= xxx_column_count(sheet))
3920 gtk_sheet_get_cell_area (GtkSheet * sheet,
3925 g_return_val_if_fail (sheet != NULL, 0);
3926 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3928 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3931 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) -
3932 (sheet->row_titles_visible
3933 ? sheet->row_title_area.width
3935 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL(sheet, row) -
3936 (sheet->column_titles_visible
3937 ? sheet->column_title_area.height
3939 area->width= (column == -1) ? sheet->row_title_area.width
3940 : xxx_column_width(sheet, column);
3942 area->height= (row == -1) ? sheet->column_title_area.height
3943 : yyy_row_height(sheet, row);
3946 if(row < 0 || column < 0) return FALSE;
3948 area->x = COLUMN_LEFT_XPIXEL(sheet, column);
3949 area->y = ROW_TOP_YPIXEL(sheet, row);
3950 if(sheet->row_titles_visible)
3951 area->x -= sheet->row_title_area.width;
3952 if(sheet->column_titles_visible)
3953 area->y -= sheet->column_title_area.height;
3955 area->width=sheet->column[column].width;
3956 area->height=yyy_row_height(sheet, row);
3962 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
3964 g_return_val_if_fail (sheet != NULL, 0);
3965 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3967 if(row < -1 || column < -1) return FALSE;
3968 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3971 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
3973 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
3976 sheet->active_cell.row = row;
3977 sheet->active_cell.col = column;
3979 if ( row == -1 || column == -1)
3981 gtk_sheet_hide_active_cell(sheet);
3985 if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE;
3987 if(gtk_sheet_autoscroll(sheet))
3988 gtk_sheet_move_query(sheet, row, column);
3994 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column)
3996 g_return_if_fail (sheet != NULL);
3997 g_return_if_fail (GTK_IS_SHEET (sheet));
3999 *row = sheet->active_cell.row;
4000 *column = sheet->active_cell.col;
4004 gtk_sheet_entry_changed(GtkWidget *widget, gpointer data)
4009 GtkJustification justification;
4010 GtkSheetCellAttr attributes;
4012 g_return_if_fail (data != NULL);
4013 g_return_if_fail (GTK_IS_SHEET (data));
4015 sheet=GTK_SHEET(data);
4017 if(!GTK_WIDGET_VISIBLE(widget)) return;
4018 if(sheet->state != GTK_STATE_NORMAL) return;
4020 row=sheet->active_cell.row;
4021 col=sheet->active_cell.col;
4023 if(row<0 || col<0) return;
4025 sheet->active_cell.row=-1;
4026 sheet->active_cell.col=-1;
4028 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
4030 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
4032 if(text && strlen(text) > 0)
4034 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4035 justification = attributes.justification;
4036 gtk_sheet_set_cell(sheet, row, col, justification, text);
4039 if(sheet->freeze_count == 0)
4040 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
4042 sheet->active_cell.row=row;;
4043 sheet->active_cell.col=col;
4048 gtk_sheet_deactivate_cell(GtkSheet *sheet)
4050 gboolean veto = TRUE;
4052 g_return_val_if_fail (sheet != NULL, FALSE);
4053 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
4055 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return FALSE;
4056 if(sheet->state != GTK_SHEET_NORMAL) return FALSE;
4058 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[DEACTIVATE],
4059 sheet->active_cell.row,
4060 sheet->active_cell.col, &veto);
4062 if(!veto) return FALSE;
4064 if ( sheet->active_cell.row == -1 || sheet->active_cell.col == -1 )
4067 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
4068 (GtkSignalFunc) gtk_sheet_entry_changed,
4069 GTK_OBJECT(GTK_WIDGET(sheet)));
4071 gtk_sheet_hide_active_cell(sheet);
4072 sheet->active_cell.row = -1;
4073 sheet->active_cell.col = -1;
4075 if(GTK_SHEET_REDRAW_PENDING(sheet)){
4076 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
4077 gtk_sheet_range_draw(sheet, NULL);
4084 gtk_sheet_hide_active_cell(GtkSheet *sheet)
4088 GtkJustification justification;
4089 GtkSheetCellAttr attributes;
4091 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4093 row=sheet->active_cell.row;
4094 col=sheet->active_cell.col;
4096 if(row < 0 || col < 0) return;
4098 if(sheet->freeze_count == 0)
4099 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
4101 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
4103 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4104 justification=attributes.justification;
4106 if(text && strlen(text) != 0)
4108 gtk_sheet_set_cell(sheet, row, col, justification, text);
4109 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col);
4113 gtk_sheet_cell_clear(sheet, row, col);
4116 row=sheet->active_cell.row;
4117 col=sheet->active_cell.col;
4120 column_button_release(sheet, col);
4121 row_button_release(sheet, row);
4124 gtk_widget_hide(sheet->sheet_entry);
4125 gtk_widget_unmap(sheet->sheet_entry);
4127 if(row != -1 && col != -1)
4128 gdk_draw_pixmap(sheet->sheet_window,
4129 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4131 COLUMN_LEFT_XPIXEL(sheet,col)-1,
4132 ROW_TOP_YPIXEL(sheet,row)-1,
4133 COLUMN_LEFT_XPIXEL(sheet,col)-1,
4134 ROW_TOP_YPIXEL(sheet,row)-1,
4135 xxx_column_width(sheet, col) + 4,
4136 yyy_row_height(sheet, row)+4);
4138 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4140 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4145 gtk_sheet_activate_cell(GtkSheet *sheet, gint row, gint col)
4147 gboolean veto = TRUE;
4149 g_return_val_if_fail (sheet != NULL, FALSE);
4150 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
4152 if(row < 0 || col < 0) return FALSE;
4153 if(row >= yyy_row_count(sheet) || col >= xxx_column_count(sheet))
4156 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4157 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
4160 if(!veto) return FALSE;
4161 if(sheet->state != GTK_SHEET_NORMAL){
4162 sheet->state=GTK_SHEET_NORMAL;
4163 gtk_sheet_real_unselect_range(sheet, NULL);
4166 sheet->range.row0 = row;
4167 sheet->range.col0 = col;
4168 sheet->range.rowi = row;
4169 sheet->range.coli = col;
4170 sheet->active_cell.row = row;
4171 sheet->active_cell.col = col;
4172 sheet->selection_cell.row = row;
4173 sheet->selection_cell.col = col;
4175 row_button_set(sheet, row);
4176 column_button_set(sheet, col);
4179 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4180 gtk_sheet_show_active_cell(sheet);
4182 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
4184 G_CALLBACK(gtk_sheet_entry_changed),
4187 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4193 gtk_sheet_show_active_cell(GtkSheet *sheet)
4195 GtkEntry *sheet_entry;
4196 GtkSheetCellAttr attributes;
4198 const gchar *old_text;
4199 GtkJustification justification;
4202 g_return_if_fail (sheet != NULL);
4203 g_return_if_fail (GTK_IS_SHEET (sheet));
4205 row = sheet->active_cell.row;
4206 col = sheet->active_cell.col;
4208 /* Don't show the active cell, if there is no active cell: */
4209 if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */
4212 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4213 if(sheet->state != GTK_SHEET_NORMAL) return;
4214 if(GTK_SHEET_IN_SELECTION(sheet)) return;
4216 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4218 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
4220 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4222 justification = GTK_JUSTIFY_LEFT;
4224 if(gtk_sheet_justify_entry(sheet))
4225 justification = attributes.justification;
4227 text = gtk_sheet_cell_get_text(sheet, row, col);
4229 text = g_strdup("");
4231 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible);
4233 if(gtk_sheet_locked(sheet) || !attributes.is_editable)
4234 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
4236 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
4238 /*** Added by John Gotts. Mar 25, 2005 *********/
4239 old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
4240 if (strcmp(old_text, text) != 0)
4242 if(!GTK_IS_ITEM_ENTRY(sheet_entry))
4243 gtk_entry_set_text(GTK_ENTRY(sheet_entry), text);
4245 gtk_item_entry_set_text(GTK_ITEM_ENTRY(sheet_entry), text, justification);
4248 gtk_sheet_entry_set_max_size(sheet);
4249 gtk_sheet_size_allocate_entry(sheet);
4251 gtk_widget_map(sheet->sheet_entry);
4252 gtk_sheet_draw_active_cell(sheet);
4254 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
4256 dispose_string(sheet, text);
4260 gtk_sheet_draw_active_cell(GtkSheet *sheet)
4264 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
4265 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4267 row = sheet->active_cell.row;
4268 col = sheet->active_cell.col;
4270 if(row < 0 || col < 0) return;
4272 if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
4274 row_button_set(sheet, row);
4275 column_button_set(sheet, col);
4277 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4278 gtk_sheet_draw_border(sheet, sheet->range);
4283 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
4285 gint pixmap_width, pixmap_height;
4287 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4289 if(width == 0 && height == 0){
4290 width=sheet->sheet_window_width+80;
4291 height=sheet->sheet_window_height+80;
4297 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4300 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4304 /* reallocate if sizes don't match */
4305 gdk_window_get_size (sheet->pixmap,
4306 &pixmap_width, &pixmap_height);
4307 if ((pixmap_width != width) || (pixmap_height != height))
4309 g_object_unref(sheet->pixmap);
4310 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4313 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4319 gtk_sheet_new_selection(GtkSheet *sheet, GtkSheetRange *range)
4321 gint i,j, mask1, mask2;
4322 gint state, selected;
4323 gint x,y,width,height;
4324 GtkSheetRange new_range, aux_range;
4326 g_return_if_fail (sheet != NULL);
4328 if(range==NULL) range=&sheet->range;
4332 range->row0=MIN(range->row0, sheet->range.row0);
4333 range->rowi=MAX(range->rowi, sheet->range.rowi);
4334 range->col0=MIN(range->col0, sheet->range.col0);
4335 range->coli=MAX(range->coli, sheet->range.coli);
4337 range->row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
4338 range->rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
4339 range->col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
4340 range->coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
4342 aux_range.row0=MAX(new_range.row0, MIN_VISIBLE_ROW(sheet));
4343 aux_range.rowi=MIN(new_range.rowi, MAX_VISIBLE_ROW(sheet));
4344 aux_range.col0=MAX(new_range.col0, MIN_VISIBLE_COLUMN(sheet));
4345 aux_range.coli=MIN(new_range.coli, MAX_VISIBLE_COLUMN(sheet));
4347 for(i=range->row0; i<=range->rowi; i++){
4348 for(j=range->col0; j<=range->coli; j++){
4350 state=gtk_sheet_cell_get_state(sheet, i, j);
4351 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4352 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4354 if(state==GTK_STATE_SELECTED && selected &&
4355 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4356 (i==sheet->range.row0 || i==sheet->range.rowi ||
4357 j==sheet->range.col0 || j==sheet->range.coli ||
4358 i==new_range.row0 || i==new_range.rowi ||
4359 j==new_range.col0 || j==new_range.coli)){
4361 mask1 = i==sheet->range.row0 ? 1 : 0;
4362 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4363 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4364 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4366 mask2 = i==new_range.row0 ? 1 : 0;
4367 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4368 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4369 mask2 = j==new_range.coli ? mask2+8 : mask2;
4372 x=COLUMN_LEFT_XPIXEL(sheet,j);
4373 y=ROW_TOP_YPIXEL(sheet, i);
4374 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4375 xxx_column_width(sheet, j);
4376 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4378 if(i==sheet->range.row0){
4382 if(i==sheet->range.rowi) height=height+3;
4383 if(j==sheet->range.col0){
4387 if(j==sheet->range.coli) width=width+3;
4389 gdk_draw_pixmap(sheet->sheet_window,
4390 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4399 if(i != sheet->active_cell.row || j != sheet->active_cell.col){
4400 x=COLUMN_LEFT_XPIXEL(sheet,j);
4401 y=ROW_TOP_YPIXEL(sheet, i);
4402 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4403 xxx_column_width(sheet, j);
4405 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4407 if(i==new_range.row0){
4411 if(i==new_range.rowi) height=height-3;
4412 if(j==new_range.col0){
4416 if(j==new_range.coli) width=width-3;
4418 gdk_draw_rectangle (sheet->sheet_window,
4429 for(i=range->row0; i<=range->rowi; i++){
4430 for(j=range->col0; j<=range->coli; j++){
4432 state=gtk_sheet_cell_get_state(sheet, i, j);
4433 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4434 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4436 if(state==GTK_STATE_SELECTED && !selected &&
4437 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4439 x=COLUMN_LEFT_XPIXEL(sheet,j);
4440 y=ROW_TOP_YPIXEL(sheet, i);
4441 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4442 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4444 if(i==sheet->range.row0){
4448 if(i==sheet->range.rowi) height=height+3;
4449 if(j==sheet->range.col0){
4453 if(j==sheet->range.coli) width=width+3;
4455 gdk_draw_pixmap(sheet->sheet_window,
4456 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4468 for(i=range->row0; i<=range->rowi; i++){
4469 for(j=range->col0; j<=range->coli; j++){
4471 state=gtk_sheet_cell_get_state(sheet, i, j);
4472 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4473 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4475 if(state!=GTK_STATE_SELECTED && selected &&
4476 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4477 (i != sheet->active_cell.row || j != sheet->active_cell.col)){
4479 x=COLUMN_LEFT_XPIXEL(sheet,j);
4480 y=ROW_TOP_YPIXEL(sheet, i);
4481 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4482 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4484 if(i==new_range.row0){
4488 if(i==new_range.rowi) height=height-3;
4489 if(j==new_range.col0){
4493 if(j==new_range.coli) width=width-3;
4495 gdk_draw_rectangle (sheet->sheet_window,
4506 for(i=aux_range.row0; i<=aux_range.rowi; i++){
4507 for(j=aux_range.col0; j<=aux_range.coli; j++){
4509 if(xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4511 state=gtk_sheet_cell_get_state(sheet, i, j);
4513 mask1 = i==sheet->range.row0 ? 1 : 0;
4514 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4515 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4516 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4518 mask2 = i==new_range.row0 ? 1 : 0;
4519 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4520 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4521 mask2 = j==new_range.coli ? mask2+8 : mask2;
4522 if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){
4523 x=COLUMN_LEFT_XPIXEL(sheet,j);
4524 y=ROW_TOP_YPIXEL(sheet, i);
4525 width=xxx_column_width(sheet, j);
4526 height=yyy_row_height(sheet, i);
4528 gdk_draw_rectangle (sheet->sheet_window,
4536 gdk_draw_rectangle (sheet->sheet_window,
4543 gdk_draw_rectangle (sheet->sheet_window,
4551 gdk_draw_rectangle (sheet->sheet_window,
4568 gtk_sheet_draw_corners(sheet, new_range);
4573 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
4578 gint x,y,width,height;
4580 widget = GTK_WIDGET(sheet);
4582 x=COLUMN_LEFT_XPIXEL(sheet,new_range.col0);
4583 y=ROW_TOP_YPIXEL(sheet,new_range.row0);
4584 width=COLUMN_LEFT_XPIXEL(sheet,new_range.coli)-x+
4585 xxx_column_width(sheet, new_range.coli);
4587 height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+
4588 yyy_row_height(sheet, new_range.rowi);
4590 area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
4591 area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
4592 area.width=sheet->sheet_window_width;
4593 area.height=sheet->sheet_window_height;
4599 if(width>area.width) width=area.width+10;
4604 if(height>area.height) height=area.height+10;
4606 gdk_gc_set_clip_rectangle(sheet->xor_gc, &area);
4608 for(i=-1; i<=1; ++i)
4609 gdk_draw_rectangle (sheet->sheet_window,
4613 width-2*i,height-2*i);
4615 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
4617 gtk_sheet_draw_corners(sheet, new_range);
4622 gtk_sheet_draw_corners(GtkSheet *sheet, GtkSheetRange range)
4627 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.col0)){
4628 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4629 y=ROW_TOP_YPIXEL(sheet,range.row0);
4630 gdk_draw_pixmap(sheet->sheet_window,
4631 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4639 gdk_draw_rectangle (sheet->sheet_window,
4646 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) ||
4647 sheet->state == GTK_SHEET_COLUMN_SELECTED){
4648 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4649 xxx_column_width(sheet, range.coli);
4650 y=ROW_TOP_YPIXEL(sheet,range.row0);
4652 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
4654 y = ROW_TOP_YPIXEL(sheet, sheet->view.row0)+3;
4657 gdk_draw_pixmap(sheet->sheet_window,
4658 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4666 gdk_draw_rectangle (sheet->sheet_window,
4669 x-width+width/2,y-width+width/2,
4673 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.col0) ||
4674 sheet->state == GTK_SHEET_ROW_SELECTED){
4675 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4676 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4677 yyy_row_height(sheet, range.rowi);
4679 if(sheet->state == GTK_SHEET_ROW_SELECTED)
4681 x = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0)+3;
4684 gdk_draw_pixmap(sheet->sheet_window,
4685 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4693 gdk_draw_rectangle (sheet->sheet_window,
4696 x-width+width/2,y-width+width/2,
4700 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){
4701 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4702 xxx_column_width(sheet, range.coli);
4703 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4704 yyy_row_height(sheet, range.rowi);
4706 if(sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
4707 if(sheet->state == GTK_SHEET_NORMAL) width = 3;
4708 gdk_draw_pixmap(sheet->sheet_window,
4709 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4717 gdk_draw_rectangle (sheet->sheet_window,
4720 x-width+width/2,y-width+width/2,
4729 gtk_sheet_real_select_range (GtkSheet * sheet,
4730 const GtkSheetRange * range)
4734 g_return_if_fail (sheet != NULL);
4736 if(range==NULL) range=&sheet->range;
4738 memcpy(&sheet->range, range, sizeof(*range));
4740 if(range->row0 < 0 || range->rowi < 0) return;
4741 if(range->col0 < 0 || range->coli < 0) return;
4743 state = sheet->state;
4746 if(state==GTK_SHEET_COLUMN_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4747 for(i=sheet->range.col0; i< range->col0; i++)
4748 column_button_release(sheet, i);
4749 for(i=range->coli+1; i<= sheet->range.coli; i++)
4750 column_button_release(sheet, i);
4751 for(i=range->col0; i<=range->coli; i++){
4752 column_button_set(sheet, i);
4756 if(state==GTK_SHEET_ROW_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4757 for(i=sheet->range.row0; i< range->row0; i++)
4758 row_button_release(sheet, i);
4759 for(i=range->rowi+1; i<= sheet->range.rowi; i++)
4760 row_button_release(sheet, i);
4761 for(i=range->row0; i<=range->rowi; i++){
4762 row_button_set(sheet, i);
4767 if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
4768 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
4771 gtk_sheet_new_selection(sheet, range);
4773 sheet->range.col0=range->col0;
4774 sheet->range.coli=range->coli;
4775 sheet->range.row0=range->row0;
4776 sheet->range.rowi=range->rowi;
4781 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4782 gtk_sheet_range_draw_selection(sheet, sheet->range);
4785 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[SELECT_RANGE], range);
4789 gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range)
4791 g_return_if_fail (sheet != NULL);
4793 if(range==NULL) range=&sheet->range;
4795 if(range->row0 < 0 || range->rowi < 0) return;
4796 if(range->col0 < 0 || range->coli < 0) return;
4799 if ( gtk_sheet_locked(sheet)) return ;
4801 if(sheet->state != GTK_SHEET_NORMAL)
4802 gtk_sheet_real_unselect_range(sheet, NULL);
4805 gboolean veto = TRUE;
4806 veto = gtk_sheet_deactivate_cell(sheet);
4810 sheet->range.row0=range->row0;
4811 sheet->range.rowi=range->rowi;
4812 sheet->range.col0=range->col0;
4813 sheet->range.coli=range->coli;
4814 sheet->active_cell.row=range->row0;
4815 sheet->active_cell.col=range->col0;
4816 sheet->selection_cell.row=range->rowi;
4817 sheet->selection_cell.col=range->coli;
4819 sheet->state = GTK_SHEET_RANGE_SELECTED;
4820 gtk_sheet_real_select_range(sheet, NULL);
4825 gtk_sheet_unselect_range (GtkSheet * sheet)
4827 gtk_sheet_real_unselect_range(sheet, NULL);
4828 sheet->state = GTK_STATE_NORMAL;
4829 gtk_sheet_activate_cell(sheet,
4830 sheet->active_cell.row, sheet->active_cell.col);
4835 gtk_sheet_real_unselect_range (GtkSheet * sheet,
4836 const GtkSheetRange *range)
4838 g_return_if_fail (sheet != NULL);
4839 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)));
4842 range = &sheet->range;
4844 if(range->row0 < 0 || range->rowi < 0) return;
4845 if(range->col0 < 0 || range->coli < 0) return;
4847 if (gtk_sheet_range_isvisible (sheet, *range))
4848 gtk_sheet_draw_backing_pixmap(sheet, *range);
4851 for(i=range->col0; i<=range->coli; i++){
4852 column_button_release(sheet, i);
4855 for(i=range->row0; i<=range->rowi; i++){
4856 row_button_release(sheet, i);
4860 sheet->range.row0 = -1;
4861 sheet->range.rowi = -1;
4862 sheet->range.col0 = -1;
4863 sheet->range.coli = -1;
4865 gtk_sheet_position_children(sheet);
4870 gtk_sheet_expose (GtkWidget * widget,
4871 GdkEventExpose * event)
4874 GtkSheetRange range;
4876 g_return_val_if_fail (widget != NULL, FALSE);
4877 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4878 g_return_val_if_fail (event != NULL, FALSE);
4880 sheet = GTK_SHEET (widget);
4882 if (GTK_WIDGET_DRAWABLE (widget))
4884 range.row0 = ROW_FROM_YPIXEL(sheet, event->area.y);
4885 range.col0 = COLUMN_FROM_XPIXEL(sheet, event->area.x);
4886 range.rowi = ROW_FROM_YPIXEL(sheet, event->area.y + event->area.height);
4887 range.coli = COLUMN_FROM_XPIXEL(sheet, event->area.x + event->area.width);
4889 /* exposure events on the sheet */
4890 if(event->window == sheet->row_title_window &&
4891 sheet->row_titles_visible)
4894 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
4895 gtk_sheet_row_title_button_draw(sheet, i);
4898 if(event->window == sheet->column_title_window &&
4899 sheet->column_titles_visible)
4902 for(i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
4903 gtk_sheet_column_title_button_draw(sheet, i);
4906 if (event->window == sheet->sheet_window)
4908 gtk_sheet_draw_backing_pixmap(sheet, range);
4910 if(sheet->state != GTK_SHEET_NORMAL)
4912 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4913 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4914 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4915 gtk_sheet_draw_backing_pixmap(sheet, sheet->drag_range);
4917 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4918 gtk_sheet_range_draw_selection(sheet, sheet->range);
4919 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4920 draw_xor_rectangle(sheet, sheet->drag_range);
4923 if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet)))
4925 if(sheet->state == GTK_SHEET_NORMAL){
4926 gtk_sheet_draw_active_cell(sheet);
4927 if(!GTK_SHEET_IN_SELECTION(sheet))
4928 gtk_widget_queue_draw(sheet->sheet_entry);
4934 if(sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet))
4935 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4937 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
4944 gtk_sheet_button_press (GtkWidget * widget,
4945 GdkEventButton * event)
4948 GdkModifierType mods;
4949 gint x, y, row, column;
4952 g_return_val_if_fail (widget != NULL, FALSE);
4953 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4954 g_return_val_if_fail (event != NULL, FALSE);
4956 sheet = GTK_SHEET (widget);
4958 if ( event->type == GDK_2BUTTON_PRESS)
4960 gtk_widget_get_pointer (widget, &x, &y);
4961 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4963 if (event->window == sheet->column_title_window )
4965 gtk_signal_emit (GTK_OBJECT (sheet),
4966 sheet_signals[DOUBLE_CLICK_COLUMN], column);
4968 else if (event->window == sheet->row_title_window )
4970 gtk_signal_emit (GTK_OBJECT (sheet),
4971 sheet_signals[DOUBLE_CLICK_ROW], row);
4977 if(event->type != GDK_BUTTON_PRESS) return TRUE;
4979 gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
4981 if(!(mods & GDK_BUTTON1_MASK)) return TRUE;
4984 /* press on resize windows */
4985 if (event->window == sheet->column_title_window &&
4986 gtk_sheet_columns_resizable(sheet))
4988 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
4989 if(POSSIBLE_XDRAG(sheet, sheet->x_drag, &sheet->drag_cell.col)){
4991 if (event->type == GDK_2BUTTON_PRESS){
4992 gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
4993 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_XDRAG);
4996 gtk_sheet_column_size_request(sheet, sheet->drag_cell.col, &req);
4997 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4998 gdk_pointer_grab (sheet->column_title_window, FALSE,
4999 GDK_POINTER_MOTION_HINT_MASK |
5000 GDK_BUTTON1_MOTION_MASK |
5001 GDK_BUTTON_RELEASE_MASK,
5002 NULL, NULL, event->time);
5004 draw_xor_vline (sheet);
5009 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet))
5011 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
5013 if(POSSIBLE_YDRAG(sheet, sheet->y_drag, &sheet->drag_cell.row)){
5015 gtk_sheet_row_size_request(sheet, sheet->drag_cell.row, &req);
5016 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5017 gdk_pointer_grab (sheet->row_title_window, FALSE,
5018 GDK_POINTER_MOTION_HINT_MASK |
5019 GDK_BUTTON1_MOTION_MASK |
5020 GDK_BUTTON_RELEASE_MASK,
5021 NULL, NULL, event->time);
5023 draw_xor_hline (sheet);
5028 /* the sheet itself does not handle other than single click events */
5029 if(event->type != GDK_BUTTON_PRESS) return FALSE;
5031 /* selections on the sheet */
5032 if(event->window == sheet->sheet_window){
5033 gtk_widget_get_pointer (widget, &x, &y);
5034 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5035 gdk_pointer_grab (sheet->sheet_window, FALSE,
5036 GDK_POINTER_MOTION_HINT_MASK |
5037 GDK_BUTTON1_MOTION_MASK |
5038 GDK_BUTTON_RELEASE_MASK,
5039 NULL, NULL, event->time);
5040 gtk_grab_add(GTK_WIDGET(sheet));
5041 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5042 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5044 if(sheet->selection_mode != GTK_SELECTION_SINGLE &&
5045 sheet->cursor_drag->type==GDK_SIZING &&
5046 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_RESIZE(sheet)){
5047 if(sheet->state==GTK_STATE_NORMAL) {
5048 row=sheet->active_cell.row;
5049 column=sheet->active_cell.col;
5050 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
5051 sheet->active_cell.row=row;
5052 sheet->active_cell.col=column;
5053 sheet->drag_range=sheet->range;
5054 sheet->state=GTK_SHEET_RANGE_SELECTED;
5055 gtk_sheet_select_range(sheet, &sheet->drag_range);
5059 if(row > sheet->range.rowi) row--;
5060 if(column > sheet->range.coli) column--;
5061 sheet->drag_cell.row = row;
5062 sheet->drag_cell.col = column;
5063 sheet->drag_range=sheet->range;
5064 draw_xor_rectangle(sheet, sheet->drag_range);
5065 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5067 else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW &&
5068 !GTK_SHEET_IN_SELECTION(sheet)
5069 && ! GTK_SHEET_IN_DRAG(sheet)
5070 && ! gtk_sheet_locked(sheet)
5071 && sheet->active_cell.row >= 0
5072 && sheet->active_cell.col >= 0
5075 if(sheet->state==GTK_STATE_NORMAL) {
5076 row=sheet->active_cell.row;
5077 column=sheet->active_cell.col;
5078 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
5079 sheet->active_cell.row=row;
5080 sheet->active_cell.col=column;
5081 sheet->drag_range=sheet->range;
5082 sheet->state=GTK_SHEET_RANGE_SELECTED;
5083 gtk_sheet_select_range(sheet, &sheet->drag_range);
5087 if(row < sheet->range.row0) row++;
5088 if(row > sheet->range.rowi) row--;
5089 if(column < sheet->range.col0) column++;
5090 if(column > sheet->range.coli) column--;
5091 sheet->drag_cell.row=row;
5092 sheet->drag_cell.col=column;
5093 sheet->drag_range=sheet->range;
5094 draw_xor_rectangle(sheet, sheet->drag_range);
5095 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5099 gtk_sheet_click_cell(sheet, row, column, &veto);
5100 if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5104 if(event->window == sheet->column_title_window){
5105 gtk_widget_get_pointer (widget, &x, &y);
5106 column = COLUMN_FROM_XPIXEL(sheet, x);
5107 if(xxx_column_is_sensitive(sheet, column)){
5108 gtk_sheet_click_cell(sheet, -1, column, &veto);
5109 gtk_grab_add(GTK_WIDGET(sheet));
5110 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5111 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5112 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5116 if(event->window == sheet->row_title_window){
5117 gtk_widget_get_pointer (widget, &x, &y);
5118 row = ROW_FROM_YPIXEL(sheet, y);
5119 if(yyy_row_is_sensitive(sheet, row)){
5120 gtk_sheet_click_cell(sheet, row, -1, &veto);
5121 gtk_grab_add(GTK_WIDGET(sheet));
5122 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5123 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5124 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5132 gtk_sheet_scroll(gpointer data)
5135 gint x,y,row,column;
5138 sheet=GTK_SHEET(data);
5140 GDK_THREADS_ENTER();
5142 gtk_widget_get_pointer (GTK_WIDGET(sheet), &x, &y);
5143 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5147 if(GTK_SHEET_IN_SELECTION(sheet))
5148 gtk_sheet_extend_selection(sheet, row, column);
5150 if(GTK_SHEET_IN_DRAG(sheet) || GTK_SHEET_IN_RESIZE(sheet)){
5151 move=gtk_sheet_move_query(sheet, row, column);
5152 if(move) draw_xor_rectangle(sheet, sheet->drag_range);
5155 GDK_THREADS_LEAVE();
5162 gtk_sheet_click_cell(GtkSheet *sheet, gint row, gint column, gboolean *veto)
5166 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)){
5171 if(column >= 0 && row >= 0)
5172 if(! xxx_column_is_visible(sheet, column) || !yyy_row_is_visible(sheet, row))
5178 _gtkextra_signal_emit(GTK_OBJECT(sheet), sheet_signals[TRAVERSE],
5179 sheet->active_cell.row, sheet->active_cell.col,
5180 &row, &column, veto);
5183 if(sheet->state == GTK_STATE_NORMAL) return;
5185 row = sheet->active_cell.row;
5186 column = sheet->active_cell.col;
5188 gtk_sheet_activate_cell(sheet, row, column);
5192 if(row == -1 && column >= 0){
5193 if(gtk_sheet_autoscroll(sheet))
5194 gtk_sheet_move_query(sheet, row, column);
5195 gtk_sheet_select_column(sheet, column);
5198 if(column == -1 && row >= 0){
5199 if(gtk_sheet_autoscroll(sheet))
5200 gtk_sheet_move_query(sheet, row, column);
5201 gtk_sheet_select_row(sheet, row);
5205 if(row==-1 && column ==-1){
5206 sheet->range.row0=0;
5207 sheet->range.col0=0;
5208 sheet->range.rowi = yyy_row_count(sheet) - 1;
5209 sheet->range.coli = xxx_column_count(sheet) - 1;
5210 sheet->active_cell.row=0;
5211 sheet->active_cell.col=0;
5212 gtk_sheet_select_range(sheet, NULL);
5216 if(row!=-1 && column !=-1){
5217 if(sheet->state != GTK_SHEET_NORMAL){
5218 sheet->state = GTK_SHEET_NORMAL;
5219 gtk_sheet_real_unselect_range(sheet, NULL);
5223 if(!gtk_sheet_deactivate_cell(sheet)){
5229 if(gtk_sheet_autoscroll(sheet))
5230 gtk_sheet_move_query(sheet, row, column);
5231 sheet->active_cell.row=row;
5232 sheet->active_cell.col=column;
5233 sheet->selection_cell.row=row;
5234 sheet->selection_cell.col=column;
5235 sheet->range.row0=row;
5236 sheet->range.col0=column;
5237 sheet->range.rowi=row;
5238 sheet->range.coli=column;
5239 sheet->state=GTK_SHEET_NORMAL;
5240 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5241 gtk_sheet_draw_active_cell(sheet);
5245 g_assert_not_reached();
5246 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5247 sheet->active_cell.col);
5251 gtk_sheet_button_release (GtkWidget * widget,
5252 GdkEventButton * event)
5257 sheet=GTK_SHEET(widget);
5259 /* release on resize windows */
5260 if (GTK_SHEET_IN_XDRAG (sheet)){
5261 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
5262 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5263 gtk_widget_get_pointer (widget, &x, NULL);
5264 gdk_pointer_ungrab (event->time);
5265 draw_xor_vline (sheet);
5267 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col, new_column_width (sheet, sheet->drag_cell.col, &x));
5268 sheet->old_hadjustment = -1.;
5269 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed");
5273 if (GTK_SHEET_IN_YDRAG (sheet)){
5274 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5275 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5276 gtk_widget_get_pointer (widget, NULL, &y);
5277 gdk_pointer_ungrab (event->time);
5278 draw_xor_hline (sheet);
5280 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
5281 sheet->old_vadjustment = -1.;
5282 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed");
5287 if (GTK_SHEET_IN_DRAG(sheet)){
5288 GtkSheetRange old_range;
5289 draw_xor_rectangle(sheet, sheet->drag_range);
5290 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5291 gdk_pointer_ungrab (event->time);
5293 gtk_sheet_real_unselect_range(sheet, NULL);
5295 sheet->active_cell.row = sheet->active_cell.row +
5296 (sheet->drag_range.row0 - sheet->range.row0);
5297 sheet->active_cell.col = sheet->active_cell.col +
5298 (sheet->drag_range.col0 - sheet->range.col0);
5299 sheet->selection_cell.row = sheet->selection_cell.row +
5300 (sheet->drag_range.row0 - sheet->range.row0);
5301 sheet->selection_cell.col = sheet->selection_cell.col +
5302 (sheet->drag_range.col0 - sheet->range.col0);
5303 old_range=sheet->range;
5304 sheet->range=sheet->drag_range;
5305 sheet->drag_range=old_range;
5306 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[MOVE_RANGE],
5307 &sheet->drag_range, &sheet->range);
5308 gtk_sheet_select_range(sheet, &sheet->range);
5311 if (GTK_SHEET_IN_RESIZE(sheet)){
5312 GtkSheetRange old_range;
5313 draw_xor_rectangle(sheet, sheet->drag_range);
5314 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5315 gdk_pointer_ungrab (event->time);
5317 gtk_sheet_real_unselect_range(sheet, NULL);
5319 sheet->active_cell.row = sheet->active_cell.row +
5320 (sheet->drag_range.row0 - sheet->range.row0);
5321 sheet->active_cell.col = sheet->active_cell.col +
5322 (sheet->drag_range.col0 - sheet->range.col0);
5323 if(sheet->drag_range.row0 < sheet->range.row0)
5324 sheet->selection_cell.row = sheet->drag_range.row0;
5325 if(sheet->drag_range.rowi >= sheet->range.rowi)
5326 sheet->selection_cell.row = sheet->drag_range.rowi;
5327 if(sheet->drag_range.col0 < sheet->range.col0)
5328 sheet->selection_cell.col = sheet->drag_range.col0;
5329 if(sheet->drag_range.coli >= sheet->range.coli)
5330 sheet->selection_cell.col = sheet->drag_range.coli;
5331 old_range = sheet->range;
5332 sheet->range = sheet->drag_range;
5333 sheet->drag_range = old_range;
5335 if(sheet->state==GTK_STATE_NORMAL) sheet->state=GTK_SHEET_RANGE_SELECTED;
5336 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[RESIZE_RANGE],
5337 &sheet->drag_range, &sheet->range);
5338 gtk_sheet_select_range(sheet, &sheet->range);
5341 if(sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)){
5342 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5343 gdk_pointer_ungrab (event->time);
5344 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5345 sheet->active_cell.col);
5348 if(GTK_SHEET_IN_SELECTION)
5349 gdk_pointer_ungrab (event->time);
5351 gtk_timeout_remove(sheet->timer);
5352 gtk_grab_remove(GTK_WIDGET(sheet));
5354 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5360 gtk_sheet_motion (GtkWidget * widget,
5361 GdkEventMotion * event)
5364 GdkModifierType mods;
5365 GdkCursorType new_cursor;
5369 g_return_val_if_fail (widget != NULL, FALSE);
5370 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
5371 g_return_val_if_fail (event != NULL, FALSE);
5373 sheet = GTK_SHEET (widget);
5375 /* selections on the sheet */
5379 if(event->window == sheet->column_title_window &&
5380 gtk_sheet_columns_resizable(sheet))
5382 gtk_widget_get_pointer(widget, &x, &y);
5383 if(!GTK_SHEET_IN_SELECTION(sheet) &&
5384 POSSIBLE_XDRAG(sheet, x, &column))
5386 new_cursor = GDK_SB_H_DOUBLE_ARROW;
5387 if(new_cursor != sheet->cursor_drag->type)
5389 gdk_cursor_destroy(sheet->cursor_drag);
5390 sheet->cursor_drag = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
5391 gdk_window_set_cursor(sheet->column_title_window,
5392 sheet->cursor_drag);
5397 new_cursor = GDK_TOP_LEFT_ARROW;
5398 if(!GTK_SHEET_IN_XDRAG(sheet) &&
5399 new_cursor != sheet->cursor_drag->type)
5401 gdk_cursor_destroy(sheet->cursor_drag);
5402 sheet->cursor_drag = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5403 gdk_window_set_cursor(sheet->column_title_window,
5404 sheet->cursor_drag);
5409 if(event->window == sheet->row_title_window &&
5410 gtk_sheet_rows_resizable(sheet))
5412 gtk_widget_get_pointer(widget, &x, &y);
5413 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_YDRAG(sheet,y, &column))
5415 new_cursor = GDK_SB_V_DOUBLE_ARROW;
5416 if(new_cursor != sheet->cursor_drag->type){
5417 gdk_cursor_destroy(sheet->cursor_drag);
5418 sheet->cursor_drag = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
5419 gdk_window_set_cursor(sheet->row_title_window, sheet->cursor_drag);
5424 new_cursor = GDK_TOP_LEFT_ARROW;
5425 if(!GTK_SHEET_IN_YDRAG(sheet) &&
5426 new_cursor != sheet->cursor_drag->type)
5428 gdk_cursor_destroy(sheet->cursor_drag);
5429 sheet->cursor_drag = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5430 gdk_window_set_cursor(sheet->row_title_window, sheet->cursor_drag);
5435 new_cursor = GDK_PLUS;
5436 if( event->window == sheet->sheet_window &&
5437 !POSSIBLE_DRAG(sheet, x, y, &row, &column) &&
5438 !GTK_SHEET_IN_DRAG(sheet) &&
5439 !POSSIBLE_RESIZE(sheet, x, y, &row, &column) &&
5440 !GTK_SHEET_IN_RESIZE(sheet) &&
5441 new_cursor != sheet->cursor_drag->type)
5443 gdk_cursor_destroy(sheet->cursor_drag);
5444 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
5445 gdk_window_set_cursor(sheet->sheet_window, sheet->cursor_drag);
5448 new_cursor = GDK_TOP_LEFT_ARROW;
5449 if( event->window == sheet->sheet_window &&
5450 !(POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) && (POSSIBLE_DRAG(sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG(sheet)) &&
5452 new_cursor != sheet->cursor_drag->type)
5454 gdk_cursor_destroy(sheet->cursor_drag);
5455 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5456 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5459 new_cursor=GDK_SIZING;
5460 if( event->window == sheet->sheet_window &&
5461 !GTK_SHEET_IN_DRAG(sheet) &&
5462 (POSSIBLE_RESIZE(sheet, x, y, &row, &column) ||
5463 GTK_SHEET_IN_RESIZE(sheet)) &&
5464 new_cursor != sheet->cursor_drag->type)
5466 gdk_cursor_destroy(sheet->cursor_drag);
5467 sheet->cursor_drag=gdk_cursor_new(GDK_SIZING);
5468 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5471 gdk_window_get_pointer (widget->window, &x, &y, &mods);
5472 if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
5474 if (GTK_SHEET_IN_XDRAG (sheet))
5476 if (event->is_hint || event->window != widget->window)
5477 gtk_widget_get_pointer (widget, &x, NULL);
5481 new_column_width (sheet, sheet->drag_cell.col, &x);
5482 if (x != sheet->x_drag)
5484 draw_xor_vline (sheet);
5486 draw_xor_vline (sheet);
5491 if (GTK_SHEET_IN_YDRAG (sheet))
5493 if (event->is_hint || event->window != widget->window)
5494 gtk_widget_get_pointer (widget, NULL, &y);
5498 new_row_height (sheet, sheet->drag_cell.row, &y);
5499 if (y != sheet->y_drag)
5501 draw_xor_hline (sheet);
5503 draw_xor_hline (sheet);
5508 if (GTK_SHEET_IN_DRAG(sheet))
5511 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col;
5512 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row;
5513 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5514 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5518 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5519 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet))
5521 aux=sheet->drag_range;
5522 sheet->drag_range.row0 = sheet->range.row0 + row;
5523 sheet->drag_range.col0 = sheet->range.col0 + column;
5524 sheet->drag_range.rowi = sheet->range.rowi + row;
5525 sheet->drag_range.coli = sheet->range.coli + column;
5526 if(aux.row0 != sheet->drag_range.row0 ||
5527 aux.col0 != sheet->drag_range.col0)
5529 draw_xor_rectangle (sheet, aux);
5530 draw_xor_rectangle (sheet, sheet->drag_range);
5536 if (GTK_SHEET_IN_RESIZE(sheet))
5539 gint v_h, current_col, current_row, col_threshold, row_threshold;
5542 if(abs(x-COLUMN_LEFT_XPIXEL(sheet,sheet->drag_cell.col)) >
5543 abs(y-ROW_TOP_YPIXEL(sheet,sheet->drag_cell.row))) v_h=2;
5545 current_col = COLUMN_FROM_XPIXEL(sheet,x);
5546 current_row = ROW_FROM_YPIXEL(sheet,y);
5547 column = current_col-sheet->drag_cell.col;
5548 row = current_row-sheet->drag_cell.row;
5550 /*use half of column width resp. row height as threshold to expand selection*/
5551 col_threshold = COLUMN_LEFT_XPIXEL(sheet,current_col)+xxx_column_width (sheet,current_col)/2;
5554 if (x < col_threshold)
5557 else if (column < 0)
5559 if (x > col_threshold)
5562 row_threshold = ROW_TOP_YPIXEL(sheet,current_row) +
5563 yyy_row_height (sheet, current_row)/2;
5566 if(y < row_threshold)
5571 if(y > row_threshold)
5575 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5576 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5586 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5587 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5589 aux=sheet->drag_range;
5590 sheet->drag_range=sheet->range;
5592 if(row<0) sheet->drag_range.row0=sheet->range.row0+row;
5593 if(row>0) sheet->drag_range.rowi=sheet->range.rowi+row;
5594 if(column<0) sheet->drag_range.col0=sheet->range.col0+column;
5595 if(column>0) sheet->drag_range.coli=sheet->range.coli+column;
5597 if(aux.row0 != sheet->drag_range.row0 ||
5598 aux.rowi != sheet->drag_range.rowi ||
5599 aux.col0 != sheet->drag_range.col0 ||
5600 aux.coli != sheet->drag_range.coli){
5601 draw_xor_rectangle (sheet, aux);
5602 draw_xor_rectangle (sheet, sheet->drag_range);
5610 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5612 if(sheet->state==GTK_SHEET_NORMAL && row==sheet->active_cell.row &&
5613 column==sheet->active_cell.col) return TRUE;
5615 if(GTK_SHEET_IN_SELECTION(sheet) && mods&GDK_BUTTON1_MASK)
5616 gtk_sheet_extend_selection(sheet, row, column);
5622 gtk_sheet_move_query(GtkSheet *sheet, gint row, gint column)
5624 gint row_move, column_move;
5625 gfloat row_align, col_align;
5626 guint height, width;
5628 gint new_col = column;
5635 height = sheet->sheet_window_height;
5636 width = sheet->sheet_window_width;
5638 if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5640 new_row = MIN(yyy_row_count(sheet), row + 1);
5642 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet) - 1 &&
5643 ROW_TOP_YPIXEL(sheet, yyy_row_count(sheet)-1) +
5644 yyy_row_height(sheet, yyy_row_count(sheet)-1) < height){
5649 if(row<MIN_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5653 if(column>=MAX_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5655 new_col = MIN(xxx_column_count(sheet) - 1, column + 1);
5657 if(MAX_VISIBLE_COLUMN(sheet) == (xxx_column_count(sheet) - 1) &&
5658 COLUMN_LEFT_XPIXEL(sheet, xxx_column_count(sheet) - 1) +
5659 xxx_column_width(sheet, xxx_column_count(sheet) - 1) < width)
5661 column_move = FALSE;
5665 if(column<MIN_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5670 if(row_move || column_move){
5671 gtk_sheet_moveto(sheet, new_row, new_col, row_align, col_align);
5674 return(row_move || column_move);
5678 gtk_sheet_extend_selection(GtkSheet *sheet, gint row, gint column)
5680 GtkSheetRange range;
5684 if(row == sheet->selection_cell.row && column == sheet->selection_cell.col)
5687 if(sheet->selection_mode == GTK_SELECTION_SINGLE) return;
5689 gtk_sheet_move_query(sheet, row, column);
5690 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5692 if(GTK_SHEET_IN_DRAG(sheet)) return;
5696 switch(sheet->state){
5697 case GTK_SHEET_ROW_SELECTED:
5698 column = xxx_column_count(sheet) - 1;
5700 case GTK_SHEET_COLUMN_SELECTED:
5701 row = yyy_row_count(sheet) - 1;
5703 case GTK_SHEET_NORMAL:
5704 sheet->state=GTK_SHEET_RANGE_SELECTED;
5705 r=sheet->active_cell.row;
5706 c=sheet->active_cell.col;
5707 sheet->range.col0=c;
5708 sheet->range.row0=r;
5709 sheet->range.coli=c;
5710 sheet->range.rowi=r;
5711 gdk_draw_pixmap(sheet->sheet_window,
5712 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
5714 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5715 ROW_TOP_YPIXEL(sheet,r)-1,
5716 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5717 ROW_TOP_YPIXEL(sheet,r)-1,
5718 xxx_column_width(sheet, c)+4,
5719 yyy_row_height(sheet, r)+4);
5720 gtk_sheet_range_draw_selection(sheet, sheet->range);
5721 case GTK_SHEET_RANGE_SELECTED:
5722 sheet->state=GTK_SHEET_RANGE_SELECTED;
5725 sheet->selection_cell.row = row;
5726 sheet->selection_cell.col = column;
5728 range.col0=MIN(column,sheet->active_cell.col);
5729 range.coli=MAX(column,sheet->active_cell.col);
5730 range.row0=MIN(row,sheet->active_cell.row);
5731 range.rowi=MAX(row,sheet->active_cell.row);
5733 if(range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi ||
5734 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli ||
5735 state==GTK_SHEET_NORMAL)
5736 gtk_sheet_real_select_range(sheet, &range);
5741 gtk_sheet_entry_key_press(GtkWidget *widget,
5745 gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", key, &focus);
5750 gtk_sheet_key_press(GtkWidget *widget,
5756 gboolean extend_selection = FALSE;
5757 gboolean force_move = FALSE;
5758 gboolean in_selection = FALSE;
5759 gboolean veto = TRUE;
5762 sheet = GTK_SHEET(widget);
5764 if(key->state & GDK_CONTROL_MASK || key->keyval==GDK_Control_L ||
5765 key->keyval==GDK_Control_R) return FALSE;
5769 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL)
5770 gtk_sheet_clip_range(sheet, sheet->range);
5771 if(key->keyval=='x' || key->keyval == 'X')
5772 gtk_sheet_unclip_range(sheet);
5777 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval==GDK_Shift_L
5778 || key->keyval==GDK_Shift_R;
5781 in_selection = GTK_SHEET_IN_SELECTION(sheet);
5782 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5784 switch(key->keyval){
5785 case GDK_Return: case GDK_KP_Enter:
5786 if(sheet->state == GTK_SHEET_NORMAL &&
5787 !GTK_SHEET_IN_SELECTION(sheet))
5788 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
5790 row = sheet->active_cell.row;
5791 col = sheet->active_cell.col;
5792 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5793 row = MIN_VISIBLE_ROW(sheet)-1;
5794 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5795 col = MIN_VISIBLE_COLUMN(sheet);
5796 if(row < yyy_row_count(sheet) - 1){
5798 while(!yyy_row_is_visible(sheet, row) && row<yyy_row_count(sheet)-1)
5801 gtk_sheet_click_cell(sheet, row, col, &veto);
5802 extend_selection = FALSE;
5804 case GDK_ISO_Left_Tab:
5805 row = sheet->active_cell.row;
5806 col = sheet->active_cell.col;
5807 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5808 col = MIN_VISIBLE_COLUMN(sheet)-1;
5809 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5810 row = MIN_VISIBLE_ROW(sheet);
5813 while(! xxx_column_is_visible(sheet, col) && col>0) col--;
5816 gtk_sheet_click_cell(sheet, row, col, &veto);
5817 extend_selection = FALSE;
5820 row = sheet->active_cell.row;
5821 col = sheet->active_cell.col;
5822 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5823 col = MIN_VISIBLE_COLUMN(sheet)-1;
5824 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5825 row = MIN_VISIBLE_ROW(sheet);
5826 if(col < xxx_column_count(sheet) - 1)
5829 while(! xxx_column_is_visible(sheet, col) &&
5830 col < xxx_column_count(sheet) - 1)
5833 gtk_sheet_click_cell(sheet, row, col, &veto);
5834 extend_selection = FALSE;
5836 /* case GDK_BackSpace:
5837 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){
5838 if(sheet->active_cell.col > 0){
5839 col = sheet->active_cell.col - scroll;
5840 row = sheet->active_cell.row;
5841 while(!sheet->column[col].is_visible && col > 0) col--;
5844 gtk_sheet_click_cell(sheet, row, col, &veto);
5845 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 > 0){
5859 row = sheet->selection_cell.row - scroll;
5860 while(!yyy_row_is_visible(sheet, row) && row > 0) 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(state==GTK_SHEET_COLUMN_SELECTED)
5869 row = MIN_VISIBLE_ROW(sheet);
5870 if(state==GTK_SHEET_ROW_SELECTED)
5871 col = MIN_VISIBLE_COLUMN(sheet);
5873 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5875 gtk_sheet_click_cell(sheet, row, col, &veto);
5876 extend_selection = FALSE;
5879 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
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.row < yyy_row_count(sheet)-1){
5889 row = sheet->selection_cell.row + scroll;
5890 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5891 row = MIN(yyy_row_count(sheet)-1, row);
5892 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5896 col = sheet->active_cell.col;
5897 row = sheet->active_cell.row;
5898 if(sheet->active_cell.row < yyy_row_count(sheet)-1){
5899 if(state==GTK_SHEET_COLUMN_SELECTED)
5900 row = MIN_VISIBLE_ROW(sheet)-1;
5901 if(state==GTK_SHEET_ROW_SELECTED)
5902 col = MIN_VISIBLE_COLUMN(sheet);
5904 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5905 row = MIN(yyy_row_count(sheet)-1, row);
5907 gtk_sheet_click_cell(sheet, row, col, &veto);
5908 extend_selection = FALSE;
5911 if(extend_selection){
5912 if(state==GTK_STATE_NORMAL){
5913 row=sheet->active_cell.row;
5914 col=sheet->active_cell.col;
5915 gtk_sheet_click_cell(sheet, row, col, &veto);
5918 if(sheet->selection_cell.col < xxx_column_count(sheet) - 1)
5920 col = sheet->selection_cell.col + 1;
5921 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1)
5923 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5927 col = sheet->active_cell.col;
5928 row = sheet->active_cell.row;
5929 if(sheet->active_cell.col < xxx_column_count(sheet) - 1){
5931 if(state==GTK_SHEET_ROW_SELECTED)
5932 col = MIN_VISIBLE_COLUMN(sheet)-1;
5933 if(state==GTK_SHEET_COLUMN_SELECTED)
5934 row = MIN_VISIBLE_ROW(sheet);
5935 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1) col++;
5936 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5938 gtk_sheet_click_cell(sheet, row, col, &veto);
5943 extend_selection = FALSE;
5946 if(extend_selection){
5947 if(state==GTK_STATE_NORMAL){
5948 row=sheet->active_cell.row;
5949 col=sheet->active_cell.col;
5950 gtk_sheet_click_cell(sheet, row, col, &veto);
5953 if(sheet->selection_cell.col > 0){
5954 col = sheet->selection_cell.col - 1;
5955 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5956 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5960 col = sheet->active_cell.col - 1;
5961 row = sheet->active_cell.row;
5962 if(state==GTK_SHEET_ROW_SELECTED)
5963 col = MIN_VISIBLE_COLUMN(sheet)-1;
5964 if(state==GTK_SHEET_COLUMN_SELECTED)
5965 row = MIN_VISIBLE_ROW(sheet);
5966 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5969 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5971 gtk_sheet_click_cell(sheet, row, col, &veto);
5975 extend_selection = FALSE;
5979 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5980 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5981 extend_selection = FALSE;
5984 row=yyy_row_count(sheet)-1;
5985 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5986 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5987 extend_selection = FALSE;
5991 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5992 if(extend_selection) return TRUE;
5994 if(state == GTK_SHEET_ROW_SELECTED)
5995 sheet->active_cell.col=MIN_VISIBLE_COLUMN(sheet);
5996 if(state == GTK_SHEET_COLUMN_SELECTED)
5997 sheet->active_cell.row=MIN_VISIBLE_ROW(sheet);
6001 if(extend_selection) return TRUE;
6003 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
6004 sheet->active_cell.col);
6010 gtk_sheet_size_request (GtkWidget * widget,
6011 GtkRequisition * requisition)
6015 GtkSheetChild *child;
6016 GtkRequisition child_requisition;
6018 g_return_if_fail (widget != NULL);
6019 g_return_if_fail (GTK_IS_SHEET (widget));
6020 g_return_if_fail (requisition != NULL);
6022 sheet = GTK_SHEET (widget);
6024 requisition->width = 3*DEFAULT_COLUMN_WIDTH;
6025 requisition->height = 3*DEFAULT_ROW_HEIGHT(widget);
6027 /* compute the size of the column title area */
6028 if(sheet->column_titles_visible)
6029 requisition->height += sheet->column_title_area.height;
6031 /* compute the size of the row title area */
6032 if(sheet->row_titles_visible)
6033 requisition->width += sheet->row_title_area.width;
6035 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6036 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6037 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6038 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6040 if(!sheet->column_titles_visible)
6041 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6043 if(!sheet->row_titles_visible)
6044 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6046 children = sheet->children;
6049 child = children->data;
6050 children = children->next;
6052 gtk_widget_size_request(child->widget, &child_requisition);
6058 gtk_sheet_size_allocate (GtkWidget * widget,
6059 GtkAllocation * allocation)
6062 GtkAllocation sheet_allocation;
6065 g_return_if_fail (widget != NULL);
6066 g_return_if_fail (GTK_IS_SHEET (widget));
6067 g_return_if_fail (allocation != NULL);
6069 sheet = GTK_SHEET (widget);
6070 widget->allocation = *allocation;
6071 border_width = GTK_CONTAINER(widget)->border_width;
6073 if (GTK_WIDGET_REALIZED (widget))
6074 gdk_window_move_resize (widget->window,
6075 allocation->x + border_width,
6076 allocation->y + border_width,
6077 allocation->width - 2*border_width,
6078 allocation->height - 2*border_width);
6080 /* use internal allocation structure for all the math
6081 * because it's easier than always subtracting the container
6083 sheet->internal_allocation.x = 0;
6084 sheet->internal_allocation.y = 0;
6085 sheet->internal_allocation.width = allocation->width - 2*border_width;
6086 sheet->internal_allocation.height = allocation->height - 2*border_width;
6088 sheet_allocation.x = 0;
6089 sheet_allocation.y = 0;
6090 sheet_allocation.width = allocation->width - 2*border_width;
6091 sheet_allocation.height = allocation->height - 2*border_width;
6093 sheet->sheet_window_width = sheet_allocation.width;
6094 sheet->sheet_window_height = sheet_allocation.height;
6096 if (GTK_WIDGET_REALIZED (widget))
6097 gdk_window_move_resize (sheet->sheet_window,
6100 sheet_allocation.width,
6101 sheet_allocation.height);
6103 /* position the window which holds the column title buttons */
6104 sheet->column_title_area.x = 0;
6105 sheet->column_title_area.y = 0;
6106 if(sheet->row_titles_visible)
6107 sheet->column_title_area.x = sheet->row_title_area.width;
6108 sheet->column_title_area.width = sheet_allocation.width -
6109 sheet->column_title_area.x;
6110 if(GTK_WIDGET_REALIZED(widget) && sheet->column_titles_visible)
6111 gdk_window_move_resize (sheet->column_title_window,
6112 sheet->column_title_area.x,
6113 sheet->column_title_area.y,
6114 sheet->column_title_area.width,
6115 sheet->column_title_area.height);
6117 sheet->sheet_window_width = sheet_allocation.width;
6118 sheet->sheet_window_height = sheet_allocation.height;
6120 /* column button allocation */
6121 size_allocate_column_title_buttons (sheet);
6123 /* position the window which holds the row title buttons */
6124 sheet->row_title_area.x = 0;
6125 sheet->row_title_area.y = 0;
6126 if(sheet->column_titles_visible)
6127 sheet->row_title_area.y = sheet->column_title_area.height;
6128 sheet->row_title_area.height = sheet_allocation.height -
6129 sheet->row_title_area.y;
6131 if(GTK_WIDGET_REALIZED(widget) && sheet->row_titles_visible)
6132 gdk_window_move_resize (sheet->row_title_window,
6133 sheet->row_title_area.x,
6134 sheet->row_title_area.y,
6135 sheet->row_title_area.width,
6136 sheet->row_title_area.height);
6139 /* row button allocation */
6140 size_allocate_row_title_buttons (sheet);
6142 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6143 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6144 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6145 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6147 if(!sheet->column_titles_visible)
6148 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6150 if(!sheet->row_titles_visible)
6151 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6153 size_allocate_column_title_buttons(sheet);
6154 size_allocate_row_title_buttons(sheet);
6156 /* re-scale backing pixmap */
6157 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
6158 gtk_sheet_position_children(sheet);
6160 /* set the scrollbars adjustments */
6161 adjust_scrollbars (sheet);
6165 size_allocate_column_title_buttons (GtkSheet * sheet)
6170 if (!sheet->column_titles_visible) return;
6171 if (!GTK_WIDGET_REALIZED (sheet))
6174 width = sheet->sheet_window_width;
6177 if(sheet->row_titles_visible)
6179 width -= sheet->row_title_area.width;
6180 x = sheet->row_title_area.width;
6183 if(sheet->column_title_area.width != width || sheet->column_title_area.x != x)
6185 sheet->column_title_area.width = width;
6186 sheet->column_title_area.x = x;
6187 gdk_window_move_resize (sheet->column_title_window,
6188 sheet->column_title_area.x,
6189 sheet->column_title_area.y,
6190 sheet->column_title_area.width,
6191 sheet->column_title_area.height);
6195 if(MAX_VISIBLE_COLUMN(sheet) == xxx_column_count(sheet) - 1)
6196 gdk_window_clear_area (sheet->column_title_window,
6198 sheet->column_title_area.width,
6199 sheet->column_title_area.height);
6201 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6203 for (i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
6204 gtk_sheet_column_title_button_draw(sheet, i);
6208 size_allocate_row_title_buttons (GtkSheet * sheet)
6213 if (!sheet->row_titles_visible) return;
6214 if (!GTK_WIDGET_REALIZED (sheet))
6217 height = sheet->sheet_window_height;
6220 if(sheet->column_titles_visible)
6222 height -= sheet->column_title_area.height;
6223 y = sheet->column_title_area.height;
6226 if(sheet->row_title_area.height != height || sheet->row_title_area.y != y)
6228 sheet->row_title_area.y = y;
6229 sheet->row_title_area.height = height;
6230 gdk_window_move_resize (sheet->row_title_window,
6231 sheet->row_title_area.x,
6232 sheet->row_title_area.y,
6233 sheet->row_title_area.width,
6234 sheet->row_title_area.height);
6236 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet)-1)
6237 gdk_window_clear_area (sheet->row_title_window,
6239 sheet->row_title_area.width,
6240 sheet->row_title_area.height);
6242 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6244 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
6246 if ( i >= yyy_row_count(sheet))
6248 gtk_sheet_row_title_button_draw(sheet, i);
6254 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
6256 GtkAllocation shentry_allocation;
6257 GtkSheetCellAttr attributes = { 0 };
6258 GtkEntry *sheet_entry;
6259 GtkStyle *style = NULL, *previous_style = NULL;
6261 gint size, max_size, text_size, column_width;
6264 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6265 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
6267 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
6269 gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes);
6271 if(GTK_WIDGET_REALIZED(sheet->sheet_entry))
6274 if(!GTK_WIDGET(sheet_entry)->style)
6275 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry));
6277 previous_style = GTK_WIDGET(sheet_entry)->style;
6279 style = gtk_style_copy(previous_style);
6280 style->bg[GTK_STATE_NORMAL] = attributes.background;
6281 style->fg[GTK_STATE_NORMAL] = attributes.foreground;
6282 style->text[GTK_STATE_NORMAL] = attributes.foreground;
6283 style->bg[GTK_STATE_ACTIVE] = attributes.background;
6284 style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
6285 style->text[GTK_STATE_ACTIVE] = attributes.foreground;
6287 pango_font_description_free(style->font_desc);
6288 style->font_desc = pango_font_description_copy(attributes.font_desc);
6290 GTK_WIDGET(sheet_entry)->style = style;
6291 gtk_widget_size_request(sheet->sheet_entry, NULL);
6292 GTK_WIDGET(sheet_entry)->style = previous_style;
6294 if(style != previous_style){
6295 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6296 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
6297 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
6298 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
6299 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
6301 gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
6305 if(GTK_IS_ITEM_ENTRY(sheet_entry))
6306 max_size = GTK_ITEM_ENTRY(sheet_entry)->text_max_size;
6311 text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
6312 if(text && strlen(text) > 0){
6313 text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
6316 column_width=xxx_column_width(sheet, sheet->active_cell.col);
6318 size=MIN(text_size, max_size);
6319 size=MAX(size,column_width-2*CELLOFFSET);
6321 row=sheet->active_cell.row;
6322 col=sheet->active_cell.col;
6324 shentry_allocation.x = COLUMN_LEFT_XPIXEL(sheet,sheet->active_cell.col);
6325 shentry_allocation.y = ROW_TOP_YPIXEL(sheet,sheet->active_cell.row);
6326 shentry_allocation.width = column_width;
6327 shentry_allocation.height = yyy_row_height(sheet, sheet->active_cell.row);
6329 if(GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6331 shentry_allocation.height -= 2*CELLOFFSET;
6332 shentry_allocation.y += CELLOFFSET;
6333 if(gtk_sheet_clip_text(sheet))
6334 shentry_allocation.width = column_width - 2*CELLOFFSET;
6336 shentry_allocation.width = size;
6338 switch(GTK_ITEM_ENTRY(sheet_entry)->justification){
6339 case GTK_JUSTIFY_CENTER:
6340 shentry_allocation.x += (column_width)/2 - size/2;
6342 case GTK_JUSTIFY_RIGHT:
6343 shentry_allocation.x += column_width - size - CELLOFFSET;
6345 case GTK_JUSTIFY_LEFT:
6346 case GTK_JUSTIFY_FILL:
6347 shentry_allocation.x += CELLOFFSET;
6353 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry))
6355 shentry_allocation.x += 2;
6356 shentry_allocation.y += 2;
6357 shentry_allocation.width -= MIN(shentry_allocation.width, 3);
6358 shentry_allocation.height -= MIN(shentry_allocation.height, 3);
6361 gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation);
6363 if(previous_style == style) gtk_style_unref(previous_style);
6367 gtk_sheet_entry_set_max_size(GtkSheet *sheet)
6371 gint sizel=0, sizer=0;
6373 GtkJustification justification;
6376 row=sheet->active_cell.row;
6377 col=sheet->active_cell.col;
6379 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry) || gtk_sheet_clip_text(sheet)) return;
6381 justification = GTK_ITEM_ENTRY(sheet->sheet_entry)->justification;
6383 switch(justification){
6384 case GTK_JUSTIFY_FILL:
6385 case GTK_JUSTIFY_LEFT:
6386 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6387 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6392 size+=xxx_column_width(sheet, i);
6394 size = MIN(size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL(sheet, col));
6396 case GTK_JUSTIFY_RIGHT:
6397 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--)
6399 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6404 size+=xxx_column_width(sheet, i);
6407 case GTK_JUSTIFY_CENTER:
6408 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6409 /* if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6415 sizer+=xxx_column_width(sheet, i);
6417 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--)
6419 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6424 sizel+=xxx_column_width(sheet, i);
6426 size=2*MIN(sizel, sizer);
6431 size += xxx_column_width(sheet, col);
6432 GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size = size;
6436 create_sheet_entry(GtkSheet *sheet)
6441 gint found_entry = FALSE;
6443 widget = GTK_WIDGET(sheet);
6445 if(sheet->sheet_entry)
6447 /* avoids warnings */
6448 gtk_widget_ref(sheet->sheet_entry);
6449 gtk_widget_unparent(sheet->sheet_entry);
6450 gtk_widget_destroy(sheet->sheet_entry);
6453 if(sheet->entry_type)
6455 if(!g_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY))
6457 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6459 sheet->sheet_entry = parent;
6461 entry = gtk_sheet_get_entry (sheet);
6462 if(GTK_IS_ENTRY(entry))
6467 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6474 g_warning ("Entry type must be GtkEntry subclass, using default");
6475 entry = gtk_item_entry_new();
6476 sheet->sheet_entry = entry;
6479 sheet->sheet_entry = parent;
6483 entry = gtk_item_entry_new();
6484 sheet->sheet_entry = entry;
6487 gtk_widget_size_request(sheet->sheet_entry, NULL);
6489 if(GTK_WIDGET_REALIZED(sheet))
6491 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
6492 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
6493 gtk_widget_realize(sheet->sheet_entry);
6496 gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event",
6497 (GtkSignalFunc) gtk_sheet_entry_key_press,
6500 gtk_widget_show (sheet->sheet_entry);
6504 /* Finds the last child widget that happens to be of type GtkEntry */
6506 find_entry(GtkWidget *w, gpointer user_data)
6508 GtkWidget **entry = user_data;
6509 if ( GTK_IS_ENTRY(w))
6516 gtk_sheet_get_entry(GtkSheet *sheet)
6519 GtkWidget *entry = NULL;
6520 GtkTableChild *table_child;
6521 GtkBoxChild *box_child;
6522 GList *children = NULL;
6524 g_return_val_if_fail (sheet != NULL, NULL);
6525 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6526 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6528 if(GTK_IS_ENTRY(sheet->sheet_entry)) return (sheet->sheet_entry);
6530 parent = GTK_WIDGET(sheet->sheet_entry);
6532 if(GTK_IS_TABLE(parent)) children = GTK_TABLE(parent)->children;
6533 if(GTK_IS_BOX(parent)) children = GTK_BOX(parent)->children;
6535 if(GTK_IS_CONTAINER(parent))
6537 gtk_container_forall(GTK_CONTAINER(parent), find_entry, &entry);
6539 if(GTK_IS_ENTRY(entry))
6543 if(!children) return NULL;
6546 if(GTK_IS_TABLE(parent)) {
6547 table_child = children->data;
6548 entry = table_child->widget;
6550 if(GTK_IS_BOX(parent)){
6551 box_child = children->data;
6552 entry = box_child->widget;
6555 if(GTK_IS_ENTRY(entry))
6557 children = children->next;
6561 if(!GTK_IS_ENTRY(entry)) return NULL;
6568 gtk_sheet_get_entry_widget(GtkSheet *sheet)
6570 g_return_val_if_fail (sheet != NULL, NULL);
6571 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6572 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6574 return (sheet->sheet_entry);
6579 gtk_sheet_button_draw(GtkSheet *sheet, GdkWindow *window,
6580 GtkSheetButton *button, gboolean is_sensitive,
6581 GdkRectangle allocation)
6583 GtkShadowType shadow_type;
6584 gint text_width = 0, text_height = 0;
6585 GtkSheetChild *child = NULL;
6586 PangoAlignment align = PANGO_ALIGN_LEFT;
6594 g_return_if_fail(sheet != NULL);
6595 g_return_if_fail(button != NULL);
6597 rtl = gtk_widget_get_direction(GTK_WIDGET(sheet)) == GTK_TEXT_DIR_RTL;
6599 gdk_window_clear_area (window,
6600 allocation.x, allocation.y,
6601 allocation.width, allocation.height);
6603 gtk_paint_box (sheet->button->style, window,
6604 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
6605 &allocation, GTK_WIDGET(sheet->button),
6607 allocation.x, allocation.y,
6608 allocation.width, allocation.height);
6610 state = button->state;
6611 if(!is_sensitive) state = GTK_STATE_INSENSITIVE;
6613 if (state == GTK_STATE_ACTIVE)
6614 shadow_type = GTK_SHADOW_IN;
6616 shadow_type = GTK_SHADOW_OUT;
6618 if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
6619 gtk_paint_box (sheet->button->style, window,
6620 button->state, shadow_type,
6621 &allocation, GTK_WIDGET(sheet->button),
6623 allocation.x, allocation.y,
6624 allocation.width, allocation.height);
6626 if(button->label_visible)
6629 text_height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))-2*CELLOFFSET;
6631 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6633 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation);
6635 allocation.y += 2*sheet->button->style->ythickness;
6638 if(button->label && strlen(button->label)>0){
6640 PangoLayout *layout = NULL;
6641 gint real_x = allocation.x, real_y = allocation.y;
6643 words=button->label;
6644 line = g_new(gchar, 1);
6647 while(words && *words != '\0'){
6650 line=g_realloc(line, len+2);
6654 if(*words == '\n' || *(words+1) == '\0'){
6655 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, line);
6657 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), line);
6658 switch(button->justification){
6659 case GTK_JUSTIFY_LEFT:
6660 real_x = allocation.x + CELLOFFSET;
6661 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6663 case GTK_JUSTIFY_RIGHT:
6664 real_x = allocation.x + allocation.width - text_width - CELLOFFSET;
6665 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6667 case GTK_JUSTIFY_CENTER:
6669 real_x = allocation.x + (allocation.width - text_width)/2;
6670 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6671 pango_layout_set_justify (layout, TRUE);
6673 pango_layout_set_alignment (layout, align);
6674 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6683 g_object_unref(G_OBJECT(layout));
6685 real_y += text_height + 2;
6688 line = g_new(gchar, 1);
6696 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6698 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, NULL);
6702 if((child = button->child) && (child->widget))
6704 child->x = allocation.x;
6705 child->y = allocation.y;
6707 child->x += (allocation.width - child->widget->requisition.width) / 2;
6708 child->y += (allocation.height - child->widget->requisition.height) / 2;
6709 allocation.x = child->x;
6710 allocation.y = child->y;
6711 allocation.width = child->widget->requisition.width;
6712 allocation.height = child->widget->requisition.height;
6714 allocation.x = child->x;
6715 allocation.y = child->y;
6717 gtk_widget_set_state(child->widget, button->state);
6719 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
6720 GTK_WIDGET_MAPPED(child->widget))
6722 gtk_widget_size_allocate(child->widget,
6724 gtk_widget_queue_draw(child->widget);
6728 gtk_sheet_button_free(button);
6732 /* COLUMN value of -1 indicates that the area to the right of the rightmost
6733 button should be redrawn */
6735 gtk_sheet_column_title_button_draw(GtkSheet *sheet, gint column)
6737 GdkWindow *window = NULL;
6738 GdkRectangle allocation;
6739 GtkSheetButton *button = NULL;
6740 gboolean is_sensitive = FALSE;
6742 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6744 if(column >= 0 && ! xxx_column_is_visible(sheet, column)) return;
6745 if(column >= 0 && !sheet->column_titles_visible) return;
6746 if(column>=0 && column < MIN_VISIBLE_COLUMN(sheet)) return;
6747 if(column>=0 && column > MAX_VISIBLE_COLUMN(sheet)) return;
6749 window = sheet->column_title_window;
6751 allocation.height = sheet->column_title_area.height;
6755 const gint cols = xxx_column_count(sheet) ;
6756 allocation.x = COLUMN_LEFT_XPIXEL(sheet, cols - 1)
6758 allocation.width = sheet->column_title_area.width
6759 + sheet->column_title_area.x
6762 gdk_window_clear_area (window,
6763 allocation.x, allocation.y,
6764 allocation.width, allocation.height);
6768 button = xxx_column_button(sheet, column);
6769 allocation.x = COLUMN_LEFT_XPIXEL(sheet, column) + CELL_SPACING;
6770 if(sheet->row_titles_visible)
6771 allocation.x -= sheet->row_title_area.width;
6773 allocation.width = xxx_column_width(sheet, column);
6775 is_sensitive = xxx_column_is_sensitive(sheet, column);
6776 gtk_sheet_button_draw(sheet, window, button,
6777 is_sensitive, allocation);
6782 gtk_sheet_row_title_button_draw(GtkSheet *sheet, gint row)
6784 GdkWindow *window = NULL;
6785 GdkRectangle allocation;
6786 GtkSheetButton *button = NULL;
6787 gboolean is_sensitive = FALSE;
6790 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6792 if(row >= 0 && !yyy_row_is_visible(sheet, row)) return;
6793 if(row >= 0 && !sheet->row_titles_visible) return;
6794 if(row>=0 && row < MIN_VISIBLE_ROW(sheet)) return;
6795 if(row>=0 && row > MAX_VISIBLE_ROW(sheet)) return;
6798 window=sheet->row_title_window;
6799 button = yyy_row_button(sheet, row);
6801 allocation.y = ROW_TOP_YPIXEL(sheet, row) + CELL_SPACING;
6802 if(sheet->column_titles_visible)
6803 allocation.y -= sheet->column_title_area.height;
6804 allocation.width = sheet->row_title_area.width;
6805 allocation.height = yyy_row_height(sheet, row);
6806 is_sensitive = yyy_row_is_sensitive(sheet, row);
6808 gtk_sheet_button_draw(sheet, window, button, is_sensitive, allocation);
6815 * vadjustment_changed
6816 * hadjustment_changed
6817 * vadjustment_value_changed
6818 * hadjustment_value_changed */
6821 adjust_scrollbars (GtkSheet * sheet)
6824 if(sheet->vadjustment){
6825 sheet->vadjustment->page_size = sheet->sheet_window_height;
6826 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
6827 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
6828 sheet->vadjustment->lower = 0;
6829 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
6831 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet))
6833 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) -
6834 sheet->sheet_window_height);
6835 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
6839 gtk_signal_emit_by_name (GTK_OBJECT(sheet->vadjustment), "changed");
6843 if(sheet->hadjustment){
6844 sheet->hadjustment->page_size = sheet->sheet_window_width;
6845 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
6846 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
6847 sheet->hadjustment->lower = 0;
6848 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
6850 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet))
6852 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) -
6853 sheet->sheet_window_width);
6854 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment),
6858 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), "changed");
6862 if(GTK_WIDGET_REALIZED(sheet))
6864 if(sheet->row_titles_visible){
6865 size_allocate_row_title_buttons(sheet);
6866 gdk_window_show(sheet->row_title_window);
6869 if(sheet->column_titles_visible){
6870 size_allocate_column_title_buttons(sheet);
6871 gdk_window_show(sheet->column_title_window);
6874 gtk_sheet_range_draw(sheet, NULL);
6881 vadjustment_changed (GtkAdjustment * adjustment,
6886 g_return_if_fail (adjustment != NULL);
6887 g_return_if_fail (data != NULL);
6889 sheet = GTK_SHEET (data);
6894 hadjustment_changed (GtkAdjustment * adjustment,
6899 g_return_if_fail (adjustment != NULL);
6900 g_return_if_fail (data != NULL);
6902 sheet = GTK_SHEET (data);
6907 vadjustment_value_changed (GtkAdjustment * adjustment,
6911 gint diff, value, old_value;
6915 g_return_if_fail (adjustment != NULL);
6916 g_return_if_fail (data != NULL);
6917 g_return_if_fail (GTK_IS_SHEET (data));
6919 sheet = GTK_SHEET (data);
6921 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6923 row = ROW_FROM_YPIXEL(sheet,sheet->column_title_area.height + CELL_SPACING);
6924 if(!sheet->column_titles_visible)
6925 row=ROW_FROM_YPIXEL(sheet, CELL_SPACING);
6927 old_value = -sheet->voffset;
6929 new_row = g_sheet_row_pixel_to_row(sheet->row_geometry,
6930 adjustment->value,sheet);
6932 y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
6934 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
6935 yyy_row_height(sheet, row) > sheet->vadjustment->step_increment)
6937 /* This avoids embarrassing twitching */
6938 if(row == new_row && row != yyy_row_count(sheet) - 1 &&
6939 adjustment->value - sheet->old_vadjustment >=
6940 sheet->vadjustment->step_increment &&
6941 new_row + 1 != MIN_VISIBLE_ROW(sheet)){
6943 y=y+yyy_row_height(sheet, row);
6947 /* Negative old_adjustment enforces the redraw, otherwise avoid
6949 if(sheet->old_vadjustment >= 0. && row == new_row)
6951 sheet->old_vadjustment = sheet->vadjustment->value;
6955 sheet->old_vadjustment = sheet->vadjustment->value;
6956 adjustment->value=y;
6961 sheet->vadjustment->step_increment = yyy_row_height(sheet, 0);
6965 sheet->vadjustment->step_increment =
6966 MIN(yyy_row_height(sheet, new_row), yyy_row_height(sheet, new_row-1));
6969 sheet->vadjustment->value = adjustment->value;
6971 value = adjustment->value;
6973 if (value >= -sheet->voffset)
6976 diff = value + sheet->voffset;
6981 diff = -sheet->voffset - value;
6984 sheet->voffset = -value;
6986 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height + 1);
6987 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height - 1);
6988 if(!sheet->column_titles_visible)
6989 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6991 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6992 sheet->state == GTK_SHEET_NORMAL &&
6993 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6994 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6995 sheet->active_cell.col))
6999 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
7001 if(!text || strlen(text)==0)
7002 gtk_sheet_cell_clear(sheet,
7003 sheet->active_cell.row,
7004 sheet->active_cell.col);
7005 gtk_widget_unmap(sheet->sheet_entry);
7008 gtk_sheet_position_children(sheet);
7010 gtk_sheet_range_draw(sheet, NULL);
7011 size_allocate_row_title_buttons(sheet);
7012 size_allocate_global_button(sheet);
7016 hadjustment_value_changed (GtkAdjustment * adjustment,
7020 gint i, diff, value, old_value;
7021 gint column, new_column;
7024 g_return_if_fail (adjustment != NULL);
7025 g_return_if_fail (data != NULL);
7026 g_return_if_fail (GTK_IS_SHEET (data));
7028 sheet = GTK_SHEET (data);
7030 if(GTK_SHEET_IS_FROZEN(sheet)) return;
7032 column=COLUMN_FROM_XPIXEL(sheet,sheet->row_title_area.width + CELL_SPACING);
7033 if(!sheet->row_titles_visible)
7034 column=COLUMN_FROM_XPIXEL(sheet, CELL_SPACING);
7036 old_value = -sheet->hoffset;
7038 for(i=0; i < xxx_column_count(sheet); i++)
7040 if(xxx_column_is_visible(sheet, i)) x += xxx_column_width(sheet, i);
7041 if(x > adjustment->value) break;
7043 x-=xxx_column_width(sheet, i);
7046 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
7047 xxx_column_width(sheet, i) > sheet->hadjustment->step_increment){
7048 /* This avoids embarrassing twitching */
7049 if(column == new_column && column != xxx_column_count(sheet) - 1 &&
7050 adjustment->value - sheet->old_hadjustment >=
7051 sheet->hadjustment->step_increment &&
7052 new_column + 1 != MIN_VISIBLE_COLUMN(sheet)){
7054 x=x+xxx_column_width(sheet, column);
7058 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
7059 if(sheet->old_hadjustment >= 0. && new_column == column){
7060 sheet->old_hadjustment = sheet->hadjustment->value;
7064 sheet->old_hadjustment = sheet->hadjustment->value;
7065 adjustment->value=x;
7067 if(new_column == 0){
7068 sheet->hadjustment->step_increment=
7069 xxx_column_width(sheet, 0);
7071 sheet->hadjustment->step_increment=
7072 MIN(xxx_column_width(sheet, new_column), xxx_column_width(sheet, new_column-1));
7076 sheet->hadjustment->value=adjustment->value;
7078 value = adjustment->value;
7080 if (value >= -sheet->hoffset)
7083 diff = value + sheet->hoffset;
7088 diff = -sheet->hoffset - value;
7091 sheet->hoffset = -value;
7093 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
7094 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7095 if(!sheet->row_titles_visible)
7096 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
7098 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
7099 sheet->state == GTK_SHEET_NORMAL &&
7100 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
7101 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
7102 sheet->active_cell.col))
7106 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
7107 if(!text || strlen(text)==0)
7108 gtk_sheet_cell_clear(sheet,
7109 sheet->active_cell.row,
7110 sheet->active_cell.col);
7112 gtk_widget_unmap(sheet->sheet_entry);
7115 gtk_sheet_position_children(sheet);
7117 gtk_sheet_range_draw(sheet, NULL);
7118 size_allocate_column_title_buttons(sheet);
7122 /* COLUMN RESIZING */
7124 draw_xor_vline (GtkSheet * sheet)
7128 g_return_if_fail (sheet != NULL);
7130 widget = GTK_WIDGET (sheet);
7132 gdk_draw_line (widget->window, sheet->xor_gc,
7134 sheet->column_title_area.height,
7136 sheet->sheet_window_height + 1);
7141 draw_xor_hline (GtkSheet * sheet)
7145 g_return_if_fail (sheet != NULL);
7147 widget = GTK_WIDGET (sheet);
7149 gdk_draw_line (widget->window, sheet->xor_gc,
7150 sheet->row_title_area.width,
7153 sheet->sheet_window_width + 1,
7157 /* SELECTED RANGE */
7159 draw_xor_rectangle(GtkSheet *sheet, GtkSheetRange range)
7162 GdkRectangle clip_area, area;
7165 area.x=COLUMN_LEFT_XPIXEL(sheet, range.col0);
7166 area.y=ROW_TOP_YPIXEL(sheet, range.row0);
7167 area.width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-area.x+
7168 xxx_column_width(sheet, range.coli);
7169 area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+
7170 yyy_row_height(sheet, range.rowi);
7172 clip_area.x=sheet->row_title_area.width;
7173 clip_area.y=sheet->column_title_area.height;
7174 clip_area.width=sheet->sheet_window_width;
7175 clip_area.height=sheet->sheet_window_height;
7177 if(!sheet->row_titles_visible) clip_area.x = 0;
7178 if(!sheet->column_titles_visible) clip_area.y = 0;
7181 area.width=area.width+area.x;
7184 if(area.width>clip_area.width) area.width=clip_area.width+10;
7186 area.height=area.height+area.y;
7189 if(area.height>clip_area.height) area.height=clip_area.height+10;
7194 clip_area.height+=3;
7196 gdk_gc_get_values(sheet->xor_gc, &values);
7198 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
7201 gdk_draw_rectangle(sheet->sheet_window,
7205 area.width-2*i, area.height-2*i);
7208 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
7210 gdk_gc_set_foreground(sheet->xor_gc, &values.foreground);
7215 /* this function returns the new width of the column being resized given
7216 * the column and x position of the cursor; the x cursor position is passed
7217 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7219 new_column_width (GtkSheet * sheet,
7228 min_width = sheet->column_requisition;
7230 /* you can't shrink a column to less than its minimum width */
7231 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
7233 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
7236 /* don't grow past the end of the window */
7238 if (cx > sheet->sheet_window_width)
7240 *x = cx = sheet->sheet_window_width;
7243 /* calculate new column width making sure it doesn't end up
7244 * less than the minimum width */
7245 width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
7246 if (width < min_width)
7249 xxx_set_column_width(sheet, column, width);
7250 sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7251 size_allocate_column_title_buttons (sheet);
7256 /* this function returns the new height of the row being resized given
7257 * the row and y position of the cursor; the y cursor position is passed
7258 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7260 new_row_height (GtkSheet * sheet,
7268 min_height = sheet->row_requisition;
7270 /* you can't shrink a row to less than its minimum height */
7271 if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
7274 *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
7277 /* don't grow past the end of the window */
7279 if (cy > sheet->sheet_window_height)
7281 *y = cy = sheet->sheet_window_height;
7284 /* calculate new row height making sure it doesn't end up
7285 * less than the minimum height */
7286 height = (cy - ROW_TOP_YPIXEL (sheet, row));
7287 if (height < min_height)
7288 height = min_height;
7290 yyy_set_row_height(sheet, row, height);
7291 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
7292 size_allocate_row_title_buttons (sheet);
7298 gtk_sheet_set_column_width (GtkSheet * sheet,
7304 g_return_if_fail (sheet != NULL);
7305 g_return_if_fail (GTK_IS_SHEET (sheet));
7307 if (column < 0 || column >= xxx_column_count(sheet))
7310 gtk_sheet_column_size_request(sheet, column, &min_width);
7311 if(width < min_width) return;
7313 xxx_set_column_width(sheet, column, width);
7315 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7316 size_allocate_column_title_buttons (sheet);
7317 adjust_scrollbars (sheet);
7318 gtk_sheet_size_allocate_entry(sheet);
7319 gtk_sheet_range_draw (sheet, NULL);
7322 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, column);
7323 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_COL_WIDTH], column, width);
7330 gtk_sheet_set_row_height (GtkSheet * sheet,
7336 g_return_if_fail (sheet != NULL);
7337 g_return_if_fail (GTK_IS_SHEET (sheet));
7339 if (row < 0 || row >= yyy_row_count(sheet))
7342 gtk_sheet_row_size_request(sheet, row, &min_height);
7343 if(height < min_height) return;
7345 yyy_set_row_height(sheet, row, height);
7347 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7348 size_allocate_row_title_buttons (sheet);
7349 adjust_scrollbars (sheet);
7350 gtk_sheet_size_allocate_entry(sheet);
7351 gtk_sheet_range_draw (sheet, NULL);
7354 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], row, -1);
7355 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_ROW_HEIGHT], row, height);
7361 gtk_sheet_get_attributes(const GtkSheet *sheet, gint row, gint col,
7362 GtkSheetCellAttr *attributes)
7364 const GdkColor *fg, *bg;
7365 const GtkJustification *j ;
7366 const PangoFontDescription *font_desc ;
7367 const GtkSheetCellBorder *border ;
7369 g_return_val_if_fail (sheet != NULL, FALSE);
7370 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
7372 if(row < 0 || col < 0) return FALSE;
7374 init_attributes(sheet, col, attributes);
7379 attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
7380 attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
7382 fg = g_sheet_model_get_foreground(sheet->model, row, col);
7384 attributes->foreground = *fg;
7386 bg = g_sheet_model_get_background(sheet->model, row, col);
7388 attributes->background = *bg;
7390 j = g_sheet_model_get_justification(sheet->model, row, col);
7391 if (j) attributes->justification = *j;
7393 font_desc = g_sheet_model_get_font_desc(sheet->model, row, col);
7394 if ( font_desc ) attributes->font_desc = font_desc;
7396 border = g_sheet_model_get_cell_border(sheet->model, row, col);
7398 if ( border ) attributes->border = *border;
7404 init_attributes(const GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
7406 /* DEFAULT VALUES */
7407 attributes->foreground = GTK_WIDGET(sheet)->style->black;
7408 attributes->background = sheet->bg_color;
7409 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
7410 GdkColormap *colormap;
7411 colormap=gdk_colormap_get_system();
7412 gdk_color_black(colormap, &attributes->foreground);
7413 attributes->background = sheet->bg_color;
7415 attributes->justification = xxx_column_justification(sheet, col);
7416 attributes->border.width = 0;
7417 attributes->border.line_style = GDK_LINE_SOLID;
7418 attributes->border.cap_style = GDK_CAP_NOT_LAST;
7419 attributes->border.join_style = GDK_JOIN_MITER;
7420 attributes->border.mask = 0;
7421 attributes->border.color = GTK_WIDGET(sheet)->style->black;
7422 attributes->is_editable = TRUE;
7423 attributes->is_visible = TRUE;
7424 attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
7428 /********************************************************************
7429 * Container Functions:
7434 * gtk_sheet_move_child
7435 * gtk_sheet_position_child
7436 * gtk_sheet_position_children
7437 * gtk_sheet_realize_child
7438 * gtk_sheet_get_child_at
7439 ********************************************************************/
7442 gtk_sheet_put(GtkSheet *sheet, GtkWidget *child, gint x, gint y)
7444 GtkRequisition child_requisition;
7445 GtkSheetChild *child_info;
7447 g_return_val_if_fail(sheet != NULL, NULL);
7448 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7449 g_return_val_if_fail(child != NULL, NULL);
7450 g_return_val_if_fail(child->parent == NULL, NULL);
7452 child_info = g_new (GtkSheetChild, 1);
7453 child_info->widget = child;
7456 child_info->attached_to_cell = FALSE;
7457 child_info->floating = TRUE;
7458 child_info->xpadding = child_info->ypadding = 0;
7459 child_info->xexpand = child_info->yexpand = FALSE;
7460 child_info->xshrink = child_info->yshrink = FALSE;
7461 child_info->xfill = child_info->yfill = FALSE;
7463 sheet->children = g_list_append(sheet->children, child_info);
7465 gtk_widget_set_parent (child, GTK_WIDGET(sheet));
7467 gtk_widget_size_request(child, &child_requisition);
7469 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7471 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7472 (!GTK_WIDGET_REALIZED(child) || GTK_WIDGET_NO_WINDOW(child)))
7473 gtk_sheet_realize_child(sheet, child_info);
7475 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7476 !GTK_WIDGET_MAPPED(child))
7477 gtk_widget_map(child);
7480 gtk_sheet_position_child(sheet, child_info);
7482 /* This will avoid drawing on the titles */
7484 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7486 if(sheet->row_titles_visible)
7487 gdk_window_show(sheet->row_title_window);
7488 if(sheet->column_titles_visible)
7489 gdk_window_show(sheet->column_title_window);
7492 return (child_info);
7496 gtk_sheet_attach_floating (GtkSheet *sheet,
7501 GtkSheetChild *child;
7503 if(row < 0 || col < 0){
7504 gtk_sheet_button_attach(sheet, widget, row, col);
7508 gtk_sheet_get_cell_area(sheet, row, col, &area);
7509 child = gtk_sheet_put(sheet, widget, area.x, area.y);
7510 child->attached_to_cell = TRUE;
7516 gtk_sheet_attach_default (GtkSheet *sheet,
7520 if(row < 0 || col < 0){
7521 gtk_sheet_button_attach(sheet, widget, row, col);
7525 gtk_sheet_attach(sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
7529 gtk_sheet_attach (GtkSheet *sheet,
7538 GtkSheetChild *child = NULL;
7540 if(row < 0 || col < 0){
7541 gtk_sheet_button_attach(sheet, widget, row, col);
7545 child = g_new0(GtkSheetChild, 1);
7546 child->attached_to_cell = TRUE;
7547 child->floating = FALSE;
7548 child->widget = widget;
7551 child->xpadding = xpadding;
7552 child->ypadding = ypadding;
7553 child->xexpand = (xoptions & GTK_EXPAND) != 0;
7554 child->yexpand = (yoptions & GTK_EXPAND) != 0;
7555 child->xshrink = (xoptions & GTK_SHRINK) != 0;
7556 child->yshrink = (yoptions & GTK_SHRINK) != 0;
7557 child->xfill = (xoptions & GTK_FILL) != 0;
7558 child->yfill = (yoptions & GTK_FILL) != 0;
7560 sheet->children = g_list_append(sheet->children, child);
7562 gtk_sheet_get_cell_area(sheet, row, col, &area);
7564 child->x = area.x + child->xpadding;
7565 child->y = area.y + child->ypadding;
7567 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7569 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7570 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7571 gtk_sheet_realize_child(sheet, child);
7573 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7574 !GTK_WIDGET_MAPPED(widget))
7575 gtk_widget_map(widget);
7578 gtk_sheet_position_child(sheet, child);
7580 /* This will avoid drawing on the titles */
7582 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7584 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
7585 gdk_window_show(sheet->row_title_window);
7586 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
7587 gdk_window_show(sheet->column_title_window);
7593 gtk_sheet_button_attach (GtkSheet *sheet,
7597 GtkSheetButton *button = 0;
7598 GtkSheetChild *child;
7599 GtkRequisition button_requisition;
7601 if(row >= 0 && col >= 0) return;
7602 if(row < 0 && col < 0) return;
7604 child = g_new (GtkSheetChild, 1);
7605 child->widget = widget;
7608 child->attached_to_cell = TRUE;
7609 child->floating = FALSE;
7612 child->xpadding = child->ypadding = 0;
7613 child->xshrink = child->yshrink = FALSE;
7614 child->xfill = child->yfill = FALSE;
7617 sheet->children = g_list_append(sheet->children, child);
7619 gtk_sheet_button_size_request(sheet, button, &button_requisition);
7622 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7624 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7625 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7626 gtk_sheet_realize_child(sheet, child);
7628 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7629 !GTK_WIDGET_MAPPED(widget))
7630 gtk_widget_map(widget);
7633 if(row == -1) size_allocate_column_title_buttons(sheet);
7634 if(col == -1) size_allocate_row_title_buttons(sheet);
7639 label_size_request(GtkSheet *sheet, gchar *label, GtkRequisition *req)
7644 gint row_height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)) - 2*CELLOFFSET + 2;
7650 while(words && *words != '\0'){
7651 if(*words == '\n' || *(words+1) == '\0'){
7652 req->height += row_height;
7655 req->width = MAX(req->width, STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, word));
7663 if(n > 0) req->height -= 2;
7667 gtk_sheet_button_size_request (GtkSheet *sheet,
7668 const GtkSheetButton *button,
7669 GtkRequisition *button_requisition)
7671 GtkRequisition requisition;
7672 GtkRequisition label_requisition;
7674 if(gtk_sheet_autoresize(sheet) && button->label && strlen(button->label) > 0){
7675 label_size_request(sheet, button->label, &label_requisition);
7676 label_requisition.width += 2*CELLOFFSET;
7677 label_requisition.height += 2*CELLOFFSET;
7679 label_requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7680 label_requisition.width = COLUMN_MIN_WIDTH;
7685 gtk_widget_size_request(button->child->widget, &requisition);
7686 requisition.width += 2*button->child->xpadding;
7687 requisition.height += 2*button->child->ypadding;
7688 requisition.width += 2*sheet->button->style->xthickness;
7689 requisition.height += 2*sheet->button->style->ythickness;
7693 requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7694 requisition.width = COLUMN_MIN_WIDTH;
7697 *button_requisition = requisition;
7698 button_requisition->width = MAX(requisition.width, label_requisition.width);
7699 button_requisition->height = MAX(requisition.height, label_requisition.height);
7704 gtk_sheet_row_size_request (GtkSheet *sheet,
7708 GtkRequisition button_requisition;
7711 gtk_sheet_button_size_request(sheet,
7712 yyy_row_button(sheet, row),
7713 &button_requisition);
7715 *requisition = button_requisition.height;
7717 children = sheet->children;
7719 GtkSheetChild *child = (GtkSheetChild *)children->data;
7720 GtkRequisition child_requisition;
7722 if(child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink){
7723 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7725 if(child_requisition.height + 2 * child->ypadding > *requisition)
7726 *requisition = child_requisition.height + 2 * child->ypadding;
7728 children = children->next;
7731 sheet->row_requisition = * requisition;
7735 gtk_sheet_column_size_request (GtkSheet *sheet,
7739 GtkRequisition button_requisition;
7742 gtk_sheet_button_size_request(sheet,
7743 xxx_column_button(sheet, col),
7744 &button_requisition);
7746 *requisition = button_requisition.width;
7748 children = sheet->children;
7750 GtkSheetChild *child = (GtkSheetChild *)children->data;
7751 GtkRequisition child_requisition;
7753 if(child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink){
7754 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7756 if(child_requisition.width + 2 * child->xpadding > *requisition)
7757 *requisition = child_requisition.width + 2 * child->xpadding;
7759 children = children->next;
7762 sheet->column_requisition = *requisition;
7766 gtk_sheet_move_child(GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
7768 GtkSheetChild *child;
7771 g_return_if_fail(sheet != NULL);
7772 g_return_if_fail(GTK_IS_SHEET(sheet));
7774 children = sheet->children;
7777 child = children->data;
7779 if(child->widget == widget){
7782 child->row = ROW_FROM_YPIXEL(sheet, y);
7783 child->col = COLUMN_FROM_XPIXEL(sheet, x);
7784 gtk_sheet_position_child(sheet, child);
7788 children = children->next;
7791 g_warning("Widget must be a GtkSheet child");
7796 gtk_sheet_position_child(GtkSheet *sheet, GtkSheetChild *child)
7798 GtkRequisition child_requisition;
7799 GtkAllocation child_allocation;
7805 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7807 if(sheet->column_titles_visible)
7808 yoffset = sheet->column_title_area.height;
7810 if(sheet->row_titles_visible)
7811 xoffset = sheet->row_title_area.width;
7813 if(child->attached_to_cell){
7815 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col);
7816 child->y = ROW_TOP_YPIXEL(sheet, child->row);
7818 if(sheet->row_titles_visible)
7819 child->x-=sheet->row_title_area.width;
7820 if(sheet->column_titles_visible)
7821 child->y-=sheet->column_title_area.height;
7823 width = xxx_column_width(sheet, child->col);
7824 height = yyy_row_height(sheet, child->row);
7827 gtk_sheet_get_cell_area(sheet, child->row, child->col, &area);
7828 child->x = area.x + child->xpadding;
7829 child->y = area.y + child->ypadding;
7831 if(!child->floating){
7832 if(child_requisition.width + 2*child->xpadding <= xxx_column_width(sheet, child->col)){
7834 child_requisition.width = child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7837 child->x = area.x + xxx_column_width(sheet, child->col) / 2 -
7838 child_requisition.width / 2;
7840 child_allocation.width = child_requisition.width;
7843 if(!child->xshrink){
7844 gtk_sheet_set_column_width(sheet, child->col, child_requisition.width + 2 * child->xpadding);
7846 child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7849 if(child_requisition.height + 2*child->ypadding <= yyy_row_height(sheet, child->row)){
7851 child_requisition.height = child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7854 child->y = area.y + yyy_row_height(sheet, child->row) / 2 -
7855 child_requisition.height / 2;
7857 child_allocation.height = child_requisition.height;
7860 if(!child->yshrink){
7861 gtk_sheet_set_row_height(sheet, child->row, child_requisition.height + 2 * child->ypadding);
7863 child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7866 child_allocation.width = child_requisition.width;
7867 child_allocation.height = child_requisition.height;
7870 x = child_allocation.x = child->x + xoffset;
7871 y = child_allocation.y = child->y + yoffset;
7875 x = child_allocation.x = child->x + sheet->hoffset + xoffset;
7876 x = child_allocation.x = child->x + xoffset;
7877 y = child_allocation.y = child->y + sheet->voffset + yoffset;
7878 y = child_allocation.y = child->y + yoffset;
7879 child_allocation.width = child_requisition.width;
7880 child_allocation.height = child_requisition.height;
7883 gtk_widget_size_allocate(child->widget, &child_allocation);
7884 gtk_widget_queue_draw(child->widget);
7888 gtk_sheet_forall (GtkContainer *container,
7889 gboolean include_internals,
7890 GtkCallback callback,
7891 gpointer callback_data)
7894 GtkSheetChild *child;
7897 g_return_if_fail (GTK_IS_SHEET (container));
7898 g_return_if_fail (callback != NULL);
7900 sheet = GTK_SHEET (container);
7901 children = sheet->children;
7904 child = children->data;
7905 children = children->next;
7907 (* callback) (child->widget, callback_data);
7910 (* callback) (sheet->button, callback_data);
7911 if(sheet->sheet_entry)
7912 (* callback) (sheet->sheet_entry, callback_data);
7917 gtk_sheet_position_children(GtkSheet *sheet)
7920 GtkSheetChild *child;
7922 children = sheet->children;
7926 child = (GtkSheetChild *)children->data;
7928 if(child->col !=-1 && child->row != -1)
7929 gtk_sheet_position_child(sheet, child);
7931 if(child->row == -1){
7932 if(child->col < MIN_VISIBLE_COLUMN(sheet) ||
7933 child->col > MAX_VISIBLE_COLUMN(sheet))
7934 gtk_sheet_child_hide(child);
7936 gtk_sheet_child_show(child);
7938 if(child->col == -1){
7939 if(child->row < MIN_VISIBLE_ROW(sheet) ||
7940 child->row > MAX_VISIBLE_ROW(sheet))
7941 gtk_sheet_child_hide(child);
7943 gtk_sheet_child_show(child);
7946 children = children->next;
7952 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
7956 GtkSheetChild *child = 0;
7958 g_return_if_fail(container != NULL);
7959 g_return_if_fail(GTK_IS_SHEET(container));
7961 sheet = GTK_SHEET(container);
7963 children = sheet->children;
7967 child = (GtkSheetChild *)children->data;
7969 if(child->widget == widget) break;
7971 children = children->next;
7976 gtk_widget_unparent (widget);
7977 child->widget = NULL;
7979 sheet->children = g_list_remove_link (sheet->children, children);
7980 g_list_free_1 (children);
7987 gtk_sheet_realize_child(GtkSheet *sheet, GtkSheetChild *child)
7991 widget = GTK_WIDGET(sheet);
7993 if(GTK_WIDGET_REALIZED(widget)){
7994 if(child->row == -1)
7995 gtk_widget_set_parent_window(child->widget, sheet->column_title_window);
7996 else if(child->col == -1)
7997 gtk_widget_set_parent_window(child->widget, sheet->row_title_window);
7999 gtk_widget_set_parent_window(child->widget, sheet->sheet_window);
8002 gtk_widget_set_parent(child->widget, widget);
8008 gtk_sheet_get_child_at(GtkSheet *sheet, gint row, gint col)
8011 GtkSheetChild *child = 0;
8013 g_return_val_if_fail(sheet != NULL, NULL);
8014 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
8016 children = sheet->children;
8020 child = (GtkSheetChild *)children->data;
8022 if(child->attached_to_cell)
8023 if(child->row == row && child->col == col) break;
8025 children = children->next;
8028 if(children) return child;
8034 gtk_sheet_child_hide(GtkSheetChild *child)
8036 g_return_if_fail(child != NULL);
8037 gtk_widget_hide(child->widget);
8041 gtk_sheet_child_show(GtkSheetChild *child)
8043 g_return_if_fail(child != NULL);
8045 gtk_widget_show(child->widget);
8049 gtk_sheet_get_model(const GtkSheet *sheet)
8051 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
8053 return sheet->model;
8058 gtk_sheet_button_new(void)
8060 GtkSheetButton *button = g_malloc(sizeof(GtkSheetButton));
8062 button->state = GTK_STATE_NORMAL;
8063 button->label = NULL;
8064 button->label_visible = TRUE;
8065 button->child = NULL;
8066 button->justification = GTK_JUSTIFY_FILL;
8073 gtk_sheet_button_free(GtkSheetButton *button)
8075 if (!button) return ;
8077 g_free(button->label);