1 /* This version of GtkSheet has been *heavily* modified, for the specific
2 requirements of PSPPIRE. */
4 /* GtkSheet widget for Gtk+.
5 * Copyright (C) 1999-2001 Adrian E. Feiguin <adrian@ifir.ifir.edu.ar>
7 * Based on GtkClist widget by Jay Painter, but major changes.
8 * Memory allocation routines inspired on SC (Spreadsheet Calculator)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 * @short_description: spreadsheet widget for gtk2
28 * GtkSheet is a matrix widget for GTK+. It consists of an scrollable grid of
29 * cells where you can allocate text. Cell contents can be edited interactively
30 * through a specially designed entry, GtkItemEntry. It is also a container
31 * subclass, allowing you to display buttons, curves, pixmaps and any other
34 * You can also set many attributes as: border, foreground and background color,
35 * text justification, and more.
37 * The testgtksheet program shows how easy is to create a spreadsheet-like GUI
45 #include <gdk/gdkkeysyms.h>
46 #include <gtk/gtksignal.h>
47 #include <gtk/gtklabel.h>
48 #include <gtk/gtkbutton.h>
49 #include <gtk/gtkadjustment.h>
50 #include <gtk/gtktable.h>
51 #include <gtk/gtkbox.h>
52 #include <gtk/gtkmain.h>
53 #include <gtk/gtktypeutils.h>
54 #include <gtk/gtkentry.h>
55 #include <gtk/gtkcontainer.h>
56 #include <gtk/gtkpixmap.h>
57 #include <pango/pango.h>
58 #include "gtkitementry.h"
60 #include "gtkextra-marshal.h"
61 #include "gsheetmodel.h"
67 GTK_SHEET_IS_LOCKED = 1 << 0,
68 GTK_SHEET_IS_FROZEN = 1 << 1,
69 GTK_SHEET_IN_XDRAG = 1 << 2,
70 GTK_SHEET_IN_YDRAG = 1 << 3,
71 GTK_SHEET_IN_DRAG = 1 << 4,
72 GTK_SHEET_IN_SELECTION = 1 << 5,
73 GTK_SHEET_IN_RESIZE = 1 << 6,
74 GTK_SHEET_IN_CLIP = 1 << 7,
75 GTK_SHEET_REDRAW_PENDING = 1 << 8,
78 #define GTK_SHEET_FLAGS(sheet) (GTK_SHEET (sheet)->flags)
79 #define GTK_SHEET_SET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) |= (flag))
80 #define GTK_SHEET_UNSET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) &= ~(flag))
82 #define GTK_SHEET_IS_LOCKED(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_LOCKED)
85 #define GTK_SHEET_IS_FROZEN(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN)
86 #define GTK_SHEET_IN_XDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG)
87 #define GTK_SHEET_IN_YDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG)
88 #define GTK_SHEET_IN_DRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_DRAG)
89 #define GTK_SHEET_IN_SELECTION(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_SELECTION)
90 #define GTK_SHEET_IN_RESIZE(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_RESIZE)
91 #define GTK_SHEET_IN_CLIP(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_CLIP)
92 #define GTK_SHEET_REDRAW_PENDING(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_REDRAW_PENDING)
94 #define CELL_SPACING 1
96 #define TIMEOUT_SCROLL 20
97 #define TIMEOUT_FLASH 200
98 #define TIME_INTERVAL 8
99 #define COLUMN_MIN_WIDTH 10
104 #define DEFAULT_COLUMN_WIDTH 80
108 static gboolean gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col);
111 void dispose_string (const GtkSheet *sheet, gchar *text)
113 GSheetModel *model = gtk_sheet_get_model(sheet);
118 if (g_sheet_model_free_strings(model))
123 guint DEFAULT_ROW_HEIGHT(GtkWidget *widget)
125 if(!widget->style->font_desc) return 24;
127 PangoContext *context = gtk_widget_get_pango_context(widget);
128 PangoFontMetrics *metrics = pango_context_get_metrics(context,
129 widget->style->font_desc,
130 pango_context_get_language(context));
131 guint val = pango_font_metrics_get_descent(metrics) +
132 pango_font_metrics_get_ascent(metrics);
133 pango_font_metrics_unref(metrics);
134 return PANGO_PIXELS(val)+2*CELLOFFSET;
137 static inline guint DEFAULT_FONT_ASCENT(GtkWidget *widget)
139 if(!widget->style->font_desc) return 12;
141 PangoContext *context = gtk_widget_get_pango_context(widget);
142 PangoFontMetrics *metrics = pango_context_get_metrics(context,
143 widget->style->font_desc,
144 pango_context_get_language(context));
145 guint val = pango_font_metrics_get_ascent(metrics);
146 pango_font_metrics_unref(metrics);
147 return PANGO_PIXELS(val);
150 static inline guint STRING_WIDTH(GtkWidget *widget,
151 const PangoFontDescription *font, const gchar *text)
156 layout = gtk_widget_create_pango_layout (widget, text);
157 pango_layout_set_font_description (layout, font);
159 pango_layout_get_extents (layout, NULL, &rect);
161 g_object_unref(G_OBJECT(layout));
162 return PANGO_PIXELS(rect.width);
165 static inline guint DEFAULT_FONT_DESCENT(GtkWidget *widget)
167 if(!widget->style->font_desc) return 12;
169 PangoContext *context = gtk_widget_get_pango_context(widget);
170 PangoFontMetrics *metrics = pango_context_get_metrics(context,
171 widget->style->font_desc,
172 pango_context_get_language(context));
173 guint val = pango_font_metrics_get_descent(metrics);
174 pango_font_metrics_unref(metrics);
175 return PANGO_PIXELS(val);
181 yyy_row_is_visible(GtkSheet *sheet, gint row)
183 GSheetRow *row_geo = sheet->row_geometry;
185 return g_sheet_row_get_visibility(row_geo, row, sheet);
190 yyy_row_is_sensitive(GtkSheet *sheet, gint row)
192 GSheetRow *row_geo = sheet->row_geometry;
194 return g_sheet_row_get_sensitivity(row_geo, row, sheet);
200 yyy_row_count(const GtkSheet *sheet)
202 GSheetRow *row_geo = sheet->row_geometry;
204 return g_sheet_row_get_row_count(row_geo, sheet);
208 yyy_row_height(const GtkSheet *sheet, gint row)
210 GSheetRow *row_geo = sheet->row_geometry;
212 return g_sheet_row_get_height(row_geo, row, sheet);
216 yyy_row_top_ypixel(GtkSheet *sheet, gint row)
218 GSheetRow *geo = sheet->row_geometry;
220 gint y = g_sheet_row_start_pixel(geo, row, sheet);
222 if ( sheet->column_titles_visible )
223 y += sheet->column_title_area.height;
229 /* Return the row containing pixel Y */
231 yyy_row_ypixel_to_row(GtkSheet *sheet, gint y)
233 GSheetRow *geo = sheet->row_geometry;
235 gint cy = sheet->voffset;
237 if(sheet->column_titles_visible)
238 cy += sheet->column_title_area.height;
243 return g_sheet_row_pixel_to_row(geo, y - cy, sheet);
247 /* gives the top pixel of the given row in context of
248 * the sheet's voffset */
250 ROW_TOP_YPIXEL(GtkSheet *sheet, gint row)
252 return (sheet->voffset + yyy_row_top_ypixel(sheet, row));
256 /* returns the row index from a y pixel location in the
257 * context of the sheet's voffset */
259 ROW_FROM_YPIXEL(GtkSheet *sheet, gint y)
261 return (yyy_row_ypixel_to_row(sheet, y));
264 static inline GtkSheetButton *
265 xxx_column_button(GtkSheet *sheet, gint col)
267 GSheetColumn *col_geo = sheet->column_geometry;
269 return g_sheet_column_get_button(col_geo, col, sheet);
274 xxx_column_left_xpixel(GtkSheet *sheet, gint col)
276 GSheetColumn *geo = sheet->column_geometry;
278 gint x = g_sheet_column_start_pixel(geo, col, sheet);
280 if ( sheet->row_titles_visible )
281 x += sheet->row_title_area.width;
287 xxx_column_width(const GtkSheet *sheet, gint col)
289 GSheetColumn *col_geo = sheet->column_geometry;
291 return g_sheet_column_get_width(col_geo, col, sheet);
296 xxx_set_column_width(GtkSheet *sheet, gint col, gint width)
298 if ( sheet->column_geometry )
299 g_sheet_column_set_width(sheet->column_geometry, col, width, sheet);
303 xxx_column_set_left_column(GtkSheet *sheet, gint col, gint i)
305 GSheetColumn *col_geo = sheet->column_geometry;
307 g_sheet_column_set_left_text_column(col_geo, col, i, sheet);
311 xxx_column_left_column(const GtkSheet *sheet, gint col)
313 GSheetColumn *col_geo = sheet->column_geometry;
315 return g_sheet_column_get_left_text_column(col_geo, col, sheet);
319 xxx_column_set_right_column(GtkSheet *sheet, gint col, gint i)
321 GSheetColumn *col_geo = sheet->column_geometry;
323 g_sheet_column_set_right_text_column(col_geo, col, i, sheet);
327 xxx_column_right_column(const GtkSheet *sheet, gint col)
329 GSheetColumn *col_geo = sheet->column_geometry;
331 return g_sheet_column_get_right_text_column(col_geo, col, sheet);
334 static inline GtkJustification
335 xxx_column_justification(const GtkSheet *sheet, gint col)
337 GSheetColumn *col_geo = sheet->column_geometry;
339 return g_sheet_column_get_justification(col_geo, col, sheet);
343 xxx_column_is_visible(GtkSheet *sheet, gint col)
345 GSheetColumn *col_geo = sheet->column_geometry;
347 return g_sheet_column_get_visibility(col_geo, col, sheet);
352 xxx_column_is_sensitive(GtkSheet *sheet, gint col)
354 GSheetColumn *col_geo = sheet->column_geometry;
356 return g_sheet_column_get_sensitivity(col_geo, col, sheet);
360 /* gives the left pixel of the given column in context of
361 * the sheet's hoffset */
363 COLUMN_LEFT_XPIXEL(GtkSheet *sheet, gint ncol)
365 return (sheet->hoffset + xxx_column_left_xpixel(sheet, ncol));
369 xxx_column_count(const GtkSheet *sheet)
371 GSheetColumn *col_geo = sheet->column_geometry;
373 return g_sheet_column_get_column_count(col_geo, sheet);
376 /* returns the column index from a x pixel location in the
377 * context of the sheet's hoffset */
379 COLUMN_FROM_XPIXEL (GtkSheet * sheet,
385 if( sheet->row_titles_visible )
386 cx += sheet->row_title_area.width;
389 for (i = 0; i < xxx_column_count(sheet); i++)
391 if (x >= cx && x <= (cx + xxx_column_width(sheet, i)) &&
392 xxx_column_is_visible(sheet, i))
394 if( xxx_column_is_visible(sheet, i))
395 cx += xxx_column_width(sheet, i);
399 return xxx_column_count(sheet) - 1;
402 /* returns the total height of the sheet */
403 static inline gint SHEET_HEIGHT(GtkSheet *sheet)
405 const gint n_rows = yyy_row_count(sheet);
407 return yyy_row_top_ypixel(sheet, n_rows - 1) +
408 yyy_row_height(sheet, n_rows - 1);
412 static inline GtkSheetButton *
413 yyy_row_button(GtkSheet *sheet, gint row)
415 GSheetRow *row_geo = sheet->row_geometry;
417 return g_sheet_row_get_button(row_geo, row, sheet);
424 yyy_set_row_height(GtkSheet *sheet, gint row, gint height)
426 if ( sheet->row_geometry )
427 g_sheet_row_set_height(sheet->row_geometry, row, height, sheet);
432 /* returns the total width of the sheet */
433 static inline gint SHEET_WIDTH(GtkSheet *sheet)
437 cx = ( sheet->row_titles_visible ? sheet->row_title_area.width : 0);
439 for (i=0; i < xxx_column_count(sheet); i++)
440 if(xxx_column_is_visible(sheet, i)) cx += xxx_column_width(sheet, i);
445 #define MIN_VISIBLE_ROW(sheet) sheet->view.row0
446 #define MAX_VISIBLE_ROW(sheet) sheet->view.rowi
447 #define MIN_VISIBLE_COLUMN(sheet) sheet->view.col0
448 #define MAX_VISIBLE_COLUMN(sheet) sheet->view.coli
452 POSSIBLE_XDRAG(GtkSheet *sheet, gint x, gint *drag_column)
456 column=COLUMN_FROM_XPIXEL(sheet, x);
459 xdrag=COLUMN_LEFT_XPIXEL(sheet,column)+CELL_SPACING;
460 if(x <= xdrag+DRAG_WIDTH/2 && column != 0){
461 while(! xxx_column_is_visible(sheet, column-1) && column>0) column--;
462 *drag_column=column-1;
463 return xxx_column_is_sensitive(sheet, column-1);
466 xdrag+= xxx_column_width(sheet, column);
467 if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag+DRAG_WIDTH/2)
468 return xxx_column_is_sensitive(sheet, column);
474 POSSIBLE_YDRAG(GtkSheet *sheet, gint y, gint *drag_row)
478 row=ROW_FROM_YPIXEL(sheet, y);
481 ydrag=ROW_TOP_YPIXEL(sheet,row)+CELL_SPACING;
482 if(y <= ydrag+DRAG_WIDTH/2 && row != 0){
483 while(!yyy_row_is_visible(sheet, row-1) && row>0) row--;
485 return yyy_row_is_sensitive(sheet, row-1);
488 ydrag+=yyy_row_height(sheet, row);
490 if(y >= ydrag-DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2)
491 return yyy_row_is_sensitive(sheet, row);
497 static inline gint POSSIBLE_DRAG(GtkSheet *sheet, gint x, gint y,
498 gint *drag_row, gint *drag_column)
502 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
503 *drag_row=ROW_FROM_YPIXEL(sheet,y);
505 if(x>=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0)-DRAG_WIDTH/2 &&
506 x<=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
507 xxx_column_width(sheet, sheet->range.coli) + DRAG_WIDTH/2){
508 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.row0);
509 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
510 *drag_row=sheet->range.row0;
513 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
514 yyy_row_height(sheet, sheet->range.rowi);
515 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
516 *drag_row=sheet->range.rowi;
521 if(y>=ROW_TOP_YPIXEL(sheet,sheet->range.row0)-DRAG_WIDTH/2 &&
522 y<=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
523 yyy_row_height(sheet, sheet->range.rowi)+DRAG_WIDTH/2){
524 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0);
525 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
526 *drag_column=sheet->range.col0;
529 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
530 xxx_column_width(sheet, sheet->range.coli);
531 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
532 *drag_column=sheet->range.coli;
539 static inline gint POSSIBLE_RESIZE(GtkSheet *sheet, gint x, gint y,
540 gint *drag_row, gint *drag_column)
544 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
545 xxx_column_width(sheet, sheet->range.coli);
547 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
548 yyy_row_height(sheet, sheet->range.rowi);
550 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
551 ydrag = ROW_TOP_YPIXEL(sheet, sheet->view.row0);
553 if(sheet->state == GTK_SHEET_ROW_SELECTED)
554 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0);
556 *drag_column=COLUMN_FROM_XPIXEL(sheet,x);
557 *drag_row=ROW_FROM_YPIXEL(sheet,y);
559 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2 &&
560 y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2) return TRUE;
565 static void gtk_sheet_class_init (GtkSheetClass * klass);
566 static void gtk_sheet_init (GtkSheet * sheet);
567 static void gtk_sheet_destroy (GtkObject * object);
568 static void gtk_sheet_finalize (GObject * object);
569 static void gtk_sheet_style_set (GtkWidget *widget,
570 GtkStyle *previous_style);
571 static void gtk_sheet_realize (GtkWidget * widget);
572 static void gtk_sheet_unrealize (GtkWidget * widget);
573 static void gtk_sheet_map (GtkWidget * widget);
574 static void gtk_sheet_unmap (GtkWidget * widget);
575 static gint gtk_sheet_expose (GtkWidget * widget,
576 GdkEventExpose * event);
577 static void gtk_sheet_forall (GtkContainer *container,
578 gboolean include_internals,
579 GtkCallback callback,
580 gpointer callback_data);
582 static void gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
583 GtkAdjustment *hadjustment,
584 GtkAdjustment *vadjustment);
586 static gint gtk_sheet_button_press (GtkWidget * widget,
587 GdkEventButton * event);
588 static gint gtk_sheet_button_release (GtkWidget * widget,
589 GdkEventButton * event);
590 static gint gtk_sheet_motion (GtkWidget * widget,
591 GdkEventMotion * event);
592 static gint gtk_sheet_entry_key_press (GtkWidget *widget,
594 static gint gtk_sheet_key_press (GtkWidget *widget,
596 static void gtk_sheet_size_request (GtkWidget * widget,
597 GtkRequisition * requisition);
598 static void gtk_sheet_size_allocate (GtkWidget * widget,
599 GtkAllocation * allocation);
603 static gint gtk_sheet_range_isvisible (GtkSheet * sheet,
604 GtkSheetRange range);
605 static gint gtk_sheet_cell_isvisible (GtkSheet * sheet,
606 gint row, gint column);
609 static gint gtk_sheet_scroll (gpointer data);
610 static gint gtk_sheet_flash (gpointer data);
612 /* Drawing Routines */
614 /* draw cell background and frame */
615 static void gtk_sheet_cell_draw_default (GtkSheet *sheet,
616 gint row, gint column);
618 /* draw cell border */
619 static void gtk_sheet_cell_draw_border (GtkSheet *sheet,
620 gint row, gint column,
623 /* draw cell contents */
624 static void gtk_sheet_cell_draw_label (GtkSheet *sheet,
625 gint row, gint column);
627 /* draw visible part of range. If range==NULL then draw the whole screen */
628 static void gtk_sheet_range_draw (GtkSheet *sheet,
629 const GtkSheetRange *range);
631 /* highlight the visible part of the selected range */
632 static void gtk_sheet_range_draw_selection (GtkSheet *sheet,
633 GtkSheetRange range);
637 static gint gtk_sheet_move_query (GtkSheet *sheet,
638 gint row, gint column);
639 static void gtk_sheet_real_select_range (GtkSheet * sheet,
640 GtkSheetRange * range);
641 static void gtk_sheet_real_unselect_range (GtkSheet * sheet,
642 const GtkSheetRange * range);
643 static void gtk_sheet_extend_selection (GtkSheet *sheet,
644 gint row, gint column);
645 static void gtk_sheet_new_selection (GtkSheet *sheet,
646 GtkSheetRange *range);
647 static void gtk_sheet_draw_border (GtkSheet *sheet,
648 GtkSheetRange range);
649 static void gtk_sheet_draw_corners (GtkSheet *sheet,
650 GtkSheetRange range);
653 /* Active Cell handling */
655 static void gtk_sheet_entry_changed (GtkWidget *widget,
657 static gboolean gtk_sheet_deactivate_cell (GtkSheet *sheet);
658 static void gtk_sheet_hide_active_cell (GtkSheet *sheet);
659 static gboolean gtk_sheet_activate_cell (GtkSheet *sheet,
661 static void gtk_sheet_draw_active_cell (GtkSheet *sheet);
662 static void gtk_sheet_show_active_cell (GtkSheet *sheet);
663 static void gtk_sheet_click_cell (GtkSheet *sheet,
670 static void gtk_sheet_make_backing_pixmap (GtkSheet *sheet,
671 guint width, guint height);
672 static void gtk_sheet_draw_backing_pixmap (GtkSheet *sheet,
673 GtkSheetRange range);
676 static void adjust_scrollbars (GtkSheet * sheet);
677 static void vadjustment_changed (GtkAdjustment * adjustment,
679 static void hadjustment_changed (GtkAdjustment * adjustment,
681 static void vadjustment_value_changed (GtkAdjustment * adjustment,
683 static void hadjustment_value_changed (GtkAdjustment * adjustment,
687 static void draw_xor_vline (GtkSheet * sheet);
688 static void draw_xor_hline (GtkSheet * sheet);
689 static void draw_xor_rectangle (GtkSheet *sheet,
690 GtkSheetRange range);
691 static void gtk_sheet_draw_flashing_range (GtkSheet *sheet,
692 GtkSheetRange range);
693 static guint new_column_width (GtkSheet * sheet,
696 static guint new_row_height (GtkSheet * sheet,
701 static void create_global_button (GtkSheet *sheet);
702 static void global_button_clicked (GtkWidget *widget,
706 static void create_sheet_entry (GtkSheet *sheet);
707 static void gtk_sheet_size_allocate_entry (GtkSheet *sheet);
708 static void gtk_sheet_entry_set_max_size (GtkSheet *sheet);
710 /* Sheet button gadgets */
712 static void size_allocate_column_title_buttons (GtkSheet * sheet);
713 static void size_allocate_row_title_buttons (GtkSheet * sheet);
716 static void gtk_sheet_button_draw (GtkSheet *sheet,
717 gint row, gint column);
718 static void size_allocate_global_button (GtkSheet *sheet);
719 static void gtk_sheet_button_size_request (GtkSheet *sheet,
720 const GtkSheetButton *button,
721 GtkRequisition *requisition);
723 /* Attributes routines */
724 static void init_attributes (const GtkSheet *sheet, gint col,
725 GtkSheetCellAttr *attributes);
728 /* Memory allocation routines */
729 static void gtk_sheet_real_range_clear (GtkSheet *sheet,
730 const GtkSheetRange *range,
732 static void gtk_sheet_real_cell_clear (GtkSheet *sheet,
738 /* Container Functions */
739 static void gtk_sheet_remove (GtkContainer *container,
741 static void gtk_sheet_realize_child (GtkSheet *sheet,
742 GtkSheetChild *child);
743 static void gtk_sheet_position_child (GtkSheet *sheet,
744 GtkSheetChild *child);
745 static void gtk_sheet_position_children (GtkSheet *sheet);
746 static void gtk_sheet_child_show (GtkSheetChild *child);
747 static void gtk_sheet_child_hide (GtkSheetChild *child);
748 static void gtk_sheet_column_size_request (GtkSheet *sheet,
751 static void gtk_sheet_row_size_request (GtkSheet *sheet,
759 _gtkextra_signal_emit(GtkObject *object, guint signal_id, ...);
781 static GtkContainerClass *parent_class = NULL;
782 static guint sheet_signals[LAST_SIGNAL] = {0};
786 gtk_sheet_get_type ()
788 static GType sheet_type = 0;
792 static const GTypeInfo sheet_info =
794 sizeof (GtkSheetClass),
797 (GClassInitFunc) gtk_sheet_class_init,
802 (GInstanceInitFunc) gtk_sheet_init,
806 g_type_register_static (GTK_TYPE_CONTAINER, "GtkSheet",
812 static GtkSheetRange*
813 gtk_sheet_range_copy (const GtkSheetRange *range)
815 GtkSheetRange *new_range;
817 g_return_val_if_fail (range != NULL, NULL);
819 new_range = g_new (GtkSheetRange, 1);
827 gtk_sheet_range_free (GtkSheetRange *range)
829 g_return_if_fail (range != NULL);
835 gtk_sheet_range_get_type (void)
837 static GType sheet_range_type=0;
839 if(!sheet_range_type)
841 sheet_range_type = g_boxed_type_register_static("GtkSheetRange", (GBoxedCopyFunc)gtk_sheet_range_copy, (GBoxedFreeFunc)gtk_sheet_range_free);
843 return sheet_range_type;
848 gtk_sheet_class_init (GtkSheetClass * klass)
850 GtkObjectClass *object_class;
851 GtkWidgetClass *widget_class;
852 GtkContainerClass *container_class;
853 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
855 object_class = (GtkObjectClass *) klass;
856 widget_class = (GtkWidgetClass *) klass;
857 container_class = (GtkContainerClass *) klass;
859 parent_class = g_type_class_peek_parent (klass);
862 * GtkSheet::select-row
863 * @sheet: the sheet widget that emitted the signal
864 * @row: the newly selected row index
866 * A row has been selected.
868 sheet_signals[SELECT_ROW] =
869 gtk_signal_new ("select-row",
871 GTK_CLASS_TYPE(object_class),
872 GTK_SIGNAL_OFFSET (GtkSheetClass, select_row),
874 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
877 * GtkSheet::select-column
878 * @sheet: the sheet widget that emitted the signal
879 * @column: the newly selected column index
881 * A column has been selected.
883 sheet_signals[SELECT_COLUMN] =
884 gtk_signal_new ("select-column",
886 GTK_CLASS_TYPE(object_class),
887 GTK_SIGNAL_OFFSET (GtkSheetClass, select_column),
889 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
893 * GtkSheet::double-click-row
894 * @sheet: the sheet widget that emitted the signal
895 * @row: the row that was double clicked.
897 * A row's title button has been double clicked
899 sheet_signals[DOUBLE_CLICK_ROW] =
900 gtk_signal_new ("double-click-row",
902 GTK_CLASS_TYPE(object_class),
905 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
909 * GtkSheet::double-click-column
910 * @sheet: the sheet widget that emitted the signal
911 * @column: the column that was double clicked.
913 * A column's title button has been double clicked
915 sheet_signals[DOUBLE_CLICK_COLUMN] =
916 gtk_signal_new ("double-click-column",
918 GTK_CLASS_TYPE(object_class),
921 GTK_TYPE_NONE, 1, GTK_TYPE_INT);
923 sheet_signals[SELECT_RANGE] =
924 gtk_signal_new ("select-range",
926 GTK_CLASS_TYPE(object_class),
927 GTK_SIGNAL_OFFSET (GtkSheetClass, select_range),
928 gtkextra_VOID__BOXED,
929 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
931 sheet_signals[CLIP_RANGE] =
932 gtk_signal_new ("clip-range",
934 GTK_CLASS_TYPE(object_class),
935 GTK_SIGNAL_OFFSET (GtkSheetClass, clip_range),
936 gtkextra_VOID__BOXED,
937 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE);
939 sheet_signals[RESIZE_RANGE] =
940 gtk_signal_new ("resize-range",
942 GTK_CLASS_TYPE(object_class),
943 GTK_SIGNAL_OFFSET (GtkSheetClass, resize_range),
944 gtkextra_VOID__BOXED_BOXED,
945 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
946 sheet_signals[MOVE_RANGE] =
947 gtk_signal_new ("move-range",
949 GTK_CLASS_TYPE(object_class),
950 GTK_SIGNAL_OFFSET (GtkSheetClass, move_range),
951 gtkextra_VOID__BOXED_BOXED,
952 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE);
953 sheet_signals[TRAVERSE] =
954 gtk_signal_new ("traverse",
956 GTK_CLASS_TYPE(object_class),
957 GTK_SIGNAL_OFFSET (GtkSheetClass, traverse),
958 gtkextra_BOOLEAN__INT_INT_POINTER_POINTER,
959 GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT,
960 GTK_TYPE_POINTER, GTK_TYPE_POINTER);
962 sheet_signals[DEACTIVATE] =
963 gtk_signal_new ("deactivate",
965 GTK_CLASS_TYPE(object_class),
966 GTK_SIGNAL_OFFSET (GtkSheetClass, deactivate),
967 gtkextra_BOOLEAN__INT_INT,
968 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
970 sheet_signals[ACTIVATE] =
971 gtk_signal_new ("activate",
973 GTK_CLASS_TYPE(object_class),
974 GTK_SIGNAL_OFFSET (GtkSheetClass, activate),
975 gtkextra_BOOLEAN__INT_INT,
976 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT);
978 sheet_signals[SET_CELL] =
979 gtk_signal_new ("set-cell",
981 GTK_CLASS_TYPE(object_class),
982 GTK_SIGNAL_OFFSET (GtkSheetClass, set_cell),
983 gtkextra_VOID__INT_INT,
984 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
986 sheet_signals[CLEAR_CELL] =
987 gtk_signal_new ("clear-cell",
989 GTK_CLASS_TYPE(object_class),
990 GTK_SIGNAL_OFFSET (GtkSheetClass, clear_cell),
991 gtkextra_VOID__INT_INT,
992 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
994 sheet_signals[CHANGED] =
995 gtk_signal_new ("changed",
997 GTK_CLASS_TYPE(object_class),
998 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
999 gtkextra_VOID__INT_INT,
1000 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1002 sheet_signals[NEW_COL_WIDTH] =
1003 gtk_signal_new ("new-column-width",
1005 GTK_CLASS_TYPE(object_class),
1006 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1007 gtkextra_VOID__INT_INT,
1008 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1010 sheet_signals[NEW_ROW_HEIGHT] =
1011 gtk_signal_new ("new-row-height",
1013 GTK_CLASS_TYPE(object_class),
1014 GTK_SIGNAL_OFFSET (GtkSheetClass, changed),
1015 gtkextra_VOID__INT_INT,
1016 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
1018 widget_class->set_scroll_adjustments_signal =
1019 gtk_signal_new ("set-scroll-adjustments",
1021 GTK_CLASS_TYPE(object_class),
1022 GTK_SIGNAL_OFFSET (GtkSheetClass, set_scroll_adjustments),
1023 gtkextra_VOID__OBJECT_OBJECT,
1024 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
1027 container_class->add = NULL;
1028 container_class->remove = gtk_sheet_remove;
1029 container_class->forall = gtk_sheet_forall;
1031 object_class->destroy = gtk_sheet_destroy;
1032 gobject_class->finalize = gtk_sheet_finalize;
1034 widget_class->realize = gtk_sheet_realize;
1035 widget_class->unrealize = gtk_sheet_unrealize;
1036 widget_class->map = gtk_sheet_map;
1037 widget_class->unmap = gtk_sheet_unmap;
1038 widget_class->style_set = gtk_sheet_style_set;
1039 widget_class->button_press_event = gtk_sheet_button_press;
1040 widget_class->button_release_event = gtk_sheet_button_release;
1041 widget_class->motion_notify_event = gtk_sheet_motion;
1042 widget_class->key_press_event = gtk_sheet_key_press;
1043 widget_class->expose_event = gtk_sheet_expose;
1044 widget_class->size_request = gtk_sheet_size_request;
1045 widget_class->size_allocate = gtk_sheet_size_allocate;
1046 widget_class->focus_in_event = NULL;
1047 widget_class->focus_out_event = NULL;
1049 klass->set_scroll_adjustments = gtk_sheet_set_scroll_adjustments;
1050 klass->select_row = NULL;
1051 klass->select_column = NULL;
1052 klass->select_range = NULL;
1053 klass->clip_range = NULL;
1054 klass->resize_range = NULL;
1055 klass->move_range = NULL;
1056 klass->traverse = NULL;
1057 klass->deactivate = NULL;
1058 klass->activate = NULL;
1059 klass->set_cell = NULL;
1060 klass->clear_cell = NULL;
1061 klass->changed = NULL;
1066 gtk_sheet_init (GtkSheet *sheet)
1068 sheet->column_geometry = NULL;
1069 sheet->row_geometry = NULL;
1071 sheet->children = NULL;
1074 sheet->selection_mode = GTK_SELECTION_BROWSE;
1075 sheet->freeze_count = 0;
1076 sheet->state = GTK_SHEET_NORMAL;
1078 GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW);
1079 GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS);
1081 sheet->view.row0 = 0;
1082 sheet->view.col0 = 0;
1083 sheet->view.rowi = 0;
1084 sheet->view.coli = 0;
1086 sheet->column_title_window=NULL;
1087 sheet->column_title_area.x=0;
1088 sheet->column_title_area.y=0;
1089 sheet->column_title_area.width=0;
1090 sheet->column_title_area.height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
1092 sheet->row_title_window=NULL;
1093 sheet->row_title_area.x=0;
1094 sheet->row_title_area.y=0;
1095 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1096 sheet->row_title_area.height=0;
1099 sheet->active_cell.row=0;
1100 sheet->active_cell.col=0;
1101 sheet->selection_cell.row=0;
1102 sheet->selection_cell.col=0;
1104 sheet->sheet_entry=NULL;
1107 sheet->range.row0=0;
1108 sheet->range.rowi=0;
1109 sheet->range.col0=0;
1110 sheet->range.coli=0;
1112 sheet->state=GTK_SHEET_NORMAL;
1114 sheet->sheet_window = NULL;
1115 sheet->sheet_window_width = 0;
1116 sheet->sheet_window_height = 0;
1117 sheet->sheet_entry = NULL;
1118 sheet->button = NULL;
1123 sheet->hadjustment = NULL;
1124 sheet->vadjustment = NULL;
1126 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
1127 sheet->xor_gc = NULL;
1128 sheet->fg_gc = NULL;
1129 sheet->bg_gc = NULL;
1133 gdk_color_parse("white", &sheet->bg_color);
1134 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1135 gdk_color_parse("gray", &sheet->grid_color);
1136 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1137 sheet->show_grid = TRUE;
1141 /* Callback which occurs whenever columns are inserted/deleted in the model */
1143 columns_inserted_deleted_callback (GSheetModel *model, gint first_column, gint n_columns,
1146 GtkSheet *sheet = GTK_SHEET(data);
1148 GtkSheetRange range;
1149 gint model_columns = g_sheet_model_get_column_count(model);
1152 /* Need to update all the columns starting from the first column and onwards.
1153 * Previous column are unchanged, so don't need to be updated.
1155 range.col0 = first_column;
1157 range.coli = xxx_column_count(sheet) - 1;
1158 range.rowi = yyy_row_count(sheet) - 1;
1160 if (sheet->active_cell.col >= model_columns)
1161 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, model_columns - 1);
1163 gtk_sheet_range_draw(sheet, &range);
1167 /* Callback which occurs whenever rows are inserted/deleted in the model */
1169 rows_inserted_deleted_callback (GSheetModel *m, gint first_row, gint n_rows,
1172 GtkSheet *sheet = GTK_SHEET(data);
1174 GtkSheetRange range;
1176 /* Need to update all the rows starting from the first row and onwards.
1177 * Previous rows are unchanged, so don't need to be updated.
1179 range.row0 = first_row;
1181 range.rowi = yyy_row_count(sheet) - 1;
1182 range.coli = xxx_column_count(sheet) - 1;
1184 gtk_sheet_range_draw(sheet, &range);
1189 If row0 or rowi are negative, then all rows will be updated.
1190 If col0 or coli are negative, then all columns will be updated.
1193 range_update_callback (GSheetModel *m, gint row0, gint col0,
1194 gint rowi, gint coli, gpointer data)
1196 GtkSheet *sheet = GTK_SHEET(data);
1198 GtkSheetRange range;
1205 if( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
1207 gtk_sheet_range_draw(sheet, NULL);
1210 else if ( row0 < 0 || rowi < 0 )
1212 range.row0=MIN_VISIBLE_ROW(sheet);
1213 range.rowi=MAX_VISIBLE_ROW(sheet);
1215 else if ( col0 < 0 || coli < 0 )
1217 range.col0=MIN_VISIBLE_COLUMN(sheet);
1218 range.coli=MAX_VISIBLE_COLUMN(sheet);
1221 gtk_sheet_range_draw(sheet, &range);
1225 static void gtk_sheet_construct (GtkSheet *sheet,
1228 const gchar *title);
1233 * @rows: initial number of rows
1234 * @columns: initial number of columns
1235 * @title: sheet title
1236 * @model: the model to use for the sheet data
1238 * Creates a new sheet widget with the given number of rows and columns.
1240 * Returns: the new sheet widget
1243 gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, const gchar *title,
1248 widget = gtk_type_new (gtk_sheet_get_type ());
1250 gtk_sheet_construct(GTK_SHEET(widget), vgeo, hgeo, title);
1253 gtk_sheet_set_model(GTK_SHEET(widget), model);
1261 * gtk_sheet_set_model
1262 * @sheet: the sheet to set the model for
1263 * @model: the model to use for the sheet data
1265 * Sets the model for a GtkSheet
1269 gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model)
1271 g_return_if_fail (GTK_IS_SHEET (sheet));
1272 g_return_if_fail (G_IS_SHEET_MODEL (model));
1274 sheet->model = model;
1276 g_signal_connect(model, "range_changed",
1277 G_CALLBACK(range_update_callback), sheet);
1279 g_signal_connect(model, "rows_inserted",
1280 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1282 g_signal_connect(model, "rows_deleted",
1283 G_CALLBACK(rows_inserted_deleted_callback), sheet);
1285 g_signal_connect(model, "columns_inserted",
1286 G_CALLBACK(columns_inserted_deleted_callback), sheet);
1288 g_signal_connect(model, "columns_deleted",
1289 G_CALLBACK(columns_inserted_deleted_callback), sheet);
1296 column_titles_changed(GtkWidget *w, gint first, gint n_columns, gpointer data)
1298 GtkSheet *sheet = GTK_SHEET(data);
1301 if(!GTK_SHEET_IS_FROZEN(sheet)){
1303 for ( i = first ; i <= MAX_VISIBLE_COLUMN(sheet) ; ++i )
1305 gtk_sheet_button_draw(sheet, -1, i);
1306 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, i);
1312 gtk_sheet_construct (GtkSheet *sheet,
1317 g_return_if_fail(G_IS_SHEET_COLUMN(hgeo));
1318 g_return_if_fail(G_IS_SHEET_ROW(vgeo));
1320 sheet->column_geometry = hgeo;
1321 sheet->row_geometry = vgeo;
1324 sheet->columns_resizable = TRUE;
1325 sheet->rows_resizable = TRUE;
1327 sheet->row_titles_visible = TRUE;
1328 sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
1330 sheet->column_titles_visible = TRUE;
1331 sheet->autoscroll = TRUE;
1332 sheet->justify_entry = TRUE;
1335 /* create sheet entry */
1336 sheet->entry_type = 0;
1337 create_sheet_entry (sheet);
1339 /* create global selection button */
1340 create_global_button(sheet);
1343 sheet->name = g_strdup(title);
1345 g_signal_connect(sheet->column_geometry, "columns_changed",
1346 G_CALLBACK(column_titles_changed), sheet);
1352 gtk_sheet_new_with_custom_entry (GSheetRow *rows, GSheetColumn *columns, const gchar *title,
1357 widget = gtk_type_new (gtk_sheet_get_type ());
1359 gtk_sheet_construct_with_custom_entry(GTK_SHEET(widget),
1360 rows, columns, title, entry_type);
1366 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet,
1372 gtk_sheet_construct(sheet, vgeo, hgeo, title);
1374 sheet->entry_type = entry_type;
1375 create_sheet_entry(sheet);
1381 gtk_sheet_change_entry(GtkSheet *sheet, GtkType entry_type)
1385 g_return_if_fail (sheet != NULL);
1386 g_return_if_fail (GTK_IS_SHEET (sheet));
1388 state = sheet->state;
1390 if(sheet->state == GTK_SHEET_NORMAL)
1391 gtk_sheet_hide_active_cell(sheet);
1393 sheet->entry_type = entry_type;
1395 create_sheet_entry(sheet);
1397 if(state == GTK_SHEET_NORMAL)
1399 gtk_sheet_show_active_cell(sheet);
1400 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
1402 G_CALLBACK(gtk_sheet_entry_changed),
1411 gtk_sheet_show_grid(GtkSheet *sheet, gboolean show)
1413 g_return_if_fail (sheet != NULL);
1414 g_return_if_fail (GTK_IS_SHEET (sheet));
1416 if(show == sheet->show_grid) return;
1418 sheet->show_grid = show;
1420 if(!GTK_SHEET_IS_FROZEN(sheet))
1421 gtk_sheet_range_draw(sheet, NULL);
1425 gtk_sheet_grid_visible(GtkSheet *sheet)
1427 g_return_val_if_fail (sheet != NULL, 0);
1428 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1430 return sheet->show_grid;
1434 gtk_sheet_set_background(GtkSheet *sheet, GdkColor *color)
1436 g_return_if_fail (sheet != NULL);
1437 g_return_if_fail (GTK_IS_SHEET (sheet));
1440 gdk_color_parse("white", &sheet->bg_color);
1441 gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
1443 sheet->bg_color = *color;
1445 if(!GTK_SHEET_IS_FROZEN(sheet))
1446 gtk_sheet_range_draw(sheet, NULL);
1450 gtk_sheet_set_grid(GtkSheet *sheet, GdkColor *color)
1452 g_return_if_fail (sheet != NULL);
1453 g_return_if_fail (GTK_IS_SHEET (sheet));
1456 gdk_color_parse("black", &sheet->grid_color);
1457 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
1459 sheet->grid_color = *color;
1461 if(!GTK_SHEET_IS_FROZEN(sheet))
1462 gtk_sheet_range_draw(sheet, NULL);
1466 gtk_sheet_get_columns_count(GtkSheet *sheet)
1468 g_return_val_if_fail (sheet != NULL, 0);
1469 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1471 return xxx_column_count(sheet);
1475 gtk_sheet_get_rows_count(GtkSheet *sheet)
1477 g_return_val_if_fail (sheet != NULL, 0);
1478 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1480 return yyy_row_count(sheet);
1484 gtk_sheet_get_state(GtkSheet *sheet)
1486 g_return_val_if_fail (sheet != NULL, 0);
1487 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
1489 return (sheet->state);
1493 gtk_sheet_set_selection_mode(GtkSheet *sheet, gint mode)
1495 g_return_if_fail (sheet != NULL);
1496 g_return_if_fail (GTK_IS_SHEET (sheet));
1498 if(GTK_WIDGET_REALIZED(sheet))
1499 gtk_sheet_real_unselect_range(sheet, NULL);
1501 sheet->selection_mode = mode;
1505 gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize)
1507 g_return_if_fail (sheet != NULL);
1508 g_return_if_fail (GTK_IS_SHEET (sheet));
1510 sheet->autoresize = autoresize;
1514 gtk_sheet_autoresize (GtkSheet *sheet)
1516 g_return_val_if_fail (sheet != NULL, FALSE);
1517 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1519 return sheet->autoresize;
1523 gtk_sheet_set_column_width (GtkSheet * sheet,
1529 gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
1531 gint text_width = 0;
1534 g_return_if_fail (sheet != NULL);
1535 g_return_if_fail (GTK_IS_SHEET (sheet));
1536 if (column >= xxx_column_count(sheet) || column < 0) return;
1538 for (row = 0; row < yyy_row_count(sheet); row++)
1540 gchar *text = gtk_sheet_cell_get_text(sheet, row, column);
1541 if (text && strlen(text) > 0){
1542 GtkSheetCellAttr attributes;
1544 gtk_sheet_get_attributes(sheet, row, column, &attributes);
1545 if(attributes.is_visible){
1546 gint width = STRING_WIDTH(GTK_WIDGET(sheet),
1547 attributes.font_desc,
1549 + 2*CELLOFFSET + attributes.border.width;
1550 text_width = MAX (text_width, width);
1553 dispose_string(sheet, text);
1556 if(text_width > xxx_column_width(sheet, column) )
1558 gtk_sheet_set_column_width(sheet, column, text_width);
1559 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
1565 gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll)
1567 g_return_if_fail (sheet != NULL);
1568 g_return_if_fail (GTK_IS_SHEET (sheet));
1570 sheet->autoscroll = autoscroll;
1574 gtk_sheet_autoscroll (GtkSheet *sheet)
1576 g_return_val_if_fail (sheet != NULL, FALSE);
1577 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1579 return sheet->autoscroll;
1583 gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text)
1585 g_return_if_fail (sheet != NULL);
1586 g_return_if_fail (GTK_IS_SHEET (sheet));
1588 sheet->clip_text = clip_text;
1592 gtk_sheet_clip_text (GtkSheet *sheet)
1594 g_return_val_if_fail (sheet != NULL, FALSE);
1595 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1597 return sheet->clip_text;
1601 gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify)
1603 g_return_if_fail (sheet != NULL);
1604 g_return_if_fail (GTK_IS_SHEET (sheet));
1606 sheet->justify_entry = justify;
1610 gtk_sheet_justify_entry (GtkSheet *sheet)
1612 g_return_val_if_fail (sheet != NULL, FALSE);
1613 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1615 return sheet->justify_entry;
1619 gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked)
1621 g_return_if_fail (sheet != NULL);
1622 g_return_if_fail (GTK_IS_SHEET (sheet));
1626 GTK_SHEET_SET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
1627 gtk_widget_hide(sheet->sheet_entry);
1628 gtk_widget_unmap(sheet->sheet_entry);
1632 GTK_SHEET_UNSET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
1633 if (GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)))
1635 gtk_widget_show (sheet->sheet_entry);
1636 gtk_widget_map (sheet->sheet_entry);
1640 gtk_entry_set_editable(GTK_ENTRY(sheet->sheet_entry), locked);
1645 gtk_sheet_locked (const GtkSheet *sheet)
1647 g_return_val_if_fail (sheet != NULL, FALSE);
1648 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1650 return GTK_SHEET_IS_LOCKED(sheet);
1653 /* This routine has problems with gtk+-1.2 related with the
1654 * label/button drawing - I think it's a bug in gtk+-1.2 */
1657 gtk_sheet_set_title(GtkSheet *sheet, const gchar *title)
1659 /* GtkWidget *old_widget;
1660 */ GtkWidget *label;
1662 g_return_if_fail (sheet != NULL);
1663 g_return_if_fail (title != NULL);
1664 g_return_if_fail (GTK_IS_SHEET (sheet));
1667 g_free (sheet->name);
1669 sheet->name = g_strdup (title);
1671 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) || !title) return;
1673 if(GTK_BIN(sheet->button)->child)
1674 label = GTK_BIN(sheet->button)->child;
1676 gtk_label_set_text(GTK_LABEL(label), title);
1678 size_allocate_global_button(sheet);
1680 /* remove and destroy the old widget */
1682 old_widget = GTK_BIN (sheet->button)->child;
1685 gtk_container_remove (GTK_CONTAINER (sheet->button), old_widget);
1688 label = gtk_label_new (title);
1689 gtk_misc_set_alignment(GTK_MISC(label), 0.5 , 0.5 );
1691 gtk_container_add (GTK_CONTAINER (sheet->button), label);
1692 gtk_widget_show (label);
1694 size_allocate_global_button(sheet);
1696 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, -1);
1699 gtk_widget_destroy (old_widget);
1704 gtk_sheet_freeze (GtkSheet *sheet)
1706 g_return_if_fail (sheet != NULL);
1707 g_return_if_fail (GTK_IS_SHEET (sheet));
1709 sheet->freeze_count++;
1710 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1714 gtk_sheet_thaw(GtkSheet *sheet)
1716 g_return_if_fail (sheet != NULL);
1717 g_return_if_fail (GTK_IS_SHEET (sheet));
1719 if(sheet->freeze_count == 0) return;
1721 sheet->freeze_count--;
1722 if(sheet->freeze_count > 0) return;
1724 adjust_scrollbars(sheet);
1726 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
1728 sheet->old_vadjustment = -1.;
1729 sheet->old_hadjustment = -1.;
1731 if(sheet->hadjustment)
1732 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1734 if(sheet->vadjustment)
1735 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1738 if(sheet->state == GTK_STATE_NORMAL)
1739 if(sheet->sheet_entry && GTK_WIDGET_MAPPED(sheet->sheet_entry)){
1740 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
1742 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
1744 (GtkSignalFunc)gtk_sheet_entry_changed,
1745 GTK_OBJECT(GTK_WIDGET(sheet)));
1746 gtk_sheet_show_active_cell(sheet);
1753 gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width)
1755 if(width < COLUMN_MIN_WIDTH) return;
1757 sheet->row_title_area.width = width;
1758 sheet->view.col0 = COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
1759 sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
1762 adjust_scrollbars(sheet);
1764 sheet->old_hadjustment = -1.;
1765 if(sheet->hadjustment)
1766 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1768 size_allocate_global_button(sheet);
1772 gtk_sheet_set_column_titles_height(GtkSheet *sheet, guint height)
1774 if(height < DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))) return;
1776 sheet->column_title_area.height = height;
1777 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
1778 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
1780 adjust_scrollbars(sheet);
1782 sheet->old_vadjustment = -1.;
1783 if(sheet->vadjustment)
1784 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1786 size_allocate_global_button(sheet);
1790 gtk_sheet_show_column_titles(GtkSheet *sheet)
1794 if(sheet->column_titles_visible) return;
1796 sheet->column_titles_visible = TRUE;
1799 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1800 gdk_window_show(sheet->column_title_window);
1801 gdk_window_move_resize (sheet->column_title_window,
1802 sheet->column_title_area.x,
1803 sheet->column_title_area.y,
1804 sheet->column_title_area.width,
1805 sheet->column_title_area.height);
1807 for(col = MIN_VISIBLE_COLUMN(sheet);
1808 col <= MAX_VISIBLE_COLUMN(sheet);
1811 GtkSheetButton *button = xxx_column_button(sheet, col);
1812 GtkSheetChild *child = button->child;
1814 gtk_sheet_child_show(child);
1815 gtk_sheet_button_free(button);
1817 adjust_scrollbars(sheet);
1820 sheet->old_vadjustment = -1.;
1821 if(sheet->vadjustment)
1822 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1824 size_allocate_global_button(sheet);
1829 gtk_sheet_show_row_titles(GtkSheet *sheet)
1833 if(sheet->row_titles_visible) return;
1835 sheet->row_titles_visible = TRUE;
1838 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1839 gdk_window_show(sheet->row_title_window);
1840 gdk_window_move_resize (sheet->row_title_window,
1841 sheet->row_title_area.x,
1842 sheet->row_title_area.y,
1843 sheet->row_title_area.width,
1844 sheet->row_title_area.height);
1846 for(row = MIN_VISIBLE_ROW(sheet);
1847 row <= MAX_VISIBLE_ROW(sheet);
1850 const GtkSheetButton *button = yyy_row_button(sheet, row);
1851 GtkSheetChild *child = button->child;
1854 gtk_sheet_child_show(child);
1857 adjust_scrollbars(sheet);
1860 sheet->old_hadjustment = -1.;
1861 if(sheet->hadjustment)
1862 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1864 size_allocate_global_button(sheet);
1868 gtk_sheet_hide_column_titles(GtkSheet *sheet)
1872 if(!sheet->column_titles_visible) return;
1874 sheet->column_titles_visible = FALSE;
1876 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1877 if(sheet->column_title_window)
1878 gdk_window_hide(sheet->column_title_window);
1879 if(GTK_WIDGET_VISIBLE(sheet->button))
1880 gtk_widget_hide(sheet->button);
1882 for(col = MIN_VISIBLE_COLUMN(sheet);
1883 col <= MAX_VISIBLE_COLUMN(sheet);
1886 GtkSheetButton *button = xxx_column_button(sheet, col);
1887 GtkSheetChild *child = button->child;
1889 gtk_sheet_child_hide(child);
1890 gtk_sheet_button_free(button);
1892 adjust_scrollbars(sheet);
1895 sheet->old_vadjustment = -1.;
1896 if(sheet->vadjustment)
1897 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
1902 gtk_sheet_hide_row_titles(GtkSheet *sheet)
1906 if(!sheet->row_titles_visible) return;
1908 sheet->row_titles_visible = FALSE;
1911 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
1912 if(sheet->row_title_window)
1913 gdk_window_hide(sheet->row_title_window);
1914 if(GTK_WIDGET_VISIBLE(sheet->button))
1915 gtk_widget_hide(sheet->button);
1916 for(row = MIN_VISIBLE_ROW(sheet);
1917 row <= MAX_VISIBLE_ROW(sheet);
1920 const GtkSheetButton *button = yyy_row_button(sheet, row);
1921 GtkSheetChild *child = button->child;
1924 gtk_sheet_child_hide(child);
1926 adjust_scrollbars(sheet);
1929 sheet->old_hadjustment = -1.;
1930 if(sheet->hadjustment)
1931 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
1936 gtk_sheet_column_titles_visible(GtkSheet *sheet)
1938 g_return_val_if_fail (sheet != NULL, FALSE);
1939 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1940 return sheet->column_titles_visible;
1944 gtk_sheet_row_titles_visible(GtkSheet *sheet)
1946 g_return_val_if_fail (sheet != NULL, FALSE);
1947 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
1948 return sheet->row_titles_visible;
1954 gtk_sheet_moveto (GtkSheet * sheet,
1961 guint width, height;
1963 gint min_row, min_col;
1965 g_return_if_fail (sheet != NULL);
1966 g_return_if_fail (GTK_IS_SHEET (sheet));
1967 g_return_if_fail (sheet->hadjustment != NULL);
1968 g_return_if_fail (sheet->vadjustment != NULL);
1970 if (row < 0 || row >= yyy_row_count(sheet))
1972 if (column < 0 || column >= xxx_column_count(sheet))
1975 height = sheet->sheet_window_height;
1976 width = sheet->sheet_window_width;
1978 /* adjust vertical scrollbar */
1980 if (row >= 0 && row_align >=0.)
1983 y = ROW_TOP_YPIXEL(sheet, row) - sheet->voffset -
1985 (1.-row_align)*yyy_row_height(sheet, row);
1987 y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
1988 - (gint) ( row_align*height + (1. - row_align) * yyy_row_height(sheet, row));
1990 /* This forces the sheet to scroll when you don't see the entire cell */
1993 if(row_align == 1.){
1994 while(min_row >= 0 && min_row > MIN_VISIBLE_ROW(sheet)){
1995 if(yyy_row_is_visible(sheet, min_row))
1996 adjust += yyy_row_height(sheet, min_row);
1997 if(adjust >= height){
2002 min_row = MAX(min_row, 0);
2003 y = ROW_TOP_YPIXEL(sheet, min_row) - sheet->voffset +
2004 yyy_row_height(sheet, min_row) - 1;
2008 sheet->vadjustment->value = 0.0;
2010 sheet->vadjustment->value = y;
2012 sheet->old_vadjustment = -1.;
2013 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
2018 /* adjust horizontal scrollbar */
2019 if (column >= 0 && col_align >= 0.)
2022 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset -
2024 (1.-col_align)*sheet->column[column].width;
2026 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
2027 - (gint) ( col_align*width + (1.-col_align)*
2028 xxx_column_width(sheet, column));
2031 /* This forces the sheet to scroll when you don't see the entire cell */
2034 if(col_align == 1.){
2035 while(min_col >= 0 && min_col > MIN_VISIBLE_COLUMN(sheet)){
2036 if(xxx_column_is_visible(sheet, min_col))
2037 adjust += xxx_column_width(sheet, min_col);
2039 if(adjust >= width){
2044 min_col = MAX(min_col, 0);
2045 x = COLUMN_LEFT_XPIXEL(sheet, min_col) - sheet->hoffset +
2046 xxx_column_width(sheet, min_col) - 1;
2050 sheet->hadjustment->value = 0.0;
2052 sheet->hadjustment->value = x;
2054 sheet->old_vadjustment = -1.;
2055 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment),
2063 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
2065 g_return_if_fail (sheet != NULL);
2066 g_return_if_fail (GTK_IS_SHEET (sheet));
2068 sheet->columns_resizable = resizable;
2072 gtk_sheet_columns_resizable (GtkSheet *sheet)
2074 g_return_val_if_fail (sheet != NULL, FALSE);
2075 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2077 return sheet->columns_resizable;
2082 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
2084 g_return_if_fail (sheet != NULL);
2085 g_return_if_fail (GTK_IS_SHEET (sheet));
2087 sheet->rows_resizable = resizable;
2091 gtk_sheet_rows_resizable (GtkSheet *sheet)
2093 g_return_val_if_fail (sheet != NULL, FALSE);
2094 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2096 return sheet->rows_resizable;
2101 gtk_sheet_select_row (GtkSheet * sheet,
2104 g_return_if_fail (sheet != NULL);
2105 g_return_if_fail (GTK_IS_SHEET (sheet));
2107 if (row < 0 || row >= yyy_row_count(sheet))
2110 if(sheet->state != GTK_SHEET_NORMAL)
2111 gtk_sheet_real_unselect_range(sheet, NULL);
2114 gboolean veto = TRUE;
2115 veto = gtk_sheet_deactivate_cell(sheet);
2119 sheet->state=GTK_SHEET_ROW_SELECTED;
2120 sheet->range.row0=row;
2121 sheet->range.col0=0;
2122 sheet->range.rowi=row;
2123 sheet->range.coli = xxx_column_count(sheet) - 1;
2124 sheet->active_cell.row=row;
2125 sheet->active_cell.col=0;
2127 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_ROW], row);
2128 gtk_sheet_real_select_range(sheet, NULL);
2134 gtk_sheet_select_column (GtkSheet * sheet,
2138 g_return_if_fail (sheet != NULL);
2139 g_return_if_fail (GTK_IS_SHEET (sheet));
2141 if (column < 0 || column >= xxx_column_count(sheet))
2144 if(sheet->state != GTK_SHEET_NORMAL)
2145 gtk_sheet_real_unselect_range(sheet, NULL);
2148 gboolean veto = TRUE;
2149 veto = gtk_sheet_deactivate_cell(sheet);
2153 sheet->state=GTK_SHEET_COLUMN_SELECTED;
2154 sheet->range.row0=0;
2155 sheet->range.col0=column;
2156 sheet->range.rowi= yyy_row_count(sheet) - 1;
2157 sheet->range.coli=column;
2158 sheet->active_cell.row=0;
2159 sheet->active_cell.col=column;
2161 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_COLUMN], column);
2162 gtk_sheet_real_select_range(sheet, NULL);
2167 gtk_sheet_clip_range (GtkSheet *sheet, const GtkSheetRange *range)
2170 g_return_if_fail (sheet != NULL);
2171 g_return_if_fail (GTK_IS_SHEET (sheet));
2173 if(GTK_SHEET_IN_CLIP(sheet)) return;
2175 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2178 sheet->clip_range = sheet->range;
2180 sheet->clip_range=*range;
2183 sheet->clip_timer=gtk_timeout_add(TIMEOUT_FLASH, gtk_sheet_flash, sheet);
2185 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CLIP_RANGE],
2186 &sheet->clip_range);
2191 gtk_sheet_unclip_range(GtkSheet *sheet)
2194 g_return_if_fail (sheet != NULL);
2195 g_return_if_fail (GTK_IS_SHEET (sheet));
2197 if(!GTK_SHEET_IN_CLIP(sheet)) return;
2199 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_CLIP);
2200 gtk_timeout_remove(sheet->clip_timer);
2201 gtk_sheet_range_draw(sheet, &sheet->clip_range);
2203 if(gtk_sheet_range_isvisible(sheet, sheet->range))
2204 gtk_sheet_range_draw(sheet, &sheet->range);
2208 gtk_sheet_in_clip (GtkSheet *sheet)
2210 g_return_val_if_fail (sheet != NULL, FALSE);
2211 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
2213 return GTK_SHEET_IN_CLIP(sheet);
2217 gtk_sheet_flash(gpointer data)
2220 gint x,y,width,height;
2221 GdkRectangle clip_area;
2223 sheet=GTK_SHEET(data);
2225 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return TRUE;
2226 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return TRUE;
2227 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return TRUE;
2228 if(GTK_SHEET_IN_XDRAG(sheet)) return TRUE;
2229 if(GTK_SHEET_IN_YDRAG(sheet)) return TRUE;
2231 GDK_THREADS_ENTER();
2233 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2234 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2235 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2236 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2237 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2238 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2240 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2241 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2242 clip_area.width=sheet->sheet_window_width;
2243 clip_area.height=sheet->sheet_window_height;
2249 if(width>clip_area.width) width=clip_area.width+10;
2254 if(height>clip_area.height) height=clip_area.height+10;
2256 gdk_draw_pixmap(sheet->sheet_window,
2257 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2263 gdk_draw_pixmap(sheet->sheet_window,
2264 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2270 gdk_draw_pixmap(sheet->sheet_window,
2271 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2277 gdk_draw_pixmap(sheet->sheet_window,
2278 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
2285 sheet->interval=sheet->interval+1;
2286 if(sheet->interval==TIME_INTERVAL) sheet->interval=0;
2288 gdk_gc_set_dashes(sheet->xor_gc, sheet->interval, (gint8*)"\4\4", 2);
2289 gtk_sheet_draw_flashing_range(sheet,sheet->clip_range);
2290 gdk_gc_set_dashes(sheet->xor_gc, 0, (gint8*)"\4\4", 2);
2292 GDK_THREADS_LEAVE();
2299 gtk_sheet_draw_flashing_range(GtkSheet *sheet, GtkSheetRange range)
2301 GdkRectangle clip_area;
2302 gint x,y,width,height;
2304 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return;
2306 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
2307 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
2308 clip_area.width=sheet->sheet_window_width;
2309 clip_area.height=sheet->sheet_window_height;
2311 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
2313 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
2314 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
2315 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+
2316 xxx_column_width(sheet, sheet->clip_range.coli) - 1;
2317 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
2318 yyy_row_height(sheet, sheet->clip_range.rowi)-1;
2324 if(width>clip_area.width) width=clip_area.width+10;
2329 if(height>clip_area.height) height=clip_area.height+10;
2331 gdk_gc_set_line_attributes(sheet->xor_gc, 1, 1, 0 ,0 );
2333 gdk_draw_rectangle(sheet->sheet_window, sheet->xor_gc, FALSE,
2337 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 0, 0, 0);
2339 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
2344 gtk_sheet_range_isvisible (GtkSheet * sheet,
2345 GtkSheetRange range)
2347 g_return_val_if_fail (sheet != NULL, FALSE);
2349 if (range.row0 < 0 || range.row0 >= yyy_row_count(sheet))
2352 if (range.rowi < 0 || range.rowi >= yyy_row_count(sheet))
2355 if (range.col0 < 0 || range.col0 >= xxx_column_count(sheet))
2358 if (range.coli < 0 || range.coli >= xxx_column_count(sheet))
2361 if (range.rowi < MIN_VISIBLE_ROW (sheet))
2364 if (range.row0 > MAX_VISIBLE_ROW (sheet))
2367 if (range.coli < MIN_VISIBLE_COLUMN (sheet))
2370 if (range.col0 > MAX_VISIBLE_COLUMN (sheet))
2377 gtk_sheet_cell_isvisible (GtkSheet * sheet,
2378 gint row, gint column)
2380 GtkSheetRange range;
2383 range.col0 = column;
2385 range.coli = column;
2387 return gtk_sheet_range_isvisible(sheet, range);
2391 gtk_sheet_get_visible_range(GtkSheet *sheet, GtkSheetRange *range)
2394 g_return_if_fail (sheet != NULL);
2395 g_return_if_fail (GTK_IS_SHEET (sheet)) ;
2396 g_return_if_fail (range != NULL);
2398 range->row0 = MIN_VISIBLE_ROW(sheet);
2399 range->col0 = MIN_VISIBLE_COLUMN(sheet);
2400 range->rowi = MAX_VISIBLE_ROW(sheet);
2401 range->coli = MAX_VISIBLE_COLUMN(sheet);
2406 gtk_sheet_get_vadjustment (GtkSheet * sheet)
2408 g_return_val_if_fail (sheet != NULL, NULL);
2409 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2411 return sheet->vadjustment;
2415 gtk_sheet_get_hadjustment (GtkSheet * sheet)
2417 g_return_val_if_fail (sheet != NULL, NULL);
2418 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
2420 return sheet->hadjustment;
2424 gtk_sheet_set_vadjustment (GtkSheet *sheet,
2425 GtkAdjustment *adjustment)
2427 GtkAdjustment *old_adjustment;
2429 g_return_if_fail (sheet != NULL);
2430 g_return_if_fail (GTK_IS_SHEET (sheet));
2432 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2434 if (sheet->vadjustment == adjustment)
2437 old_adjustment = sheet->vadjustment;
2439 if (sheet->vadjustment)
2441 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2442 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2445 sheet->vadjustment = adjustment;
2447 if (sheet->vadjustment)
2449 gtk_object_ref (GTK_OBJECT (sheet->vadjustment));
2450 gtk_object_sink (GTK_OBJECT (sheet->vadjustment));
2452 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "changed",
2453 (GtkSignalFunc) vadjustment_changed,
2455 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "value_changed",
2456 (GtkSignalFunc) vadjustment_value_changed,
2460 if (!sheet->vadjustment || !old_adjustment)
2462 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2466 sheet->old_vadjustment = sheet->vadjustment->value;
2470 gtk_sheet_set_hadjustment (GtkSheet *sheet,
2471 GtkAdjustment *adjustment)
2473 GtkAdjustment *old_adjustment;
2475 g_return_if_fail (sheet != NULL);
2476 g_return_if_fail (GTK_IS_SHEET (sheet));
2478 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
2480 if (sheet->hadjustment == adjustment)
2483 old_adjustment = sheet->hadjustment;
2485 if (sheet->hadjustment)
2487 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2488 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2491 sheet->hadjustment = adjustment;
2493 if (sheet->hadjustment)
2495 gtk_object_ref (GTK_OBJECT (sheet->hadjustment));
2496 gtk_object_sink (GTK_OBJECT (sheet->hadjustment));
2498 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "changed",
2499 (GtkSignalFunc) hadjustment_changed,
2501 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "value_changed",
2502 (GtkSignalFunc) hadjustment_value_changed,
2506 if (!sheet->hadjustment || !old_adjustment)
2508 gtk_widget_queue_resize (GTK_WIDGET (sheet));
2512 sheet->old_hadjustment = sheet->hadjustment->value;
2516 gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
2517 GtkAdjustment *hadjustment,
2518 GtkAdjustment *vadjustment)
2520 if(sheet->hadjustment != hadjustment)
2521 gtk_sheet_set_hadjustment (sheet, hadjustment);
2522 if(sheet->vadjustment != vadjustment)
2523 gtk_sheet_set_vadjustment (sheet, vadjustment);
2527 gtk_sheet_finalize (GObject * object)
2531 g_return_if_fail (object != NULL);
2532 g_return_if_fail (GTK_IS_SHEET (object));
2534 sheet = GTK_SHEET (object);
2536 /* get rid of all the cells */
2537 gtk_sheet_range_clear (sheet, NULL);
2538 gtk_sheet_range_delete(sheet, NULL);
2541 g_free(sheet->name);
2545 if (G_OBJECT_CLASS (parent_class)->finalize)
2546 (*G_OBJECT_CLASS (parent_class)->finalize) (object);
2550 gtk_sheet_destroy (GtkObject * object)
2555 g_return_if_fail (object != NULL);
2556 g_return_if_fail (GTK_IS_SHEET (object));
2558 sheet = GTK_SHEET (object);
2560 /* destroy the entry */
2561 if(sheet->sheet_entry && GTK_IS_WIDGET(sheet->sheet_entry)){
2562 gtk_widget_destroy (sheet->sheet_entry);
2563 sheet->sheet_entry = NULL;
2566 /* destroy the global selection button */
2567 if(sheet->button && GTK_IS_WIDGET(sheet->button)){
2568 gtk_widget_destroy (sheet->button);
2569 sheet->button = NULL;
2573 gtk_timeout_remove(sheet->timer);
2577 if(sheet->clip_timer){
2578 gtk_timeout_remove(sheet->clip_timer);
2579 sheet->clip_timer = 0;
2582 /* unref adjustments */
2583 if (sheet->hadjustment)
2585 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet);
2586 gtk_object_unref (GTK_OBJECT (sheet->hadjustment));
2587 sheet->hadjustment = NULL;
2589 if (sheet->vadjustment)
2591 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet);
2592 gtk_object_unref (GTK_OBJECT (sheet->vadjustment));
2593 sheet->vadjustment = NULL;
2596 children = sheet->children;
2598 GtkSheetChild *child = (GtkSheetChild *)children->data;
2599 if(child && child->widget)
2600 gtk_sheet_remove(GTK_CONTAINER(sheet), child->widget);
2601 children = sheet->children;
2603 sheet->children = NULL;
2605 if (GTK_OBJECT_CLASS (parent_class)->destroy)
2606 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
2610 gtk_sheet_style_set (GtkWidget *widget,
2611 GtkStyle *previous_style)
2615 g_return_if_fail (widget != NULL);
2616 g_return_if_fail (GTK_IS_SHEET (widget));
2618 if (GTK_WIDGET_CLASS (parent_class)->style_set)
2619 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
2621 sheet = GTK_SHEET (widget);
2623 if(GTK_WIDGET_REALIZED(widget))
2625 gtk_style_set_background (widget->style, widget->window, widget->state);
2631 gtk_sheet_realize (GtkWidget * widget)
2634 GdkWindowAttr attributes;
2635 gint attributes_mask;
2636 GdkGCValues values, auxvalues;
2637 GdkColormap *colormap;
2639 GtkSheetChild *child;
2642 g_return_if_fail (widget != NULL);
2643 g_return_if_fail (GTK_IS_SHEET (widget));
2645 sheet = GTK_SHEET (widget);
2647 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
2649 attributes.window_type = GDK_WINDOW_CHILD;
2650 attributes.x = widget->allocation.x;
2651 attributes.y = widget->allocation.y;
2652 attributes.width = widget->allocation.width;
2653 attributes.height = widget->allocation.height;
2654 attributes.wclass = GDK_INPUT_OUTPUT;
2656 attributes.visual = gtk_widget_get_visual (widget);
2657 attributes.colormap = gtk_widget_get_colormap (widget);
2659 attributes.event_mask = gtk_widget_get_events (widget);
2660 attributes.event_mask |= (GDK_EXPOSURE_MASK |
2661 GDK_BUTTON_PRESS_MASK |
2662 GDK_BUTTON_RELEASE_MASK |
2663 GDK_KEY_PRESS_MASK |
2664 GDK_POINTER_MOTION_MASK |
2665 GDK_POINTER_MOTION_HINT_MASK);
2666 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
2669 attributes.cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
2672 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
2674 gdk_window_set_user_data (widget->window, sheet);
2676 widget->style = gtk_style_attach (widget->style, widget->window);
2678 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
2681 if(sheet->row_titles_visible)
2682 attributes.x = sheet->row_title_area.width;
2684 attributes.width = sheet->column_title_area.width;
2685 attributes.height = sheet->column_title_area.height;
2687 /* column-title window */
2688 sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2689 gdk_window_set_user_data (sheet->column_title_window, sheet);
2690 gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL);
2694 if(sheet->column_titles_visible)
2695 attributes.y = sheet->column_title_area.height;
2696 attributes.width = sheet->row_title_area.width;
2697 attributes.height = sheet->row_title_area.height;
2699 /* row-title window */
2700 sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2701 gdk_window_set_user_data (sheet->row_title_window, sheet);
2702 gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL);
2705 attributes.cursor = gdk_cursor_new(GDK_PLUS);
2709 attributes.width = sheet->sheet_window_width,
2710 attributes.height = sheet->sheet_window_height;
2712 sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask);
2713 gdk_window_set_user_data (sheet->sheet_window, sheet);
2715 gdk_cursor_unref(attributes.cursor);
2717 gdk_window_set_background (sheet->sheet_window, &widget->style->white);
2718 gdk_window_show (sheet->sheet_window);
2720 /* backing_pixmap */
2721 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
2725 gdk_gc_unref(sheet->fg_gc);
2727 gdk_gc_unref(sheet->bg_gc);
2728 sheet->fg_gc = gdk_gc_new (widget->window);
2729 sheet->bg_gc = gdk_gc_new (widget->window);
2731 colormap = gtk_widget_get_colormap(widget);
2733 gdk_color_white(colormap, &widget->style->white);
2734 gdk_color_black(colormap, &widget->style->black);
2736 gdk_gc_get_values(sheet->fg_gc, &auxvalues);
2738 values.foreground = widget->style->white;
2739 values.function = GDK_INVERT;
2740 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
2742 gdk_gc_unref(sheet->xor_gc);
2743 sheet->xor_gc = gdk_gc_new_with_values (widget->window,
2749 if(sheet->sheet_entry->parent){
2750 gtk_widget_ref(sheet->sheet_entry);
2751 gtk_widget_unparent(sheet->sheet_entry);
2753 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
2754 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
2756 if(sheet->button && sheet->button->parent){
2757 gtk_widget_ref(sheet->button);
2758 gtk_widget_unparent(sheet->button);
2760 gtk_widget_set_parent_window(sheet->button, sheet->sheet_window);
2761 gtk_widget_set_parent(sheet->button, GTK_WIDGET(sheet));
2764 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
2766 if(!sheet->cursor_drag)
2767 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS);
2769 if(sheet->column_titles_visible)
2770 gdk_window_show(sheet->column_title_window);
2771 if(sheet->row_titles_visible)
2772 gdk_window_show(sheet->row_title_window);
2774 size_allocate_row_title_buttons(sheet);
2775 size_allocate_column_title_buttons(sheet);
2777 name = g_strdup(sheet->name);
2778 gtk_sheet_set_title(sheet, name);
2782 children = sheet->children;
2785 child = children->data;
2786 children = children->next;
2788 gtk_sheet_realize_child(sheet, child);
2793 create_global_button(GtkSheet *sheet)
2795 sheet->button = gtk_button_new_with_label(" ");
2797 gtk_signal_connect (GTK_OBJECT (sheet->button),
2799 (GtkSignalFunc) global_button_clicked,
2804 size_allocate_global_button(GtkSheet *sheet)
2806 GtkAllocation allocation;
2808 if(!sheet->column_titles_visible) return;
2809 if(!sheet->row_titles_visible) return;
2811 gtk_widget_size_request(sheet->button, NULL);
2815 allocation.width=sheet->row_title_area.width;
2816 allocation.height=sheet->column_title_area.height;
2818 gtk_widget_size_allocate(sheet->button, &allocation);
2819 gtk_widget_show(sheet->button);
2823 global_button_clicked(GtkWidget *widget, gpointer data)
2827 gtk_sheet_click_cell(GTK_SHEET(data), -1, -1, &veto);
2828 gtk_widget_grab_focus(GTK_WIDGET(data));
2833 gtk_sheet_unrealize (GtkWidget * widget)
2837 g_return_if_fail (widget != NULL);
2838 g_return_if_fail (GTK_IS_SHEET (widget));
2840 sheet = GTK_SHEET (widget);
2842 gdk_cursor_destroy (sheet->cursor_drag);
2844 gdk_gc_destroy (sheet->xor_gc);
2845 gdk_gc_destroy (sheet->fg_gc);
2846 gdk_gc_destroy (sheet->bg_gc);
2848 gdk_window_destroy (sheet->sheet_window);
2849 gdk_window_destroy (sheet->column_title_window);
2850 gdk_window_destroy (sheet->row_title_window);
2853 g_object_unref(sheet->pixmap);
2854 sheet->pixmap = NULL;
2857 sheet->column_title_window=NULL;
2858 sheet->sheet_window = NULL;
2859 sheet->cursor_drag = NULL;
2860 sheet->xor_gc = NULL;
2861 sheet->fg_gc = NULL;
2862 sheet->bg_gc = NULL;
2864 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
2865 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
2869 gtk_sheet_map (GtkWidget * widget)
2872 GtkSheetChild *child;
2875 g_return_if_fail (widget != NULL);
2876 g_return_if_fail (GTK_IS_SHEET (widget));
2878 sheet = GTK_SHEET (widget);
2880 if (!GTK_WIDGET_MAPPED (widget))
2882 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
2884 if(!sheet->cursor_drag) sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
2886 gdk_window_show (widget->window);
2888 gdk_window_show (sheet->sheet_window);
2890 if(sheet->column_titles_visible){
2891 size_allocate_column_title_buttons(sheet);
2892 gdk_window_show (sheet->column_title_window);
2894 if(sheet->row_titles_visible){
2895 size_allocate_row_title_buttons(sheet);
2896 gdk_window_show (sheet->row_title_window);
2899 if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)
2900 && ! gtk_sheet_locked(sheet)
2901 && sheet->active_cell.row >=0
2902 && sheet->active_cell.col >=0 )
2904 gtk_widget_show (sheet->sheet_entry);
2905 gtk_widget_map (sheet->sheet_entry);
2908 if (GTK_WIDGET_VISIBLE (sheet->button) &&
2909 !GTK_WIDGET_MAPPED (sheet->button)){
2910 gtk_widget_show(sheet->button);
2911 gtk_widget_map (sheet->button);
2914 if(GTK_BIN(sheet->button)->child)
2915 if (GTK_WIDGET_VISIBLE (GTK_BIN(sheet->button)->child) &&
2916 !GTK_WIDGET_MAPPED (GTK_BIN(sheet->button)->child))
2917 gtk_widget_map (GTK_BIN(sheet->button)->child);
2919 gtk_sheet_range_draw(sheet, NULL);
2920 gtk_sheet_activate_cell(sheet,
2921 sheet->active_cell.row,
2922 sheet->active_cell.col);
2924 children = sheet->children;
2927 child = children->data;
2928 children = children->next;
2930 if (GTK_WIDGET_VISIBLE (child->widget) &&
2931 !GTK_WIDGET_MAPPED (child->widget)){
2932 gtk_widget_map (child->widget);
2933 gtk_sheet_position_child(sheet, child);
2941 gtk_sheet_unmap (GtkWidget * widget)
2944 GtkSheetChild *child;
2947 g_return_if_fail (widget != NULL);
2948 g_return_if_fail (GTK_IS_SHEET (widget));
2950 sheet = GTK_SHEET (widget);
2952 if (GTK_WIDGET_MAPPED (widget))
2954 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
2956 gdk_window_hide (sheet->sheet_window);
2957 if(sheet->column_titles_visible)
2958 gdk_window_hide (sheet->column_title_window);
2959 if(sheet->row_titles_visible)
2960 gdk_window_hide (sheet->row_title_window);
2961 gdk_window_hide (widget->window);
2963 if (GTK_WIDGET_MAPPED (sheet->sheet_entry))
2964 gtk_widget_unmap (sheet->sheet_entry);
2966 if (GTK_WIDGET_MAPPED (sheet->button))
2967 gtk_widget_unmap (sheet->button);
2969 children = sheet->children;
2972 child = children->data;
2973 children = children->next;
2975 if (GTK_WIDGET_VISIBLE (child->widget) &&
2976 GTK_WIDGET_MAPPED (child->widget))
2978 gtk_widget_unmap (child->widget);
2987 gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
2990 GdkGC *fg_gc, *bg_gc;
2991 GtkSheetCellAttr attributes;
2994 g_return_if_fail (sheet != NULL);
2996 /* bail now if we arn't drawable yet */
2997 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
2999 if (row < 0 || row >= yyy_row_count(sheet)) return;
3000 if (col < 0 || col >= xxx_column_count(sheet)) return;
3001 if (! xxx_column_is_visible(sheet, col)) return;
3002 if (! yyy_row_is_visible(sheet, row)) return;
3004 widget = GTK_WIDGET (sheet);
3006 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3008 /* select GC for background rectangle */
3009 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3010 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3012 fg_gc = sheet->fg_gc;
3013 bg_gc = sheet->bg_gc;
3015 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3016 area.y=ROW_TOP_YPIXEL(sheet,row);
3017 area.width= xxx_column_width(sheet, col);
3018 area.height=yyy_row_height(sheet, row);
3020 gdk_draw_rectangle (sheet->pixmap,
3028 gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0);
3030 if(sheet->show_grid){
3031 gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color);
3033 gdk_draw_rectangle (sheet->pixmap,
3037 area.width, area.height);
3042 gtk_sheet_cell_draw_border (GtkSheet *sheet, gint row, gint col, gint mask)
3045 GdkGC *fg_gc, *bg_gc;
3046 GtkSheetCellAttr attributes;
3050 g_return_if_fail (sheet != NULL);
3052 /* bail now if we arn't drawable yet */
3053 if (!GTK_WIDGET_DRAWABLE (sheet)) return;
3055 if (row < 0 || row >= yyy_row_count(sheet)) return;
3056 if (col < 0 || col >= xxx_column_count(sheet)) return;
3057 if (!xxx_column_is_visible(sheet, col)) return;
3058 if (!yyy_row_is_visible(sheet, row)) return;
3060 widget = GTK_WIDGET (sheet);
3062 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3064 /* select GC for background rectangle */
3065 gdk_gc_set_foreground (sheet->fg_gc, &attributes.border.color);
3066 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3068 fg_gc = sheet->fg_gc;
3069 bg_gc = sheet->bg_gc;
3071 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3072 area.y=ROW_TOP_YPIXEL(sheet,row);
3073 area.width=xxx_column_width(sheet, col);
3074 area.height=yyy_row_height(sheet, row);
3076 width = attributes.border.width;
3077 gdk_gc_set_line_attributes(sheet->fg_gc, attributes.border.width,
3078 attributes.border.line_style,
3079 attributes.border.cap_style,
3080 attributes.border.join_style);
3083 if(attributes.border.mask & GTK_SHEET_LEFT_BORDER & mask)
3084 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3085 area.x, area.y-width/2,
3086 area.x, area.y+area.height+width/2+1);
3088 if(attributes.border.mask & GTK_SHEET_RIGHT_BORDER & mask)
3089 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3090 area.x+area.width, area.y-width/2,
3092 area.y+area.height+width/2+1);
3094 if(attributes.border.mask & GTK_SHEET_TOP_BORDER & mask)
3095 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3096 area.x-width/2,area.y,
3097 area.x+area.width+width/2+1,
3100 if(attributes.border.mask & GTK_SHEET_BOTTOM_BORDER & mask)
3101 gdk_draw_line(sheet->pixmap, sheet->fg_gc,
3102 area.x-width/2, area.y+area.height,
3103 area.x+area.width+width/2+1,
3104 area.y+area.height);
3111 gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
3114 GdkRectangle area, clip_area;
3116 gint text_width, text_height, y;
3118 gint size, sizel, sizer;
3119 GdkGC *fg_gc, *bg_gc;
3120 GtkSheetCellAttr attributes;
3121 PangoLayout *layout;
3122 PangoRectangle rect;
3123 PangoRectangle logical_rect;
3124 PangoLayoutLine *line;
3125 PangoFontMetrics *metrics;
3126 PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet));
3127 gint ascent, descent, y_pos;
3131 g_return_if_fail (sheet != NULL);
3133 /* bail now if we aren't drawable yet */
3134 if (!GTK_WIDGET_DRAWABLE (sheet))
3137 label = gtk_sheet_cell_get_text(sheet, row, col);
3141 if (row < 0 || row >= yyy_row_count(sheet)) return;
3142 if (col < 0 || col >= xxx_column_count(sheet)) return;
3143 if (! xxx_column_is_visible(sheet, col)) return;
3144 if (!yyy_row_is_visible(sheet, row)) return;
3147 widget = GTK_WIDGET(sheet);
3149 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3151 /* select GC for background rectangle */
3152 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
3153 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
3155 fg_gc = sheet->fg_gc;
3156 bg_gc = sheet->bg_gc;
3158 area.x=COLUMN_LEFT_XPIXEL(sheet,col);
3159 area.y=ROW_TOP_YPIXEL(sheet,row);
3160 area.width = xxx_column_width(sheet, col);
3161 area.height = yyy_row_height(sheet, row);
3165 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label);
3166 dispose_string(sheet, label);
3167 pango_layout_set_font_description (layout, attributes.font_desc);
3169 pango_layout_get_pixel_extents (layout, NULL, &rect);
3171 line = pango_layout_get_lines (layout)->data;
3172 pango_layout_line_get_extents (line, NULL, &logical_rect);
3174 metrics = pango_context_get_metrics(context,
3175 attributes.font_desc,
3176 pango_context_get_language(context));
3178 ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
3179 descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
3181 pango_font_metrics_unref(metrics);
3183 /* Align primarily for locale's ascent/descent */
3185 logical_rect.height /= PANGO_SCALE;
3186 logical_rect.y /= PANGO_SCALE;
3187 y_pos = area.height - logical_rect.height;
3189 if (logical_rect.height > area.height)
3190 y_pos = (logical_rect.height - area.height - 2*CELLOFFSET) / 2;
3193 else if (y_pos + logical_rect.height > area.height)
3194 y_pos = area.height - logical_rect.height;
3196 text_width = rect.width;
3197 text_height = rect.height;
3198 y = area.y + y_pos - CELLOFFSET;
3200 switch(attributes.justification){
3201 case GTK_JUSTIFY_RIGHT:
3204 if(!gtk_sheet_clip_text(sheet)){
3205 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3206 if( !gtk_sheet_cell_empty(sheet, row, i)) break;
3207 if(size>=text_width+CELLOFFSET) break;
3208 size+=xxx_column_width(sheet, i);
3209 xxx_column_set_right_column(sheet, i,
3211 xxx_column_right_column(sheet, i)));
3216 xoffset+=area.width-text_width - 2 * CELLOFFSET -
3217 attributes.border.width/2;
3219 case GTK_JUSTIFY_CENTER:
3222 area.x+=area.width/2;
3223 if(!gtk_sheet_clip_text(sheet)){
3224 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3225 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3226 if(sizer>=text_width/2) break;
3227 sizer+= xxx_column_width(sheet, i);
3228 xxx_column_set_left_column(sheet, i,
3231 xxx_column_left_column(sheet, i)));
3233 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
3234 if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
3235 if(sizel>=text_width/2) break;
3236 sizel+=xxx_column_width(sheet, i);
3237 xxx_column_set_right_column(sheet, i,
3239 xxx_column_right_column(sheet, i)));
3241 size=MIN(sizel, sizer);
3244 xoffset+= sizel - text_width/2 - CELLOFFSET;
3245 area.width=sizel+sizer;
3247 case GTK_JUSTIFY_LEFT:
3250 if(!gtk_sheet_clip_text(sheet)){
3251 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
3252 if(! gtk_sheet_cell_empty(sheet, row, i)) break;
3253 if(size>=text_width+CELLOFFSET) break;
3254 size+=xxx_column_width(sheet, i);
3255 xxx_column_set_left_column(sheet, i,
3258 xxx_column_left_column(sheet, i)));
3263 xoffset += attributes.border.width/2;
3267 if(!gtk_sheet_clip_text(sheet)) clip_area = area;
3268 gdk_gc_set_clip_rectangle(fg_gc, &clip_area);
3271 gdk_draw_layout (sheet->pixmap, fg_gc,
3272 area.x + xoffset + CELLOFFSET,
3276 gdk_gc_set_clip_rectangle(fg_gc, NULL);
3277 g_object_unref(G_OBJECT(layout));
3279 gdk_draw_pixmap(sheet->sheet_window,
3280 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3294 gtk_sheet_range_draw(GtkSheet *sheet, const GtkSheetRange *range)
3297 GtkSheetRange drawing_range;
3300 g_return_if_fail(sheet != NULL);
3301 g_return_if_fail(GTK_SHEET(sheet));
3303 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
3304 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3305 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
3309 drawing_range.row0=MIN_VISIBLE_ROW(sheet);
3310 drawing_range.col0=MIN_VISIBLE_COLUMN(sheet);
3311 drawing_range.rowi=MAX_VISIBLE_ROW(sheet);
3312 drawing_range.coli=MAX_VISIBLE_COLUMN(sheet);
3314 gdk_draw_rectangle (sheet->pixmap,
3315 GTK_WIDGET(sheet)->style->white_gc,
3318 sheet->sheet_window_width,sheet->sheet_window_height);
3323 drawing_range.row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
3324 drawing_range.col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
3325 drawing_range.rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
3326 drawing_range.coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
3330 if(drawing_range.coli == xxx_column_count(sheet) - 1)
3332 area.x=COLUMN_LEFT_XPIXEL(sheet,
3333 xxx_column_count(sheet) - 1) +
3334 xxx_column_width(sheet, xxx_column_count(sheet) - 1) + 1;
3338 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3340 gdk_draw_rectangle (sheet->pixmap,
3344 sheet->sheet_window_width - area.x,
3345 sheet->sheet_window_height);
3347 gdk_draw_pixmap(sheet->sheet_window,
3348 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3354 sheet->sheet_window_width - area.x,
3355 sheet->sheet_window_height);
3358 if(drawing_range.rowi == yyy_row_count(sheet) - 1){
3360 area.y=ROW_TOP_YPIXEL(sheet,
3361 yyy_row_count(sheet) - 1) +
3362 yyy_row_height(sheet, yyy_row_count(sheet) - 1) + 1;
3364 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color);
3366 gdk_draw_rectangle (sheet->pixmap,
3370 sheet->sheet_window_width,
3371 sheet->sheet_window_height - area.y);
3373 gdk_draw_pixmap(sheet->sheet_window,
3374 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3380 sheet->sheet_window_width,
3381 sheet->sheet_window_height - area.y);
3384 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3385 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3386 gtk_sheet_cell_draw_default(sheet, i, j);
3389 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3390 for(j=drawing_range.col0; j<=drawing_range.coli; j++){
3391 gtk_sheet_cell_draw_border(sheet, i-1, j, GTK_SHEET_BOTTOM_BORDER);
3392 gtk_sheet_cell_draw_border(sheet, i+1, j, GTK_SHEET_TOP_BORDER);
3393 gtk_sheet_cell_draw_border(sheet, i, j-1, GTK_SHEET_RIGHT_BORDER);
3394 gtk_sheet_cell_draw_border(sheet, i, j+1, GTK_SHEET_LEFT_BORDER);
3395 gtk_sheet_cell_draw_border(sheet, i, j, 15);
3398 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3399 for(j=drawing_range.col0; j<=drawing_range.coli; j++)
3400 gtk_sheet_cell_draw_label (sheet, i, j);
3402 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3403 for(j= xxx_column_left_column(sheet, drawing_range.col0);
3404 j<drawing_range.col0; j++)
3405 gtk_sheet_cell_draw_label (sheet, i, j);
3407 for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
3408 for(j = drawing_range.coli+1;
3409 j <= xxx_column_right_column(sheet, drawing_range.coli);
3411 gtk_sheet_cell_draw_label (sheet, i, j);
3413 gtk_sheet_draw_backing_pixmap(sheet, drawing_range);
3415 if(sheet->state != GTK_SHEET_NORMAL && gtk_sheet_range_isvisible(sheet, sheet->range))
3416 gtk_sheet_range_draw_selection(sheet, drawing_range);
3418 if(sheet->state == GTK_STATE_NORMAL &&
3419 sheet->active_cell.row >= drawing_range.row0 &&
3420 sheet->active_cell.row <= drawing_range.rowi &&
3421 sheet->active_cell.col >= drawing_range.col0 &&
3422 sheet->active_cell.col <= drawing_range.coli)
3423 gtk_sheet_show_active_cell(sheet);
3428 gtk_sheet_range_draw_selection(GtkSheet *sheet, GtkSheetRange range)
3434 if(range.col0 > sheet->range.coli || range.coli < sheet->range.col0 ||
3435 range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0)
3438 if(!gtk_sheet_range_isvisible(sheet, range)) return;
3439 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3443 range.col0=MAX(sheet->range.col0, range.col0);
3444 range.coli=MIN(sheet->range.coli, range.coli);
3445 range.row0=MAX(sheet->range.row0, range.row0);
3446 range.rowi=MIN(sheet->range.rowi, range.rowi);
3448 range.col0=MAX(range.col0, MIN_VISIBLE_COLUMN(sheet));
3449 range.coli=MIN(range.coli, MAX_VISIBLE_COLUMN(sheet));
3450 range.row0=MAX(range.row0, MIN_VISIBLE_ROW(sheet));
3451 range.rowi=MIN(range.rowi, MAX_VISIBLE_ROW(sheet));
3453 for(i=range.row0; i<=range.rowi; i++){
3454 for(j=range.col0; j<=range.coli; j++){
3456 if(gtk_sheet_cell_get_state(sheet, i, j)==GTK_STATE_SELECTED &&
3457 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
3460 row_button_set(sheet, i);
3461 column_button_set(sheet, j);
3464 area.x=COLUMN_LEFT_XPIXEL(sheet,j);
3465 area.y=ROW_TOP_YPIXEL(sheet,i);
3466 area.width= xxx_column_width(sheet, j);
3467 area.height=yyy_row_height(sheet, i);
3469 if(i==sheet->range.row0){
3471 area.height=area.height-2;
3473 if(i==sheet->range.rowi) area.height=area.height-3;
3474 if(j==sheet->range.col0){
3476 area.width=area.width-2;
3478 if(j==sheet->range.coli) area.width=area.width-3;
3480 if(i!=sheet->active_cell.row || j!=sheet->active_cell.col){
3481 gdk_draw_rectangle (sheet->sheet_window,
3485 area.width,area.height);
3492 gtk_sheet_draw_border(sheet, sheet->range);
3497 gtk_sheet_draw_backing_pixmap(GtkSheet *sheet, GtkSheetRange range)
3499 gint x,y,width,height;
3501 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
3503 x = COLUMN_LEFT_XPIXEL(sheet,range.col0);
3504 y = ROW_TOP_YPIXEL(sheet, range.row0);
3505 width = COLUMN_LEFT_XPIXEL(sheet, range.coli) - x +
3506 xxx_column_width(sheet, range.coli);
3508 height=ROW_TOP_YPIXEL(sheet, range.rowi)-y+yyy_row_height(sheet, range.rowi);
3510 if(range.row0==sheet->range.row0){
3514 if(range.rowi==sheet->range.rowi) height=height+5;
3515 if(range.col0==sheet->range.col0){
3519 if(range.coli==sheet->range.coli) width=width+5;
3522 width=MIN(width, sheet->sheet_window_width-x);
3523 height=MIN(height, sheet->sheet_window_height-y);
3530 x = (sheet->row_titles_visible)
3531 ? MAX(x, sheet->row_title_area.width) : MAX(x, 0);
3532 y = (sheet->column_titles_visible)
3533 ? MAX(y, sheet->column_title_area.height) : MAX(y, 0);
3535 if(range.coli == xxx_column_count(sheet) - 1)
3536 width = sheet->sheet_window_width - x;
3537 if(range.rowi == yyy_row_count(sheet) - 1)
3538 height=sheet->sheet_window_height - y;
3540 gdk_draw_pixmap(sheet->sheet_window,
3541 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
3553 gtk_sheet_set_cell_text(GtkSheet *sheet, gint row, gint col, const gchar *text)
3555 GtkSheetCellAttr attributes;
3557 g_return_if_fail (sheet != NULL);
3558 g_return_if_fail (GTK_IS_SHEET (sheet));
3559 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3560 if (col < 0 || row < 0) return;
3562 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3563 gtk_sheet_set_cell(sheet, row, col, attributes.justification, text);
3567 safe_strcmp(const gchar *s1, const gchar *s2)
3569 if ( !s1 && !s2) return 0;
3570 if ( !s1) return -1;
3571 if ( !s2) return +1;
3572 return strcmp(s1, s2);
3576 gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col,
3577 GtkJustification justification,
3580 GSheetModel *model ;
3584 GtkSheetRange range;
3586 GtkSheetCellAttr attributes;
3588 g_return_if_fail (sheet != NULL);
3589 g_return_if_fail (GTK_IS_SHEET (sheet));
3590 if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3591 if (col < 0 || row < 0) return;
3593 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3595 attributes.justification = justification;
3597 model = gtk_sheet_get_model(sheet);
3599 old_text = g_sheet_model_get_string(model, row, col);
3603 if (0 != safe_strcmp(old_text, text))
3604 changed = g_sheet_model_set_string(model, text, row, col);
3606 if ( g_sheet_model_free_strings(model))
3610 if(changed && attributes.is_visible)
3612 gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
3614 if(s && strlen(s) > 0) {
3615 text_width = STRING_WIDTH(GTK_WIDGET(sheet),
3616 attributes.font_desc, text);
3618 dispose_string(sheet, s);
3622 range.col0 = sheet->view.col0;
3623 range.coli = sheet->view.coli;
3625 if(gtk_sheet_autoresize(sheet) &&
3626 text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
3627 gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width);
3628 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
3631 if(!GTK_SHEET_IS_FROZEN(sheet))
3632 gtk_sheet_range_draw(sheet, &range);
3636 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
3642 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
3644 GtkSheetRange range;
3646 g_return_if_fail (sheet != NULL);
3647 g_return_if_fail (GTK_IS_SHEET (sheet));
3648 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3649 if (column < 0 || row < 0) return;
3653 range.col0 = sheet->view.col0;
3654 range.coli = sheet->view.coli;
3656 gtk_sheet_real_cell_clear(sheet, row, column, FALSE);
3658 if(!GTK_SHEET_IS_FROZEN(sheet)){
3659 gtk_sheet_range_draw(sheet, &range);
3664 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
3666 GtkSheetRange range;
3668 g_return_if_fail (sheet != NULL);
3669 g_return_if_fail (GTK_IS_SHEET (sheet));
3670 if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
3671 if (column < 0 || row < 0) return;
3675 range.col0 = sheet->view.col0;
3676 range.coli = sheet->view.coli;
3678 gtk_sheet_real_cell_clear(sheet, row, column, TRUE);
3680 if(!GTK_SHEET_IS_FROZEN(sheet)){
3681 gtk_sheet_range_draw(sheet, &range);
3686 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
3688 GSheetModel *model = gtk_sheet_get_model(sheet);
3690 gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column);
3692 if (old_text && strlen(old_text) > 0 )
3694 g_sheet_model_datum_clear(model, row, column);
3696 if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0)
3697 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL],
3701 dispose_string (sheet, old_text);
3705 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
3707 g_return_if_fail (sheet != NULL);
3708 g_return_if_fail (GTK_IS_SHEET (sheet));
3710 gtk_sheet_real_range_clear(sheet, range, FALSE);
3714 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range)
3716 g_return_if_fail (sheet != NULL);
3717 g_return_if_fail (GTK_IS_SHEET (sheet));
3719 gtk_sheet_real_range_clear(sheet, range, TRUE);
3724 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
3728 GtkSheetRange clear;
3732 clear.rowi = yyy_row_count(sheet) - 1;
3734 clear.coli = xxx_column_count(sheet) - 1;
3738 clear.row0=MAX(clear.row0, 0);
3739 clear.col0=MAX(clear.col0, 0);
3740 clear.rowi=MIN(clear.rowi, yyy_row_count(sheet) - 1 );
3741 clear.coli=MIN(clear.coli, xxx_column_count(sheet) - 1 );
3743 for(i=clear.row0; i<=clear.rowi; i++)
3744 for(j=clear.col0; j<=clear.coli; j++){
3745 gtk_sheet_real_cell_clear(sheet, i, j, delete);
3748 gtk_sheet_range_draw(sheet, NULL);
3753 gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col)
3756 char *text = gtk_sheet_cell_get_text(sheet, row, col);
3757 empty = (text == NULL );
3759 dispose_string(sheet, text);
3766 gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
3769 g_return_val_if_fail (sheet != NULL, NULL);
3770 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
3772 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet))
3774 if(col < 0 || row < 0) return NULL;
3776 model = gtk_sheet_get_model(sheet);
3781 return g_sheet_model_get_string(model, row, col);
3786 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
3789 GtkSheetRange *range;
3791 g_return_val_if_fail (sheet != NULL, 0);
3792 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3793 if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return 0;
3794 if(col < 0 || row < 0) return 0;
3796 state = sheet->state;
3797 range = &sheet->range;
3801 case GTK_SHEET_NORMAL:
3802 return GTK_STATE_NORMAL;
3804 case GTK_SHEET_ROW_SELECTED:
3805 if(row>=range->row0 && row<=range->rowi)
3806 return GTK_STATE_SELECTED;
3808 case GTK_SHEET_COLUMN_SELECTED:
3809 if(col>=range->col0 && col<=range->coli)
3810 return GTK_STATE_SELECTED;
3812 case GTK_SHEET_RANGE_SELECTED:
3813 if(row >= range->row0 && row <= range->rowi && \
3814 col >= range->col0 && col <= range->coli)
3815 return GTK_STATE_SELECTED;
3818 return GTK_STATE_NORMAL;
3822 gtk_sheet_get_pixel_info (GtkSheet * sheet,
3830 g_return_val_if_fail (sheet != NULL, 0);
3831 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3833 /* bounds checking, return false if the user clicked
3834 * on a blank area */
3835 trow = ROW_FROM_YPIXEL (sheet, y);
3836 if (trow >= yyy_row_count(sheet))
3841 tcol = COLUMN_FROM_XPIXEL (sheet, x);
3842 if (tcol >= xxx_column_count(sheet))
3851 gtk_sheet_get_cell_area (GtkSheet * sheet,
3856 g_return_val_if_fail (sheet != NULL, 0);
3857 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3859 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3862 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) -
3863 (sheet->row_titles_visible
3864 ? sheet->row_title_area.width
3866 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL(sheet, row) -
3867 (sheet->column_titles_visible
3868 ? sheet->column_title_area.height
3870 area->width= (column == -1) ? sheet->row_title_area.width
3871 : xxx_column_width(sheet, column);
3873 area->height= (row == -1) ? sheet->column_title_area.height
3874 : yyy_row_height(sheet, row);
3877 if(row < 0 || column < 0) return FALSE;
3879 area->x = COLUMN_LEFT_XPIXEL(sheet, column);
3880 area->y = ROW_TOP_YPIXEL(sheet, row);
3881 if(sheet->row_titles_visible)
3882 area->x -= sheet->row_title_area.width;
3883 if(sheet->column_titles_visible)
3884 area->y -= sheet->column_title_area.height;
3886 area->width=sheet->column[column].width;
3887 area->height=yyy_row_height(sheet, row);
3893 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
3895 g_return_val_if_fail (sheet != NULL, 0);
3896 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
3898 if(row < -1 || column < -1) return FALSE;
3899 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet))
3902 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
3904 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
3907 sheet->active_cell.row = row;
3908 sheet->active_cell.col = column;
3910 if ( row == -1 || column == -1)
3912 gtk_sheet_hide_active_cell(sheet);
3916 if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE;
3918 if(gtk_sheet_autoscroll(sheet))
3919 gtk_sheet_move_query(sheet, row, column);
3925 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column)
3927 g_return_if_fail (sheet != NULL);
3928 g_return_if_fail (GTK_IS_SHEET (sheet));
3930 *row = sheet->active_cell.row;
3931 *column = sheet->active_cell.col;
3935 gtk_sheet_entry_changed(GtkWidget *widget, gpointer data)
3940 GtkJustification justification;
3941 GtkSheetCellAttr attributes;
3943 g_return_if_fail (data != NULL);
3944 g_return_if_fail (GTK_IS_SHEET (data));
3946 sheet=GTK_SHEET(data);
3948 if(!GTK_WIDGET_VISIBLE(widget)) return;
3949 if(sheet->state != GTK_STATE_NORMAL) return;
3951 row=sheet->active_cell.row;
3952 col=sheet->active_cell.col;
3954 if(row<0 || col<0) return;
3956 sheet->active_cell.row=-1;
3957 sheet->active_cell.col=-1;
3959 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
3961 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3963 if(text && strlen(text) > 0)
3965 gtk_sheet_get_attributes(sheet, row, col, &attributes);
3966 justification = attributes.justification;
3967 gtk_sheet_set_cell(sheet, row, col, justification, text);
3970 if(sheet->freeze_count == 0)
3971 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
3973 sheet->active_cell.row=row;;
3974 sheet->active_cell.col=col;
3979 gtk_sheet_deactivate_cell(GtkSheet *sheet)
3981 gboolean veto = TRUE;
3983 g_return_val_if_fail (sheet != NULL, FALSE);
3984 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
3986 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return FALSE;
3987 if(sheet->state != GTK_SHEET_NORMAL) return FALSE;
3989 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[DEACTIVATE],
3990 sheet->active_cell.row,
3991 sheet->active_cell.col, &veto);
3993 if(!veto) return FALSE;
3995 if ( sheet->active_cell.row == -1 || sheet->active_cell.col == -1 )
3998 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
3999 (GtkSignalFunc) gtk_sheet_entry_changed,
4000 GTK_OBJECT(GTK_WIDGET(sheet)));
4002 gtk_sheet_hide_active_cell(sheet);
4003 sheet->active_cell.row = -1;
4004 sheet->active_cell.col = -1;
4006 if(GTK_SHEET_REDRAW_PENDING(sheet)){
4007 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
4008 gtk_sheet_range_draw(sheet, NULL);
4015 gtk_sheet_hide_active_cell(GtkSheet *sheet)
4019 GtkJustification justification;
4020 GtkSheetCellAttr attributes;
4022 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4024 row=sheet->active_cell.row;
4025 col=sheet->active_cell.col;
4027 if(row < 0 || col < 0) return;
4029 if(sheet->freeze_count == 0)
4030 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
4032 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
4034 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4035 justification=attributes.justification;
4037 if(text && strlen(text) != 0)
4039 gtk_sheet_set_cell(sheet, row, col, justification, text);
4040 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col);
4044 gtk_sheet_cell_clear(sheet, row, col);
4047 row=sheet->active_cell.row;
4048 col=sheet->active_cell.col;
4051 column_button_release(sheet, col);
4052 row_button_release(sheet, row);
4055 gtk_widget_hide(sheet->sheet_entry);
4056 gtk_widget_unmap(sheet->sheet_entry);
4058 if(row != -1 && col != -1)
4059 gdk_draw_pixmap(sheet->sheet_window,
4060 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4062 COLUMN_LEFT_XPIXEL(sheet,col)-1,
4063 ROW_TOP_YPIXEL(sheet,row)-1,
4064 COLUMN_LEFT_XPIXEL(sheet,col)-1,
4065 ROW_TOP_YPIXEL(sheet,row)-1,
4066 xxx_column_width(sheet, col) + 4,
4067 yyy_row_height(sheet, row)+4);
4069 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4071 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4076 gtk_sheet_activate_cell(GtkSheet *sheet, gint row, gint col)
4078 gboolean veto = TRUE;
4080 g_return_val_if_fail (sheet != NULL, FALSE);
4081 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
4083 if(row < 0 || col < 0) return FALSE;
4084 if(row >= yyy_row_count(sheet) || col >= xxx_column_count(sheet))
4087 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4088 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
4091 if(!veto) return FALSE;
4092 if(sheet->state != GTK_SHEET_NORMAL){
4093 sheet->state=GTK_SHEET_NORMAL;
4094 gtk_sheet_real_unselect_range(sheet, NULL);
4097 sheet->range.row0=row;
4098 sheet->range.col0=col;
4099 sheet->range.rowi=row;
4100 sheet->range.coli=col;
4101 sheet->active_cell.row=row;
4102 sheet->active_cell.col=col;
4103 sheet->selection_cell.row=row;
4104 sheet->selection_cell.col=col;
4106 row_button_set(sheet, row);
4107 column_button_set(sheet, col);
4110 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
4111 gtk_sheet_show_active_cell(sheet);
4113 g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
4115 G_CALLBACK(gtk_sheet_entry_changed),
4118 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
4124 gtk_sheet_show_active_cell(GtkSheet *sheet)
4126 GtkEntry *sheet_entry;
4127 GtkSheetCellAttr attributes;
4129 const gchar *old_text;
4130 GtkJustification justification;
4133 g_return_if_fail (sheet != NULL);
4134 g_return_if_fail (GTK_IS_SHEET (sheet));
4136 row = sheet->active_cell.row;
4137 col = sheet->active_cell.col;
4139 /* Don't show the active cell, if there is no active cell: */
4140 if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */
4143 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4144 if(sheet->state != GTK_SHEET_NORMAL) return;
4145 if(GTK_SHEET_IN_SELECTION(sheet)) return;
4147 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
4149 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
4151 gtk_sheet_get_attributes(sheet, row, col, &attributes);
4153 justification = GTK_JUSTIFY_LEFT;
4155 if(gtk_sheet_justify_entry(sheet))
4156 justification = attributes.justification;
4158 text = gtk_sheet_cell_get_text(sheet, row, col);
4160 text = g_strdup("");
4162 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible);
4164 if(gtk_sheet_locked(sheet) || !attributes.is_editable)
4165 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
4167 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
4169 /*** Added by John Gotts. Mar 25, 2005 *********/
4170 old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
4171 if (strcmp(old_text, text) != 0)
4173 if(!GTK_IS_ITEM_ENTRY(sheet_entry))
4174 gtk_entry_set_text(GTK_ENTRY(sheet_entry), text);
4176 gtk_item_entry_set_text(GTK_ITEM_ENTRY(sheet_entry), text, justification);
4179 gtk_sheet_entry_set_max_size(sheet);
4180 gtk_sheet_size_allocate_entry(sheet);
4182 gtk_widget_map(sheet->sheet_entry);
4183 gtk_sheet_draw_active_cell(sheet);
4185 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
4187 dispose_string(sheet, text);
4191 gtk_sheet_draw_active_cell(GtkSheet *sheet)
4195 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return;
4196 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4198 row = sheet->active_cell.row;
4199 col = sheet->active_cell.col;
4201 if(row < 0 || col < 0) return;
4203 if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
4205 row_button_set(sheet, row);
4206 column_button_set(sheet, col);
4208 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4209 gtk_sheet_draw_border(sheet, sheet->range);
4214 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
4216 gint pixmap_width, pixmap_height;
4218 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
4220 if(width == 0 && height == 0){
4221 width=sheet->sheet_window_width+80;
4222 height=sheet->sheet_window_height+80;
4228 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4231 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4235 /* reallocate if sizes don't match */
4236 gdk_window_get_size (sheet->pixmap,
4237 &pixmap_width, &pixmap_height);
4238 if ((pixmap_width != width) || (pixmap_height != height))
4240 g_object_unref(sheet->pixmap);
4241 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
4244 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL);
4250 gtk_sheet_new_selection(GtkSheet *sheet, GtkSheetRange *range)
4252 gint i,j, mask1, mask2;
4253 gint state, selected;
4254 gint x,y,width,height;
4255 GtkSheetRange new_range, aux_range;
4257 g_return_if_fail (sheet != NULL);
4259 if(range==NULL) range=&sheet->range;
4263 range->row0=MIN(range->row0, sheet->range.row0);
4264 range->rowi=MAX(range->rowi, sheet->range.rowi);
4265 range->col0=MIN(range->col0, sheet->range.col0);
4266 range->coli=MAX(range->coli, sheet->range.coli);
4268 range->row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet));
4269 range->rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet));
4270 range->col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet));
4271 range->coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
4273 aux_range.row0=MAX(new_range.row0, MIN_VISIBLE_ROW(sheet));
4274 aux_range.rowi=MIN(new_range.rowi, MAX_VISIBLE_ROW(sheet));
4275 aux_range.col0=MAX(new_range.col0, MIN_VISIBLE_COLUMN(sheet));
4276 aux_range.coli=MIN(new_range.coli, MAX_VISIBLE_COLUMN(sheet));
4278 for(i=range->row0; i<=range->rowi; i++){
4279 for(j=range->col0; j<=range->coli; j++){
4281 state=gtk_sheet_cell_get_state(sheet, i, j);
4282 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4283 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4285 if(state==GTK_STATE_SELECTED && selected &&
4286 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4287 (i==sheet->range.row0 || i==sheet->range.rowi ||
4288 j==sheet->range.col0 || j==sheet->range.coli ||
4289 i==new_range.row0 || i==new_range.rowi ||
4290 j==new_range.col0 || j==new_range.coli)){
4292 mask1 = i==sheet->range.row0 ? 1 : 0;
4293 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4294 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4295 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4297 mask2 = i==new_range.row0 ? 1 : 0;
4298 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4299 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4300 mask2 = j==new_range.coli ? mask2+8 : mask2;
4303 x=COLUMN_LEFT_XPIXEL(sheet,j);
4304 y=ROW_TOP_YPIXEL(sheet, i);
4305 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4306 xxx_column_width(sheet, j);
4307 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4309 if(i==sheet->range.row0){
4313 if(i==sheet->range.rowi) height=height+3;
4314 if(j==sheet->range.col0){
4318 if(j==sheet->range.coli) width=width+3;
4320 gdk_draw_pixmap(sheet->sheet_window,
4321 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4330 if(i != sheet->active_cell.row || j != sheet->active_cell.col){
4331 x=COLUMN_LEFT_XPIXEL(sheet,j);
4332 y=ROW_TOP_YPIXEL(sheet, i);
4333 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
4334 xxx_column_width(sheet, j);
4336 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4338 if(i==new_range.row0){
4342 if(i==new_range.rowi) height=height-3;
4343 if(j==new_range.col0){
4347 if(j==new_range.coli) width=width-3;
4349 gdk_draw_rectangle (sheet->sheet_window,
4360 for(i=range->row0; i<=range->rowi; i++){
4361 for(j=range->col0; j<=range->coli; j++){
4363 state=gtk_sheet_cell_get_state(sheet, i, j);
4364 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4365 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4367 if(state==GTK_STATE_SELECTED && !selected &&
4368 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4370 x=COLUMN_LEFT_XPIXEL(sheet,j);
4371 y=ROW_TOP_YPIXEL(sheet, i);
4372 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4373 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4375 if(i==sheet->range.row0){
4379 if(i==sheet->range.rowi) height=height+3;
4380 if(j==sheet->range.col0){
4384 if(j==sheet->range.coli) width=width+3;
4386 gdk_draw_pixmap(sheet->sheet_window,
4387 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4399 for(i=range->row0; i<=range->rowi; i++){
4400 for(j=range->col0; j<=range->coli; j++){
4402 state=gtk_sheet_cell_get_state(sheet, i, j);
4403 selected=(i<=new_range.rowi && i>=new_range.row0 &&
4404 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
4406 if(state!=GTK_STATE_SELECTED && selected &&
4407 xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i) &&
4408 (i != sheet->active_cell.row || j != sheet->active_cell.col)){
4410 x=COLUMN_LEFT_XPIXEL(sheet,j);
4411 y=ROW_TOP_YPIXEL(sheet, i);
4412 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
4413 height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
4415 if(i==new_range.row0){
4419 if(i==new_range.rowi) height=height-3;
4420 if(j==new_range.col0){
4424 if(j==new_range.coli) width=width-3;
4426 gdk_draw_rectangle (sheet->sheet_window,
4437 for(i=aux_range.row0; i<=aux_range.rowi; i++){
4438 for(j=aux_range.col0; j<=aux_range.coli; j++){
4440 if(xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
4442 state=gtk_sheet_cell_get_state(sheet, i, j);
4444 mask1 = i==sheet->range.row0 ? 1 : 0;
4445 mask1 = i==sheet->range.rowi ? mask1+2 : mask1;
4446 mask1 = j==sheet->range.col0 ? mask1+4 : mask1;
4447 mask1 = j==sheet->range.coli ? mask1+8 : mask1;
4449 mask2 = i==new_range.row0 ? 1 : 0;
4450 mask2 = i==new_range.rowi ? mask2+2 : mask2;
4451 mask2 = j==new_range.col0 ? mask2+4 : mask2;
4452 mask2 = j==new_range.coli ? mask2+8 : mask2;
4453 if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){
4454 x=COLUMN_LEFT_XPIXEL(sheet,j);
4455 y=ROW_TOP_YPIXEL(sheet, i);
4456 width=xxx_column_width(sheet, j);
4457 height=yyy_row_height(sheet, i);
4459 gdk_draw_rectangle (sheet->sheet_window,
4467 gdk_draw_rectangle (sheet->sheet_window,
4474 gdk_draw_rectangle (sheet->sheet_window,
4482 gdk_draw_rectangle (sheet->sheet_window,
4499 gtk_sheet_draw_corners(sheet, new_range);
4504 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
4509 gint x,y,width,height;
4511 widget = GTK_WIDGET(sheet);
4513 x=COLUMN_LEFT_XPIXEL(sheet,new_range.col0);
4514 y=ROW_TOP_YPIXEL(sheet,new_range.row0);
4515 width=COLUMN_LEFT_XPIXEL(sheet,new_range.coli)-x+
4516 xxx_column_width(sheet, new_range.coli);
4518 height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+
4519 yyy_row_height(sheet, new_range.rowi);
4521 area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
4522 area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
4523 area.width=sheet->sheet_window_width;
4524 area.height=sheet->sheet_window_height;
4530 if(width>area.width) width=area.width+10;
4535 if(height>area.height) height=area.height+10;
4537 gdk_gc_set_clip_rectangle(sheet->xor_gc, &area);
4539 for(i=-1; i<=1; ++i)
4540 gdk_draw_rectangle (sheet->sheet_window,
4544 width-2*i,height-2*i);
4546 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
4548 gtk_sheet_draw_corners(sheet, new_range);
4553 gtk_sheet_draw_corners(GtkSheet *sheet, GtkSheetRange range)
4558 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.col0)){
4559 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4560 y=ROW_TOP_YPIXEL(sheet,range.row0);
4561 gdk_draw_pixmap(sheet->sheet_window,
4562 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4570 gdk_draw_rectangle (sheet->sheet_window,
4577 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) ||
4578 sheet->state == GTK_SHEET_COLUMN_SELECTED){
4579 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4580 xxx_column_width(sheet, range.coli);
4581 y=ROW_TOP_YPIXEL(sheet,range.row0);
4583 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
4585 y = ROW_TOP_YPIXEL(sheet, sheet->view.row0)+3;
4588 gdk_draw_pixmap(sheet->sheet_window,
4589 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4597 gdk_draw_rectangle (sheet->sheet_window,
4600 x-width+width/2,y-width+width/2,
4604 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.col0) ||
4605 sheet->state == GTK_SHEET_ROW_SELECTED){
4606 x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
4607 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4608 yyy_row_height(sheet, range.rowi);
4610 if(sheet->state == GTK_SHEET_ROW_SELECTED)
4612 x = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0)+3;
4615 gdk_draw_pixmap(sheet->sheet_window,
4616 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4624 gdk_draw_rectangle (sheet->sheet_window,
4627 x-width+width/2,y-width+width/2,
4631 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){
4632 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
4633 xxx_column_width(sheet, range.coli);
4634 y=ROW_TOP_YPIXEL(sheet,range.rowi)+
4635 yyy_row_height(sheet, range.rowi);
4637 if(sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
4638 if(sheet->state == GTK_SHEET_NORMAL) width = 3;
4639 gdk_draw_pixmap(sheet->sheet_window,
4640 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
4648 gdk_draw_rectangle (sheet->sheet_window,
4651 x-width+width/2,y-width+width/2,
4660 gtk_sheet_real_select_range (GtkSheet * sheet,
4661 GtkSheetRange * range)
4665 g_return_if_fail (sheet != NULL);
4667 if(range==NULL) range=&sheet->range;
4669 if(range->row0 < 0 || range->rowi < 0) return;
4670 if(range->col0 < 0 || range->coli < 0) return;
4675 if(state==GTK_SHEET_COLUMN_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4676 for(i=sheet->range.col0; i< range->col0; i++)
4677 column_button_release(sheet, i);
4678 for(i=range->coli+1; i<= sheet->range.coli; i++)
4679 column_button_release(sheet, i);
4680 for(i=range->col0; i<=range->coli; i++){
4681 column_button_set(sheet, i);
4685 if(state==GTK_SHEET_ROW_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
4686 for(i=sheet->range.row0; i< range->row0; i++)
4687 row_button_release(sheet, i);
4688 for(i=range->rowi+1; i<= sheet->range.rowi; i++)
4689 row_button_release(sheet, i);
4690 for(i=range->row0; i<=range->rowi; i++){
4691 row_button_set(sheet, i);
4696 if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
4697 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
4700 gtk_sheet_new_selection(sheet, range);
4702 sheet->range.col0=range->col0;
4703 sheet->range.coli=range->coli;
4704 sheet->range.row0=range->row0;
4705 sheet->range.rowi=range->rowi;
4710 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4711 gtk_sheet_range_draw_selection(sheet, sheet->range);
4714 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[SELECT_RANGE], range);
4718 gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range)
4720 g_return_if_fail (sheet != NULL);
4722 if(range==NULL) range=&sheet->range;
4724 if(range->row0 < 0 || range->rowi < 0) return;
4725 if(range->col0 < 0 || range->coli < 0) return;
4728 if ( gtk_sheet_locked(sheet)) return ;
4730 if(sheet->state != GTK_SHEET_NORMAL)
4731 gtk_sheet_real_unselect_range(sheet, NULL);
4734 gboolean veto = TRUE;
4735 veto = gtk_sheet_deactivate_cell(sheet);
4739 sheet->range.row0=range->row0;
4740 sheet->range.rowi=range->rowi;
4741 sheet->range.col0=range->col0;
4742 sheet->range.coli=range->coli;
4743 sheet->active_cell.row=range->row0;
4744 sheet->active_cell.col=range->col0;
4745 sheet->selection_cell.row=range->rowi;
4746 sheet->selection_cell.col=range->coli;
4748 sheet->state = GTK_SHEET_RANGE_SELECTED;
4749 gtk_sheet_real_select_range(sheet, NULL);
4754 gtk_sheet_unselect_range (GtkSheet * sheet)
4756 gtk_sheet_real_unselect_range(sheet, NULL);
4757 sheet->state = GTK_STATE_NORMAL;
4758 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
4763 gtk_sheet_real_unselect_range (GtkSheet * sheet,
4764 const GtkSheetRange *range)
4766 g_return_if_fail (sheet != NULL);
4767 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)));
4770 range=&sheet->range;
4773 if(range->row0 < 0 || range->rowi < 0) return;
4774 if(range->col0 < 0 || range->coli < 0) return;
4776 if (gtk_sheet_range_isvisible (sheet, *range)){
4777 gtk_sheet_draw_backing_pixmap(sheet, *range);
4781 for(i=range->col0; i<=range->coli; i++){
4782 column_button_release(sheet, i);
4785 for(i=range->row0; i<=range->rowi; i++){
4786 row_button_release(sheet, i);
4790 gtk_sheet_position_children(sheet);
4795 gtk_sheet_expose (GtkWidget * widget,
4796 GdkEventExpose * event)
4799 GtkSheetRange range;
4801 g_return_val_if_fail (widget != NULL, FALSE);
4802 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4803 g_return_val_if_fail (event != NULL, FALSE);
4805 sheet = GTK_SHEET (widget);
4807 if (GTK_WIDGET_DRAWABLE (widget))
4809 range.row0=ROW_FROM_YPIXEL(sheet,event->area.y);
4810 range.col0=COLUMN_FROM_XPIXEL(sheet,event->area.x);
4811 range.rowi=ROW_FROM_YPIXEL(sheet,event->area.y+event->area.height);
4812 range.coli=COLUMN_FROM_XPIXEL(sheet,event->area.x+event->area.width);
4814 /* exposure events on the sheet */
4816 if(event->window == sheet->row_title_window && sheet->row_titles_visible){
4818 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
4819 gtk_sheet_button_draw(sheet,i,-1);
4822 if(event->window == sheet->column_title_window && sheet->column_titles_visible){
4824 for(i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
4825 gtk_sheet_button_draw(sheet,-1,i);
4828 if (event->window == sheet->sheet_window){
4829 gtk_sheet_draw_backing_pixmap(sheet, range);
4831 if(sheet->state != GTK_SHEET_NORMAL){
4832 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4833 gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
4834 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4835 gtk_sheet_draw_backing_pixmap(sheet, sheet->drag_range);
4837 if(gtk_sheet_range_isvisible(sheet, sheet->range))
4838 gtk_sheet_range_draw_selection(sheet, sheet->range);
4839 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet))
4840 draw_xor_rectangle(sheet, sheet->drag_range);
4843 if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet))){
4844 if(sheet->state == GTK_SHEET_NORMAL){
4845 gtk_sheet_draw_active_cell(sheet);
4846 if(!GTK_SHEET_IN_SELECTION(sheet))
4847 gtk_widget_queue_draw(sheet->sheet_entry);
4856 if(sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet))
4857 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4859 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
4866 gtk_sheet_button_press (GtkWidget * widget,
4867 GdkEventButton * event)
4870 GdkModifierType mods;
4871 gint x, y, row, column;
4874 g_return_val_if_fail (widget != NULL, FALSE);
4875 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
4876 g_return_val_if_fail (event != NULL, FALSE);
4878 sheet = GTK_SHEET (widget);
4880 if ( event->type == GDK_2BUTTON_PRESS)
4882 gtk_widget_get_pointer (widget, &x, &y);
4883 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4885 if (event->window == sheet->column_title_window )
4887 gtk_signal_emit (GTK_OBJECT (sheet),
4888 sheet_signals[DOUBLE_CLICK_COLUMN], column);
4890 else if (event->window == sheet->row_title_window )
4892 gtk_signal_emit (GTK_OBJECT (sheet),
4893 sheet_signals[DOUBLE_CLICK_ROW], row);
4899 if(event->type != GDK_BUTTON_PRESS) return TRUE;
4901 gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
4903 if(!(mods & GDK_BUTTON1_MASK)) return TRUE;
4906 /* press on resize windows */
4907 if (event->window == sheet->column_title_window &&
4908 gtk_sheet_columns_resizable(sheet))
4910 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
4911 if(POSSIBLE_XDRAG(sheet, sheet->x_drag, &sheet->drag_cell.col)){
4913 if (event->type == GDK_2BUTTON_PRESS){
4914 gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
4915 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_XDRAG);
4918 gtk_sheet_column_size_request(sheet, sheet->drag_cell.col, &req);
4919 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
4920 gdk_pointer_grab (sheet->column_title_window, FALSE,
4921 GDK_POINTER_MOTION_HINT_MASK |
4922 GDK_BUTTON1_MOTION_MASK |
4923 GDK_BUTTON_RELEASE_MASK,
4924 NULL, NULL, event->time);
4926 draw_xor_vline (sheet);
4931 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet))
4933 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
4935 if(POSSIBLE_YDRAG(sheet, sheet->y_drag, &sheet->drag_cell.row)){
4937 gtk_sheet_row_size_request(sheet, sheet->drag_cell.row, &req);
4938 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
4939 gdk_pointer_grab (sheet->row_title_window, FALSE,
4940 GDK_POINTER_MOTION_HINT_MASK |
4941 GDK_BUTTON1_MOTION_MASK |
4942 GDK_BUTTON_RELEASE_MASK,
4943 NULL, NULL, event->time);
4945 draw_xor_hline (sheet);
4950 /* the sheet itself does not handle other than single click events */
4951 if(event->type != GDK_BUTTON_PRESS) return FALSE;
4953 /* selections on the sheet */
4954 if(event->window == sheet->sheet_window){
4955 gtk_widget_get_pointer (widget, &x, &y);
4956 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
4957 gdk_pointer_grab (sheet->sheet_window, FALSE,
4958 GDK_POINTER_MOTION_HINT_MASK |
4959 GDK_BUTTON1_MOTION_MASK |
4960 GDK_BUTTON_RELEASE_MASK,
4961 NULL, NULL, event->time);
4962 gtk_grab_add(GTK_WIDGET(sheet));
4963 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
4964 gtk_widget_grab_focus(GTK_WIDGET(sheet));
4966 if(sheet->selection_mode != GTK_SELECTION_SINGLE &&
4967 sheet->cursor_drag->type==GDK_SIZING &&
4968 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_RESIZE(sheet)){
4969 if(sheet->state==GTK_STATE_NORMAL) {
4970 row=sheet->active_cell.row;
4971 column=sheet->active_cell.col;
4972 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
4973 sheet->active_cell.row=row;
4974 sheet->active_cell.col=column;
4975 sheet->drag_range=sheet->range;
4976 sheet->state=GTK_SHEET_RANGE_SELECTED;
4977 gtk_sheet_select_range(sheet, &sheet->drag_range);
4981 if(row > sheet->range.rowi) row--;
4982 if(column > sheet->range.coli) column--;
4983 sheet->drag_cell.row = row;
4984 sheet->drag_cell.col = column;
4985 sheet->drag_range=sheet->range;
4986 draw_xor_rectangle(sheet, sheet->drag_range);
4987 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
4989 else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW &&
4990 !GTK_SHEET_IN_SELECTION(sheet)
4991 && ! GTK_SHEET_IN_DRAG(sheet)
4992 && ! gtk_sheet_locked(sheet)
4993 && sheet->active_cell.row >= 0
4994 && sheet->active_cell.col >= 0
4997 if(sheet->state==GTK_STATE_NORMAL) {
4998 row=sheet->active_cell.row;
4999 column=sheet->active_cell.col;
5000 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
5001 sheet->active_cell.row=row;
5002 sheet->active_cell.col=column;
5003 sheet->drag_range=sheet->range;
5004 sheet->state=GTK_SHEET_RANGE_SELECTED;
5005 gtk_sheet_select_range(sheet, &sheet->drag_range);
5009 if(row < sheet->range.row0) row++;
5010 if(row > sheet->range.rowi) row--;
5011 if(column < sheet->range.col0) column++;
5012 if(column > sheet->range.coli) column--;
5013 sheet->drag_cell.row=row;
5014 sheet->drag_cell.col=column;
5015 sheet->drag_range=sheet->range;
5016 draw_xor_rectangle(sheet, sheet->drag_range);
5017 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5021 gtk_sheet_click_cell(sheet, row, column, &veto);
5022 if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5026 if(event->window == sheet->column_title_window){
5027 gtk_widget_get_pointer (widget, &x, &y);
5028 column = COLUMN_FROM_XPIXEL(sheet, x);
5029 if(xxx_column_is_sensitive(sheet, column)){
5030 gtk_sheet_click_cell(sheet, -1, column, &veto);
5031 gtk_grab_add(GTK_WIDGET(sheet));
5032 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5033 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5034 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5038 if(event->window == sheet->row_title_window){
5039 gtk_widget_get_pointer (widget, &x, &y);
5040 row = ROW_FROM_YPIXEL(sheet, y);
5041 if(yyy_row_is_sensitive(sheet, row)){
5042 gtk_sheet_click_cell(sheet, row, -1, &veto);
5043 gtk_grab_add(GTK_WIDGET(sheet));
5044 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet);
5045 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5046 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5054 gtk_sheet_scroll(gpointer data)
5057 gint x,y,row,column;
5060 sheet=GTK_SHEET(data);
5062 GDK_THREADS_ENTER();
5064 gtk_widget_get_pointer (GTK_WIDGET(sheet), &x, &y);
5065 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5069 if(GTK_SHEET_IN_SELECTION(sheet))
5070 gtk_sheet_extend_selection(sheet, row, column);
5072 if(GTK_SHEET_IN_DRAG(sheet) || GTK_SHEET_IN_RESIZE(sheet)){
5073 move=gtk_sheet_move_query(sheet, row, column);
5074 if(move) draw_xor_rectangle(sheet, sheet->drag_range);
5077 GDK_THREADS_LEAVE();
5084 gtk_sheet_click_cell(GtkSheet *sheet, gint row, gint column, gboolean *veto)
5088 if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)){
5093 if(column >= 0 && row >= 0)
5094 if(! xxx_column_is_visible(sheet, column) || !yyy_row_is_visible(sheet, row))
5100 _gtkextra_signal_emit(GTK_OBJECT(sheet), sheet_signals[TRAVERSE],
5101 sheet->active_cell.row, sheet->active_cell.col,
5102 &row, &column, veto);
5105 if(sheet->state == GTK_STATE_NORMAL) return;
5107 row = sheet->active_cell.row;
5108 column = sheet->active_cell.col;
5110 gtk_sheet_activate_cell(sheet, row, column);
5114 if(row == -1 && column >= 0){
5115 if(gtk_sheet_autoscroll(sheet))
5116 gtk_sheet_move_query(sheet, row, column);
5117 gtk_sheet_select_column(sheet, column);
5120 if(column == -1 && row >= 0){
5121 if(gtk_sheet_autoscroll(sheet))
5122 gtk_sheet_move_query(sheet, row, column);
5123 gtk_sheet_select_row(sheet, row);
5127 if(row==-1 && column ==-1){
5128 sheet->range.row0=0;
5129 sheet->range.col0=0;
5130 sheet->range.rowi = yyy_row_count(sheet) - 1;
5131 sheet->range.coli = xxx_column_count(sheet) - 1;
5132 sheet->active_cell.row=0;
5133 sheet->active_cell.col=0;
5134 gtk_sheet_select_range(sheet, NULL);
5138 if(row!=-1 && column !=-1){
5139 if(sheet->state != GTK_SHEET_NORMAL){
5140 sheet->state = GTK_SHEET_NORMAL;
5141 gtk_sheet_real_unselect_range(sheet, NULL);
5145 if(!gtk_sheet_deactivate_cell(sheet)){
5151 if(gtk_sheet_autoscroll(sheet))
5152 gtk_sheet_move_query(sheet, row, column);
5153 sheet->active_cell.row=row;
5154 sheet->active_cell.col=column;
5155 sheet->selection_cell.row=row;
5156 sheet->selection_cell.col=column;
5157 sheet->range.row0=row;
5158 sheet->range.col0=column;
5159 sheet->range.rowi=row;
5160 sheet->range.coli=column;
5161 sheet->state=GTK_SHEET_NORMAL;
5162 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5163 gtk_sheet_draw_active_cell(sheet);
5167 g_assert_not_reached();
5168 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5169 sheet->active_cell.col);
5173 gtk_sheet_button_release (GtkWidget * widget,
5174 GdkEventButton * event)
5179 sheet=GTK_SHEET(widget);
5181 /* release on resize windows */
5182 if (GTK_SHEET_IN_XDRAG (sheet)){
5183 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
5184 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5185 gtk_widget_get_pointer (widget, &x, NULL);
5186 gdk_pointer_ungrab (event->time);
5187 draw_xor_vline (sheet);
5189 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col, new_column_width (sheet, sheet->drag_cell.col, &x));
5190 sheet->old_hadjustment = -1.;
5191 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed");
5195 if (GTK_SHEET_IN_YDRAG (sheet)){
5196 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
5197 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
5198 gtk_widget_get_pointer (widget, NULL, &y);
5199 gdk_pointer_ungrab (event->time);
5200 draw_xor_hline (sheet);
5202 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
5203 sheet->old_vadjustment = -1.;
5204 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed");
5209 if (GTK_SHEET_IN_DRAG(sheet)){
5210 GtkSheetRange old_range;
5211 draw_xor_rectangle(sheet, sheet->drag_range);
5212 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
5213 gdk_pointer_ungrab (event->time);
5215 gtk_sheet_real_unselect_range(sheet, NULL);
5217 sheet->active_cell.row = sheet->active_cell.row +
5218 (sheet->drag_range.row0 - sheet->range.row0);
5219 sheet->active_cell.col = sheet->active_cell.col +
5220 (sheet->drag_range.col0 - sheet->range.col0);
5221 sheet->selection_cell.row = sheet->selection_cell.row +
5222 (sheet->drag_range.row0 - sheet->range.row0);
5223 sheet->selection_cell.col = sheet->selection_cell.col +
5224 (sheet->drag_range.col0 - sheet->range.col0);
5225 old_range=sheet->range;
5226 sheet->range=sheet->drag_range;
5227 sheet->drag_range=old_range;
5228 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[MOVE_RANGE],
5229 &sheet->drag_range, &sheet->range);
5230 gtk_sheet_select_range(sheet, &sheet->range);
5233 if (GTK_SHEET_IN_RESIZE(sheet)){
5234 GtkSheetRange old_range;
5235 draw_xor_rectangle(sheet, sheet->drag_range);
5236 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
5237 gdk_pointer_ungrab (event->time);
5239 gtk_sheet_real_unselect_range(sheet, NULL);
5241 sheet->active_cell.row = sheet->active_cell.row +
5242 (sheet->drag_range.row0 - sheet->range.row0);
5243 sheet->active_cell.col = sheet->active_cell.col +
5244 (sheet->drag_range.col0 - sheet->range.col0);
5245 if(sheet->drag_range.row0 < sheet->range.row0)
5246 sheet->selection_cell.row = sheet->drag_range.row0;
5247 if(sheet->drag_range.rowi >= sheet->range.rowi)
5248 sheet->selection_cell.row = sheet->drag_range.rowi;
5249 if(sheet->drag_range.col0 < sheet->range.col0)
5250 sheet->selection_cell.col = sheet->drag_range.col0;
5251 if(sheet->drag_range.coli >= sheet->range.coli)
5252 sheet->selection_cell.col = sheet->drag_range.coli;
5253 old_range = sheet->range;
5254 sheet->range = sheet->drag_range;
5255 sheet->drag_range = old_range;
5257 if(sheet->state==GTK_STATE_NORMAL) sheet->state=GTK_SHEET_RANGE_SELECTED;
5258 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[RESIZE_RANGE],
5259 &sheet->drag_range, &sheet->range);
5260 gtk_sheet_select_range(sheet, &sheet->range);
5263 if(sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)){
5264 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5265 gdk_pointer_ungrab (event->time);
5266 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5267 sheet->active_cell.col);
5270 if(GTK_SHEET_IN_SELECTION)
5271 gdk_pointer_ungrab (event->time);
5273 gtk_timeout_remove(sheet->timer);
5274 gtk_grab_remove(GTK_WIDGET(sheet));
5276 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5282 gtk_sheet_motion (GtkWidget * widget,
5283 GdkEventMotion * event)
5286 GdkModifierType mods;
5287 GdkCursorType new_cursor;
5288 gint x, y, row, column;
5290 g_return_val_if_fail (widget != NULL, FALSE);
5291 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
5292 g_return_val_if_fail (event != NULL, FALSE);
5295 sheet = GTK_SHEET (widget);
5297 /* selections on the sheet */
5301 if(event->window == sheet->column_title_window && gtk_sheet_columns_resizable(sheet)){
5302 gtk_widget_get_pointer(widget, &x, &y);
5303 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_XDRAG(sheet, x, &column)){
5304 new_cursor=GDK_SB_H_DOUBLE_ARROW;
5305 if(new_cursor != sheet->cursor_drag->type){
5306 gdk_cursor_destroy(sheet->cursor_drag);
5307 sheet->cursor_drag=gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
5308 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5311 new_cursor=GDK_TOP_LEFT_ARROW;
5312 if(!GTK_SHEET_IN_XDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5313 gdk_cursor_destroy(sheet->cursor_drag);
5314 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5315 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag);
5320 if(event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet)){
5321 gtk_widget_get_pointer(widget, &x, &y);
5322 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_YDRAG(sheet,y, &column)){
5323 new_cursor=GDK_SB_V_DOUBLE_ARROW;
5324 if(new_cursor != sheet->cursor_drag->type){
5325 gdk_cursor_destroy(sheet->cursor_drag);
5326 sheet->cursor_drag=gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
5327 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5330 new_cursor=GDK_TOP_LEFT_ARROW;
5331 if(!GTK_SHEET_IN_YDRAG(sheet) && new_cursor != sheet->cursor_drag->type){
5332 gdk_cursor_destroy(sheet->cursor_drag);
5333 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5334 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag);
5339 new_cursor=GDK_PLUS;
5340 if(!POSSIBLE_DRAG(sheet,x,y,&row,&column) && !GTK_SHEET_IN_DRAG(sheet) &&
5341 !POSSIBLE_RESIZE(sheet,x,y,&row,&column) && !GTK_SHEET_IN_RESIZE(sheet) &&
5342 event->window == sheet->sheet_window &&
5343 new_cursor != sheet->cursor_drag->type){
5344 gdk_cursor_destroy(sheet->cursor_drag);
5345 sheet->cursor_drag=gdk_cursor_new(GDK_PLUS);
5346 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5349 new_cursor=GDK_TOP_LEFT_ARROW;
5350 if(!(POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5351 (POSSIBLE_DRAG(sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG(sheet)) &&
5352 event->window == sheet->sheet_window &&
5353 new_cursor != sheet->cursor_drag->type){
5354 gdk_cursor_destroy(sheet->cursor_drag);
5355 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW);
5356 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5359 new_cursor=GDK_SIZING;
5360 if(!GTK_SHEET_IN_DRAG(sheet) &&
5361 (POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) &&
5362 event->window == sheet->sheet_window &&
5363 new_cursor != sheet->cursor_drag->type){
5364 gdk_cursor_destroy(sheet->cursor_drag);
5365 sheet->cursor_drag=gdk_cursor_new(GDK_SIZING);
5366 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag);
5369 gdk_window_get_pointer (widget->window, &x, &y, &mods);
5370 if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
5372 if (GTK_SHEET_IN_XDRAG (sheet)){
5373 if (event->is_hint || event->window != widget->window)
5374 gtk_widget_get_pointer (widget, &x, NULL);
5378 new_column_width (sheet, sheet->drag_cell.col, &x);
5379 if (x != sheet->x_drag)
5381 draw_xor_vline (sheet);
5383 draw_xor_vline (sheet);
5388 if (GTK_SHEET_IN_YDRAG (sheet)){
5389 if (event->is_hint || event->window != widget->window)
5390 gtk_widget_get_pointer (widget, NULL, &y);
5394 new_row_height (sheet, sheet->drag_cell.row, &y);
5395 if (y != sheet->y_drag)
5397 draw_xor_hline (sheet);
5399 draw_xor_hline (sheet);
5404 if (GTK_SHEET_IN_DRAG(sheet)){
5406 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col;
5407 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row;
5408 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5409 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5413 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5414 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5415 aux=sheet->drag_range;
5416 sheet->drag_range.row0=sheet->range.row0+row;
5417 sheet->drag_range.col0=sheet->range.col0+column;
5418 sheet->drag_range.rowi=sheet->range.rowi+row;
5419 sheet->drag_range.coli=sheet->range.coli+column;
5420 if(aux.row0 != sheet->drag_range.row0 ||
5421 aux.col0 != sheet->drag_range.col0){
5422 draw_xor_rectangle (sheet, aux);
5423 draw_xor_rectangle (sheet, sheet->drag_range);
5429 if (GTK_SHEET_IN_RESIZE(sheet)){
5431 gint v_h, current_col, current_row, col_threshold, row_threshold;
5434 if(abs(x-COLUMN_LEFT_XPIXEL(sheet,sheet->drag_cell.col)) >
5435 abs(y-ROW_TOP_YPIXEL(sheet,sheet->drag_cell.row))) v_h=2;
5437 current_col = COLUMN_FROM_XPIXEL(sheet,x);
5438 current_row = ROW_FROM_YPIXEL(sheet,y);
5439 column = current_col-sheet->drag_cell.col;
5440 row = current_row-sheet->drag_cell.row;
5442 /*use half of column width resp. row height as threshold to expand selection*/
5443 col_threshold = COLUMN_LEFT_XPIXEL(sheet,current_col)+xxx_column_width (sheet,current_col)/2;
5445 if (x < col_threshold)
5448 else if (column < 0){
5449 if (x > col_threshold)
5452 row_threshold = ROW_TOP_YPIXEL(sheet,current_row)+yyy_row_height (sheet, current_row)/2;
5454 if(y < row_threshold)
5458 if(y > row_threshold)
5462 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0;
5463 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0;
5473 if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
5474 aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
5476 aux=sheet->drag_range;
5477 sheet->drag_range=sheet->range;
5479 if(row<0) sheet->drag_range.row0=sheet->range.row0+row;
5480 if(row>0) sheet->drag_range.rowi=sheet->range.rowi+row;
5481 if(column<0) sheet->drag_range.col0=sheet->range.col0+column;
5482 if(column>0) sheet->drag_range.coli=sheet->range.coli+column;
5484 if(aux.row0 != sheet->drag_range.row0 ||
5485 aux.rowi != sheet->drag_range.rowi ||
5486 aux.col0 != sheet->drag_range.col0 ||
5487 aux.coli != sheet->drag_range.coli){
5488 draw_xor_rectangle (sheet, aux);
5489 draw_xor_rectangle (sheet, sheet->drag_range);
5497 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column);
5499 if(sheet->state==GTK_SHEET_NORMAL && row==sheet->active_cell.row &&
5500 column==sheet->active_cell.col) return TRUE;
5502 if(GTK_SHEET_IN_SELECTION(sheet) && mods&GDK_BUTTON1_MASK)
5503 gtk_sheet_extend_selection(sheet, row, column);
5509 gtk_sheet_move_query(GtkSheet *sheet, gint row, gint column)
5511 gint row_move, column_move;
5512 gfloat row_align, col_align;
5513 guint height, width;
5515 gint new_col = column;
5522 height = sheet->sheet_window_height;
5523 width = sheet->sheet_window_width;
5525 if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5527 new_row = MIN(yyy_row_count(sheet), row + 1);
5529 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet) - 1 &&
5530 ROW_TOP_YPIXEL(sheet, yyy_row_count(sheet)-1) +
5531 yyy_row_height(sheet, yyy_row_count(sheet)-1) < height){
5536 if(row<MIN_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
5540 if(column>=MAX_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5542 new_col = MIN(xxx_column_count(sheet) - 1, column + 1);
5544 if(MAX_VISIBLE_COLUMN(sheet) == (xxx_column_count(sheet) - 1) &&
5545 COLUMN_LEFT_XPIXEL(sheet, xxx_column_count(sheet) - 1) +
5546 xxx_column_width(sheet, xxx_column_count(sheet) - 1) < width)
5548 column_move = FALSE;
5552 if(column<MIN_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) {
5557 if(row_move || column_move){
5558 gtk_sheet_moveto(sheet, new_row, new_col, row_align, col_align);
5561 return(row_move || column_move);
5565 gtk_sheet_extend_selection(GtkSheet *sheet, gint row, gint column)
5567 GtkSheetRange range;
5571 if(row == sheet->selection_cell.row && column == sheet->selection_cell.col)
5574 if(sheet->selection_mode == GTK_SELECTION_SINGLE) return;
5576 gtk_sheet_move_query(sheet, row, column);
5577 gtk_widget_grab_focus(GTK_WIDGET(sheet));
5579 if(GTK_SHEET_IN_DRAG(sheet)) return;
5583 switch(sheet->state){
5584 case GTK_SHEET_ROW_SELECTED:
5585 column = xxx_column_count(sheet) - 1;
5587 case GTK_SHEET_COLUMN_SELECTED:
5588 row = yyy_row_count(sheet) - 1;
5590 case GTK_SHEET_NORMAL:
5591 sheet->state=GTK_SHEET_RANGE_SELECTED;
5592 r=sheet->active_cell.row;
5593 c=sheet->active_cell.col;
5594 sheet->range.col0=c;
5595 sheet->range.row0=r;
5596 sheet->range.coli=c;
5597 sheet->range.rowi=r;
5598 gdk_draw_pixmap(sheet->sheet_window,
5599 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
5601 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5602 ROW_TOP_YPIXEL(sheet,r)-1,
5603 COLUMN_LEFT_XPIXEL(sheet,c)-1,
5604 ROW_TOP_YPIXEL(sheet,r)-1,
5605 xxx_column_width(sheet, c)+4,
5606 yyy_row_height(sheet, r)+4);
5607 gtk_sheet_range_draw_selection(sheet, sheet->range);
5608 case GTK_SHEET_RANGE_SELECTED:
5609 sheet->state=GTK_SHEET_RANGE_SELECTED;
5612 sheet->selection_cell.row = row;
5613 sheet->selection_cell.col = column;
5615 range.col0=MIN(column,sheet->active_cell.col);
5616 range.coli=MAX(column,sheet->active_cell.col);
5617 range.row0=MIN(row,sheet->active_cell.row);
5618 range.rowi=MAX(row,sheet->active_cell.row);
5620 if(range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi ||
5621 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli ||
5622 state==GTK_SHEET_NORMAL)
5623 gtk_sheet_real_select_range(sheet, &range);
5628 gtk_sheet_entry_key_press(GtkWidget *widget,
5632 gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", key, &focus);
5637 gtk_sheet_key_press(GtkWidget *widget,
5643 gboolean extend_selection = FALSE;
5644 gboolean force_move = FALSE;
5645 gboolean in_selection = FALSE;
5646 gboolean veto = TRUE;
5649 sheet = GTK_SHEET(widget);
5651 if(key->state & GDK_CONTROL_MASK || key->keyval==GDK_Control_L ||
5652 key->keyval==GDK_Control_R) return FALSE;
5656 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL)
5657 gtk_sheet_clip_range(sheet, sheet->range);
5658 if(key->keyval=='x' || key->keyval == 'X')
5659 gtk_sheet_unclip_range(sheet);
5664 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval==GDK_Shift_L
5665 || key->keyval==GDK_Shift_R;
5668 in_selection = GTK_SHEET_IN_SELECTION(sheet);
5669 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5671 switch(key->keyval){
5672 case GDK_Return: case GDK_KP_Enter:
5673 if(sheet->state == GTK_SHEET_NORMAL &&
5674 !GTK_SHEET_IN_SELECTION(sheet))
5675 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
5677 row = sheet->active_cell.row;
5678 col = sheet->active_cell.col;
5679 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5680 row = MIN_VISIBLE_ROW(sheet)-1;
5681 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5682 col = MIN_VISIBLE_COLUMN(sheet);
5683 if(row < yyy_row_count(sheet) - 1){
5685 while(!yyy_row_is_visible(sheet, row) && row<yyy_row_count(sheet)-1)
5688 gtk_sheet_click_cell(sheet, row, col, &veto);
5689 extend_selection = FALSE;
5691 case GDK_ISO_Left_Tab:
5692 row = sheet->active_cell.row;
5693 col = sheet->active_cell.col;
5694 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5695 col = MIN_VISIBLE_COLUMN(sheet)-1;
5696 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5697 row = MIN_VISIBLE_ROW(sheet);
5700 while(! xxx_column_is_visible(sheet, col) && col>0) col--;
5703 gtk_sheet_click_cell(sheet, row, col, &veto);
5704 extend_selection = FALSE;
5707 row = sheet->active_cell.row;
5708 col = sheet->active_cell.col;
5709 if(sheet->state == GTK_SHEET_ROW_SELECTED)
5710 col = MIN_VISIBLE_COLUMN(sheet)-1;
5711 if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
5712 row = MIN_VISIBLE_ROW(sheet);
5713 if(col < xxx_column_count(sheet) - 1)
5716 while(! xxx_column_is_visible(sheet, col) &&
5717 col < xxx_column_count(sheet) - 1)
5720 gtk_sheet_click_cell(sheet, row, col, &veto);
5721 extend_selection = FALSE;
5723 /* case GDK_BackSpace:
5724 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){
5725 if(sheet->active_cell.col > 0){
5726 col = sheet->active_cell.col - scroll;
5727 row = sheet->active_cell.row;
5728 while(!sheet->column[col].is_visible && col > 0) col--;
5731 gtk_sheet_click_cell(sheet, row, col, &veto);
5732 extend_selection = FALSE;
5736 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5738 if(extend_selection){
5739 if(state==GTK_STATE_NORMAL){
5740 row=sheet->active_cell.row;
5741 col=sheet->active_cell.col;
5742 gtk_sheet_click_cell(sheet, row, col, &veto);
5745 if(sheet->selection_cell.row > 0){
5746 row = sheet->selection_cell.row - scroll;
5747 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5749 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5753 col = sheet->active_cell.col;
5754 row = sheet->active_cell.row;
5755 if(state==GTK_SHEET_COLUMN_SELECTED)
5756 row = MIN_VISIBLE_ROW(sheet);
5757 if(state==GTK_SHEET_ROW_SELECTED)
5758 col = MIN_VISIBLE_COLUMN(sheet);
5760 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5762 gtk_sheet_click_cell(sheet, row, col, &veto);
5763 extend_selection = FALSE;
5766 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1;
5768 if(extend_selection){
5769 if(state==GTK_STATE_NORMAL){
5770 row=sheet->active_cell.row;
5771 col=sheet->active_cell.col;
5772 gtk_sheet_click_cell(sheet, row, col, &veto);
5775 if(sheet->selection_cell.row < yyy_row_count(sheet)-1){
5776 row = sheet->selection_cell.row + scroll;
5777 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5778 row = MIN(yyy_row_count(sheet)-1, row);
5779 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
5783 col = sheet->active_cell.col;
5784 row = sheet->active_cell.row;
5785 if(sheet->active_cell.row < yyy_row_count(sheet)-1){
5786 if(state==GTK_SHEET_COLUMN_SELECTED)
5787 row = MIN_VISIBLE_ROW(sheet)-1;
5788 if(state==GTK_SHEET_ROW_SELECTED)
5789 col = MIN_VISIBLE_COLUMN(sheet);
5791 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5792 row = MIN(yyy_row_count(sheet)-1, row);
5794 gtk_sheet_click_cell(sheet, row, col, &veto);
5795 extend_selection = FALSE;
5798 if(extend_selection){
5799 if(state==GTK_STATE_NORMAL){
5800 row=sheet->active_cell.row;
5801 col=sheet->active_cell.col;
5802 gtk_sheet_click_cell(sheet, row, col, &veto);
5805 if(sheet->selection_cell.col < xxx_column_count(sheet) - 1)
5807 col = sheet->selection_cell.col + 1;
5808 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1)
5810 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5814 col = sheet->active_cell.col;
5815 row = sheet->active_cell.row;
5816 if(sheet->active_cell.col < xxx_column_count(sheet) - 1){
5818 if(state==GTK_SHEET_ROW_SELECTED)
5819 col = MIN_VISIBLE_COLUMN(sheet)-1;
5820 if(state==GTK_SHEET_COLUMN_SELECTED)
5821 row = MIN_VISIBLE_ROW(sheet);
5822 while(! xxx_column_is_visible(sheet, col) && col < xxx_column_count(sheet) - 1) col++;
5823 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5825 gtk_sheet_click_cell(sheet, row, col, &veto);
5830 extend_selection = FALSE;
5833 if(extend_selection){
5834 if(state==GTK_STATE_NORMAL){
5835 row=sheet->active_cell.row;
5836 col=sheet->active_cell.col;
5837 gtk_sheet_click_cell(sheet, row, col, &veto);
5840 if(sheet->selection_cell.col > 0){
5841 col = sheet->selection_cell.col - 1;
5842 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5843 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
5847 col = sheet->active_cell.col - 1;
5848 row = sheet->active_cell.row;
5849 if(state==GTK_SHEET_ROW_SELECTED)
5850 col = MIN_VISIBLE_COLUMN(sheet)-1;
5851 if(state==GTK_SHEET_COLUMN_SELECTED)
5852 row = MIN_VISIBLE_ROW(sheet);
5853 while(! xxx_column_is_visible(sheet, col) && col > 0) col--;
5856 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0
5858 gtk_sheet_click_cell(sheet, row, col, &veto);
5862 extend_selection = FALSE;
5866 while(!yyy_row_is_visible(sheet, row) && row < yyy_row_count(sheet)-1) row++;
5867 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5868 extend_selection = FALSE;
5871 row=yyy_row_count(sheet)-1;
5872 while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
5873 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto);
5874 extend_selection = FALSE;
5878 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
5879 if(extend_selection) return TRUE;
5881 if(state == GTK_SHEET_ROW_SELECTED)
5882 sheet->active_cell.col=MIN_VISIBLE_COLUMN(sheet);
5883 if(state == GTK_SHEET_COLUMN_SELECTED)
5884 sheet->active_cell.row=MIN_VISIBLE_ROW(sheet);
5888 if(extend_selection) return TRUE;
5890 gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
5891 sheet->active_cell.col);
5897 gtk_sheet_size_request (GtkWidget * widget,
5898 GtkRequisition * requisition)
5902 GtkSheetChild *child;
5903 GtkRequisition child_requisition;
5905 g_return_if_fail (widget != NULL);
5906 g_return_if_fail (GTK_IS_SHEET (widget));
5907 g_return_if_fail (requisition != NULL);
5909 sheet = GTK_SHEET (widget);
5911 requisition->width = 3*DEFAULT_COLUMN_WIDTH;
5912 requisition->height = 3*DEFAULT_ROW_HEIGHT(widget);
5914 /* compute the size of the column title area */
5915 if(sheet->column_titles_visible)
5916 requisition->height += sheet->column_title_area.height;
5918 /* compute the size of the row title area */
5919 if(sheet->row_titles_visible)
5920 requisition->width += sheet->row_title_area.width;
5922 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
5923 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
5924 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
5925 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
5927 if(!sheet->column_titles_visible)
5928 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
5930 if(!sheet->row_titles_visible)
5931 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
5933 children = sheet->children;
5936 child = children->data;
5937 children = children->next;
5939 gtk_widget_size_request(child->widget, &child_requisition);
5945 gtk_sheet_size_allocate (GtkWidget * widget,
5946 GtkAllocation * allocation)
5949 GtkAllocation sheet_allocation;
5952 g_return_if_fail (widget != NULL);
5953 g_return_if_fail (GTK_IS_SHEET (widget));
5954 g_return_if_fail (allocation != NULL);
5956 sheet = GTK_SHEET (widget);
5957 widget->allocation = *allocation;
5958 border_width = GTK_CONTAINER(widget)->border_width;
5960 if (GTK_WIDGET_REALIZED (widget))
5961 gdk_window_move_resize (widget->window,
5962 allocation->x + border_width,
5963 allocation->y + border_width,
5964 allocation->width - 2*border_width,
5965 allocation->height - 2*border_width);
5967 /* use internal allocation structure for all the math
5968 * because it's easier than always subtracting the container
5970 sheet->internal_allocation.x = 0;
5971 sheet->internal_allocation.y = 0;
5972 sheet->internal_allocation.width = allocation->width - 2*border_width;
5973 sheet->internal_allocation.height = allocation->height - 2*border_width;
5975 sheet_allocation.x = 0;
5976 sheet_allocation.y = 0;
5977 sheet_allocation.width = allocation->width - 2*border_width;
5978 sheet_allocation.height = allocation->height - 2*border_width;
5980 sheet->sheet_window_width = sheet_allocation.width;
5981 sheet->sheet_window_height = sheet_allocation.height;
5983 if (GTK_WIDGET_REALIZED (widget))
5984 gdk_window_move_resize (sheet->sheet_window,
5987 sheet_allocation.width,
5988 sheet_allocation.height);
5990 /* position the window which holds the column title buttons */
5991 sheet->column_title_area.x = 0;
5992 sheet->column_title_area.y = 0;
5993 if(sheet->row_titles_visible)
5994 sheet->column_title_area.x = sheet->row_title_area.width;
5995 sheet->column_title_area.width = sheet_allocation.width -
5996 sheet->column_title_area.x;
5997 if(GTK_WIDGET_REALIZED(widget) && sheet->column_titles_visible)
5998 gdk_window_move_resize (sheet->column_title_window,
5999 sheet->column_title_area.x,
6000 sheet->column_title_area.y,
6001 sheet->column_title_area.width,
6002 sheet->column_title_area.height);
6004 sheet->sheet_window_width = sheet_allocation.width;
6005 sheet->sheet_window_height = sheet_allocation.height;
6007 /* column button allocation */
6008 size_allocate_column_title_buttons (sheet);
6010 /* position the window which holds the row title buttons */
6011 sheet->row_title_area.x = 0;
6012 sheet->row_title_area.y = 0;
6013 if(sheet->column_titles_visible)
6014 sheet->row_title_area.y = sheet->column_title_area.height;
6015 sheet->row_title_area.height = sheet_allocation.height -
6016 sheet->row_title_area.y;
6018 if(GTK_WIDGET_REALIZED(widget) && sheet->row_titles_visible)
6019 gdk_window_move_resize (sheet->row_title_window,
6020 sheet->row_title_area.x,
6021 sheet->row_title_area.y,
6022 sheet->row_title_area.width,
6023 sheet->row_title_area.height);
6026 /* row button allocation */
6027 size_allocate_row_title_buttons (sheet);
6029 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6030 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6031 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6032 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6034 if(!sheet->column_titles_visible)
6035 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6037 if(!sheet->row_titles_visible)
6038 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6040 size_allocate_column_title_buttons(sheet);
6041 size_allocate_row_title_buttons(sheet);
6043 /* re-scale backing pixmap */
6044 gtk_sheet_make_backing_pixmap(sheet, 0, 0);
6045 gtk_sheet_position_children(sheet);
6047 /* set the scrollbars adjustments */
6048 adjust_scrollbars (sheet);
6052 size_allocate_column_title_buttons (GtkSheet * sheet)
6057 if (!sheet->column_titles_visible) return;
6058 if (!GTK_WIDGET_REALIZED (sheet))
6061 width = sheet->sheet_window_width;
6064 if(sheet->row_titles_visible)
6066 width -= sheet->row_title_area.width;
6067 x = sheet->row_title_area.width;
6070 if(sheet->column_title_area.width != width || sheet->column_title_area.x != x)
6072 sheet->column_title_area.width = width;
6073 sheet->column_title_area.x = x;
6074 gdk_window_move_resize (sheet->column_title_window,
6075 sheet->column_title_area.x,
6076 sheet->column_title_area.y,
6077 sheet->column_title_area.width,
6078 sheet->column_title_area.height);
6082 if(MAX_VISIBLE_COLUMN(sheet) == xxx_column_count(sheet) - 1)
6083 gdk_window_clear_area (sheet->column_title_window,
6085 sheet->column_title_area.width,
6086 sheet->column_title_area.height);
6088 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6090 for (i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++)
6091 gtk_sheet_button_draw(sheet,-1,i);
6095 size_allocate_row_title_buttons (GtkSheet * sheet)
6100 if (!sheet->row_titles_visible) return;
6101 if (!GTK_WIDGET_REALIZED (sheet))
6104 height = sheet->sheet_window_height;
6107 if(sheet->column_titles_visible)
6109 height -= sheet->column_title_area.height;
6110 y = sheet->column_title_area.height;
6113 if(sheet->row_title_area.height != height || sheet->row_title_area.y != y)
6115 sheet->row_title_area.y = y;
6116 sheet->row_title_area.height = height;
6117 gdk_window_move_resize (sheet->row_title_window,
6118 sheet->row_title_area.x,
6119 sheet->row_title_area.y,
6120 sheet->row_title_area.width,
6121 sheet->row_title_area.height);
6123 if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet)-1)
6124 gdk_window_clear_area (sheet->row_title_window,
6126 sheet->row_title_area.width,
6127 sheet->row_title_area.height);
6129 if(!GTK_WIDGET_DRAWABLE(sheet)) return;
6131 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++)
6132 gtk_sheet_button_draw(sheet,i,-1);
6137 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
6139 GtkAllocation shentry_allocation;
6140 GtkSheetCellAttr attributes = { 0 };
6141 GtkEntry *sheet_entry;
6142 GtkStyle *style = NULL, *previous_style = NULL;
6144 gint size, max_size, text_size, column_width;
6147 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6148 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return;
6150 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
6152 gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes);
6154 if(GTK_WIDGET_REALIZED(sheet->sheet_entry))
6157 if(!GTK_WIDGET(sheet_entry)->style)
6158 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry));
6160 previous_style = GTK_WIDGET(sheet_entry)->style;
6162 style = gtk_style_copy(previous_style);
6163 style->bg[GTK_STATE_NORMAL] = attributes.background;
6164 style->fg[GTK_STATE_NORMAL] = attributes.foreground;
6165 style->text[GTK_STATE_NORMAL] = attributes.foreground;
6166 style->bg[GTK_STATE_ACTIVE] = attributes.background;
6167 style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
6168 style->text[GTK_STATE_ACTIVE] = attributes.foreground;
6170 pango_font_description_free(style->font_desc);
6171 style->font_desc = pango_font_description_copy(attributes.font_desc);
6173 GTK_WIDGET(sheet_entry)->style = style;
6174 gtk_widget_size_request(sheet->sheet_entry, NULL);
6175 GTK_WIDGET(sheet_entry)->style = previous_style;
6177 if(style != previous_style){
6178 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6179 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
6180 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
6181 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
6182 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
6184 gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
6188 if(GTK_IS_ITEM_ENTRY(sheet_entry))
6189 max_size = GTK_ITEM_ENTRY(sheet_entry)->text_max_size;
6194 text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
6195 if(text && strlen(text) > 0){
6196 text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
6199 column_width=xxx_column_width(sheet, sheet->active_cell.col);
6201 size=MIN(text_size, max_size);
6202 size=MAX(size,column_width-2*CELLOFFSET);
6204 row=sheet->active_cell.row;
6205 col=sheet->active_cell.col;
6207 shentry_allocation.x = COLUMN_LEFT_XPIXEL(sheet,sheet->active_cell.col);
6208 shentry_allocation.y = ROW_TOP_YPIXEL(sheet,sheet->active_cell.row);
6209 shentry_allocation.width = column_width;
6210 shentry_allocation.height = yyy_row_height(sheet, sheet->active_cell.row);
6212 if(GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
6214 shentry_allocation.height -= 2*CELLOFFSET;
6215 shentry_allocation.y += CELLOFFSET;
6216 if(gtk_sheet_clip_text(sheet))
6217 shentry_allocation.width = column_width - 2*CELLOFFSET;
6219 shentry_allocation.width = size;
6221 switch(GTK_ITEM_ENTRY(sheet_entry)->justification){
6222 case GTK_JUSTIFY_CENTER:
6223 shentry_allocation.x += (column_width)/2 - size/2;
6225 case GTK_JUSTIFY_RIGHT:
6226 shentry_allocation.x += column_width - size - CELLOFFSET;
6228 case GTK_JUSTIFY_LEFT:
6229 case GTK_JUSTIFY_FILL:
6230 shentry_allocation.x += CELLOFFSET;
6236 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry))
6238 shentry_allocation.x += 2;
6239 shentry_allocation.y += 2;
6240 shentry_allocation.width -= MIN(shentry_allocation.width, 3);
6241 shentry_allocation.height -= MIN(shentry_allocation.height, 3);
6244 gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation);
6246 if(previous_style == style) gtk_style_unref(previous_style);
6250 gtk_sheet_entry_set_max_size(GtkSheet *sheet)
6254 gint sizel=0, sizer=0;
6256 GtkJustification justification;
6259 row=sheet->active_cell.row;
6260 col=sheet->active_cell.col;
6262 if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry) || gtk_sheet_clip_text(sheet)) return;
6264 justification = GTK_ITEM_ENTRY(sheet->sheet_entry)->justification;
6266 switch(justification){
6267 case GTK_JUSTIFY_FILL:
6268 case GTK_JUSTIFY_LEFT:
6269 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6270 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6275 size+=xxx_column_width(sheet, i);
6277 size = MIN(size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL(sheet, col));
6279 case GTK_JUSTIFY_RIGHT:
6280 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--)
6282 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6287 size+=xxx_column_width(sheet, i);
6290 case GTK_JUSTIFY_CENTER:
6291 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
6292 /* if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6298 sizer+=xxx_column_width(sheet, i);
6300 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--)
6302 if((s = gtk_sheet_cell_get_text(sheet, row, i)))
6307 sizel+=xxx_column_width(sheet, i);
6309 size=2*MIN(sizel, sizer);
6314 size += xxx_column_width(sheet, col);
6315 GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size = size;
6319 create_sheet_entry(GtkSheet *sheet)
6324 gint found_entry = FALSE;
6326 widget = GTK_WIDGET(sheet);
6328 if(sheet->sheet_entry){
6329 /* avoids warnings */
6330 gtk_widget_ref(sheet->sheet_entry);
6331 gtk_widget_unparent(sheet->sheet_entry);
6332 gtk_widget_destroy(sheet->sheet_entry);
6335 if(sheet->entry_type){
6337 if(!g_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY)){
6339 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6341 sheet->sheet_entry = parent;
6343 entry = gtk_sheet_get_entry (sheet);
6344 if(GTK_IS_ENTRY(entry)) found_entry = TRUE;
6348 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type));
6356 g_warning ("Entry type must be GtkEntry subclass, using default");
6357 entry = gtk_item_entry_new();
6358 sheet->sheet_entry = entry;
6362 sheet->sheet_entry = parent;
6369 entry = gtk_item_entry_new();
6370 sheet->sheet_entry = entry;
6374 gtk_widget_size_request(sheet->sheet_entry, NULL);
6376 if(GTK_WIDGET_REALIZED(sheet))
6378 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window);
6379 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet));
6380 gtk_widget_realize(sheet->sheet_entry);
6383 gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event",
6384 (GtkSignalFunc) gtk_sheet_entry_key_press,
6387 gtk_widget_show (sheet->sheet_entry);
6391 /* Finds the last child widget that happens to be of type GtkEntry */
6393 find_entry(GtkWidget *w, gpointer user_data)
6395 GtkWidget **entry = user_data;
6396 if ( GTK_IS_ENTRY(w))
6403 gtk_sheet_get_entry(GtkSheet *sheet)
6406 GtkWidget *entry = NULL;
6407 GtkTableChild *table_child;
6408 GtkBoxChild *box_child;
6409 GList *children = NULL;
6411 g_return_val_if_fail (sheet != NULL, NULL);
6412 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6413 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6415 if(GTK_IS_ENTRY(sheet->sheet_entry)) return (sheet->sheet_entry);
6417 parent = GTK_WIDGET(sheet->sheet_entry);
6419 if(GTK_IS_TABLE(parent)) children = GTK_TABLE(parent)->children;
6420 if(GTK_IS_BOX(parent)) children = GTK_BOX(parent)->children;
6422 if(GTK_IS_CONTAINER(parent))
6424 gtk_container_forall(GTK_CONTAINER(parent), find_entry, &entry);
6426 if(GTK_IS_ENTRY(entry))
6430 if(!children) return NULL;
6433 if(GTK_IS_TABLE(parent)) {
6434 table_child = children->data;
6435 entry = table_child->widget;
6437 if(GTK_IS_BOX(parent)){
6438 box_child = children->data;
6439 entry = box_child->widget;
6442 if(GTK_IS_ENTRY(entry))
6444 children = children->next;
6448 if(!GTK_IS_ENTRY(entry)) return NULL;
6455 gtk_sheet_get_entry_widget(GtkSheet *sheet)
6457 g_return_val_if_fail (sheet != NULL, NULL);
6458 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
6459 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL);
6461 return (sheet->sheet_entry);
6467 row_button_set (GtkSheet *sheet, gint row)
6469 if(sheet->row[row].button.state == GTK_STATE_ACTIVE) return;
6471 sheet->row[row].button.state = GTK_STATE_ACTIVE;
6472 gtk_sheet_button_draw(sheet, row, -1);
6477 row_button_release (GtkSheet *sheet, gint row)
6479 if(sheet->row[row].button.state == GTK_STATE_NORMAL) return;
6481 sheet->row[row].button.state = GTK_STATE_NORMAL;
6482 gtk_sheet_button_draw(sheet, row, -1);
6487 gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
6489 GdkWindow *window = NULL;
6490 GtkShadowType shadow_type;
6491 guint width = 0, height = 0;
6494 gint text_width = 0, text_height = 0;
6495 GtkSheetButton *button = NULL;
6496 GtkSheetChild *child = NULL;
6497 GdkRectangle allocation;
6498 gboolean is_sensitive = FALSE;
6503 PangoAlignment align = PANGO_ALIGN_LEFT;
6506 rtl = gtk_widget_get_direction(GTK_WIDGET(sheet)) == GTK_TEXT_DIR_RTL;
6508 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
6510 if(row >= 0 && !yyy_row_is_visible(sheet, row)) return;
6511 if(column >= 0 && ! xxx_column_is_visible(sheet, column)) return;
6512 if(row >= 0 && !sheet->row_titles_visible) return;
6513 if(column >= 0 && !sheet->column_titles_visible) return;
6514 if(column>=0 && column < MIN_VISIBLE_COLUMN(sheet)) return;
6515 if(column>=0 && column > MAX_VISIBLE_COLUMN(sheet)) return;
6516 if(row>=0 && row < MIN_VISIBLE_ROW(sheet)) return;
6517 if(row>=0 && row > MAX_VISIBLE_ROW(sheet)) return;
6518 if( (row == -1) && (column == -1) ) return;
6521 window=sheet->column_title_window;
6522 button= xxx_column_button(sheet, column);
6524 x = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING;
6525 if(sheet->row_titles_visible) x -= sheet->row_title_area.width;
6527 width = xxx_column_width(sheet, column);
6528 height = sheet->column_title_area.height;
6529 is_sensitive=xxx_column_is_sensitive(sheet, column);
6532 window=sheet->row_title_window;
6533 button = yyy_row_button(sheet, row);
6536 y = ROW_TOP_YPIXEL(sheet, row)+CELL_SPACING;
6537 if(sheet->column_titles_visible) y-=sheet->column_title_area.height;
6538 width = sheet->row_title_area.width;
6539 height = yyy_row_height(sheet, row);
6540 is_sensitive=yyy_row_is_sensitive(sheet, row);
6545 allocation.width = width;
6546 allocation.height = height;
6548 gdk_window_clear_area (window,
6552 gtk_paint_box (sheet->button->style, window,
6553 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
6554 &allocation, GTK_WIDGET(sheet->button),
6555 "buttondefault", x, y, width, height);
6557 state = button->state;
6558 if(!is_sensitive) state=GTK_STATE_INSENSITIVE;
6560 if (state == GTK_STATE_ACTIVE)
6561 shadow_type = GTK_SHADOW_IN;
6563 shadow_type = GTK_SHADOW_OUT;
6565 if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
6566 gtk_paint_box (sheet->button->style, window,
6567 button->state, shadow_type,
6568 &allocation, GTK_WIDGET(sheet->button),
6569 "button", x, y, width, height);
6571 if(button->label_visible){
6573 text_height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))-2*CELLOFFSET;
6575 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6577 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation);
6579 y += 2*sheet->button->style->ythickness;
6582 if(button->label && strlen(button->label)>0){
6584 PangoLayout *layout = NULL;
6585 gint real_x = x, real_y = y;
6587 words=button->label;
6588 line = g_new(gchar, 1);
6591 while(words && *words != '\0'){
6594 line=g_realloc(line, len+2);
6598 if(*words == '\n' || *(words+1) == '\0'){
6599 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, line);
6601 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), line);
6602 switch(button->justification){
6603 case GTK_JUSTIFY_LEFT:
6604 real_x = x + CELLOFFSET;
6605 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6607 case GTK_JUSTIFY_RIGHT:
6608 real_x = x + width - text_width - CELLOFFSET;
6609 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
6611 case GTK_JUSTIFY_CENTER:
6613 real_x = x + (width - text_width)/2;
6614 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
6615 pango_layout_set_justify (layout, TRUE);
6617 pango_layout_set_alignment (layout, align);
6618 gtk_paint_layout (GTK_WIDGET(sheet)->style,
6627 g_object_unref(G_OBJECT(layout));
6629 real_y += text_height + 2;
6632 line = g_new(gchar, 1);
6640 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
6642 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, NULL);
6646 if((child = button->child) && (child->widget)){
6647 child->x = allocation.x;
6648 child->y = allocation.y;
6650 child->x += (width - child->widget->requisition.width) / 2;
6651 child->y += (height - child->widget->requisition.height) / 2;
6652 allocation.x = child->x;
6653 allocation.y = child->y;
6654 allocation.width = child->widget->requisition.width;
6655 allocation.height = child->widget->requisition.height;
6660 gtk_widget_set_state(child->widget, button->state);
6662 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
6663 GTK_WIDGET_MAPPED(child->widget))
6665 gtk_widget_size_allocate(child->widget,
6667 gtk_widget_queue_draw(child->widget);
6671 gtk_sheet_button_free(button);
6680 * vadjustment_changed
6681 * hadjustment_changed
6682 * vadjustment_value_changed
6683 * hadjustment_value_changed */
6686 adjust_scrollbars (GtkSheet * sheet)
6689 if(sheet->vadjustment){
6690 sheet->vadjustment->page_size = sheet->sheet_window_height;
6691 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
6692 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
6693 sheet->vadjustment->lower = 0;
6694 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
6696 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet))
6698 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) -
6699 sheet->sheet_window_height);
6700 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
6704 gtk_signal_emit_by_name (GTK_OBJECT(sheet->vadjustment), "changed");
6708 if(sheet->hadjustment){
6709 sheet->hadjustment->page_size = sheet->sheet_window_width;
6710 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
6711 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
6712 sheet->hadjustment->lower = 0;
6713 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
6715 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet))
6717 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) -
6718 sheet->sheet_window_width);
6719 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment),
6723 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), "changed");
6727 if(GTK_WIDGET_REALIZED(sheet))
6729 if(sheet->row_titles_visible){
6730 size_allocate_row_title_buttons(sheet);
6731 gdk_window_show(sheet->row_title_window);
6734 if(sheet->column_titles_visible){
6735 size_allocate_column_title_buttons(sheet);
6736 gdk_window_show(sheet->column_title_window);
6739 gtk_sheet_range_draw(sheet, NULL);
6746 vadjustment_changed (GtkAdjustment * adjustment,
6751 g_return_if_fail (adjustment != NULL);
6752 g_return_if_fail (data != NULL);
6754 sheet = GTK_SHEET (data);
6759 hadjustment_changed (GtkAdjustment * adjustment,
6764 g_return_if_fail (adjustment != NULL);
6765 g_return_if_fail (data != NULL);
6767 sheet = GTK_SHEET (data);
6772 vadjustment_value_changed (GtkAdjustment * adjustment,
6776 gint diff, value, old_value;
6780 g_return_if_fail (adjustment != NULL);
6781 g_return_if_fail (data != NULL);
6782 g_return_if_fail (GTK_IS_SHEET (data));
6784 sheet = GTK_SHEET (data);
6786 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6788 row=ROW_FROM_YPIXEL(sheet,sheet->column_title_area.height + CELL_SPACING);
6789 if(!sheet->column_titles_visible)
6790 row=ROW_FROM_YPIXEL(sheet,CELL_SPACING);
6792 old_value = -sheet->voffset;
6794 new_row = g_sheet_row_pixel_to_row(sheet->row_geometry,
6795 adjustment->value,sheet);
6797 y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
6799 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
6800 yyy_row_height(sheet, row) > sheet->vadjustment->step_increment){
6801 /* This avoids embarrassing twitching */
6802 if(row == new_row && row != yyy_row_count(sheet) - 1 &&
6803 adjustment->value - sheet->old_vadjustment >=
6804 sheet->vadjustment->step_increment &&
6805 new_row + 1 != MIN_VISIBLE_ROW(sheet)){
6807 y=y+yyy_row_height(sheet, row);
6811 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6812 if(sheet->old_vadjustment >= 0. && row == new_row){
6813 sheet->old_vadjustment = sheet->vadjustment->value;
6817 sheet->old_vadjustment = sheet->vadjustment->value;
6818 adjustment->value=y;
6822 sheet->vadjustment->step_increment= yyy_row_height(sheet, 0);
6824 sheet->vadjustment->step_increment=
6825 MIN(yyy_row_height(sheet, new_row), yyy_row_height(sheet, new_row-1));
6828 sheet->vadjustment->value=adjustment->value;
6830 value = adjustment->value;
6832 if (value >= -sheet->voffset)
6835 diff = value + sheet->voffset;
6840 diff = -sheet->voffset - value;
6843 sheet->voffset = -value;
6845 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
6846 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
6847 if(!sheet->column_titles_visible)
6848 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1);
6850 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6851 sheet->state == GTK_SHEET_NORMAL &&
6852 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6853 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6854 sheet->active_cell.col))
6858 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6860 if(!text || strlen(text)==0)
6861 gtk_sheet_cell_clear(sheet,
6862 sheet->active_cell.row,
6863 sheet->active_cell.col);
6864 gtk_widget_unmap(sheet->sheet_entry);
6867 gtk_sheet_position_children(sheet);
6869 gtk_sheet_range_draw(sheet, NULL);
6870 size_allocate_row_title_buttons(sheet);
6871 size_allocate_global_button(sheet);
6875 hadjustment_value_changed (GtkAdjustment * adjustment,
6879 gint i, diff, value, old_value;
6880 gint column, new_column;
6883 g_return_if_fail (adjustment != NULL);
6884 g_return_if_fail (data != NULL);
6885 g_return_if_fail (GTK_IS_SHEET (data));
6887 sheet = GTK_SHEET (data);
6889 if(GTK_SHEET_IS_FROZEN(sheet)) return;
6891 column=COLUMN_FROM_XPIXEL(sheet,sheet->row_title_area.width + CELL_SPACING);
6892 if(!sheet->row_titles_visible)
6893 column=COLUMN_FROM_XPIXEL(sheet, CELL_SPACING);
6895 old_value = -sheet->hoffset;
6897 for(i=0; i < xxx_column_count(sheet); i++)
6899 if(xxx_column_is_visible(sheet, i)) x += xxx_column_width(sheet, i);
6900 if(x > adjustment->value) break;
6902 x-=xxx_column_width(sheet, i);
6905 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
6906 xxx_column_width(sheet, i) > sheet->hadjustment->step_increment){
6907 /* This avoids embarrassing twitching */
6908 if(column == new_column && column != xxx_column_count(sheet) - 1 &&
6909 adjustment->value - sheet->old_hadjustment >=
6910 sheet->hadjustment->step_increment &&
6911 new_column + 1 != MIN_VISIBLE_COLUMN(sheet)){
6913 x=x+xxx_column_width(sheet, column);
6917 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6918 if(sheet->old_hadjustment >= 0. && new_column == column){
6919 sheet->old_hadjustment = sheet->hadjustment->value;
6923 sheet->old_hadjustment = sheet->hadjustment->value;
6924 adjustment->value=x;
6926 if(new_column == 0){
6927 sheet->hadjustment->step_increment=
6928 xxx_column_width(sheet, 0);
6930 sheet->hadjustment->step_increment=
6931 MIN(xxx_column_width(sheet, new_column), xxx_column_width(sheet, new_column-1));
6935 sheet->hadjustment->value=adjustment->value;
6937 value = adjustment->value;
6939 if (value >= -sheet->hoffset)
6942 diff = value + sheet->hoffset;
6947 diff = -sheet->hoffset - value;
6950 sheet->hoffset = -value;
6952 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
6953 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
6954 if(!sheet->row_titles_visible)
6955 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1);
6957 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) &&
6958 sheet->state == GTK_SHEET_NORMAL &&
6959 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
6960 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row,
6961 sheet->active_cell.col))
6965 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
6966 if(!text || strlen(text)==0)
6967 gtk_sheet_cell_clear(sheet,
6968 sheet->active_cell.row,
6969 sheet->active_cell.col);
6971 gtk_widget_unmap(sheet->sheet_entry);
6974 gtk_sheet_position_children(sheet);
6976 gtk_sheet_range_draw(sheet, NULL);
6977 size_allocate_column_title_buttons(sheet);
6981 /* COLUMN RESIZING */
6983 draw_xor_vline (GtkSheet * sheet)
6987 g_return_if_fail (sheet != NULL);
6989 widget = GTK_WIDGET (sheet);
6991 gdk_draw_line (widget->window, sheet->xor_gc,
6993 sheet->column_title_area.height,
6995 sheet->sheet_window_height + 1);
7000 draw_xor_hline (GtkSheet * sheet)
7004 g_return_if_fail (sheet != NULL);
7006 widget = GTK_WIDGET (sheet);
7008 gdk_draw_line (widget->window, sheet->xor_gc,
7009 sheet->row_title_area.width,
7012 sheet->sheet_window_width + 1,
7016 /* SELECTED RANGE */
7018 draw_xor_rectangle(GtkSheet *sheet, GtkSheetRange range)
7021 GdkRectangle clip_area, area;
7024 area.x=COLUMN_LEFT_XPIXEL(sheet, range.col0);
7025 area.y=ROW_TOP_YPIXEL(sheet, range.row0);
7026 area.width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-area.x+
7027 xxx_column_width(sheet, range.coli);
7028 area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+
7029 yyy_row_height(sheet, range.rowi);
7031 clip_area.x=sheet->row_title_area.width;
7032 clip_area.y=sheet->column_title_area.height;
7033 clip_area.width=sheet->sheet_window_width;
7034 clip_area.height=sheet->sheet_window_height;
7036 if(!sheet->row_titles_visible) clip_area.x = 0;
7037 if(!sheet->column_titles_visible) clip_area.y = 0;
7040 area.width=area.width+area.x;
7043 if(area.width>clip_area.width) area.width=clip_area.width+10;
7045 area.height=area.height+area.y;
7048 if(area.height>clip_area.height) area.height=clip_area.height+10;
7053 clip_area.height+=3;
7055 gdk_gc_get_values(sheet->xor_gc, &values);
7057 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
7060 gdk_draw_rectangle(sheet->sheet_window,
7064 area.width-2*i, area.height-2*i);
7067 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL);
7069 gdk_gc_set_foreground(sheet->xor_gc, &values.foreground);
7074 /* this function returns the new width of the column being resized given
7075 * the column and x position of the cursor; the x cursor position is passed
7076 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7078 new_column_width (GtkSheet * sheet,
7087 min_width = sheet->column_requisition;
7089 /* you can't shrink a column to less than its minimum width */
7090 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
7092 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
7095 /* don't grow past the end of the window */
7097 if (cx > sheet->sheet_window_width)
7099 *x = cx = sheet->sheet_window_width;
7102 /* calculate new column width making sure it doesn't end up
7103 * less than the minimum width */
7104 width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
7105 if (width < min_width)
7108 xxx_set_column_width(sheet, column, width);
7109 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
7110 size_allocate_column_title_buttons (sheet);
7115 /* this function returns the new height of the row being resized given
7116 * the row and y position of the cursor; the y cursor position is passed
7117 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
7119 new_row_height (GtkSheet * sheet,
7127 min_height = sheet->row_requisition;
7129 /* you can't shrink a row to less than its minimum height */
7130 if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
7133 *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
7136 /* don't grow past the end of the window */
7138 if (cy > sheet->sheet_window_height)
7140 *y = cy = sheet->sheet_window_height;
7143 /* calculate new row height making sure it doesn't end up
7144 * less than the minimum height */
7145 height = (cy - ROW_TOP_YPIXEL (sheet, row));
7146 if (height < min_height)
7147 height = min_height;
7149 yyy_set_row_height(sheet, row, height);
7150 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
7151 size_allocate_row_title_buttons (sheet);
7157 gtk_sheet_set_column_width (GtkSheet * sheet,
7163 g_return_if_fail (sheet != NULL);
7164 g_return_if_fail (GTK_IS_SHEET (sheet));
7166 if (column < 0 || column >= xxx_column_count(sheet))
7169 gtk_sheet_column_size_request(sheet, column, &min_width);
7170 if(width < min_width) return;
7172 xxx_set_column_width(sheet, column, width);
7174 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7175 size_allocate_column_title_buttons (sheet);
7176 adjust_scrollbars (sheet);
7177 gtk_sheet_size_allocate_entry(sheet);
7178 gtk_sheet_range_draw (sheet, NULL);
7181 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, column);
7182 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_COL_WIDTH], column, width);
7189 gtk_sheet_set_row_height (GtkSheet * sheet,
7195 g_return_if_fail (sheet != NULL);
7196 g_return_if_fail (GTK_IS_SHEET (sheet));
7198 if (row < 0 || row >= yyy_row_count(sheet))
7201 gtk_sheet_row_size_request(sheet, row, &min_height);
7202 if(height < min_height) return;
7204 yyy_set_row_height(sheet, row, height);
7206 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){
7207 size_allocate_row_title_buttons (sheet);
7208 adjust_scrollbars (sheet);
7209 gtk_sheet_size_allocate_entry(sheet);
7210 gtk_sheet_range_draw (sheet, NULL);
7213 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], row, -1);
7214 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_ROW_HEIGHT], row, height);
7220 gtk_sheet_get_attributes(const GtkSheet *sheet, gint row, gint col,
7221 GtkSheetCellAttr *attributes)
7223 const GdkColor *fg, *bg;
7224 const GtkJustification *j ;
7225 const PangoFontDescription *font_desc ;
7226 const GtkSheetCellBorder *border ;
7228 g_return_val_if_fail (sheet != NULL, FALSE);
7229 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
7231 if(row < 0 || col < 0) return FALSE;
7233 init_attributes(sheet, col, attributes);
7238 attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
7239 attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
7241 fg = g_sheet_model_get_foreground(sheet->model, row, col);
7243 attributes->foreground = *fg;
7245 bg = g_sheet_model_get_background(sheet->model, row, col);
7247 attributes->background = *bg;
7249 j = g_sheet_model_get_justification(sheet->model, row, col);
7250 if (j) attributes->justification = *j;
7252 font_desc = g_sheet_model_get_font_desc(sheet->model, row, col);
7253 if ( font_desc ) attributes->font_desc = font_desc;
7255 border = g_sheet_model_get_cell_border(sheet->model, row, col);
7257 if ( border ) attributes->border = *border;
7263 init_attributes(const GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
7265 /* DEFAULT VALUES */
7266 attributes->foreground = GTK_WIDGET(sheet)->style->black;
7267 attributes->background = sheet->bg_color;
7268 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
7269 GdkColormap *colormap;
7270 colormap=gdk_colormap_get_system();
7271 gdk_color_black(colormap, &attributes->foreground);
7272 attributes->background = sheet->bg_color;
7274 attributes->justification = xxx_column_justification(sheet, col);
7275 attributes->border.width = 0;
7276 attributes->border.line_style = GDK_LINE_SOLID;
7277 attributes->border.cap_style = GDK_CAP_NOT_LAST;
7278 attributes->border.join_style = GDK_JOIN_MITER;
7279 attributes->border.mask = 0;
7280 attributes->border.color = GTK_WIDGET(sheet)->style->black;
7281 attributes->is_editable = TRUE;
7282 attributes->is_visible = TRUE;
7283 attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
7287 /********************************************************************
7288 * Container Functions:
7293 * gtk_sheet_move_child
7294 * gtk_sheet_position_child
7295 * gtk_sheet_position_children
7296 * gtk_sheet_realize_child
7297 * gtk_sheet_get_child_at
7298 ********************************************************************/
7301 gtk_sheet_put(GtkSheet *sheet, GtkWidget *child, gint x, gint y)
7303 GtkRequisition child_requisition;
7304 GtkSheetChild *child_info;
7306 g_return_val_if_fail(sheet != NULL, NULL);
7307 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7308 g_return_val_if_fail(child != NULL, NULL);
7309 g_return_val_if_fail(child->parent == NULL, NULL);
7311 child_info = g_new (GtkSheetChild, 1);
7312 child_info->widget = child;
7315 child_info->attached_to_cell = FALSE;
7316 child_info->floating = TRUE;
7317 child_info->xpadding = child_info->ypadding = 0;
7318 child_info->xexpand = child_info->yexpand = FALSE;
7319 child_info->xshrink = child_info->yshrink = FALSE;
7320 child_info->xfill = child_info->yfill = FALSE;
7322 sheet->children = g_list_append(sheet->children, child_info);
7324 gtk_widget_set_parent (child, GTK_WIDGET(sheet));
7326 gtk_widget_size_request(child, &child_requisition);
7328 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7330 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7331 (!GTK_WIDGET_REALIZED(child) || GTK_WIDGET_NO_WINDOW(child)))
7332 gtk_sheet_realize_child(sheet, child_info);
7334 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7335 !GTK_WIDGET_MAPPED(child))
7336 gtk_widget_map(child);
7339 gtk_sheet_position_child(sheet, child_info);
7341 /* This will avoid drawing on the titles */
7343 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7345 if(sheet->row_titles_visible)
7346 gdk_window_show(sheet->row_title_window);
7347 if(sheet->column_titles_visible)
7348 gdk_window_show(sheet->column_title_window);
7351 return (child_info);
7355 gtk_sheet_attach_floating (GtkSheet *sheet,
7360 GtkSheetChild *child;
7362 if(row < 0 || col < 0){
7363 gtk_sheet_button_attach(sheet, widget, row, col);
7367 gtk_sheet_get_cell_area(sheet, row, col, &area);
7368 child = gtk_sheet_put(sheet, widget, area.x, area.y);
7369 child->attached_to_cell = TRUE;
7375 gtk_sheet_attach_default (GtkSheet *sheet,
7379 if(row < 0 || col < 0){
7380 gtk_sheet_button_attach(sheet, widget, row, col);
7384 gtk_sheet_attach(sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0);
7388 gtk_sheet_attach (GtkSheet *sheet,
7397 GtkSheetChild *child = NULL;
7399 if(row < 0 || col < 0){
7400 gtk_sheet_button_attach(sheet, widget, row, col);
7404 child = g_new0(GtkSheetChild, 1);
7405 child->attached_to_cell = TRUE;
7406 child->floating = FALSE;
7407 child->widget = widget;
7410 child->xpadding = xpadding;
7411 child->ypadding = ypadding;
7412 child->xexpand = (xoptions & GTK_EXPAND) != 0;
7413 child->yexpand = (yoptions & GTK_EXPAND) != 0;
7414 child->xshrink = (xoptions & GTK_SHRINK) != 0;
7415 child->yshrink = (yoptions & GTK_SHRINK) != 0;
7416 child->xfill = (xoptions & GTK_FILL) != 0;
7417 child->yfill = (yoptions & GTK_FILL) != 0;
7419 sheet->children = g_list_append(sheet->children, child);
7421 gtk_sheet_get_cell_area(sheet, row, col, &area);
7423 child->x = area.x + child->xpadding;
7424 child->y = area.y + child->ypadding;
7426 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7428 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7429 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7430 gtk_sheet_realize_child(sheet, child);
7432 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7433 !GTK_WIDGET_MAPPED(widget))
7434 gtk_widget_map(widget);
7437 gtk_sheet_position_child(sheet, child);
7439 /* This will avoid drawing on the titles */
7441 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
7443 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
7444 gdk_window_show(sheet->row_title_window);
7445 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
7446 gdk_window_show(sheet->column_title_window);
7452 gtk_sheet_button_attach (GtkSheet *sheet,
7456 GtkSheetButton *button = 0;
7457 GtkSheetChild *child;
7458 GtkRequisition button_requisition;
7460 if(row >= 0 && col >= 0) return;
7461 if(row < 0 && col < 0) return;
7463 child = g_new (GtkSheetChild, 1);
7464 child->widget = widget;
7467 child->attached_to_cell = TRUE;
7468 child->floating = FALSE;
7471 child->xpadding = child->ypadding = 0;
7472 child->xshrink = child->yshrink = FALSE;
7473 child->xfill = child->yfill = FALSE;
7476 sheet->children = g_list_append(sheet->children, child);
7478 gtk_sheet_button_size_request(sheet, button, &button_requisition);
7481 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
7483 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) &&
7484 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget)))
7485 gtk_sheet_realize_child(sheet, child);
7487 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) &&
7488 !GTK_WIDGET_MAPPED(widget))
7489 gtk_widget_map(widget);
7492 if(row == -1) size_allocate_column_title_buttons(sheet);
7493 if(col == -1) size_allocate_row_title_buttons(sheet);
7498 label_size_request(GtkSheet *sheet, gchar *label, GtkRequisition *req)
7503 gint row_height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)) - 2*CELLOFFSET + 2;
7509 while(words && *words != '\0'){
7510 if(*words == '\n' || *(words+1) == '\0'){
7511 req->height += row_height;
7514 req->width = MAX(req->width, STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, word));
7522 if(n > 0) req->height -= 2;
7526 gtk_sheet_button_size_request (GtkSheet *sheet,
7527 const GtkSheetButton *button,
7528 GtkRequisition *button_requisition)
7530 GtkRequisition requisition;
7531 GtkRequisition label_requisition;
7533 if(gtk_sheet_autoresize(sheet) && button->label && strlen(button->label) > 0){
7534 label_size_request(sheet, button->label, &label_requisition);
7535 label_requisition.width += 2*CELLOFFSET;
7536 label_requisition.height += 2*CELLOFFSET;
7538 label_requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7539 label_requisition.width = COLUMN_MIN_WIDTH;
7544 gtk_widget_size_request(button->child->widget, &requisition);
7545 requisition.width += 2*button->child->xpadding;
7546 requisition.height += 2*button->child->ypadding;
7547 requisition.width += 2*sheet->button->style->xthickness;
7548 requisition.height += 2*sheet->button->style->ythickness;
7552 requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet));
7553 requisition.width = COLUMN_MIN_WIDTH;
7556 *button_requisition = requisition;
7557 button_requisition->width = MAX(requisition.width, label_requisition.width);
7558 button_requisition->height = MAX(requisition.height, label_requisition.height);
7563 gtk_sheet_row_size_request (GtkSheet *sheet,
7567 GtkRequisition button_requisition;
7570 gtk_sheet_button_size_request(sheet,
7571 yyy_row_button(sheet, row),
7572 &button_requisition);
7574 *requisition = button_requisition.height;
7576 children = sheet->children;
7578 GtkSheetChild *child = (GtkSheetChild *)children->data;
7579 GtkRequisition child_requisition;
7581 if(child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink){
7582 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7584 if(child_requisition.height + 2 * child->ypadding > *requisition)
7585 *requisition = child_requisition.height + 2 * child->ypadding;
7587 children = children->next;
7590 sheet->row_requisition = * requisition;
7594 gtk_sheet_column_size_request (GtkSheet *sheet,
7598 GtkRequisition button_requisition;
7601 gtk_sheet_button_size_request(sheet,
7602 xxx_column_button(sheet, col),
7603 &button_requisition);
7605 *requisition = button_requisition.width;
7607 children = sheet->children;
7609 GtkSheetChild *child = (GtkSheetChild *)children->data;
7610 GtkRequisition child_requisition;
7612 if(child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink){
7613 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7615 if(child_requisition.width + 2 * child->xpadding > *requisition)
7616 *requisition = child_requisition.width + 2 * child->xpadding;
7618 children = children->next;
7621 sheet->column_requisition = *requisition;
7625 gtk_sheet_move_child(GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
7627 GtkSheetChild *child;
7630 g_return_if_fail(sheet != NULL);
7631 g_return_if_fail(GTK_IS_SHEET(sheet));
7633 children = sheet->children;
7636 child = children->data;
7638 if(child->widget == widget){
7641 child->row = ROW_FROM_YPIXEL(sheet, y);
7642 child->col = COLUMN_FROM_XPIXEL(sheet, x);
7643 gtk_sheet_position_child(sheet, child);
7647 children = children->next;
7650 g_warning("Widget must be a GtkSheet child");
7655 gtk_sheet_position_child(GtkSheet *sheet, GtkSheetChild *child)
7657 GtkRequisition child_requisition;
7658 GtkAllocation child_allocation;
7664 gtk_widget_get_child_requisition(child->widget, &child_requisition);
7666 if(sheet->column_titles_visible)
7667 yoffset = sheet->column_title_area.height;
7669 if(sheet->row_titles_visible)
7670 xoffset = sheet->row_title_area.width;
7672 if(child->attached_to_cell){
7674 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col);
7675 child->y = ROW_TOP_YPIXEL(sheet, child->row);
7677 if(sheet->row_titles_visible)
7678 child->x-=sheet->row_title_area.width;
7679 if(sheet->column_titles_visible)
7680 child->y-=sheet->column_title_area.height;
7682 width = xxx_column_width(sheet, child->col);
7683 height = yyy_row_height(sheet, child->row);
7686 gtk_sheet_get_cell_area(sheet, child->row, child->col, &area);
7687 child->x = area.x + child->xpadding;
7688 child->y = area.y + child->ypadding;
7690 if(!child->floating){
7691 if(child_requisition.width + 2*child->xpadding <= xxx_column_width(sheet, child->col)){
7693 child_requisition.width = child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7696 child->x = area.x + xxx_column_width(sheet, child->col) / 2 -
7697 child_requisition.width / 2;
7699 child_allocation.width = child_requisition.width;
7702 if(!child->xshrink){
7703 gtk_sheet_set_column_width(sheet, child->col, child_requisition.width + 2 * child->xpadding);
7705 child_allocation.width = xxx_column_width(sheet, child->col) - 2*child->xpadding;
7708 if(child_requisition.height + 2*child->ypadding <= yyy_row_height(sheet, child->row)){
7710 child_requisition.height = child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7713 child->y = area.y + yyy_row_height(sheet, child->row) / 2 -
7714 child_requisition.height / 2;
7716 child_allocation.height = child_requisition.height;
7719 if(!child->yshrink){
7720 gtk_sheet_set_row_height(sheet, child->row, child_requisition.height + 2 * child->ypadding);
7722 child_allocation.height = yyy_row_height(sheet, child->row) - 2*child->ypadding;
7725 child_allocation.width = child_requisition.width;
7726 child_allocation.height = child_requisition.height;
7729 x = child_allocation.x = child->x + xoffset;
7730 y = child_allocation.y = child->y + yoffset;
7734 x = child_allocation.x = child->x + sheet->hoffset + xoffset;
7735 x = child_allocation.x = child->x + xoffset;
7736 y = child_allocation.y = child->y + sheet->voffset + yoffset;
7737 y = child_allocation.y = child->y + yoffset;
7738 child_allocation.width = child_requisition.width;
7739 child_allocation.height = child_requisition.height;
7742 gtk_widget_size_allocate(child->widget, &child_allocation);
7743 gtk_widget_queue_draw(child->widget);
7747 gtk_sheet_forall (GtkContainer *container,
7748 gboolean include_internals,
7749 GtkCallback callback,
7750 gpointer callback_data)
7753 GtkSheetChild *child;
7756 g_return_if_fail (GTK_IS_SHEET (container));
7757 g_return_if_fail (callback != NULL);
7759 sheet = GTK_SHEET (container);
7760 children = sheet->children;
7763 child = children->data;
7764 children = children->next;
7766 (* callback) (child->widget, callback_data);
7769 (* callback) (sheet->button, callback_data);
7770 if(sheet->sheet_entry)
7771 (* callback) (sheet->sheet_entry, callback_data);
7776 gtk_sheet_position_children(GtkSheet *sheet)
7779 GtkSheetChild *child;
7781 children = sheet->children;
7785 child = (GtkSheetChild *)children->data;
7787 if(child->col !=-1 && child->row != -1)
7788 gtk_sheet_position_child(sheet, child);
7790 if(child->row == -1){
7791 if(child->col < MIN_VISIBLE_COLUMN(sheet) ||
7792 child->col > MAX_VISIBLE_COLUMN(sheet))
7793 gtk_sheet_child_hide(child);
7795 gtk_sheet_child_show(child);
7797 if(child->col == -1){
7798 if(child->row < MIN_VISIBLE_ROW(sheet) ||
7799 child->row > MAX_VISIBLE_ROW(sheet))
7800 gtk_sheet_child_hide(child);
7802 gtk_sheet_child_show(child);
7805 children = children->next;
7811 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
7815 GtkSheetChild *child = 0;
7817 g_return_if_fail(container != NULL);
7818 g_return_if_fail(GTK_IS_SHEET(container));
7820 sheet = GTK_SHEET(container);
7822 children = sheet->children;
7826 child = (GtkSheetChild *)children->data;
7828 if(child->widget == widget) break;
7830 children = children->next;
7835 gtk_widget_unparent (widget);
7836 child->widget = NULL;
7838 sheet->children = g_list_remove_link (sheet->children, children);
7839 g_list_free_1 (children);
7846 gtk_sheet_realize_child(GtkSheet *sheet, GtkSheetChild *child)
7850 widget = GTK_WIDGET(sheet);
7852 if(GTK_WIDGET_REALIZED(widget)){
7853 if(child->row == -1)
7854 gtk_widget_set_parent_window(child->widget, sheet->column_title_window);
7855 else if(child->col == -1)
7856 gtk_widget_set_parent_window(child->widget, sheet->row_title_window);
7858 gtk_widget_set_parent_window(child->widget, sheet->sheet_window);
7861 gtk_widget_set_parent(child->widget, widget);
7867 gtk_sheet_get_child_at(GtkSheet *sheet, gint row, gint col)
7870 GtkSheetChild *child = 0;
7872 g_return_val_if_fail(sheet != NULL, NULL);
7873 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL);
7875 children = sheet->children;
7879 child = (GtkSheetChild *)children->data;
7881 if(child->attached_to_cell)
7882 if(child->row == row && child->col == col) break;
7884 children = children->next;
7887 if(children) return child;
7893 gtk_sheet_child_hide(GtkSheetChild *child)
7895 g_return_if_fail(child != NULL);
7896 gtk_widget_hide(child->widget);
7900 gtk_sheet_child_show(GtkSheetChild *child)
7902 g_return_if_fail(child != NULL);
7904 gtk_widget_show(child->widget);
7908 gtk_sheet_get_model(const GtkSheet *sheet)
7910 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
7912 return sheet->model;
7917 gtk_sheet_button_new(void)
7919 GtkSheetButton *button = g_malloc(sizeof(GtkSheetButton));
7921 button->state = GTK_STATE_NORMAL;
7922 button->label = NULL;
7923 button->label_visible = TRUE;
7924 button->child = NULL;
7925 button->justification = GTK_JUSTIFY_FILL;
7932 gtk_sheet_button_free(GtkSheetButton *button)
7934 g_free(button->label);