1 /* GtkSheet widget for Gtk+.
2 * Copyright (C) 1999-2001 Adrian E. Feiguin <adrian@ifir.ifir.edu.ar>
4 * Based on GtkClist widget by Jay Painter, but major changes.
5 * Memory allocation routines inspired on SC (Spreadsheet Calculator)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
37 #include <gdk/gdkkeysyms.h>
38 #include <gtk/gtksignal.h>
39 #include <gtk/gtklabel.h>
40 #include <gtk/gtkbutton.h>
41 #include <gtk/gtkadjustment.h>
42 #include <gtk/gtktable.h>
43 #include <gtk/gtkbox.h>
44 #include <gtk/gtkmain.h>
45 #include <gtk/gtktypeutils.h>
46 #include <gtk/gtkentry.h>
47 #include <gtk/gtkcontainer.h>
48 #include <gtk/gtkpixmap.h>
51 #include "gtksheet_1_2.h"
52 #include "gtkitementry_1_2.h"
55 #define CELL_SPACING 1
57 #define TIMEOUT_SCROLL 20
58 #define TIMEOUT_FLASH 200
59 #define TIME_INTERVAL 8
60 #define COLUMN_MIN_WIDTH 10
65 #define DEFAULT_COLUMN_WIDTH 80
68 #define DEFAULT_ROW_HEIGHT(widget) (widget->style->font->ascent + 2*widget->style->font->descent + 2*CELLOFFSET)
69 #define DEFAULT_LABEL_HEIGHT(widget) (widget->style->font->ascent+\
70 2*widget->style->font->descent)
71 #define DEFAULT_FONT_ASCENT(widget) (widget->style->font->ascent)
72 #define DEFAULT_FONT_DESCENT(widget) (widget->style->font->descent)
74 /*-----------------------------------------------------------------------------*/
75 /* scrollbar spacing class macro */
76 #define SCROLLBAR_SPACING(w) (GTK_SHEET_CLASS (GTK_OBJECT (w)->klass)->scrollbar_spacing)
79 /*-----------------------------------------------------------------------------*/
80 /* gives the top pixel of the given row in context of
81 * the sheet's voffset */
83 ROW_TOP_YPIXEL(GtkSheet
*sheet
, gint nrow
)
85 return (sheet
->voffset
+ sheet
->row
[nrow
].top_ypixel
);
88 /*-----------------------------------------------------------------------------*/
89 /* returns the row index from a y pixel location in the
90 * context of the sheet's voffset */
92 ROW_FROM_YPIXEL(GtkSheet
*sheet
, gint y
)
97 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
)) cy
+= sheet
->column_title_area
.height
;
99 for (i
= 0; i
<= sheet
->maxrow
; i
++)
101 if (y
>= cy
&& y
<= (cy
+ sheet
->row
[i
].height
) && sheet
->row
[i
].is_visible
)
103 if(sheet
->row
[i
].is_visible
) cy
+= sheet
->row
[i
].height
;
108 return sheet
->maxrow
;
112 /*-----------------------------------------------------------------------------*/
113 /* gives the left pixel of the given column in context of
114 * the sheet's hoffset */
116 COLUMN_LEFT_XPIXEL(GtkSheet
*sheet
, gint ncol
)
118 return (sheet
->hoffset
+ sheet
->column
[ncol
].left_xpixel
);
122 /*-----------------------------------------------------------------------------*/
123 /* returns the column index from a x pixel location in the
124 * context of the sheet's hoffset */
126 COLUMN_FROM_XPIXEL (GtkSheet
* sheet
,
132 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)) cx
+= sheet
->row_title_area
.width
;
134 for (i
= 0; i
<= sheet
->maxcol
; i
++)
136 if (x
>= cx
&& x
<= (cx
+ sheet
->column
[i
].width
) && sheet
->column
[i
].is_visible
)
138 if(sheet
->column
[i
].is_visible
) cx
+= sheet
->column
[i
].width
;
143 return sheet
->maxcol
;
147 /*-----------------------------------------------------------------------------*/
148 /* returns the total height of the sheet */
149 static inline gint
SHEET_HEIGHT(GtkSheet
*sheet
)
154 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
)) cx
+= sheet
->column_title_area
.height
;
155 for (i
=0;i
<=sheet
->maxrow
; i
++)
156 if(sheet
->row
[i
].is_visible
) cx
+= sheet
->row
[i
].height
;
162 /*-----------------------------------------------------------------------------*/
163 /* returns the total width of the sheet */
164 static inline gint
SHEET_WIDTH(GtkSheet
*sheet
)
169 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)) cx
+= sheet
->row_title_area
.width
;
170 for (i
=0;i
<=sheet
->maxcol
; i
++)
171 if(sheet
->column
[i
].is_visible
) cx
+= sheet
->column
[i
].width
;
176 #define MIN_VISIBLE_ROW(sheet) sheet->view.row0
177 #define MAX_VISIBLE_ROW(sheet) sheet->view.rowi
178 #define MIN_VISIBLE_COLUMN(sheet) sheet->view.col0
179 #define MAX_VISIBLE_COLUMN(sheet) sheet->view.coli
181 /*-----------------------------------------------------------------------------*/
183 POSSIBLE_XDRAG(GtkSheet
*sheet
, gint x
, gint
*drag_column
)
187 column
=COLUMN_FROM_XPIXEL(sheet
, x
);
190 xdrag
=COLUMN_LEFT_XPIXEL(sheet
,column
)+CELL_SPACING
;
191 if(x
<= xdrag
+DRAG_WIDTH
/2 && column
!= 0){
192 while(!sheet
->column
[column
-1].is_visible
&& column
>0) column
--;
193 *drag_column
=column
-1;
194 return sheet
->column
[column
-1].is_sensitive
;
197 xdrag
+=sheet
->column
[column
].width
;
198 if(x
>= xdrag
-DRAG_WIDTH
/2 && x
<= xdrag
+DRAG_WIDTH
/2)
199 return sheet
->column
[column
].is_sensitive
;
205 /*-----------------------------------------------------------------------------*/
207 POSSIBLE_YDRAG(GtkSheet
*sheet
, gint y
, gint
*drag_row
)
211 row
=ROW_FROM_YPIXEL(sheet
, y
);
214 ydrag
=ROW_TOP_YPIXEL(sheet
,row
)+CELL_SPACING
;
215 if(y
<= ydrag
+DRAG_WIDTH
/2 && row
!= 0){
216 while(!sheet
->row
[row
-1].is_visible
&& row
>0) row
--;
218 return sheet
->row
[row
-1].is_sensitive
;
221 ydrag
+=sheet
->row
[row
].height
;
223 if(y
>= ydrag
-DRAG_WIDTH
/2 && y
<= ydrag
+DRAG_WIDTH
/2)
224 return sheet
->row
[row
].is_sensitive
;
231 /*-----------------------------------------------------------------------------*/
232 static inline gint
POSSIBLE_DRAG(GtkSheet
*sheet
, gint x
, gint y
,
233 gint
*drag_row
, gint
*drag_column
)
237 *drag_column
=COLUMN_FROM_XPIXEL(sheet
,x
);
238 *drag_row
=ROW_FROM_YPIXEL(sheet
,y
);
240 if(x
>=COLUMN_LEFT_XPIXEL(sheet
,sheet
->range
.col0
)-DRAG_WIDTH
/2 &&
241 x
<=COLUMN_LEFT_XPIXEL(sheet
,sheet
->range
.coli
)+
242 sheet
->column
[sheet
->range
.coli
].width
+DRAG_WIDTH
/2){
243 ydrag
=ROW_TOP_YPIXEL(sheet
,sheet
->range
.row0
);
244 if(y
>=ydrag
-DRAG_WIDTH
/2 && y
<=ydrag
+DRAG_WIDTH
/2){
245 *drag_row
=sheet
->range
.row0
;
248 ydrag
=ROW_TOP_YPIXEL(sheet
,sheet
->range
.rowi
)+
249 sheet
->row
[sheet
->range
.rowi
].height
;
250 if(y
>=ydrag
-DRAG_WIDTH
/2 && y
<=ydrag
+DRAG_WIDTH
/2){
251 *drag_row
=sheet
->range
.rowi
;
256 if(y
>=ROW_TOP_YPIXEL(sheet
,sheet
->range
.row0
)-DRAG_WIDTH
/2 &&
257 y
<=ROW_TOP_YPIXEL(sheet
,sheet
->range
.rowi
)+
258 sheet
->row
[sheet
->range
.rowi
].height
+DRAG_WIDTH
/2){
259 xdrag
=COLUMN_LEFT_XPIXEL(sheet
,sheet
->range
.col0
);
260 if(x
>=xdrag
-DRAG_WIDTH
/2 && x
<=xdrag
+DRAG_WIDTH
/2){
261 *drag_column
=sheet
->range
.col0
;
264 xdrag
=COLUMN_LEFT_XPIXEL(sheet
,sheet
->range
.coli
)+
265 sheet
->column
[sheet
->range
.coli
].width
;
266 if(x
>=xdrag
-DRAG_WIDTH
/2 && x
<=xdrag
+DRAG_WIDTH
/2){
267 *drag_column
=sheet
->range
.coli
;
275 /*-----------------------------------------------------------------------------*/
276 static inline gint
POSSIBLE_RESIZE(GtkSheet
*sheet
, gint x
, gint y
,
277 gint
*drag_row
, gint
*drag_column
)
281 xdrag
=COLUMN_LEFT_XPIXEL(sheet
,sheet
->range
.coli
)+
282 sheet
->column
[sheet
->range
.coli
].width
;
284 ydrag
=ROW_TOP_YPIXEL(sheet
,sheet
->range
.rowi
)+
285 sheet
->row
[sheet
->range
.rowi
].height
;
287 if(sheet
->state
== GTK_SHEET_COLUMN_SELECTED
)
288 ydrag
= ROW_TOP_YPIXEL(sheet
, sheet
->view
.row0
);
290 if(sheet
->state
== GTK_SHEET_ROW_SELECTED
)
291 xdrag
= COLUMN_LEFT_XPIXEL(sheet
, sheet
->view
.col0
);
293 *drag_column
=COLUMN_FROM_XPIXEL(sheet
,x
);
294 *drag_row
=ROW_FROM_YPIXEL(sheet
,y
);
296 if(x
>=xdrag
-DRAG_WIDTH
/2 && x
<=xdrag
+DRAG_WIDTH
/2 &&
297 y
>=ydrag
-DRAG_WIDTH
/2 && y
<=ydrag
+DRAG_WIDTH
/2) return TRUE
;
302 /*-----------------------------------------------------------------------------*/
303 /* Typedefs and function prototypes */
304 /*-----------------------------------------------------------------------------*/
305 typedef gboolean (*GtkSheetSignal1
) (GtkObject
*object
,
306 gint arg1
, gint arg2
, gint
*arg3
, gint
*arg4
,
309 typedef gboolean (*GtkSheetSignal2
) (GtkObject
*object
,
310 gint arg1
, gint arg2
,
313 static void gtk_sheet_class_init (GtkSheetClass
* klass
);
314 static void gtk_sheet_init (GtkSheet
* sheet
);
315 static void gtk_sheet_destroy (GtkObject
* object
);
316 static void gtk_sheet_finalize (GtkObject
* object
);
317 static void gtk_sheet_style_set (GtkWidget
*widget
,
318 GtkStyle
*previous_style
);
319 static void gtk_sheet_realize (GtkWidget
* widget
);
320 static void gtk_sheet_unrealize (GtkWidget
* widget
);
321 static void gtk_sheet_map (GtkWidget
* widget
);
322 static void gtk_sheet_unmap (GtkWidget
* widget
);
323 static void gtk_sheet_draw (GtkWidget
* widget
,
324 GdkRectangle
* area
);
325 static gint
gtk_sheet_expose (GtkWidget
* widget
,
326 GdkEventExpose
* event
);
327 /*static void gtk_sheet_forall (GtkContainer *container,
328 gboolean include_internals,
329 GtkCallback callback,
330 gpointer callback_data);
332 static void gtk_sheet_set_scroll_adjustments (GtkSheet
*sheet
,
333 GtkAdjustment
*hadjustment
,
334 GtkAdjustment
*vadjustment
);
336 static gint
gtk_sheet_button_press (GtkWidget
* widget
,
337 GdkEventButton
* event
);
338 static gint
gtk_sheet_button_release (GtkWidget
* widget
,
339 GdkEventButton
* event
);
340 static gint
gtk_sheet_motion (GtkWidget
* widget
,
341 GdkEventMotion
* event
);
342 static gint
gtk_sheet_entry_key_press (GtkWidget
*widget
,
344 static gint
gtk_sheet_key_press (GtkWidget
*widget
,
346 static void gtk_sheet_size_request (GtkWidget
* widget
,
347 GtkRequisition
* requisition
);
348 static void gtk_sheet_size_allocate (GtkWidget
* widget
,
349 GtkAllocation
* allocation
);
353 static gint
gtk_sheet_range_isvisible (GtkSheet
* sheet
,
354 GtkSheetRange range
);
355 static gint
gtk_sheet_cell_isvisible (GtkSheet
* sheet
,
356 gint row
, gint column
);
359 static gint
gtk_sheet_scroll (gpointer data
);
360 static gint
gtk_sheet_flash (gpointer data
);
362 /* Drawing Routines */
364 /* draw cell background and frame */
365 static void gtk_sheet_cell_draw_default (GtkSheet
*sheet
,
366 gint row
, gint column
);
368 /* draw cell border */
369 static void gtk_sheet_cell_draw_border (GtkSheet
*sheet
,
370 gint row
, gint column
,
373 /* draw cell contents */
374 static void gtk_sheet_cell_draw_label (GtkSheet
*sheet
,
375 gint row
, gint column
);
377 /* draw visible part of range. If range==NULL then draw the whole screen */
378 static void gtk_sheet_range_draw (GtkSheet
*sheet
,
379 const GtkSheetRange
*range
);
381 /* highlight the visible part of the selected range */
382 static void gtk_sheet_range_draw_selection (GtkSheet
*sheet
,
383 GtkSheetRange range
);
387 static gint
gtk_sheet_move_query (GtkSheet
*sheet
,
388 gint row
, gint column
);
389 static void gtk_sheet_real_select_range (GtkSheet
* sheet
,
390 GtkSheetRange
* range
);
391 static void gtk_sheet_real_unselect_range (GtkSheet
* sheet
,
392 const GtkSheetRange
* range
);
393 static void gtk_sheet_extend_selection (GtkSheet
*sheet
,
394 gint row
, gint column
);
395 static void gtk_sheet_new_selection (GtkSheet
*sheet
,
396 GtkSheetRange
*range
);
397 static void gtk_sheet_draw_border (GtkSheet
*sheet
,
398 GtkSheetRange range
);
399 static void gtk_sheet_draw_corners (GtkSheet
*sheet
,
400 GtkSheetRange range
);
403 /* Active Cell handling */
405 static void gtk_sheet_entry_changed (GtkWidget
*widget
,
407 static gboolean
gtk_sheet_deactivate_cell (GtkSheet
*sheet
);
408 static void gtk_sheet_hide_active_cell (GtkSheet
*sheet
);
409 static gboolean
gtk_sheet_activate_cell (GtkSheet
*sheet
,
411 static void gtk_sheet_draw_active_cell (GtkSheet
*sheet
);
412 static void gtk_sheet_show_active_cell (GtkSheet
*sheet
);
413 static void gtk_sheet_click_cell (GtkSheet
*sheet
,
420 static void gtk_sheet_make_backing_pixmap (GtkSheet
*sheet
,
421 guint width
, guint height
);
422 static void gtk_sheet_draw_backing_pixmap (GtkSheet
*sheet
,
423 GtkSheetRange range
);
426 static void adjust_scrollbars (GtkSheet
* sheet
);
427 static void vadjustment_changed (GtkAdjustment
* adjustment
,
429 static void hadjustment_changed (GtkAdjustment
* adjustment
,
431 static void vadjustment_value_changed (GtkAdjustment
* adjustment
,
433 static void hadjustment_value_changed (GtkAdjustment
* adjustment
,
437 static void draw_xor_vline (GtkSheet
* sheet
);
438 static void draw_xor_hline (GtkSheet
* sheet
);
439 static void draw_xor_rectangle (GtkSheet
*sheet
,
440 GtkSheetRange range
);
441 static void gtk_sheet_draw_flashing_range (GtkSheet
*sheet
,
442 GtkSheetRange range
);
443 static guint
new_column_width (GtkSheet
* sheet
,
446 static guint
new_row_height (GtkSheet
* sheet
,
451 static void create_global_button (GtkSheet
*sheet
);
452 static void global_button_clicked (GtkWidget
*widget
,
456 static void create_sheet_entry (GtkSheet
*sheet
);
457 static void gtk_sheet_size_allocate_entry (GtkSheet
*sheet
);
458 static void gtk_sheet_entry_set_max_size (GtkSheet
*sheet
);
460 /* Sheet button gadgets */
462 static void size_allocate_column_title_buttons (GtkSheet
* sheet
);
463 static void size_allocate_row_title_buttons (GtkSheet
* sheet
);
464 static void gtk_sheet_recalc_top_ypixels (GtkSheet
*sheet
,
466 static void gtk_sheet_recalc_left_xpixels (GtkSheet
*sheet
,
468 static void row_button_set (GtkSheet
*sheet
,
470 static void column_button_set (GtkSheet
*sheet
,
472 static void row_button_release (GtkSheet
*sheet
,
474 static void column_button_release (GtkSheet
*sheet
,
476 static void gtk_sheet_button_draw (GtkSheet
*sheet
,
477 gint row
, gint column
);
478 static void size_allocate_global_button (GtkSheet
*sheet
);
479 static void label_size_request (GtkSheet
*sheet
, gchar
*label
,
480 GtkRequisition
*req
);
481 static void gtk_sheet_button_size_request (GtkSheet
*sheet
,
482 GtkSheetButton
*button
,
483 GtkRequisition
*requisition
);
485 /* Attributes routines */
487 static void gtk_sheet_set_cell_attributes (GtkSheet
*sheet
,
489 GtkSheetCellAttr attributes
);
491 static void init_attributes (GtkSheet
*sheet
, gint col
,
492 GtkSheetCellAttr
*attributes
);
493 /* Memory allocation routines */
494 static void gtk_sheet_real_range_clear (GtkSheet
*sheet
,
495 const GtkSheetRange
*range
,
497 static void gtk_sheet_real_cell_clear (GtkSheet
*sheet
,
501 static GtkSheetCell
* gtk_sheet_cell_new (void);
502 static gint
AddRow (GtkSheet
*sheet
, gint nrows
);
503 static gint
AddColumn (GtkSheet
*sheet
, gint ncols
);
504 static gint
InsertRow (GtkSheet
*sheet
, gint row
, gint nrows
);
505 static gint
InsertColumn (GtkSheet
*sheet
, gint col
, gint ncols
);
506 static gint
DeleteRow (GtkSheet
*sheet
, gint row
, gint nrows
);
507 static gint
DeleteColumn (GtkSheet
*sheet
, gint col
, gint ncols
);
508 static gint
GrowSheet (GtkSheet
*sheet
,
509 gint newrows
, gint newcols
);
510 static gint
CheckBounds (GtkSheet
*sheet
,
513 /* Container Functions */
514 static void gtk_sheet_remove (GtkContainer
*container
,
516 static void gtk_sheet_realize_child (GtkSheet
*sheet
,
517 GtkSheetChild
*child
);
518 static void gtk_sheet_position_child (GtkSheet
*sheet
,
519 GtkSheetChild
*child
);
520 static void gtk_sheet_position_children (GtkSheet
*sheet
);
521 static void gtk_sheet_child_show (GtkSheetChild
*child
);
522 static void gtk_sheet_child_hide (GtkSheetChild
*child
);
545 gtk_sheet_marshal_BOOL__INT_INT (GtkObject
*object
,
550 gtk_sheet_marshal_BOOL__INT_INT_POINTER_POINTER (GtkObject
*object
,
555 static GtkContainerClass
*parent_class
= NULL
;
556 static guint sheet_signals
[LAST_SIGNAL
] = {0};
558 GtkType
gtk_sheet_get_type ()
560 static guint sheet_type
= 0;
562 GtkTypeInfo sheet_info
=
566 sizeof(GtkSheetClass
),
567 (GtkClassInitFunc
) gtk_sheet_class_init
,
568 (GtkObjectInitFunc
) gtk_sheet_init
,
569 /* reserved_1 */ NULL
,
570 /* reserved_2 */ NULL
,
571 (GtkClassInitFunc
) NULL
,
573 sheet_type
= gtk_type_unique (GTK_TYPE_CONTAINER
, &sheet_info
);
580 gtk_sheet_range_get_type (void)
582 static GtkType sheet_range_type
= 0;
583 if (!sheet_range_type
){
584 static const GtkTypeInfo sheet_range_info
=
589 (GtkClassInitFunc
) NULL
,
590 (GtkObjectInitFunc
) NULL
,
591 /* reserved_1 */ NULL
,
592 /* reserved_2 */ NULL
,
593 (GtkClassInitFunc
) NULL
,
595 sheet_range_type
= gtk_type_unique(GTK_TYPE_BOXED
, &sheet_range_info
);
597 return sheet_range_type
;
601 gtk_sheet_class_init (GtkSheetClass
* klass
)
604 GtkType object_class_type
; /* SDB addition for GTK-2.X */
606 GtkObjectClass
*object_class
;
607 GtkWidgetClass
*widget_class
;
608 GtkContainerClass
*container_class
;
610 object_class
= (GtkObjectClass
*) klass
;
611 widget_class
= (GtkWidgetClass
*) klass
;
612 container_class
= (GtkContainerClass
*) klass
;
614 /* This was introduced by SDB in order to enable compilation under GTK-2.X */
616 object_class_type
= object_class
->type
;
617 parent_class
= gtk_type_class (GTK_TYPE_CONTAINER
);
619 sheet_signals
[SELECT_ROW
] =
620 gtk_signal_new ("select_row",
623 GTK_SIGNAL_OFFSET (GtkSheetClass
, select_row
),
624 gtk_marshal_NONE__INT
,
625 GTK_TYPE_NONE
, 1, GTK_TYPE_INT
);
626 sheet_signals
[SELECT_COLUMN
] =
627 gtk_signal_new ("select_column",
630 GTK_SIGNAL_OFFSET (GtkSheetClass
, select_column
),
631 gtk_marshal_NONE__INT
,
632 GTK_TYPE_NONE
, 1, GTK_TYPE_INT
);
633 sheet_signals
[SELECT_RANGE
] =
634 gtk_signal_new ("select_range",
637 GTK_SIGNAL_OFFSET (GtkSheetClass
, select_range
),
638 gtk_marshal_NONE__POINTER
,
639 GTK_TYPE_NONE
, 1, GTK_TYPE_SHEET_RANGE
);
640 sheet_signals
[CLIP_RANGE
] =
641 gtk_signal_new ("clip_range",
644 GTK_SIGNAL_OFFSET (GtkSheetClass
, clip_range
),
645 gtk_marshal_NONE__POINTER
,
646 GTK_TYPE_NONE
, 1, GTK_TYPE_SHEET_RANGE
);
647 sheet_signals
[RESIZE_RANGE
] =
648 gtk_signal_new ("resize_range",
651 GTK_SIGNAL_OFFSET (GtkSheetClass
, resize_range
),
652 gtk_marshal_NONE__POINTER_POINTER
,
653 GTK_TYPE_NONE
, 2, GTK_TYPE_SHEET_RANGE
, GTK_TYPE_SHEET_RANGE
);
654 sheet_signals
[MOVE_RANGE
] =
655 gtk_signal_new ("move_range",
658 GTK_SIGNAL_OFFSET (GtkSheetClass
, move_range
),
659 gtk_marshal_NONE__POINTER_POINTER
,
660 GTK_TYPE_NONE
, 2, GTK_TYPE_SHEET_RANGE
, GTK_TYPE_SHEET_RANGE
);
662 sheet_signals
[TRAVERSE
] =
663 gtk_signal_new ("traverse",
666 GTK_SIGNAL_OFFSET (GtkSheetClass
, traverse
),
667 gtk_sheet_marshal_BOOL__INT_INT_POINTER_POINTER
,
668 GTK_TYPE_BOOL
, 4, GTK_TYPE_INT
, GTK_TYPE_INT
,
669 GTK_TYPE_POINTER
, GTK_TYPE_POINTER
);
671 sheet_signals
[DEACTIVATE
] =
672 gtk_signal_new ("deactivate",
675 GTK_SIGNAL_OFFSET (GtkSheetClass
, deactivate
),
676 gtk_sheet_marshal_BOOL__INT_INT
,
677 GTK_TYPE_BOOL
, 2, GTK_TYPE_INT
, GTK_TYPE_INT
);
679 sheet_signals
[ACTIVATE
] =
680 gtk_signal_new ("activate",
683 GTK_SIGNAL_OFFSET (GtkSheetClass
, activate
),
684 gtk_sheet_marshal_BOOL__INT_INT
,
685 GTK_TYPE_BOOL
, 2, GTK_TYPE_INT
, GTK_TYPE_INT
);
687 sheet_signals
[SET_CELL
] =
688 gtk_signal_new ("set_cell",
691 GTK_SIGNAL_OFFSET (GtkSheetClass
, set_cell
),
692 gtk_marshal_NONE__INT_INT
,
693 GTK_TYPE_NONE
, 2, GTK_TYPE_INT
, GTK_TYPE_INT
);
694 sheet_signals
[CLEAR_CELL
] =
695 gtk_signal_new ("clear_cell",
698 GTK_SIGNAL_OFFSET (GtkSheetClass
, clear_cell
),
699 gtk_marshal_NONE__INT_INT
,
700 GTK_TYPE_NONE
, 2, GTK_TYPE_INT
, GTK_TYPE_INT
);
701 sheet_signals
[CHANGED
] =
702 gtk_signal_new ("changed",
705 GTK_SIGNAL_OFFSET (GtkSheetClass
, changed
),
706 gtk_marshal_NONE__INT_INT
,
707 GTK_TYPE_NONE
, 2, GTK_TYPE_INT
, GTK_TYPE_INT
);
708 sheet_signals
[NEW_COL_WIDTH
] =
709 gtk_signal_new ("new_column_width",
712 GTK_SIGNAL_OFFSET (GtkSheetClass
, changed
),
713 gtk_marshal_NONE__INT_INT
,
714 GTK_TYPE_NONE
, 2, GTK_TYPE_INT
, GTK_TYPE_INT
);
715 sheet_signals
[NEW_ROW_HEIGHT
] =
716 gtk_signal_new ("new_row_height",
719 GTK_SIGNAL_OFFSET (GtkSheetClass
, changed
),
720 gtk_marshal_NONE__INT_INT
,
721 GTK_TYPE_NONE
, 2, GTK_TYPE_INT
, GTK_TYPE_INT
);
723 widget_class
->set_scroll_adjustments_signal
=
724 gtk_signal_new ("set_scroll_adjustments",
727 GTK_SIGNAL_OFFSET (GtkSheetClass
, set_scroll_adjustments
),
728 gtk_marshal_NONE__POINTER_POINTER
,
729 GTK_TYPE_NONE
, 2, GTK_TYPE_ADJUSTMENT
, GTK_TYPE_ADJUSTMENT
);
731 container_class
->add
= NULL
;
732 container_class
->remove
= gtk_sheet_remove
;
733 container_class
->forall
= NULL
;
735 object_class
->destroy
= gtk_sheet_destroy
;
737 widget_class
->realize
= gtk_sheet_realize
;
738 widget_class
->unrealize
= gtk_sheet_unrealize
;
739 widget_class
->map
= gtk_sheet_map
;
740 widget_class
->unmap
= gtk_sheet_unmap
;
741 widget_class
->draw
= gtk_sheet_draw
;
742 widget_class
->style_set
= gtk_sheet_style_set
;
743 widget_class
->button_press_event
= gtk_sheet_button_press
;
744 widget_class
->button_release_event
= gtk_sheet_button_release
;
745 widget_class
->motion_notify_event
= gtk_sheet_motion
;
746 widget_class
->key_press_event
= gtk_sheet_key_press
;
747 widget_class
->expose_event
= gtk_sheet_expose
;
748 widget_class
->size_request
= gtk_sheet_size_request
;
749 widget_class
->size_allocate
= gtk_sheet_size_allocate
;
750 widget_class
->focus_in_event
= NULL
;
751 widget_class
->focus_out_event
= NULL
;
753 klass
->set_scroll_adjustments
= gtk_sheet_set_scroll_adjustments
;
754 klass
->select_row
= NULL
;
755 klass
->select_column
= NULL
;
756 klass
->select_range
= NULL
;
757 klass
->clip_range
= NULL
;
758 klass
->resize_range
= NULL
;
759 klass
->move_range
= NULL
;
760 klass
->traverse
= NULL
;
761 klass
->deactivate
= NULL
;
762 klass
->activate
= NULL
;
763 klass
->set_cell
= NULL
;
764 klass
->clear_cell
= NULL
;
765 klass
->changed
= NULL
;
770 gtk_sheet_marshal_BOOL__INT_INT_POINTER_POINTER (GtkObject
*object
,
775 GtkSheetSignal1 rfunc
;
777 veto
= GTK_RETLOC_BOOL (args
[4]);
779 rfunc
= (GtkSheetSignal1
) func
;
781 *veto
= (*rfunc
) (object
, GTK_VALUE_INT (args
[0]),
782 GTK_VALUE_INT (args
[1]),
783 GTK_VALUE_POINTER (args
[2]),
784 GTK_VALUE_POINTER (args
[3]),
789 gtk_sheet_marshal_BOOL__INT_INT (GtkObject
*object
,
794 GtkSheetSignal2 rfunc
;
796 veto
= GTK_RETLOC_BOOL (args
[2]);
798 rfunc
= (GtkSheetSignal2
) func
;
800 *veto
= (*rfunc
) (object
, GTK_VALUE_INT (args
[0]),
801 GTK_VALUE_INT (args
[1]),
808 gtk_sheet_init (GtkSheet
*sheet
)
810 sheet
->children
= NULL
;
813 sheet
->selection_mode
= GTK_SELECTION_BROWSE
;
814 sheet
->freeze_count
= 0;
815 sheet
->state
= GTK_SHEET_NORMAL
;
817 GTK_WIDGET_UNSET_FLAGS (sheet
, GTK_NO_WINDOW
);
818 GTK_WIDGET_SET_FLAGS (sheet
, GTK_CAN_FOCUS
);
823 sheet
->view
.row0
= 0;
824 sheet
->view
.col0
= 0;
825 sheet
->view
.rowi
= 0;
826 sheet
->view
.coli
= 0;
828 sheet
->maxallocrow
= 0;
829 sheet
->maxalloccol
= 0;
831 sheet
->column_title_window
=NULL
;
832 sheet
->column_title_area
.x
=0;
833 sheet
->column_title_area
.y
=0;
834 sheet
->column_title_area
.width
=0;
835 sheet
->column_title_area
.height
=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet
));
837 sheet
->row_title_window
=NULL
;
838 sheet
->row_title_area
.x
=0;
839 sheet
->row_title_area
.y
=0;
840 sheet
->row_title_area
.width
=DEFAULT_COLUMN_WIDTH
;
841 sheet
->row_title_area
.height
=0;
843 sheet
->active_cell
.row
=0;
844 sheet
->active_cell
.col
=0;
845 sheet
->selection_cell
.row
=0;
846 sheet
->selection_cell
.col
=0;
848 sheet
->sheet_entry
=NULL
;
856 sheet
->state
=GTK_SHEET_NORMAL
;
858 sheet
->sheet_window
= NULL
;
859 sheet
->sheet_window_width
= 0;
860 sheet
->sheet_window_height
= 0;
861 sheet
->sheet_entry
= NULL
;
862 sheet
->button
= NULL
;
867 sheet
->hadjustment
= NULL
;
868 sheet
->vadjustment
= NULL
;
870 sheet
->cursor_drag
= gdk_cursor_new(GDK_PLUS
);
871 sheet
->xor_gc
= NULL
;
877 gdk_color_white(gdk_colormap_get_system(), &sheet
->bg_color
);
878 gdk_color_parse("gray", &sheet
->grid_color
);
879 gdk_color_alloc(gdk_colormap_get_system(), &sheet
->grid_color
);
880 sheet
->show_grid
= TRUE
;
884 gtk_sheet_new (guint rows
, guint columns
, const gchar
*title
)
889 g_return_val_if_fail(columns
>= MINCOLS
, NULL
);
890 g_return_val_if_fail(rows
>= MINROWS
, NULL
);
892 widget
= GTK_WIDGET( gtk_type_new(gtk_sheet_get_type ()) );
894 gtk_sheet_construct(GTK_SHEET(widget
), rows
, columns
, title
);
896 return GTK_SHEET(widget
);
900 gtk_sheet_construct (GtkSheet
*sheet
, guint rows
, guint columns
, const gchar
*title
)
902 sheet
->row
=(GtkSheetRow
*)g_malloc(sizeof(GtkSheetRow
));
903 sheet
->column
=(GtkSheetColumn
*)g_malloc(sizeof(GtkSheetColumn
));
904 sheet
->data
=(GtkSheetCell
***)g_malloc(sizeof(GtkSheetCell
**));
906 sheet
->data
[0] = (GtkSheetCell
**)g_malloc(sizeof(GtkSheetCell
*)+sizeof(gdouble
));
907 sheet
->data
[0][0] = NULL
;
909 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_ROW_TITLES_VISIBLE
);
910 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_COL_TITLES_VISIBLE
);
911 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_AUTO_SCROLL
);
912 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_JUSTIFY_ENTRY
);
914 /* set number of rows and columns */
915 GrowSheet(sheet
, MINROWS
, MINCOLS
);
917 /* Init row an column zero */
921 /* Add rows and columns */
922 AddRow(sheet
,rows
-1);
923 AddColumn(sheet
,columns
-1);
925 /* create sheet entry */
926 sheet
->entry_type
= 0;
927 create_sheet_entry (sheet
);
929 /* create global selection button */
930 create_global_button(sheet
);
933 sheet
->name
= g_strdup(title
);
939 gtk_sheet_new_with_custom_entry (guint rows
, guint columns
, const gchar
*title
,
944 widget
= gtk_type_new (gtk_sheet_get_type ());
946 gtk_sheet_construct_with_custom_entry(GTK_SHEET(widget
),
947 rows
, columns
, title
, entry_type
);
953 gtk_sheet_construct_with_custom_entry (GtkSheet
*sheet
,
954 guint rows
, guint columns
,
958 gtk_sheet_construct(sheet
, rows
, columns
, title
);
960 sheet
->entry_type
= entry_type
;
961 create_sheet_entry(sheet
);
966 gtk_sheet_change_entry(GtkSheet
*sheet
, GtkType entry_type
)
970 g_return_if_fail (sheet
!= NULL
);
971 g_return_if_fail (GTK_IS_SHEET (sheet
));
973 state
= sheet
->state
;
975 if(sheet
->state
== GTK_SHEET_NORMAL
)
976 gtk_sheet_hide_active_cell(sheet
);
978 sheet
->entry_type
= entry_type
;
980 create_sheet_entry(sheet
);
982 if(state
== GTK_SHEET_NORMAL
)
984 gtk_sheet_show_active_cell(sheet
);
985 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet
)),
987 (GtkSignalFunc
)gtk_sheet_entry_changed
,
988 GTK_OBJECT(GTK_WIDGET(sheet
)));
994 gtk_sheet_show_grid(GtkSheet
*sheet
, gboolean show
)
996 g_return_if_fail (sheet
!= NULL
);
997 g_return_if_fail (GTK_IS_SHEET (sheet
));
999 if(show
== sheet
->show_grid
) return;
1001 sheet
->show_grid
= show
;
1003 if(!GTK_SHEET_IS_FROZEN(sheet
))
1004 gtk_sheet_range_draw(sheet
, NULL
);
1008 gtk_sheet_grid_visible(GtkSheet
*sheet
)
1010 g_return_val_if_fail (sheet
!= NULL
, 0);
1011 g_return_val_if_fail (GTK_IS_SHEET (sheet
), 0);
1013 return sheet
->show_grid
;
1017 gtk_sheet_set_background(GtkSheet
*sheet
, GdkColor
*color
)
1019 g_return_if_fail (sheet
!= NULL
);
1020 g_return_if_fail (GTK_IS_SHEET (sheet
));
1023 gdk_color_white(gdk_colormap_get_system(), &sheet
->bg_color
);
1025 sheet
->bg_color
= *color
;
1027 if(!GTK_SHEET_IS_FROZEN(sheet
))
1028 gtk_sheet_range_draw(sheet
, NULL
);
1032 gtk_sheet_set_grid(GtkSheet
*sheet
, GdkColor
*color
)
1034 g_return_if_fail (sheet
!= NULL
);
1035 g_return_if_fail (GTK_IS_SHEET (sheet
));
1038 gdk_color_black(gdk_colormap_get_system(), &sheet
->grid_color
);
1040 sheet
->grid_color
= *color
;
1042 if(!GTK_SHEET_IS_FROZEN(sheet
))
1043 gtk_sheet_range_draw(sheet
, NULL
);
1047 gtk_sheet_get_columns_count(GtkSheet
*sheet
)
1049 g_return_val_if_fail (sheet
!= NULL
, 0);
1050 g_return_val_if_fail (GTK_IS_SHEET (sheet
), 0);
1052 return sheet
->maxcol
+ 1;
1056 gtk_sheet_get_rows_count(GtkSheet
*sheet
)
1058 g_return_val_if_fail (sheet
!= NULL
, 0);
1059 g_return_val_if_fail (GTK_IS_SHEET (sheet
), 0);
1061 return sheet
->maxrow
+ 1;
1065 gtk_sheet_get_state(GtkSheet
*sheet
)
1067 g_return_val_if_fail (sheet
!= NULL
, 0);
1068 g_return_val_if_fail (GTK_IS_SHEET (sheet
), 0);
1070 return (sheet
->state
);
1074 gtk_sheet_set_selection_mode(GtkSheet
*sheet
, gint mode
)
1076 g_return_if_fail (sheet
!= NULL
);
1077 g_return_if_fail (GTK_IS_SHEET (sheet
));
1079 if(GTK_WIDGET_REALIZED(sheet
))
1080 gtk_sheet_real_unselect_range(sheet
, NULL
);
1082 sheet
->selection_mode
= mode
;
1085 /* This routine has problems with gtk+-1.2 related with the
1086 * label/button drawing - I think it's a bug in gtk+-1.2 */
1088 gtk_sheet_set_title(GtkSheet
*sheet
, const gchar
*title
)
1090 /* GtkWidget *old_widget;
1091 */ GtkWidget
*label
;
1093 g_return_if_fail (sheet
!= NULL
);
1094 g_return_if_fail (title
!= NULL
);
1095 g_return_if_fail (GTK_IS_SHEET (sheet
));
1098 g_free (sheet
->name
);
1100 sheet
->name
= g_strdup (title
);
1102 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
)) || !title
) return;
1104 if(GTK_BIN(sheet
->button
)->child
)
1105 label
= GTK_BIN(sheet
->button
)->child
;
1107 gtk_label_set_text(GTK_LABEL(label), title);
1109 size_allocate_global_button(sheet
);
1111 /* remove and destroy the old widget */
1113 old_widget = GTK_BIN (sheet->button)->child;
1116 gtk_container_remove (GTK_CONTAINER (sheet->button), old_widget);
1119 label = gtk_label_new (title);
1120 gtk_misc_set_alignment(GTK_MISC(label), 0.5 , 0.5 );
1122 gtk_container_add (GTK_CONTAINER (sheet->button), label);
1123 gtk_widget_show (label);
1125 size_allocate_global_button(sheet);
1127 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, -1);
1130 gtk_widget_destroy (old_widget);
1135 gtk_sheet_freeze (GtkSheet
*sheet
)
1137 g_return_if_fail (sheet
!= NULL
);
1138 g_return_if_fail (GTK_IS_SHEET (sheet
));
1140 sheet
->freeze_count
++;
1141 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_IS_FROZEN
);
1145 gtk_sheet_thaw(GtkSheet
*sheet
)
1147 g_return_if_fail (sheet
!= NULL
);
1148 g_return_if_fail (GTK_IS_SHEET (sheet
));
1150 if(sheet
->freeze_count
== 0) return;
1152 sheet
->freeze_count
--;
1153 if(sheet
->freeze_count
> 0) return;
1155 adjust_scrollbars(sheet
);
1157 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_IS_FROZEN
);
1159 sheet
->old_vadjustment
= -1.;
1160 sheet
->old_hadjustment
= -1.;
1162 if(sheet
->hadjustment
)
1163 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->hadjustment
),
1165 if(sheet
->vadjustment
)
1166 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->vadjustment
),
1169 if(sheet
->state
== GTK_STATE_NORMAL
)
1170 if(sheet
->sheet_entry
&& GTK_WIDGET_MAPPED(sheet
->sheet_entry
)){
1171 gtk_sheet_activate_cell(sheet
, sheet
->active_cell
.row
, sheet
->active_cell
.col
);
1173 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
1175 (GtkSignalFunc)gtk_sheet_entry_changed,
1176 GTK_OBJECT(GTK_WIDGET(sheet)));
1177 gtk_sheet_show_active_cell(sheet);
1184 gtk_sheet_set_row_titles_width(GtkSheet
*sheet
, guint width
)
1186 if(width
< COLUMN_MIN_WIDTH
) return;
1188 sheet
->row_title_area
.width
= width
;
1189 sheet
->view
.col0
=COLUMN_FROM_XPIXEL(sheet
, sheet
->row_title_area
.width
+1);
1190 sheet
->view
.coli
=COLUMN_FROM_XPIXEL(sheet
, sheet
->sheet_window_width
);
1191 gtk_sheet_recalc_top_ypixels(sheet
, 0);
1192 gtk_sheet_recalc_left_xpixels(sheet
, 0);
1193 adjust_scrollbars(sheet
);
1195 sheet
->old_hadjustment
= -1.;
1196 if(sheet
->hadjustment
)
1197 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->hadjustment
),
1199 size_allocate_global_button(sheet
);
1203 gtk_sheet_set_column_titles_height(GtkSheet
*sheet
, guint height
)
1205 if(height
< DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet
))) return;
1207 sheet
->column_title_area
.height
= height
;
1208 sheet
->view
.row0
=ROW_FROM_YPIXEL(sheet
, sheet
->column_title_area
.height
+1);
1209 sheet
->view
.rowi
=ROW_FROM_YPIXEL(sheet
, sheet
->sheet_window_height
-1);
1210 gtk_sheet_recalc_top_ypixels(sheet
, 0);
1211 gtk_sheet_recalc_left_xpixels(sheet
, 0);
1212 adjust_scrollbars(sheet
);
1214 sheet
->old_vadjustment
= -1.;
1215 if(sheet
->vadjustment
)
1216 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->vadjustment
),
1218 size_allocate_global_button(sheet
);
1222 gtk_sheet_show_column_titles(GtkSheet
*sheet
)
1226 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
)) return;
1228 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_COL_TITLES_VISIBLE
);
1229 gtk_sheet_recalc_top_ypixels(sheet
, 0);
1230 gtk_sheet_recalc_left_xpixels(sheet
, 0);
1231 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))){
1232 gdk_window_show(sheet
->column_title_window
);
1234 for(col
= MIN_VISIBLE_COLUMN(sheet
); col
<= MAX_VISIBLE_COLUMN(sheet
); col
++){
1235 GtkSheetChild
*child
;
1236 child
= sheet
->column
[col
].button
.child
;
1238 gtk_sheet_child_show(child
);
1241 adjust_scrollbars(sheet
);
1244 sheet
->old_vadjustment
= -1.;
1245 if(sheet
->vadjustment
)
1246 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->vadjustment
),
1248 size_allocate_global_button(sheet
);
1252 gtk_sheet_show_row_titles(GtkSheet
*sheet
)
1256 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)) return;
1258 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_ROW_TITLES_VISIBLE
);
1259 gtk_sheet_recalc_top_ypixels(sheet
, 0);
1260 gtk_sheet_recalc_left_xpixels(sheet
, 0);
1261 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))){
1262 gdk_window_show(sheet
->row_title_window
);
1264 for(row
= MIN_VISIBLE_ROW(sheet
); row
<= MAX_VISIBLE_ROW(sheet
); row
++){
1265 GtkSheetChild
*child
;
1266 child
= sheet
->row
[row
].button
.child
;
1268 gtk_sheet_child_show(child
);
1271 adjust_scrollbars(sheet
);
1274 sheet
->old_hadjustment
= -1.;
1275 if(sheet
->hadjustment
)
1276 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->hadjustment
),
1278 size_allocate_global_button(sheet
);
1282 gtk_sheet_hide_column_titles(GtkSheet
*sheet
)
1286 if(!GTK_SHEET_COL_TITLES_VISIBLE(sheet
)) return;
1288 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_COL_TITLES_VISIBLE
);
1289 gtk_sheet_recalc_top_ypixels(sheet
, 0);
1290 gtk_sheet_recalc_left_xpixels(sheet
, 0);
1291 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))){
1292 if(sheet
->column_title_window
) gdk_window_hide(sheet
->column_title_window
);
1293 if(GTK_WIDGET_VISIBLE(sheet
->button
)) gtk_widget_hide(sheet
->button
);
1295 for(col
= MIN_VISIBLE_COLUMN(sheet
); col
<= MAX_VISIBLE_COLUMN(sheet
); col
++){
1296 GtkSheetChild
*child
;
1297 child
= sheet
->column
[col
].button
.child
;
1299 gtk_sheet_child_hide(child
);
1302 adjust_scrollbars(sheet
);
1305 sheet
->old_vadjustment
= -1.;
1306 if(sheet
->vadjustment
)
1307 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->vadjustment
),
1312 gtk_sheet_hide_row_titles(GtkSheet
*sheet
)
1316 if(!GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)) return;
1318 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_ROW_TITLES_VISIBLE
);
1319 gtk_sheet_recalc_top_ypixels(sheet
, 0);
1320 gtk_sheet_recalc_left_xpixels(sheet
, 0);
1321 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))){
1322 if(sheet
->row_title_window
) gdk_window_hide(sheet
->row_title_window
);
1323 if(GTK_WIDGET_VISIBLE(sheet
->button
)) gtk_widget_hide(sheet
->button
);
1324 for(row
= MIN_VISIBLE_ROW(sheet
); row
<= MAX_VISIBLE_ROW(sheet
); row
++){
1325 GtkSheetChild
*child
;
1326 child
= sheet
->row
[row
].button
.child
;
1328 gtk_sheet_child_hide(child
);
1331 adjust_scrollbars(sheet
);
1334 sheet
->old_hadjustment
= -1.;
1335 if(sheet
->hadjustment
)
1336 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->hadjustment
),
1341 gtk_sheet_set_column_title (GtkSheet
* sheet
,
1343 const gchar
* title
)
1345 g_return_if_fail (sheet
!= NULL
);
1346 g_return_if_fail (GTK_IS_SHEET (sheet
));
1348 if (sheet
->column
[column
].name
)
1349 g_free (sheet
->column
[column
].name
);
1351 sheet
->column
[column
].name
= g_strdup(title
);
1355 gtk_sheet_set_row_title (GtkSheet
* sheet
,
1357 const gchar
* title
)
1359 g_return_if_fail (sheet
!= NULL
);
1360 g_return_if_fail (GTK_IS_SHEET (sheet
));
1362 if (sheet
->row
[row
].name
)
1363 g_free (sheet
->row
[row
].name
);
1365 sheet
->row
[row
].name
= g_strdup (title
);
1369 gtk_sheet_row_button_add_label(GtkSheet
*sheet
, gint row
, const gchar
*label
)
1371 GtkSheetButton
*button
;
1375 g_return_if_fail (sheet
!= NULL
);
1376 g_return_if_fail (GTK_IS_SHEET (sheet
));
1378 if(row
< 0 || row
> sheet
->maxrow
) return;
1381 if (sheet
->row
[row
].button
.label
)
1382 g_free (sheet
->row
[row
].button
.label
);
1384 sheet
->row
[row
].button
.label
= g_strdup (label
);
1386 button
= &sheet
->row
[row
].button
;
1388 if(button
->label
&& strlen(button
->label
)>0){
1389 words
=button
->label
;
1390 while(words
&& *words
!= '\0'){
1391 if(*words
== '\n' || *(words
+1) == '\0'){
1392 label_height
+= DEFAULT_LABEL_HEIGHT(GTK_WIDGET(sheet
));
1398 if(label_height
+2*CELLOFFSET
> sheet
->column_title_area
.height
)
1399 gtk_sheet_set_row_height(sheet
, row
, label_height
+2*CELLOFFSET
);
1401 if(!GTK_SHEET_IS_FROZEN(sheet
)){
1402 gtk_sheet_button_draw(sheet
, row
, -1);
1403 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[CHANGED
], row
, -1);
1408 gtk_sheet_row_label_set_visibility(GtkSheet
*sheet
, gint row
, gboolean visible
)
1410 g_return_if_fail (sheet
!= NULL
);
1411 g_return_if_fail (GTK_IS_SHEET (sheet
));
1413 if(row
< 0 || row
> sheet
->maxrow
) return;
1415 sheet
->row
[row
].button
.label_visible
= visible
;
1417 if(!GTK_SHEET_IS_FROZEN(sheet
)){
1418 gtk_sheet_button_draw(sheet
, row
, -1);
1419 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[CHANGED
], row
, -1);
1424 gtk_sheet_rows_labels_set_visibility(GtkSheet
*sheet
, gboolean visible
)
1428 g_return_if_fail (sheet
!= NULL
);
1429 g_return_if_fail (GTK_IS_SHEET (sheet
));
1431 for(i
= 0; i
<= sheet
->maxrow
; i
++)
1432 gtk_sheet_row_label_set_visibility(sheet
, i
, visible
);
1437 gtk_sheet_column_button_add_label(GtkSheet
*sheet
, gint column
, const gchar
*label
)
1439 GtkSheetButton
*button
;
1440 gint label_height
= 0;
1443 g_return_if_fail (sheet
!= NULL
);
1444 g_return_if_fail (GTK_IS_SHEET (sheet
));
1446 if(column
< 0 || column
>sheet
->maxcol
) return;
1448 if (sheet
->column
[column
].button
.label
)
1449 g_free (sheet
->column
[column
].button
.label
);
1452 sheet
->column
[column
].button
.label
= g_strdup (label
);
1454 button
= &sheet
->column
[column
].button
;
1455 if(button
->label
&& strlen(button
->label
)>0){
1456 words
=button
->label
;
1457 while(words
&& *words
!= '\0'){
1458 if(*words
== '\n' || *(words
+1) == '\0'){
1459 label_height
+= DEFAULT_LABEL_HEIGHT(GTK_WIDGET(sheet
));
1465 if(label_height
+2*CELLOFFSET
> sheet
->column_title_area
.height
)
1466 gtk_sheet_set_column_titles_height(sheet
, label_height
+2*CELLOFFSET
);
1468 if(!GTK_SHEET_IS_FROZEN(sheet
)){
1469 gtk_sheet_button_draw(sheet
, -1, column
);
1470 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[CHANGED
], -1, column
);
1475 gtk_sheet_column_label_set_visibility(GtkSheet
*sheet
, gint col
, gboolean visible
)
1477 g_return_if_fail (sheet
!= NULL
);
1478 g_return_if_fail (GTK_IS_SHEET (sheet
));
1480 if(col
< 0 || col
> sheet
->maxcol
) return;
1482 sheet
->column
[col
].button
.label_visible
= visible
;
1484 if(!GTK_SHEET_IS_FROZEN(sheet
)){
1485 gtk_sheet_button_draw(sheet
, -1, col
);
1486 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[CHANGED
], -1, col
);
1491 gtk_sheet_columns_labels_set_visibility(GtkSheet
*sheet
, gboolean visible
)
1495 g_return_if_fail (sheet
!= NULL
);
1496 g_return_if_fail (GTK_IS_SHEET (sheet
));
1498 for(i
= 0; i
<= sheet
->maxcol
; i
++)
1499 gtk_sheet_column_label_set_visibility(sheet
, i
, visible
);
1503 gtk_sheet_row_button_justify(GtkSheet
*sheet
, gint row
,
1504 GtkJustification justification
)
1506 GtkSheetButton
*button
;
1508 g_return_if_fail (sheet
!= NULL
);
1509 g_return_if_fail (GTK_IS_SHEET (sheet
));
1511 if(row
< 0 || row
> sheet
->maxrow
) return;
1513 button
= &sheet
->row
[row
].button
;
1514 button
->justification
= justification
;
1516 if(!GTK_SHEET_IS_FROZEN(sheet
)){
1517 gtk_sheet_button_draw(sheet
, row
, -1);
1518 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[CHANGED
], row
, -1);
1523 gtk_sheet_column_button_justify(GtkSheet
*sheet
, gint column
,
1524 GtkJustification justification
)
1526 GtkSheetButton
*button
;
1528 g_return_if_fail (sheet
!= NULL
);
1529 g_return_if_fail (GTK_IS_SHEET (sheet
));
1531 if(column
< 0 || column
> sheet
->maxcol
) return;
1533 button
= &sheet
->column
[column
].button
;
1534 button
->justification
= justification
;
1536 if(!GTK_SHEET_IS_FROZEN(sheet
)){
1537 gtk_sheet_button_draw(sheet
, -1, column
);
1538 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[CHANGED
], -1, column
);
1544 gtk_sheet_moveto (GtkSheet
* sheet
,
1551 guint width
, height
;
1553 gint min_row
, min_col
;
1555 g_return_if_fail (sheet
!= NULL
);
1556 g_return_if_fail (GTK_IS_SHEET (sheet
));
1557 g_return_if_fail (sheet
->hadjustment
!= NULL
);
1558 g_return_if_fail (sheet
->vadjustment
!= NULL
);
1560 if (row
< 0 || row
> sheet
->maxrow
)
1562 if (column
< 0 || column
> sheet
->maxcol
)
1565 height
= sheet
->sheet_window_height
;
1566 width
= sheet
->sheet_window_width
;
1568 /* adjust vertical scrollbar */
1570 if (row
>= 0 && row_align
>=0.)
1572 y
= ROW_TOP_YPIXEL(sheet
, row
) - sheet
->voffset
-
1574 (1.-row_align
)*sheet
->row
[row
].height
;
1576 /* This forces the sheet to scroll when you don't see the entire cell */
1579 if(row_align
== 1.){
1580 while(min_row
>= 0 && min_row
> MIN_VISIBLE_ROW(sheet
)){
1581 if(sheet
->row
[min_row
].is_visible
)
1582 adjust
+= sheet
->row
[min_row
].height
;
1583 if(adjust
>= height
){
1588 min_row
= MAX(min_row
, 0);
1589 y
= ROW_TOP_YPIXEL(sheet
, min_row
) - sheet
->voffset
+
1590 sheet
->row
[min_row
].height
- 1;
1594 sheet
->vadjustment
->value
= 0.0;
1596 sheet
->vadjustment
->value
= y
;
1598 sheet
->old_vadjustment
= -1.;
1599 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->vadjustment
),
1604 /* adjust horizontal scrollbar */
1605 if (column
>= 0 && col_align
>= 0.)
1607 x
= COLUMN_LEFT_XPIXEL (sheet
, column
) - sheet
->hoffset
-
1609 (1.-col_align
)*sheet
->column
[column
].width
;
1611 /* This forces the sheet to scroll when you don't see the entire cell */
1614 if(col_align
== 1.){
1615 while(min_col
>= 0 && min_col
> MIN_VISIBLE_COLUMN(sheet
)){
1616 if(sheet
->column
[min_col
].is_visible
)
1617 adjust
+= sheet
->column
[min_col
].width
;
1618 if(adjust
>= width
){
1623 min_col
= MAX(min_col
, 0);
1624 x
= COLUMN_LEFT_XPIXEL(sheet
, min_col
) - sheet
->hoffset
+
1625 sheet
->column
[min_col
].width
- 1;
1629 sheet
->hadjustment
->value
= 0.0;
1631 sheet
->hadjustment
->value
= x
;
1633 sheet
->old_vadjustment
= -1.;
1634 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->hadjustment
),
1641 gtk_sheet_column_set_sensitivity(GtkSheet
*sheet
, gint column
, gboolean sensitive
)
1643 g_return_if_fail (sheet
!= NULL
);
1644 g_return_if_fail (GTK_IS_SHEET (sheet
));
1646 if(column
< 0 || column
> sheet
->maxcol
) return;
1648 sheet
->column
[column
].is_sensitive
=sensitive
;
1650 sheet
->column
[column
].button
.state
=GTK_STATE_INSENSITIVE
;
1652 sheet
->column
[column
].button
.state
=GTK_STATE_NORMAL
;
1654 if(GTK_WIDGET_REALIZED(sheet
) && !GTK_SHEET_IS_FROZEN(sheet
))
1655 gtk_sheet_button_draw(sheet
, -1, column
);
1659 gtk_sheet_columns_set_sensitivity(GtkSheet
*sheet
, gboolean sensitive
)
1663 g_return_if_fail (sheet
!= NULL
);
1664 g_return_if_fail (GTK_IS_SHEET (sheet
));
1666 for(i
=0; i
<=sheet
->maxcol
; i
++)
1667 gtk_sheet_column_set_sensitivity(sheet
, i
, sensitive
);
1671 gtk_sheet_row_set_sensitivity(GtkSheet
*sheet
, gint row
, gboolean sensitive
)
1674 g_return_if_fail (sheet
!= NULL
);
1675 g_return_if_fail (GTK_IS_SHEET (sheet
));
1677 if(row
< 0 || row
> sheet
->maxrow
) return;
1679 sheet
->row
[row
].is_sensitive
=sensitive
;
1681 sheet
->row
[row
].button
.state
=GTK_STATE_INSENSITIVE
;
1683 sheet
->row
[row
].button
.state
=GTK_STATE_NORMAL
;
1685 if(GTK_WIDGET_REALIZED(sheet
) && !GTK_SHEET_IS_FROZEN(sheet
))
1686 gtk_sheet_button_draw(sheet
, row
, -1);
1690 gtk_sheet_rows_set_sensitivity(GtkSheet
*sheet
, gboolean sensitive
)
1694 g_return_if_fail (sheet
!= NULL
);
1695 g_return_if_fail (GTK_IS_SHEET (sheet
));
1697 for(i
=0; i
<=sheet
->maxrow
; i
++)
1698 gtk_sheet_row_set_sensitivity(sheet
, i
, sensitive
);
1702 gtk_sheet_column_set_visibility(GtkSheet
*sheet
, gint column
, gboolean visible
)
1704 g_return_if_fail (sheet
!= NULL
);
1705 g_return_if_fail (GTK_IS_SHEET (sheet
));
1707 if(column
< 0 || column
> sheet
->maxcol
) return;
1708 if(sheet
->column
[column
].is_visible
== visible
) return;
1710 sheet
->column
[column
].is_visible
= visible
;
1712 gtk_sheet_recalc_left_xpixels(sheet
, column
);
1714 if(!GTK_SHEET_IS_FROZEN(sheet
) &&
1715 gtk_sheet_cell_isvisible(sheet
, MIN_VISIBLE_ROW(sheet
), column
)){
1716 gtk_sheet_range_draw(sheet
, NULL
);
1717 size_allocate_column_title_buttons(sheet
);
1722 gtk_sheet_row_set_visibility(GtkSheet
*sheet
, gint row
, gboolean visible
)
1724 g_return_if_fail (sheet
!= NULL
);
1725 g_return_if_fail (GTK_IS_SHEET (sheet
));
1727 if(row
< 0 || row
> sheet
->maxrow
) return;
1728 if(sheet
->row
[row
].is_visible
== visible
) return;
1730 sheet
->row
[row
].is_visible
= visible
;
1732 gtk_sheet_recalc_top_ypixels(sheet
, row
);
1734 if(!GTK_SHEET_IS_FROZEN(sheet
) &&
1735 gtk_sheet_cell_isvisible(sheet
, row
, MIN_VISIBLE_COLUMN(sheet
))){
1736 gtk_sheet_range_draw(sheet
, NULL
);
1737 size_allocate_row_title_buttons(sheet
);
1742 gtk_sheet_select_row (GtkSheet
* sheet
,
1745 g_return_if_fail (sheet
!= NULL
);
1746 g_return_if_fail (GTK_IS_SHEET (sheet
));
1748 if (row
< 0 || row
> sheet
->maxrow
)
1751 if(sheet
->state
!= GTK_SHEET_NORMAL
)
1752 gtk_sheet_real_unselect_range(sheet
, NULL
);
1756 veto
= gtk_sheet_deactivate_cell(sheet
);
1760 sheet
->state
=GTK_SHEET_ROW_SELECTED
;
1761 sheet
->range
.row0
=row
;
1762 sheet
->range
.col0
=0;
1763 sheet
->range
.rowi
=row
;
1764 sheet
->range
.coli
=sheet
->maxcol
;
1765 sheet
->active_cell
.row
=row
;
1766 sheet
->active_cell
.col
=0;
1768 gtk_signal_emit (GTK_OBJECT (sheet
), sheet_signals
[SELECT_ROW
], row
);
1769 gtk_sheet_real_select_range(sheet
, NULL
);
1775 gtk_sheet_select_column (GtkSheet
* sheet
,
1779 g_return_if_fail (sheet
!= NULL
);
1780 g_return_if_fail (GTK_IS_SHEET (sheet
));
1782 if (column
< 0 || column
> sheet
->maxcol
)
1785 if(sheet
->state
!= GTK_SHEET_NORMAL
)
1786 gtk_sheet_real_unselect_range(sheet
, NULL
);
1790 veto
= gtk_sheet_deactivate_cell(sheet
);
1794 sheet
->state
=GTK_SHEET_COLUMN_SELECTED
;
1795 sheet
->range
.row0
=0;
1796 sheet
->range
.col0
=column
;
1797 sheet
->range
.rowi
=sheet
->maxrow
;
1798 sheet
->range
.coli
=column
;
1799 sheet
->active_cell
.row
=0;
1800 sheet
->active_cell
.col
=column
;
1802 gtk_signal_emit (GTK_OBJECT (sheet
), sheet_signals
[SELECT_COLUMN
], column
);
1803 gtk_sheet_real_select_range(sheet
, NULL
);
1808 gtk_sheet_clip_range (GtkSheet
*sheet
, const GtkSheetRange
*range
)
1811 g_return_if_fail (sheet
!= NULL
);
1812 g_return_if_fail (GTK_IS_SHEET (sheet
));
1814 if(GTK_SHEET_IN_CLIP(sheet
)) return;
1816 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_IN_CLIP
);
1819 sheet
->clip_range
= sheet
->range
;
1821 sheet
->clip_range
=*range
;
1824 sheet
->clip_timer
=gtk_timeout_add(TIMEOUT_FLASH
, gtk_sheet_flash
, (gpointer
) sheet
);
1826 gtk_signal_emit(GTK_OBJECT(sheet
), sheet_signals
[CLIP_RANGE
],
1827 &sheet
->clip_range
);
1832 gtk_sheet_unclip_range(GtkSheet
*sheet
)
1835 g_return_if_fail (sheet
!= NULL
);
1836 g_return_if_fail (GTK_IS_SHEET (sheet
));
1838 if(!GTK_SHEET_IN_CLIP(sheet
)) return;
1840 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_IN_CLIP
);
1841 gtk_timeout_remove(sheet
->clip_timer
);
1842 gtk_sheet_range_draw(sheet
, &sheet
->clip_range
);
1844 if(gtk_sheet_range_isvisible(sheet
, sheet
->range
))
1845 gtk_sheet_range_draw(sheet
, &sheet
->range
);
1849 gtk_sheet_flash(gpointer data
)
1852 gint x
,y
,width
,height
;
1853 GdkRectangle clip_area
;
1855 sheet
=GTK_SHEET(data
);
1857 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return TRUE
;
1858 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet
))) return TRUE
;
1859 if(!gtk_sheet_range_isvisible(sheet
, sheet
->clip_range
)) return TRUE
;
1860 if(GTK_SHEET_IN_XDRAG(sheet
)) return TRUE
;
1861 if(GTK_SHEET_IN_YDRAG(sheet
)) return TRUE
;
1863 GDK_THREADS_ENTER();
1865 x
=COLUMN_LEFT_XPIXEL(sheet
,sheet
->clip_range
.col0
)+1;
1866 y
=ROW_TOP_YPIXEL(sheet
,sheet
->clip_range
.row0
)+1;
1867 width
=COLUMN_LEFT_XPIXEL(sheet
,sheet
->clip_range
.coli
)-x
+
1868 sheet
->column
[sheet
->clip_range
.coli
].width
-1;
1869 height
=ROW_TOP_YPIXEL(sheet
,sheet
->clip_range
.rowi
)-y
+
1870 sheet
->row
[sheet
->clip_range
.rowi
].height
-1;
1872 clip_area
.x
=COLUMN_LEFT_XPIXEL(sheet
, MIN_VISIBLE_COLUMN(sheet
));
1873 clip_area
.y
=ROW_TOP_YPIXEL(sheet
, MIN_VISIBLE_ROW(sheet
));
1874 clip_area
.width
=sheet
->sheet_window_width
;
1875 clip_area
.height
=sheet
->sheet_window_height
;
1881 if(width
>clip_area
.width
) width
=clip_area
.width
+10;
1886 if(height
>clip_area
.height
) height
=clip_area
.height
+10;
1888 gdk_draw_pixmap(sheet
->sheet_window
,
1889 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
1895 gdk_draw_pixmap(sheet
->sheet_window
,
1896 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
1902 gdk_draw_pixmap(sheet
->sheet_window
,
1903 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
1909 gdk_draw_pixmap(sheet
->sheet_window
,
1910 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
1917 sheet
->interval
=sheet
->interval
+1;
1918 if(sheet
->interval
==TIME_INTERVAL
) sheet
->interval
=0;
1920 gdk_gc_set_dashes(sheet
->xor_gc
, sheet
->interval
, "\4\4", 2);
1921 gtk_sheet_draw_flashing_range(sheet
, sheet
->clip_range
);
1922 gdk_gc_set_dashes(sheet
->xor_gc
, 0, "\4\4", 2);
1924 GDK_THREADS_LEAVE();
1931 gtk_sheet_draw_flashing_range(GtkSheet
*sheet
, GtkSheetRange range
)
1933 GdkRectangle clip_area
;
1934 gint x
,y
,width
,height
;
1936 if(!gtk_sheet_range_isvisible(sheet
, sheet
->clip_range
)) return;
1938 clip_area
.x
=COLUMN_LEFT_XPIXEL(sheet
, MIN_VISIBLE_COLUMN(sheet
));
1939 clip_area
.y
=ROW_TOP_YPIXEL(sheet
, MIN_VISIBLE_ROW(sheet
));
1940 clip_area
.width
=sheet
->sheet_window_width
;
1941 clip_area
.height
=sheet
->sheet_window_height
;
1943 gdk_gc_set_clip_rectangle(sheet
->xor_gc
, &clip_area
);
1945 x
=COLUMN_LEFT_XPIXEL(sheet
,sheet
->clip_range
.col0
)+1;
1946 y
=ROW_TOP_YPIXEL(sheet
,sheet
->clip_range
.row0
)+1;
1947 width
=COLUMN_LEFT_XPIXEL(sheet
,sheet
->clip_range
.coli
)-x
+
1948 sheet
->column
[sheet
->clip_range
.coli
].width
-1;
1949 height
=ROW_TOP_YPIXEL(sheet
,sheet
->clip_range
.rowi
)-y
+
1950 sheet
->row
[sheet
->clip_range
.rowi
].height
-1;
1956 if(width
>clip_area
.width
) width
=clip_area
.width
+10;
1961 if(height
>clip_area
.height
) height
=clip_area
.height
+10;
1963 gdk_gc_set_line_attributes(sheet
->xor_gc
, 1, 1, 0 ,0 );
1965 gdk_draw_rectangle(sheet
->sheet_window
, sheet
->xor_gc
, FALSE
,
1969 gdk_gc_set_line_attributes (sheet
->xor_gc
, 1, 0, 0, 0);
1971 gdk_gc_set_clip_rectangle(sheet
->xor_gc
, NULL
);
1976 gtk_sheet_range_isvisible (GtkSheet
* sheet
,
1977 GtkSheetRange range
)
1979 g_return_val_if_fail (sheet
!= NULL
, FALSE
);
1981 if (range
.row0
< 0 || range
.row0
> sheet
->maxrow
)
1984 if (range
.rowi
< 0 || range
.rowi
> sheet
->maxrow
)
1987 if (range
.col0
< 0 || range
.col0
> sheet
->maxcol
)
1990 if (range
.coli
< 0 || range
.coli
> sheet
->maxcol
)
1993 if (range
.rowi
< MIN_VISIBLE_ROW (sheet
))
1996 if (range
.row0
> MAX_VISIBLE_ROW (sheet
))
1999 if (range
.coli
< MIN_VISIBLE_COLUMN (sheet
))
2002 if (range
.col0
> MAX_VISIBLE_COLUMN (sheet
))
2009 gtk_sheet_cell_isvisible (GtkSheet
* sheet
,
2010 gint row
, gint column
)
2012 GtkSheetRange range
;
2015 range
.col0
= column
;
2017 range
.coli
= column
;
2019 return gtk_sheet_range_isvisible(sheet
, range
);
2023 gtk_sheet_get_visible_range(GtkSheet
*sheet
, GtkSheetRange
*range
)
2026 g_return_if_fail (sheet
!= NULL
);
2027 g_return_if_fail (GTK_IS_SHEET (sheet
)) ;
2028 g_return_if_fail (range
!= NULL
);
2030 range
->row0
= MIN_VISIBLE_ROW(sheet
);
2031 range
->col0
= MIN_VISIBLE_COLUMN(sheet
);
2032 range
->rowi
= MAX_VISIBLE_ROW(sheet
);
2033 range
->coli
= MAX_VISIBLE_COLUMN(sheet
);
2038 gtk_sheet_get_vadjustment (GtkSheet
* sheet
)
2040 g_return_val_if_fail (sheet
!= NULL
, NULL
);
2041 g_return_val_if_fail (GTK_IS_SHEET (sheet
), NULL
);
2043 return sheet
->vadjustment
;
2047 gtk_sheet_get_hadjustment (GtkSheet
* sheet
)
2049 g_return_val_if_fail (sheet
!= NULL
, NULL
);
2050 g_return_val_if_fail (GTK_IS_SHEET (sheet
), NULL
);
2052 return sheet
->hadjustment
;
2056 gtk_sheet_set_vadjustment (GtkSheet
*sheet
,
2057 GtkAdjustment
*adjustment
)
2059 GtkAdjustment
*old_adjustment
;
2061 g_return_if_fail (sheet
!= NULL
);
2062 g_return_if_fail (GTK_IS_SHEET (sheet
));
2064 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment
));
2066 if (sheet
->vadjustment
== adjustment
)
2069 old_adjustment
= sheet
->vadjustment
;
2071 if (sheet
->vadjustment
)
2073 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet
->vadjustment
), sheet
);
2074 gtk_object_unref (GTK_OBJECT (sheet
->vadjustment
));
2077 sheet
->vadjustment
= adjustment
;
2079 if (sheet
->vadjustment
)
2081 gtk_object_ref (GTK_OBJECT (sheet
->vadjustment
));
2082 gtk_object_sink (GTK_OBJECT (sheet
->vadjustment
));
2084 gtk_signal_connect (GTK_OBJECT (sheet
->vadjustment
), "changed",
2085 (GtkSignalFunc
) vadjustment_changed
,
2087 gtk_signal_connect (GTK_OBJECT (sheet
->vadjustment
), "value_changed",
2088 (GtkSignalFunc
) vadjustment_value_changed
,
2092 if (!sheet
->vadjustment
|| !old_adjustment
)
2094 gtk_widget_queue_resize (GTK_WIDGET (sheet
));
2098 sheet
->old_vadjustment
= sheet
->vadjustment
->value
;
2102 gtk_sheet_set_hadjustment (GtkSheet
*sheet
,
2103 GtkAdjustment
*adjustment
)
2105 GtkAdjustment
*old_adjustment
;
2107 g_return_if_fail (sheet
!= NULL
);
2108 g_return_if_fail (GTK_IS_SHEET (sheet
));
2110 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment
));
2112 if (sheet
->hadjustment
== adjustment
)
2115 old_adjustment
= sheet
->hadjustment
;
2117 if (sheet
->hadjustment
)
2119 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet
->hadjustment
), sheet
);
2120 gtk_object_unref (GTK_OBJECT (sheet
->hadjustment
));
2123 sheet
->hadjustment
= adjustment
;
2125 if (sheet
->hadjustment
)
2127 gtk_object_ref (GTK_OBJECT (sheet
->hadjustment
));
2128 gtk_object_sink (GTK_OBJECT (sheet
->hadjustment
));
2130 gtk_signal_connect (GTK_OBJECT (sheet
->hadjustment
), "changed",
2131 (GtkSignalFunc
) hadjustment_changed
,
2133 gtk_signal_connect (GTK_OBJECT (sheet
->hadjustment
), "value_changed",
2134 (GtkSignalFunc
) hadjustment_value_changed
,
2138 if (!sheet
->hadjustment
|| !old_adjustment
)
2140 gtk_widget_queue_resize (GTK_WIDGET (sheet
));
2144 sheet
->old_hadjustment
= sheet
->hadjustment
->value
;
2148 gtk_sheet_set_scroll_adjustments (GtkSheet
*sheet
,
2149 GtkAdjustment
*hadjustment
,
2150 GtkAdjustment
*vadjustment
)
2152 if(sheet
->hadjustment
!= hadjustment
)
2153 gtk_sheet_set_hadjustment (sheet
, hadjustment
);
2154 if(sheet
->vadjustment
!= vadjustment
)
2155 gtk_sheet_set_vadjustment (sheet
, vadjustment
);
2159 gtk_sheet_destroy (GtkObject
* object
)
2163 g_return_if_fail (object
!= NULL
);
2164 g_return_if_fail (GTK_IS_SHEET (object
));
2166 sheet
= GTK_SHEET (object
);
2168 /* get rid of all the cells */
2169 gtk_sheet_range_clear (sheet
, NULL
);
2171 /* destroy the entry */
2172 gtk_widget_destroy (sheet
->sheet_entry
);
2174 /* destroy the global selection button */
2175 gtk_widget_destroy (sheet
->button
);
2178 gtk_timeout_remove(sheet
->timer
);
2182 if(sheet
->clip_timer
){
2183 gtk_timeout_remove(sheet
->clip_timer
);
2184 sheet
->clip_timer
= 0;
2187 /* unref adjustments */
2188 if (sheet
->hadjustment
)
2190 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet
->hadjustment
), sheet
);
2191 gtk_object_unref (GTK_OBJECT (sheet
->hadjustment
));
2192 sheet
->hadjustment
= NULL
;
2194 if (sheet
->vadjustment
)
2196 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet
->vadjustment
), sheet
);
2197 gtk_object_unref (GTK_OBJECT (sheet
->vadjustment
));
2198 sheet
->vadjustment
= NULL
;
2202 if (GTK_OBJECT_CLASS (parent_class
)->destroy
)
2203 (*GTK_OBJECT_CLASS (parent_class
)->destroy
) (object
);
2205 g_list_free(sheet
->children
);
2210 gtk_sheet_finalize (GtkObject
* object
)
2214 g_return_if_fail (object
!= NULL
);
2215 g_return_if_fail (GTK_IS_SHEET (object
));
2217 sheet
= GTK_SHEET(object
);
2219 gtk_sheet_range_delete(sheet
, NULL
);
2221 DeleteRow (sheet
, 0, sheet
->maxrow
+ 1);
2222 DeleteColumn (sheet
, 0, sheet
->maxcol
+ 1);
2225 g_free(sheet
->column
);
2226 g_free(sheet
->data
);
2229 g_free(sheet
->name
);
2231 if (GTK_OBJECT_CLASS (parent_class
)->finalize
)
2232 (*GTK_OBJECT_CLASS (parent_class
)->finalize
) (object
);
2238 gtk_sheet_style_set (GtkWidget
*widget
,
2239 GtkStyle
*previous_style
)
2243 g_return_if_fail (widget
!= NULL
);
2244 g_return_if_fail (GTK_IS_SHEET (widget
));
2246 if (GTK_WIDGET_CLASS (parent_class
)->style_set
)
2247 (*GTK_WIDGET_CLASS (parent_class
)->style_set
) (widget
, previous_style
);
2249 sheet
= GTK_SHEET (widget
);
2251 if(GTK_WIDGET_REALIZED(widget
))
2253 gtk_style_set_background (widget
->style
, widget
->window
, widget
->state
);
2259 gtk_sheet_realize (GtkWidget
* widget
)
2262 GdkWindowAttr attributes
;
2263 gint attributes_mask
;
2264 GdkGCValues values
, auxvalues
;
2265 GdkColormap
*colormap
;
2267 GtkSheetChild
*child
;
2270 g_return_if_fail (widget
!= NULL
);
2271 g_return_if_fail (GTK_IS_SHEET (widget
));
2273 sheet
= GTK_SHEET (widget
);
2275 GTK_WIDGET_SET_FLAGS (widget
, GTK_REALIZED
);
2277 attributes
.window_type
= GDK_WINDOW_CHILD
;
2278 attributes
.x
= widget
->allocation
.x
;
2279 attributes
.y
= widget
->allocation
.y
;
2280 attributes
.width
= widget
->allocation
.width
;
2281 attributes
.height
= widget
->allocation
.height
;
2282 attributes
.wclass
= GDK_INPUT_OUTPUT
;
2284 attributes
.visual
= gtk_widget_get_visual (widget
);
2285 attributes
.colormap
= gtk_widget_get_colormap (widget
);
2287 attributes
.event_mask
= gtk_widget_get_events (widget
);
2288 attributes
.event_mask
|= (GDK_EXPOSURE_MASK
|
2289 GDK_BUTTON_PRESS_MASK
|
2290 GDK_BUTTON_RELEASE_MASK
|
2291 GDK_KEY_PRESS_MASK
|
2292 GDK_POINTER_MOTION_MASK
|
2293 GDK_POINTER_MOTION_HINT_MASK
);
2294 attributes_mask
= GDK_WA_X
| GDK_WA_Y
| GDK_WA_VISUAL
| GDK_WA_COLORMAP
|
2297 attributes
.cursor
= gdk_cursor_new(GDK_TOP_LEFT_ARROW
);
2300 widget
->window
= gdk_window_new (gtk_widget_get_parent_window (widget
), &attributes
, attributes_mask
);
2302 gdk_window_set_user_data (widget
->window
, sheet
);
2304 widget
->style
= gtk_style_attach (widget
->style
, widget
->window
);
2306 gtk_style_set_background (widget
->style
, widget
->window
, GTK_STATE_NORMAL
);
2309 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
2310 attributes
.x
= sheet
->row_title_area
.width
;
2312 attributes
.width
= sheet
->column_title_area
.width
;
2313 attributes
.height
= sheet
->column_title_area
.height
;
2315 /* column-title window */
2316 sheet
->column_title_window
= gdk_window_new (widget
->window
, &attributes
, attributes_mask
);
2317 gdk_window_set_user_data (sheet
->column_title_window
, sheet
);
2318 gtk_style_set_background (widget
->style
, sheet
->column_title_window
, GTK_STATE_NORMAL
);
2322 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
2323 attributes
.y
= sheet
->column_title_area
.height
;
2324 attributes
.width
= sheet
->row_title_area
.width
;
2325 attributes
.height
= sheet
->row_title_area
.height
;
2327 /* row-title window */
2328 sheet
->row_title_window
= gdk_window_new (widget
->window
, &attributes
, attributes_mask
);
2329 gdk_window_set_user_data (sheet
->row_title_window
, sheet
);
2330 gtk_style_set_background (widget
->style
, sheet
->row_title_window
, GTK_STATE_NORMAL
);
2333 attributes
.cursor
= gdk_cursor_new(GDK_PLUS
);
2337 attributes
.width
= sheet
->sheet_window_width
,
2338 attributes
.height
= sheet
->sheet_window_height
;
2340 sheet
->sheet_window
= gdk_window_new (widget
->window
, &attributes
, attributes_mask
);
2341 gdk_window_set_user_data (sheet
->sheet_window
, sheet
);
2343 gdk_window_set_background (sheet
->sheet_window
, &widget
->style
->white
);
2344 gdk_window_show (sheet
->sheet_window
);
2346 /* backing_pixmap */
2347 gtk_sheet_make_backing_pixmap(sheet
, 0, 0);
2351 gdk_gc_unref(sheet
->fg_gc
);
2353 gdk_gc_unref(sheet
->bg_gc
);
2354 sheet
->fg_gc
= gdk_gc_new (widget
->window
);
2355 sheet
->bg_gc
= gdk_gc_new (widget
->window
);
2357 colormap
= gtk_widget_get_colormap(widget
);
2359 gdk_color_white(colormap
, &widget
->style
->white
);
2360 gdk_color_black(colormap
, &widget
->style
->black
);
2362 gdk_gc_get_values(sheet
->fg_gc
, &auxvalues
);
2364 values
.foreground
= widget
->style
->white
;
2365 values
.function
= GDK_INVERT
;
2366 values
.subwindow_mode
= GDK_INCLUDE_INFERIORS
;
2368 gdk_gc_unref(sheet
->xor_gc
);
2369 sheet
->xor_gc
= gdk_gc_new_with_values (widget
->window
,
2375 /* create sheet_entry_window */
2377 if(GTK_WIDGET_NO_WINDOW(sheet
->sheet_entry
)){
2379 attributes
.window_type
= GDK_WINDOW_CHILD
;
2382 attributes
.width
= sheet
->sheet_entry
->requisition
.width
;
2383 attributes
.height
= sheet
->sheet_entry
->requisition
.height
;
2384 attributes
.wclass
= GDK_INPUT_OUTPUT
;
2385 attributes
.visual
= gtk_widget_get_visual (widget
);
2386 attributes
.colormap
= gtk_widget_get_colormap (widget
);
2387 attributes
.event_mask
= GDK_EXPOSURE_MASK
;
2389 attributes_mask
= GDK_WA_X
| GDK_WA_Y
| GDK_WA_VISUAL
| GDK_WA_COLORMAP
;
2390 sheet
->sheet_entry_window
= gdk_window_new (sheet
->sheet_window
,
2391 &attributes
, attributes_mask
);
2392 gdk_window_set_user_data (sheet
->sheet_entry_window
, widget
);
2395 if(sheet
->sheet_entry
->parent
){
2396 gtk_widget_ref(sheet
->sheet_entry
);
2397 gtk_widget_unparent(sheet
->sheet_entry
);
2399 gtk_widget_set_parent(sheet
->sheet_entry
, GTK_WIDGET(sheet
));
2400 gtk_widget_set_parent_window (sheet
->sheet_entry
,
2401 sheet
->sheet_entry_window
?
2402 sheet
->sheet_entry_window
:
2403 sheet
->sheet_window
);
2405 if(sheet
->button
&& sheet
->button
->parent
){
2406 gtk_widget_ref(sheet
->button
);
2407 gtk_widget_unparent(sheet
->button
);
2409 gtk_widget_set_parent(sheet
->button
, GTK_WIDGET(sheet
));
2410 gtk_widget_set_parent_window(sheet
->button
, sheet
->sheet_window
);
2412 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col);
2414 if(!sheet
->cursor_drag
)
2415 sheet
->cursor_drag
= gdk_cursor_new(GDK_PLUS
);
2417 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
2418 gdk_window_show(sheet
->column_title_window
);
2419 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
2420 gdk_window_show(sheet
->row_title_window
);
2422 size_allocate_row_title_buttons(sheet
);
2423 size_allocate_column_title_buttons(sheet
);
2425 name
= g_strdup(sheet
->name
);
2426 gtk_sheet_set_title(sheet
, name
);
2430 children
= sheet
->children
;
2433 child
= children
->data
;
2434 children
= children
->next
;
2436 gtk_sheet_realize_child(sheet
, child
);
2441 create_global_button(GtkSheet
*sheet
)
2443 sheet
->button
= gtk_button_new_with_label(" ");
2445 gtk_widget_ensure_style(sheet
->button
);
2446 gtk_widget_show(sheet
->button
);
2448 gtk_signal_connect (GTK_OBJECT (sheet
->button
),
2450 (GtkSignalFunc
) global_button_clicked
,
2455 size_allocate_global_button(GtkSheet
*sheet
)
2457 GtkAllocation allocation
;
2459 if(!GTK_SHEET_COL_TITLES_VISIBLE(sheet
)) return;
2460 if(!GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)) return;
2462 gtk_widget_size_request(sheet
->button
, NULL
);
2466 allocation
.width
=sheet
->row_title_area
.width
;
2467 allocation
.height
=sheet
->column_title_area
.height
;
2469 gtk_widget_size_allocate(sheet
->button
, &allocation
);
2470 gtk_widget_show(sheet
->button
);
2474 global_button_clicked(GtkWidget
*widget
, gpointer data
)
2478 gtk_sheet_click_cell(GTK_SHEET(data
), -1, -1, &veto
);
2479 gtk_widget_grab_focus(GTK_WIDGET(data
));
2484 gtk_sheet_unrealize (GtkWidget
* widget
)
2487 GtkSheetChild
*child
;
2490 g_return_if_fail (widget
!= NULL
);
2491 g_return_if_fail (GTK_IS_SHEET (widget
));
2493 sheet
= GTK_SHEET (widget
);
2494 GTK_WIDGET_UNSET_FLAGS (widget
, GTK_REALIZED
| GTK_MAPPED
);
2496 gdk_cursor_destroy (sheet
->cursor_drag
);
2498 gdk_gc_destroy (sheet
->xor_gc
);
2499 gdk_gc_destroy (sheet
->fg_gc
);
2500 gdk_gc_destroy (sheet
->bg_gc
);
2502 gtk_style_detach (widget
->style
);
2504 gdk_window_destroy (sheet
->sheet_window
);
2505 gdk_window_destroy (sheet
->column_title_window
);
2506 gdk_window_destroy (sheet
->row_title_window
);
2507 gdk_window_set_user_data (widget
->window
, NULL
);
2508 gdk_window_destroy (widget
->window
);
2511 g_free (sheet
->pixmap
);
2512 sheet
->pixmap
= NULL
;
2515 widget
->window
= NULL
;
2516 sheet
->column_title_window
=NULL
;
2517 sheet
->sheet_window
= NULL
;
2518 sheet
->sheet_entry_window
= NULL
;
2519 sheet
->cursor_drag
= NULL
;
2520 sheet
->xor_gc
= NULL
;
2521 sheet
->fg_gc
= NULL
;
2522 sheet
->bg_gc
= NULL
;
2524 children
= sheet
->children
;
2527 child
= children
->data
;
2528 children
= children
->next
;
2532 gdk_window_set_user_data(child
->window
, NULL
);
2533 gdk_window_destroy(child
->window
);
2534 child
->window
= NULL
;
2542 gtk_sheet_map (GtkWidget
* widget
)
2545 GtkSheetChild
*child
;
2548 g_return_if_fail (widget
!= NULL
);
2549 g_return_if_fail (GTK_IS_SHEET (widget
));
2551 sheet
= GTK_SHEET (widget
);
2553 if (!GTK_WIDGET_MAPPED (widget
))
2555 GTK_WIDGET_SET_FLAGS (widget
, GTK_MAPPED
);
2557 if(!sheet
->cursor_drag
) sheet
->cursor_drag
=gdk_cursor_new(GDK_PLUS
);
2559 gdk_window_show (widget
->window
);
2561 gdk_window_show (sheet
->sheet_window
);
2563 if(sheet
->sheet_entry_window
)
2564 gdk_window_show(sheet
->sheet_entry_window
);
2566 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
)){
2567 gdk_window_show (sheet
->column_title_window
);
2569 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)){
2570 gdk_window_show (sheet
->row_title_window
);
2573 if(!GTK_WIDGET_MAPPED (sheet
->sheet_entry
)){
2574 gtk_widget_show (sheet
->sheet_entry
);
2575 gtk_widget_map (sheet
->sheet_entry
);
2578 if (GTK_WIDGET_VISIBLE (sheet
->button
) &&
2579 !GTK_WIDGET_MAPPED (sheet
->button
)){
2580 gtk_widget_show(sheet
->button
);
2581 gtk_widget_map (sheet
->button
);
2584 if(GTK_BIN(sheet
->button
)->child
)
2585 if (GTK_WIDGET_VISIBLE (GTK_BIN(sheet
->button
)->child
) &&
2586 !GTK_WIDGET_MAPPED (GTK_BIN(sheet
->button
)->child
))
2587 gtk_widget_map (GTK_BIN(sheet
->button
)->child
);
2589 gtk_sheet_range_draw(sheet
, NULL
);
2590 gtk_sheet_activate_cell(sheet
,
2591 sheet
->active_cell
.row
,
2592 sheet
->active_cell
.col
);
2594 children
= sheet
->children
;
2597 child
= children
->data
;
2598 children
= children
->next
;
2600 if (GTK_WIDGET_VISIBLE (child
->widget
) &&
2601 !GTK_WIDGET_MAPPED (child
->widget
)){
2602 gtk_widget_map (child
->widget
);
2603 gtk_sheet_position_child(sheet
, child
);
2604 if (GTK_WIDGET_NO_WINDOW(child
->widget
) && child
->window
)
2605 gdk_window_show(child
->window
);
2613 gtk_sheet_unmap (GtkWidget
* widget
)
2616 GtkSheetChild
*child
;
2619 g_return_if_fail (widget
!= NULL
);
2620 g_return_if_fail (GTK_IS_SHEET (widget
));
2622 sheet
= GTK_SHEET (widget
);
2624 if (GTK_WIDGET_MAPPED (widget
))
2626 GTK_WIDGET_UNSET_FLAGS (widget
, GTK_MAPPED
);
2628 gdk_window_hide (sheet
->sheet_window
);
2629 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
2630 gdk_window_hide (sheet
->column_title_window
);
2631 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
2632 gdk_window_hide (sheet
->row_title_window
);
2633 gdk_window_hide (widget
->window
);
2635 if(sheet
->sheet_entry_window
)
2636 gdk_window_hide (sheet
->sheet_entry_window
);
2638 if (GTK_WIDGET_MAPPED (sheet
->sheet_entry
))
2639 gtk_widget_unmap (sheet
->sheet_entry
);
2641 if (GTK_WIDGET_MAPPED (sheet
->button
))
2642 gtk_widget_unmap (sheet
->button
);
2644 children
= sheet
->children
;
2647 child
= children
->data
;
2648 children
= children
->next
;
2650 if (GTK_WIDGET_VISIBLE (child
->widget
) &&
2651 GTK_WIDGET_MAPPED (child
->widget
))
2653 gtk_widget_unmap (child
->widget
);
2654 if(child
->window
) gdk_window_hide(child
->window
);
2663 gtk_sheet_cell_draw_default (GtkSheet
*sheet
, gint row
, gint col
)
2666 GdkGC
*fg_gc
, *bg_gc
;
2667 GtkSheetCellAttr attributes
;
2670 g_return_if_fail (sheet
!= NULL
);
2672 /* bail now if we arn't drawable yet */
2673 if (!GTK_WIDGET_DRAWABLE (sheet
)) return;
2675 if (row
< 0 || row
> sheet
->maxrow
) return;
2676 if (col
< 0 || col
> sheet
->maxcol
) return;
2677 if (!sheet
->column
[col
].is_visible
) return;
2678 if (!sheet
->row
[row
].is_visible
) return;
2680 widget
= GTK_WIDGET (sheet
);
2682 gtk_sheet_get_attributes(sheet
, row
, col
, &attributes
);
2684 /* select GC for background rectangle */
2685 gdk_gc_set_foreground (sheet
->fg_gc
, &attributes
.foreground
);
2686 gdk_gc_set_foreground (sheet
->bg_gc
, &attributes
.background
);
2688 fg_gc
= sheet
->fg_gc
;
2689 bg_gc
= sheet
->bg_gc
;
2691 area
.x
=COLUMN_LEFT_XPIXEL(sheet
,col
);
2692 area
.y
=ROW_TOP_YPIXEL(sheet
,row
);
2693 area
.width
=sheet
->column
[col
].width
;
2694 area
.height
=sheet
->row
[row
].height
;
2696 gdk_draw_rectangle (sheet
->pixmap
,
2704 gdk_gc_set_line_attributes (sheet
->fg_gc
, 1, 0, 0, 0);
2706 if(sheet
->show_grid
&& attributes
.background
.pixel
== sheet
->bg_color
.pixel
){
2707 gdk_gc_set_foreground (sheet
->bg_gc
, &sheet
->grid_color
);
2708 gdk_draw_rectangle (sheet
->pixmap
,
2712 area
.width
, area
.height
);
2717 gtk_sheet_cell_draw_border (GtkSheet
*sheet
, gint row
, gint col
, gint mask
)
2720 GdkGC
*fg_gc
, *bg_gc
;
2721 GtkSheetCellAttr attributes
;
2725 g_return_if_fail (sheet
!= NULL
);
2727 /* bail now if we arn't drawable yet */
2728 if (!GTK_WIDGET_DRAWABLE (sheet
)) return;
2730 if (row
< 0 || row
> sheet
->maxrow
) return;
2731 if (col
< 0 || col
> sheet
->maxcol
) return;
2732 if (!sheet
->column
[col
].is_visible
) return;
2733 if (!sheet
->row
[row
].is_visible
) return;
2735 widget
= GTK_WIDGET (sheet
);
2737 gtk_sheet_get_attributes(sheet
, row
, col
, &attributes
);
2739 /* select GC for background rectangle */
2740 gdk_gc_set_foreground (sheet
->fg_gc
, &attributes
.border
.color
);
2741 gdk_gc_set_foreground (sheet
->bg_gc
, &attributes
.background
);
2743 fg_gc
= sheet
->fg_gc
;
2744 bg_gc
= sheet
->bg_gc
;
2746 area
.x
=COLUMN_LEFT_XPIXEL(sheet
,col
);
2747 area
.y
=ROW_TOP_YPIXEL(sheet
,row
);
2748 area
.width
=sheet
->column
[col
].width
;
2749 area
.height
=sheet
->row
[row
].height
;
2751 width
= attributes
.border
.width
;
2752 gdk_gc_set_line_attributes(sheet
->fg_gc
, attributes
.border
.width
,
2753 attributes
.border
.line_style
,
2754 attributes
.border
.cap_style
,
2755 attributes
.border
.join_style
);
2758 if(attributes
.border
.mask
& GTK_SHEET_LEFT_BORDER
& mask
)
2759 gdk_draw_line(sheet
->pixmap
, sheet
->fg_gc
,
2760 area
.x
, area
.y
-width
/2,
2761 area
.x
, area
.y
+area
.height
+width
/2+1);
2763 if(attributes
.border
.mask
& GTK_SHEET_RIGHT_BORDER
& mask
)
2764 gdk_draw_line(sheet
->pixmap
, sheet
->fg_gc
,
2765 area
.x
+area
.width
, area
.y
-width
/2,
2767 area
.y
+area
.height
+width
/2+1);
2769 if(attributes
.border
.mask
& GTK_SHEET_TOP_BORDER
& mask
)
2770 gdk_draw_line(sheet
->pixmap
, sheet
->fg_gc
,
2771 area
.x
-width
/2,area
.y
,
2772 area
.x
+area
.width
+width
/2+1,
2775 if(attributes
.border
.mask
& GTK_SHEET_BOTTOM_BORDER
& mask
)
2776 gdk_draw_line(sheet
->pixmap
, sheet
->fg_gc
,
2777 area
.x
-width
/2, area
.y
+area
.height
,
2778 area
.x
+area
.width
+width
/2+1,
2779 area
.y
+area
.height
);
2787 gtk_sheet_cell_draw_label (GtkSheet
*sheet
, gint row
, gint col
)
2790 GdkRectangle area
, clip_area
;
2792 gint text_width
, text_height
, y
;
2794 gint size
, sizel
, sizer
;
2795 GdkGC
*fg_gc
, *bg_gc
;
2796 GtkSheetCellAttr attributes
;
2799 g_return_if_fail (sheet
!= NULL
);
2801 /* bail now if we arn't drawable yet */
2802 if (!GTK_WIDGET_DRAWABLE (sheet
))
2805 if (row
> sheet
->maxallocrow
) return;
2806 if (col
> sheet
->maxalloccol
) return;
2807 if (!sheet
->data
[row
]) return;
2808 if (!sheet
->data
[row
][col
]) return;
2809 if (!sheet
->data
[row
][col
]->text
|| strlen(sheet
->data
[row
][col
]->text
)==0)
2812 if (row
< 0 || row
> sheet
->maxrow
) return;
2813 if (col
< 0 || col
> sheet
->maxcol
) return;
2814 if (!sheet
->column
[col
].is_visible
) return;
2815 if (!sheet
->row
[row
].is_visible
) return;
2818 widget
= GTK_WIDGET(sheet
);
2820 label
= sheet
->data
[row
][col
]->text
;
2822 gtk_sheet_get_attributes(sheet
, row
, col
, &attributes
);
2824 /* select GC for background rectangle */
2825 gdk_gc_set_foreground (sheet
->fg_gc
, &attributes
.foreground
);
2826 gdk_gc_set_foreground (sheet
->bg_gc
, &attributes
.background
);
2827 gdk_gc_set_font(sheet
->fg_gc
, attributes
.font
);
2829 fg_gc
= sheet
->fg_gc
;
2830 bg_gc
= sheet
->bg_gc
;
2832 area
.x
=COLUMN_LEFT_XPIXEL(sheet
,col
);
2833 area
.y
=ROW_TOP_YPIXEL(sheet
,row
);
2834 area
.width
=sheet
->column
[col
].width
;
2835 area
.height
=sheet
->row
[row
].height
;
2839 text_width
= gdk_string_width (attributes
.font
, label
);
2840 text_height
= attributes
.font
->ascent
+ attributes
.font
->descent
;
2841 y
= area
.y
+ area
.height
- CELLOFFSET
;
2842 y
= y
- text_height
+ attributes
.font
->ascent
;
2844 switch(attributes
.justification
){
2845 case GTK_JUSTIFY_RIGHT
:
2848 if(!GTK_SHEET_CLIP_TEXT(sheet
)){
2849 for(i
=col
-1; i
>=MIN_VISIBLE_COLUMN(sheet
); i
--){
2850 if(gtk_sheet_cell_get_text(sheet
, row
, i
)) break;
2851 if(size
>=text_width
+CELLOFFSET
) break;
2852 size
+=sheet
->column
[i
].width
;
2853 sheet
->column
[i
].right_text_column
= MAX(col
, sheet
->column
[i
].right_text_column
);
2858 xoffset
+=area
.width
-text_width
- 2 * CELLOFFSET
-
2859 attributes
.border
.width
/2;
2861 case GTK_JUSTIFY_CENTER
:
2864 area
.x
+=area
.width
/2;
2865 if(!GTK_SHEET_CLIP_TEXT(sheet
)){
2866 for(i
=col
+1; i
<=MAX_VISIBLE_COLUMN(sheet
); i
++){
2867 if(gtk_sheet_cell_get_text(sheet
, row
, i
)) break;
2868 if(sizer
>=text_width
/2) break;
2869 sizer
+=sheet
->column
[i
].width
;
2870 sheet
->column
[i
].left_text_column
= MIN(col
, sheet
->column
[i
].left_text_column
);
2872 for(i
=col
-1; i
>=MIN_VISIBLE_COLUMN(sheet
); i
--){
2873 if(gtk_sheet_cell_get_text(sheet
, row
, i
)) break;
2874 if(sizel
>=text_width
/2) break;
2875 sizel
+=sheet
->column
[i
].width
;
2876 sheet
->column
[i
].right_text_column
= MAX(col
, sheet
->column
[i
].right_text_column
);
2878 size
=MIN(sizel
, sizer
);
2881 xoffset
+= sizel
- text_width
/2 - CELLOFFSET
;
2882 area
.width
=sizel
+sizer
;
2884 case GTK_JUSTIFY_LEFT
:
2887 if(!GTK_SHEET_CLIP_TEXT(sheet
)){
2888 for(i
=col
+1; i
<=MAX_VISIBLE_COLUMN(sheet
); i
++){
2889 if(gtk_sheet_cell_get_text(sheet
, row
, i
)) break;
2890 if(size
>=text_width
+CELLOFFSET
) break;
2891 size
+=sheet
->column
[i
].width
;
2892 sheet
->column
[i
].left_text_column
= MIN(col
, sheet
->column
[i
].left_text_column
);
2896 xoffset
+= attributes
.border
.width
/2;
2900 if(!GTK_SHEET_CLIP_TEXT(sheet
)) clip_area
= area
;
2901 gdk_gc_set_clip_rectangle(fg_gc
, &clip_area
);
2903 gdk_draw_string (sheet
->pixmap
,
2906 area
.x
+ xoffset
+ CELLOFFSET
,
2910 gdk_gc_set_clip_rectangle(fg_gc
, NULL
);
2912 gdk_draw_pixmap(sheet
->sheet_window
,
2913 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
2928 gtk_sheet_range_draw(GtkSheet
*sheet
, const GtkSheetRange
*range
)
2931 GtkSheetRange drawing_range
;
2934 g_return_if_fail(sheet
!= NULL
);
2935 g_return_if_fail(GTK_SHEET(sheet
));
2937 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet
))) return;
2938 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return;
2939 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet
))) return;
2943 drawing_range
.row0
=MIN_VISIBLE_ROW(sheet
);
2944 drawing_range
.col0
=MIN_VISIBLE_COLUMN(sheet
);
2945 drawing_range
.rowi
=MAX_VISIBLE_ROW(sheet
);
2946 drawing_range
.coli
=MAX_VISIBLE_COLUMN(sheet
);
2948 gdk_draw_rectangle (sheet->pixmap,
2949 GTK_WIDGET(sheet)->style->white_gc,
2952 sheet->sheet_window_width,sheet->sheet_window_height);
2957 drawing_range
.row0
=MAX(range
->row0
, MIN_VISIBLE_ROW(sheet
));
2958 drawing_range
.col0
=MAX(range
->col0
, MIN_VISIBLE_COLUMN(sheet
));
2959 drawing_range
.rowi
=MIN(range
->rowi
, MAX_VISIBLE_ROW(sheet
));
2960 drawing_range
.coli
=MIN(range
->coli
, MAX_VISIBLE_COLUMN(sheet
));
2963 if(drawing_range
.coli
== sheet
->maxcol
){
2964 area
.x
=COLUMN_LEFT_XPIXEL(sheet
,sheet
->maxcol
)+
2965 sheet
->column
[sheet
->maxcol
].width
+1;
2968 gdk_gc_set_foreground(sheet
->fg_gc
, &sheet
->bg_color
);
2969 gdk_draw_rectangle (sheet
->pixmap
,
2973 sheet
->sheet_window_width
- area
.x
,
2974 sheet
->sheet_window_height
);
2975 gdk_draw_pixmap(sheet
->sheet_window
,
2976 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
2982 sheet
->sheet_window_width
- area
.x
,
2983 sheet
->sheet_window_height
);
2986 if(drawing_range
.rowi
== sheet
->maxrow
){
2988 area
.y
=ROW_TOP_YPIXEL(sheet
,sheet
->maxrow
)+sheet
->row
[sheet
->maxrow
].height
+1;
2990 gdk_gc_set_foreground(sheet
->fg_gc
, &sheet
->bg_color
);
2991 gdk_draw_rectangle (sheet
->pixmap
,
2995 sheet
->sheet_window_width
,
2996 sheet
->sheet_window_height
- area
.y
);
2998 gdk_draw_pixmap(sheet
->sheet_window
,
2999 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
3005 sheet
->sheet_window_width
,
3006 sheet
->sheet_window_height
- area
.y
);
3009 for(i
=drawing_range
.row0
; i
<=drawing_range
.rowi
; i
++)
3010 for(j
=drawing_range
.col0
; j
<=drawing_range
.coli
; j
++){
3011 gtk_sheet_cell_draw_default(sheet
, i
, j
);
3014 for(i
=drawing_range
.row0
; i
<=drawing_range
.rowi
; i
++)
3015 for(j
=drawing_range
.col0
; j
<=drawing_range
.coli
; j
++){
3016 gtk_sheet_cell_draw_border(sheet
, i
-1, j
, GTK_SHEET_BOTTOM_BORDER
);
3017 gtk_sheet_cell_draw_border(sheet
, i
+1, j
, GTK_SHEET_TOP_BORDER
);
3018 gtk_sheet_cell_draw_border(sheet
, i
, j
-1, GTK_SHEET_RIGHT_BORDER
);
3019 gtk_sheet_cell_draw_border(sheet
, i
, j
+1, GTK_SHEET_LEFT_BORDER
);
3020 gtk_sheet_cell_draw_border(sheet
, i
, j
, 15);
3023 for(i
=drawing_range
.row0
; i
<=drawing_range
.rowi
; i
++)
3024 for(j
=drawing_range
.col0
; j
<=drawing_range
.coli
; j
++)
3025 if(i
<=sheet
->maxallocrow
&& j
<=sheet
->maxalloccol
&&
3026 sheet
->data
[i
] && sheet
->data
[i
][j
])
3027 gtk_sheet_cell_draw_label (sheet
, i
, j
);
3029 for(i
=drawing_range
.row0
; i
<=drawing_range
.rowi
; i
++)
3030 for(j
=sheet
->column
[drawing_range
.col0
].left_text_column
; j
<drawing_range
.col0
; j
++)
3031 if(i
<=sheet
->maxallocrow
&& j
<=sheet
->maxalloccol
&&
3032 sheet
->data
[i
] && sheet
->data
[i
][j
])
3033 gtk_sheet_cell_draw_label (sheet
, i
, j
);
3035 for(i
=drawing_range
.row0
; i
<=drawing_range
.rowi
; i
++)
3036 for(j
=drawing_range
.coli
+1; j
<=sheet
->column
[drawing_range
.coli
].right_text_column
; j
++)
3037 if(i
<=sheet
->maxallocrow
&& j
<=sheet
->maxalloccol
&&
3038 sheet
->data
[i
] && sheet
->data
[i
][j
])
3039 gtk_sheet_cell_draw_label (sheet
, i
, j
);
3041 gtk_sheet_draw_backing_pixmap(sheet
, drawing_range
);
3043 if(sheet
->state
!= GTK_SHEET_NORMAL
&& gtk_sheet_range_isvisible(sheet
, sheet
->range
))
3044 gtk_sheet_range_draw_selection(sheet
, drawing_range
);
3046 if(sheet
->state
== GTK_STATE_NORMAL
&&
3047 sheet
->active_cell
.row
>= drawing_range
.row0
&&
3048 sheet
->active_cell
.row
<= drawing_range
.rowi
&&
3049 sheet
->active_cell
.col
>= drawing_range
.col0
&&
3050 sheet
->active_cell
.col
<= drawing_range
.coli
)
3051 gtk_sheet_show_active_cell(sheet
);
3055 gtk_sheet_range_draw_selection(GtkSheet
*sheet
, GtkSheetRange range
)
3061 if(range
.col0
> sheet
->range
.coli
|| range
.coli
< sheet
->range
.col0
||
3062 range
.row0
> sheet
->range
.rowi
|| range
.rowi
< sheet
->range
.row0
)
3065 if(!gtk_sheet_range_isvisible(sheet
, range
)) return;
3066 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return;
3070 range
.col0
=MAX(sheet
->range
.col0
, range
.col0
);
3071 range
.coli
=MIN(sheet
->range
.coli
, range
.coli
);
3072 range
.row0
=MAX(sheet
->range
.row0
, range
.row0
);
3073 range
.rowi
=MIN(sheet
->range
.rowi
, range
.rowi
);
3075 range
.col0
=MAX(range
.col0
, MIN_VISIBLE_COLUMN(sheet
));
3076 range
.coli
=MIN(range
.coli
, MAX_VISIBLE_COLUMN(sheet
));
3077 range
.row0
=MAX(range
.row0
, MIN_VISIBLE_ROW(sheet
));
3078 range
.rowi
=MIN(range
.rowi
, MAX_VISIBLE_ROW(sheet
));
3080 for(i
=range
.row0
; i
<=range
.rowi
; i
++){
3081 for(j
=range
.col0
; j
<=range
.coli
; j
++){
3083 if(gtk_sheet_cell_get_state(sheet
, i
, j
)==GTK_STATE_SELECTED
&&
3084 sheet
->column
[j
].is_visible
&& sheet
->row
[i
].is_visible
){
3086 row_button_set(sheet
, i
);
3087 column_button_set(sheet
, j
);
3089 area
.x
=COLUMN_LEFT_XPIXEL(sheet
,j
);
3090 area
.y
=ROW_TOP_YPIXEL(sheet
,i
);
3091 area
.width
=sheet
->column
[j
].width
;
3092 area
.height
=sheet
->row
[i
].height
;
3094 if(i
==sheet
->range
.row0
){
3096 area
.height
=area
.height
-2;
3098 if(i
==sheet
->range
.rowi
) area
.height
=area
.height
-3;
3099 if(j
==sheet
->range
.col0
){
3101 area
.width
=area
.width
-2;
3103 if(j
==sheet
->range
.coli
) area
.width
=area
.width
-3;
3105 if(i
!=sheet
->active_cell
.row
|| j
!=sheet
->active_cell
.col
){
3106 gdk_draw_rectangle (sheet
->sheet_window
,
3110 area
.width
,area
.height
);
3117 gtk_sheet_draw_border(sheet
, sheet
->range
);
3122 gtk_sheet_draw_backing_pixmap(GtkSheet
*sheet
, GtkSheetRange range
)
3124 gint x
,y
,width
,height
;
3126 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return;
3128 x
=COLUMN_LEFT_XPIXEL(sheet
,range
.col0
);
3129 y
=ROW_TOP_YPIXEL(sheet
, range
.row0
);
3130 width
=COLUMN_LEFT_XPIXEL(sheet
, range
.coli
)-x
+sheet
->column
[range
.coli
].width
;
3131 height
=ROW_TOP_YPIXEL(sheet
, range
.rowi
)-y
+sheet
->row
[range
.rowi
].height
;
3133 if(range
.row0
==sheet
->range
.row0
){
3137 if(range
.rowi
==sheet
->range
.rowi
) height
=height
+5;
3138 if(range
.col0
==sheet
->range
.col0
){
3142 if(range
.coli
==sheet
->range
.coli
) width
=width
+5;
3145 width
=MIN(width
, sheet
->sheet_window_width
-x
);
3146 height
=MIN(height
, sheet
->sheet_window_height
-y
);
3153 x
= (GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
3154 ? MAX(x
, sheet
->row_title_area
.width
) : MAX(x
, 0);
3155 y
= (GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
3156 ? MAX(y
, sheet
->column_title_area
.height
) : MAX(y
, 0);
3158 if(range
.coli
==sheet
->maxcol
) width
=sheet
->sheet_window_width
-x
;
3159 if(range
.rowi
==sheet
->maxrow
) height
=sheet
->sheet_window_height
-y
;
3161 gdk_draw_pixmap(sheet
->sheet_window
,
3162 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
3173 static GtkSheetCell
*
3174 gtk_sheet_cell_new()
3177 cell
= g_new(GtkSheetCell
, 1);
3180 cell
->attributes
= NULL
;
3185 gtk_sheet_set_cell_text(GtkSheet
*sheet
, gint row
, gint col
, const gchar
*text
)
3187 GtkSheetCellAttr attributes
;
3189 g_return_if_fail (sheet
!= NULL
);
3190 g_return_if_fail (GTK_IS_SHEET (sheet
));
3191 if (col
> sheet
->maxcol
|| row
> sheet
->maxrow
) return;
3192 if (col
< 0 || row
< 0) return;
3194 gtk_sheet_get_attributes(sheet
, row
, col
, &attributes
);
3195 gtk_sheet_set_cell(sheet
, row
, col
, attributes
.justification
, text
);
3199 gtk_sheet_set_cell(GtkSheet
*sheet
, gint row
, gint col
,
3200 GtkJustification justification
,
3203 GtkSheetCell
**cell
;
3204 GtkSheetRange range
;
3206 GtkSheetCellAttr attributes
;
3208 g_return_if_fail (sheet
!= NULL
);
3209 g_return_if_fail (GTK_IS_SHEET (sheet
));
3210 if (col
> sheet
->maxcol
|| row
> sheet
->maxrow
) return;
3211 if (col
< 0 || row
< 0) return;
3213 CheckBounds(sheet
, row
, col
);
3215 cell
=&sheet
->data
[row
][col
];
3218 (*cell
) = gtk_sheet_cell_new();
3220 gtk_sheet_get_attributes(sheet
, row
, col
, &attributes
);
3225 attributes
.justification
= justification
;
3226 gtk_sheet_set_cell_attributes(sheet
, row
, col
, attributes
);
3229 g_free((*cell
)->text
);
3230 (*cell
)->text
= NULL
;
3234 (*cell
)->text
=g_strdup(text
);
3236 if(attributes
.is_visible
){
3239 if((*cell
)->text
&& strlen((*cell
)->text
) > 0) {
3240 text_width
= gdk_string_width (attributes
.font
, (*cell
)->text
);
3245 range
.col0
= sheet
->view
.col0
;
3246 range
.coli
= sheet
->view
.coli
;
3248 if(GTK_SHEET_AUTORESIZE(sheet
) &&
3249 text_width
> sheet
->column
[col
].width
-2*CELLOFFSET
-attributes
.border
.width
){
3250 gtk_sheet_set_column_width(sheet
, col
, text_width
+2*CELLOFFSET
+attributes
.border
.width
);
3253 if(!GTK_SHEET_IS_FROZEN(sheet
))
3254 gtk_sheet_range_draw(sheet
, &range
);
3257 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[CHANGED
], row
, col
);
3262 gtk_sheet_cell_clear (GtkSheet
*sheet
, gint row
, gint column
)
3264 GtkSheetRange range
;
3266 g_return_if_fail (sheet
!= NULL
);
3267 g_return_if_fail (GTK_IS_SHEET (sheet
));
3268 if (column
> sheet
->maxcol
|| row
> sheet
->maxrow
) return;
3269 if (column
> sheet
->maxalloccol
|| row
> sheet
->maxallocrow
) return;
3270 if (column
< 0 || row
< 0) return;
3274 range
.col0
= sheet
->view
.col0
;
3275 range
.coli
= sheet
->view
.coli
;
3277 gtk_sheet_real_cell_clear(sheet
, row
, column
, FALSE
);
3279 if(!GTK_SHEET_IS_FROZEN(sheet
)){
3280 gtk_sheet_range_draw(sheet
, &range
);
3285 gtk_sheet_cell_delete (GtkSheet
*sheet
, gint row
, gint column
)
3287 GtkSheetRange range
;
3289 g_return_if_fail (sheet
!= NULL
);
3290 g_return_if_fail (GTK_IS_SHEET (sheet
));
3291 if (column
> sheet
->maxcol
|| row
> sheet
->maxrow
) return;
3292 if (column
> sheet
->maxalloccol
|| row
> sheet
->maxallocrow
) return;
3293 if (column
< 0 || row
< 0) return;
3297 range
.col0
= sheet
->view
.col0
;
3298 range
.coli
= sheet
->view
.coli
;
3300 gtk_sheet_real_cell_clear(sheet
, row
, column
, TRUE
);
3302 if(!GTK_SHEET_IS_FROZEN(sheet
)){
3303 gtk_sheet_range_draw(sheet
, &range
);
3308 gtk_sheet_real_cell_clear (GtkSheet
*sheet
, gint row
, gint column
, gboolean
delete)
3313 if(row
> sheet
->maxallocrow
|| column
> sheet
->maxalloccol
) return;
3314 if(!sheet
->data
[row
]) return;
3315 if(!sheet
->data
[row
][column
]) return;
3317 text
= gtk_sheet_cell_get_text(sheet
, row
, column
);
3318 link
= gtk_sheet_get_link(sheet
, row
, column
);
3321 g_free(sheet
->data
[row
][column
]->text
);
3322 sheet
->data
[row
][column
]->text
= NULL
;
3324 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[CLEAR_CELL
], row
, column
);
3328 if(sheet
->data
[row
][column
]->attributes
){
3329 g_free(sheet
->data
[row
][column
]->attributes
);
3330 sheet
->data
[row
][column
]->attributes
= NULL
;
3332 sheet
->data
[row
][column
]->link
= NULL
;
3334 if(sheet
->data
[row
][column
]) g_free(sheet
->data
[row
][column
]);
3336 sheet
->data
[row
][column
] = NULL
;
3342 gtk_sheet_range_clear (GtkSheet
*sheet
, const GtkSheetRange
*range
)
3344 g_return_if_fail (sheet
!= NULL
);
3345 g_return_if_fail (GTK_IS_SHEET (sheet
));
3347 gtk_sheet_real_range_clear(sheet
, range
, FALSE
);
3351 gtk_sheet_range_delete (GtkSheet
*sheet
, const GtkSheetRange
*range
)
3353 g_return_if_fail (sheet
!= NULL
);
3354 g_return_if_fail (GTK_IS_SHEET (sheet
));
3356 gtk_sheet_real_range_clear(sheet
, range
, TRUE
);
3360 gtk_sheet_real_range_clear (GtkSheet
*sheet
, const GtkSheetRange
*range
,
3364 GtkSheetRange clear
;
3368 clear
.rowi
=sheet
->maxallocrow
;
3370 clear
.coli
=sheet
->maxalloccol
;
3374 clear
.row0
=MAX(clear
.row0
, 0);
3375 clear
.col0
=MAX(clear
.col0
, 0);
3376 clear
.rowi
=MIN(clear
.rowi
, sheet
->maxallocrow
);
3377 clear
.coli
=MIN(clear
.coli
, sheet
->maxalloccol
);
3379 for(i
=clear
.row0
; i
<=clear
.rowi
; i
++)
3380 for(j
=clear
.col0
; j
<=clear
.coli
; j
++){
3381 gtk_sheet_real_cell_clear(sheet
, i
, j
, delete);
3384 gtk_sheet_range_draw(sheet
, NULL
);
3389 gtk_sheet_cell_get_text (GtkSheet
*sheet
, gint row
, gint col
)
3391 g_return_val_if_fail (sheet
!= NULL
, NULL
);
3392 g_return_val_if_fail (GTK_IS_SHEET (sheet
), NULL
);
3394 if(col
> sheet
->maxcol
|| row
> sheet
->maxrow
) return NULL
;
3395 if(col
< 0 || row
< 0) return NULL
;
3396 if(row
> sheet
->maxallocrow
|| col
> sheet
->maxalloccol
) return NULL
;
3397 if(!sheet
->data
[row
]) return NULL
;
3398 if(!sheet
->data
[row
][col
]) return NULL
;
3399 if(!sheet
->data
[row
][col
]->text
) return NULL
;
3400 if(strlen(sheet
->data
[row
][col
]->text
) == 0) return NULL
;
3402 return (sheet
->data
[row
][col
]->text
);
3406 gtk_sheet_link_cell(GtkSheet
*sheet
, gint row
, gint col
, gpointer link
)
3408 g_return_if_fail (sheet
!= NULL
);
3409 g_return_if_fail (GTK_IS_SHEET (sheet
));
3410 if(col
> sheet
->maxcol
|| row
> sheet
->maxrow
) return;
3411 if(col
< 0 || row
< 0) return;
3413 if(row
> sheet
->maxallocrow
|| col
> sheet
->maxalloccol
||
3414 !sheet
->data
[row
] || !sheet
->data
[row
][col
])
3415 gtk_sheet_set_cell_text(sheet
, row
, col
, "");
3417 sheet
->data
[row
][col
]->link
= link
;
3421 gtk_sheet_get_link(GtkSheet
*sheet
, gint row
, gint col
)
3423 g_return_val_if_fail (sheet
!= NULL
, NULL
);
3424 g_return_val_if_fail (GTK_IS_SHEET (sheet
), NULL
);
3425 if(col
> sheet
->maxcol
|| row
> sheet
->maxrow
) return NULL
;
3426 if(col
< 0 || row
< 0) return NULL
;
3428 if (row
> sheet
->maxallocrow
|| col
> sheet
->maxalloccol
) return NULL
;
3429 if (!sheet
->data
[row
]) return NULL
; /* Added by Chris Howell */
3430 if (!sheet
->data
[row
][col
]) return NULL
; /* Added by Bob Lissner */
3432 return(sheet
->data
[row
][col
]->link
);
3436 gtk_sheet_remove_link(GtkSheet
*sheet
, gint row
, gint col
)
3438 g_return_if_fail (sheet
!= NULL
);
3439 g_return_if_fail (GTK_IS_SHEET (sheet
));
3440 if(col
> sheet
->maxcol
|| row
> sheet
->maxrow
) return;
3441 if(col
< 0 || row
< 0) return;
3443 /* Fixed by Andreas Voegele */
3444 if(row
< sheet
->maxallocrow
&& col
< sheet
->maxalloccol
&&
3445 sheet
->data
[row
] && sheet
->data
[row
][col
] &&
3446 sheet
->data
[row
][col
]->link
)
3447 sheet
->data
[row
][col
]->link
= NULL
;
3452 gtk_sheet_cell_get_state (GtkSheet
*sheet
, gint row
, gint col
)
3455 GtkSheetRange
*range
;
3457 g_return_val_if_fail (sheet
!= NULL
, 0);
3458 g_return_val_if_fail (GTK_IS_SHEET (sheet
), 0);
3459 if(col
> sheet
->maxcol
|| row
> sheet
->maxrow
) return 0;
3460 if(col
< 0 || row
< 0) return 0;
3462 state
= sheet
->state
;
3463 range
= &sheet
->range
;
3466 case GTK_SHEET_NORMAL
:
3467 return GTK_STATE_NORMAL
;
3469 case GTK_SHEET_ROW_SELECTED
:
3470 if(row
>=range
->row0
&& row
<=range
->rowi
)
3471 return GTK_STATE_SELECTED
;
3473 case GTK_SHEET_COLUMN_SELECTED
:
3474 if(col
>=range
->col0
&& col
<=range
->coli
)
3475 return GTK_STATE_SELECTED
;
3477 case GTK_SHEET_RANGE_SELECTED
:
3478 if(row
>= range
->row0
&& row
<= range
->rowi
&& \
3479 col
>= range
->col0
&& col
<= range
->coli
)
3480 return GTK_STATE_SELECTED
;
3483 return GTK_STATE_NORMAL
;
3487 gtk_sheet_get_pixel_info (GtkSheet
* sheet
,
3495 g_return_val_if_fail (sheet
!= NULL
, 0);
3496 g_return_val_if_fail (GTK_IS_SHEET (sheet
), 0);
3498 /* bounds checking, return false if the user clicked
3499 * on a blank area */
3500 trow
= ROW_FROM_YPIXEL (sheet
, y
);
3501 if (trow
> sheet
->maxrow
)
3506 tcol
= COLUMN_FROM_XPIXEL (sheet
, x
);
3507 if (tcol
> sheet
->maxcol
)
3516 gtk_sheet_get_cell_area (GtkSheet
* sheet
,
3521 g_return_val_if_fail (sheet
!= NULL
, 0);
3522 g_return_val_if_fail (GTK_IS_SHEET (sheet
), 0);
3524 if(row
> sheet
->maxrow
|| column
> sheet
->maxcol
) return FALSE
;
3526 area
->x
= (column
== -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet
, column
) -
3527 ((GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
3528 ? sheet
->row_title_area
.width
3530 area
->y
= (row
== -1) ? 0 : (ROW_TOP_YPIXEL(sheet
, row
) -
3531 ((GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
3532 ? sheet
->column_title_area
.height
3534 area
->width
= (column
== -1) ? sheet
->row_title_area
.width
3535 : sheet
->column
[column
].width
;
3536 area
->height
= (row
== -1) ? sheet
->column_title_area
.height
3537 : sheet
->row
[row
].height
;
3540 if(row < 0 || column < 0) return FALSE;
3542 area->x = COLUMN_LEFT_XPIXEL(sheet, column);
3543 area->y = ROW_TOP_YPIXEL(sheet, row);
3544 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
3545 area->x -= sheet->row_title_area.width;
3546 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
3547 area->y -= sheet->column_title_area.height;
3549 area->width=sheet->column[column].width;
3550 area->height=sheet->row[row].height;
3556 gtk_sheet_set_active_cell (GtkSheet
*sheet
, gint row
, gint column
)
3558 g_return_val_if_fail (sheet
!= NULL
, 0);
3559 g_return_val_if_fail (GTK_IS_SHEET (sheet
), 0);
3561 if(row
< 0 || column
< 0) return FALSE
;
3562 if(row
> sheet
->maxrow
|| column
> sheet
->maxcol
) return FALSE
;
3564 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
)))
3566 if(!gtk_sheet_deactivate_cell(sheet
)) return FALSE
;
3569 sheet
->active_cell
.row
=row
;
3570 sheet
->active_cell
.col
=column
;
3572 if(!gtk_sheet_activate_cell(sheet
, row
, column
)) return FALSE
;
3578 gtk_sheet_get_active_cell (GtkSheet
*sheet
, gint
*row
, gint
*column
)
3580 g_return_if_fail (sheet
!= NULL
);
3581 g_return_if_fail (GTK_IS_SHEET (sheet
));
3583 *row
= sheet
->active_cell
.row
;
3584 *column
= sheet
->active_cell
.col
;
3588 gtk_sheet_entry_changed(GtkWidget
*widget
, gpointer data
)
3593 GtkJustification justification
;
3594 GtkSheetCellAttr attributes
;
3596 g_return_if_fail (data
!= NULL
);
3597 g_return_if_fail (GTK_IS_SHEET (data
));
3599 sheet
=GTK_SHEET(data
);
3601 if(!GTK_WIDGET_VISIBLE(widget
)) return;
3602 if(sheet
->state
!= GTK_STATE_NORMAL
) return;
3604 row
=sheet
->active_cell
.row
;
3605 col
=sheet
->active_cell
.col
;
3607 if(row
<0 || col
<0) return;
3609 sheet
->active_cell
.row
=-1;
3610 sheet
->active_cell
.col
=-1;
3612 text
= (gchar
*) gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet
)));
3614 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_IS_FROZEN
);
3616 if(text
&& strlen(text
)!=0){
3617 gtk_sheet_get_attributes(sheet
, row
, col
, &attributes
);
3618 justification
=attributes
.justification
;
3619 gtk_sheet_set_cell(sheet
, row
, col
, justification
, text
);
3623 /* Added by Matias Mutchinick */
3624 gtk_sheet_cell_clear(sheet
, row
, col
);
3627 if(sheet
->freeze_count
== 0)
3628 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_IS_FROZEN
);
3630 sheet
->active_cell
.row
=row
;;
3631 sheet
->active_cell
.col
=col
;
3637 gtk_sheet_deactivate_cell(GtkSheet
*sheet
)
3639 gboolean veto
= TRUE
;
3641 g_return_val_if_fail (sheet
!= NULL
, FALSE
);
3642 g_return_val_if_fail (GTK_IS_SHEET (sheet
), FALSE
);
3644 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return FALSE
;
3645 if(sheet
->state
!= GTK_SHEET_NORMAL
) return FALSE
;
3646 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[DEACTIVATE
],
3647 sheet
->active_cell
.row
,
3648 sheet
->active_cell
.col
, &veto
);
3650 if(!veto
) return FALSE
;
3652 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet
)),
3653 (GtkSignalFunc
) gtk_sheet_entry_changed
,
3654 GTK_OBJECT(GTK_WIDGET(sheet
)));
3656 gtk_sheet_hide_active_cell(sheet
);
3658 sheet
->active_cell
.row
=-1;
3659 sheet
->active_cell
.col
=-1;
3665 gtk_sheet_hide_active_cell(GtkSheet
*sheet
)
3669 GtkJustification justification
;
3670 GtkSheetCellAttr attributes
;
3672 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return;
3674 row
=sheet
->active_cell
.row
;
3675 col
=sheet
->active_cell
.col
;
3677 if(row
< 0 || col
< 0) return;
3679 if(sheet
->freeze_count
== 0)
3680 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_IS_FROZEN
);
3682 text
= (gchar
*) gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet
)));
3684 gtk_sheet_get_attributes(sheet
, row
, col
, &attributes
);
3685 justification
=attributes
.justification
;
3687 if(text
&& strlen(text
)!=0){
3688 gtk_sheet_set_cell(sheet
, row
, col
, justification
, text
);
3689 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[SET_CELL
], row
, col
);
3693 gtk_sheet_cell_clear(sheet
, row
, col
);
3696 row
=sheet
->active_cell
.row
;
3697 col
=sheet
->active_cell
.col
;
3699 column_button_release(sheet
, col
);
3700 row_button_release(sheet
, row
);
3702 if(sheet
->sheet_entry_window
)
3703 gdk_window_hide(sheet
->sheet_entry_window
);
3705 gdk_window_hide(sheet
->sheet_entry
->window
);
3707 if(row
!= -1 && col
!= -1)
3708 gdk_draw_pixmap(sheet
->sheet_window
,
3709 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
3711 COLUMN_LEFT_XPIXEL(sheet
,col
)-1,
3712 ROW_TOP_YPIXEL(sheet
,row
)-1,
3713 COLUMN_LEFT_XPIXEL(sheet
,col
)-1,
3714 ROW_TOP_YPIXEL(sheet
,row
)-1,
3715 sheet
->column
[col
].width
+4,
3716 sheet
->row
[row
].height
+4);
3718 GTK_WIDGET_UNSET_FLAGS(sheet
->sheet_entry
, GTK_HAS_FOCUS
);
3719 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet
), GTK_HAS_FOCUS
);
3720 gtk_widget_grab_focus(GTK_WIDGET(sheet
));
3722 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet
->sheet_entry
), GTK_VISIBLE
);
3727 gtk_sheet_activate_cell(GtkSheet
*sheet
, gint row
, gint col
)
3729 gboolean veto
= TRUE
;
3731 g_return_val_if_fail (sheet
!= NULL
, FALSE
);
3732 g_return_val_if_fail (GTK_IS_SHEET (sheet
), FALSE
);
3734 if(row
< 0 || col
< 0) return FALSE
;
3735 if(row
> sheet
->maxrow
|| col
> sheet
->maxcol
) return FALSE
;
3737 /* gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto);
3738 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
3741 if(!veto
) return FALSE
;
3742 if(sheet
->state
!= GTK_SHEET_NORMAL
){
3743 sheet
->state
=GTK_SHEET_NORMAL
;
3744 gtk_sheet_real_unselect_range(sheet
, NULL
);
3747 sheet
->range
.row0
=row
;
3748 sheet
->range
.col0
=col
;
3749 sheet
->range
.rowi
=row
;
3750 sheet
->range
.coli
=col
;
3751 sheet
->active_cell
.row
=row
;
3752 sheet
->active_cell
.col
=col
;
3753 sheet
->selection_cell
.row
=row
;
3754 sheet
->selection_cell
.col
=col
;
3755 row_button_set(sheet
, row
);
3756 column_button_set(sheet
, col
);
3758 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_IN_SELECTION
);
3759 gtk_sheet_show_active_cell(sheet
);
3761 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet
)),
3763 (GtkSignalFunc
)gtk_sheet_entry_changed
,
3764 GTK_OBJECT(GTK_WIDGET(sheet
)));
3766 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[ACTIVATE
], row
, col
, &veto
);
3772 gtk_sheet_show_active_cell(GtkSheet
*sheet
)
3775 GtkEntry
*sheet_entry
;
3776 GtkSheetCellAttr attributes
;
3778 GtkJustification justification
;
3781 g_return_if_fail (sheet
!= NULL
);
3782 g_return_if_fail (GTK_IS_SHEET (sheet
));
3784 row
= sheet
->active_cell
.row
;
3785 col
= sheet
->active_cell
.col
;
3787 /* Don't show the active cell, if there is no active cell: */
3788 if(!(row
>= 0 && col
>= 0)) /* e.g row or coll == -1. */
3791 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return;
3792 if(sheet
->state
!= GTK_SHEET_NORMAL
) return;
3793 if(GTK_SHEET_IN_SELECTION(sheet
)) return;
3795 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet
->sheet_entry
), GTK_VISIBLE
);
3797 sheet_entry
= GTK_ENTRY(gtk_sheet_get_entry(sheet
));
3799 gtk_sheet_get_attributes(sheet
, row
, col
, &attributes
);
3801 justification
= GTK_JUSTIFY_LEFT
;
3803 if(GTK_SHEET_JUSTIFY_ENTRY(sheet
))
3804 justification
= attributes
.justification
;
3806 if(row
<= sheet
->maxallocrow
&& col
<= sheet
->maxalloccol
) {
3807 if(sheet
->data
[row
]) {
3808 if(sheet
->data
[row
][col
]) {
3809 cell
= sheet
->data
[row
][col
];
3811 text
= g_strdup(cell
->text
);
3816 if(!text
) text
= (gchar
*) g_strdup("");
3818 if(!GTK_IS_ITEM_ENTRY(sheet_entry
))
3819 gtk_entry_set_text(GTK_ENTRY(sheet_entry
), text
);
3821 gtk_item_entry_set_text(GTK_ITEM_ENTRY(sheet_entry
), (const gchar
*) text
, justification
);
3823 if(GTK_SHEET_IS_LOCKED(sheet
) || !attributes
.is_editable
)
3824 gtk_entry_set_editable(GTK_ENTRY(sheet_entry
), FALSE
);
3826 gtk_entry_set_editable(GTK_ENTRY(sheet_entry
), TRUE
);
3828 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry
), attributes
.is_visible
);
3830 gtk_sheet_entry_set_max_size(sheet
);
3831 gtk_sheet_size_allocate_entry(sheet
);
3833 if(GTK_WIDGET_REALIZED(sheet
->sheet_entry
)){
3834 if(sheet
->sheet_entry_window
)
3835 gdk_window_show(sheet
->sheet_entry_window
);
3837 gdk_window_show(sheet
->sheet_entry
->window
);
3838 gtk_widget_queue_draw(sheet
->sheet_entry
);
3840 gtk_sheet_draw_active_cell(sheet
);
3842 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry
));
3843 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet_entry
), GTK_HAS_FOCUS
);
3844 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet
), GTK_HAS_FOCUS
);
3850 gtk_sheet_draw_active_cell(GtkSheet
*sheet
)
3854 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet
))) return;
3855 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return;
3857 row
= sheet
->active_cell
.row
;
3858 col
= sheet
->active_cell
.col
;
3860 if(row
<0 || col
<0) return;
3862 if(!gtk_sheet_cell_isvisible(sheet
, row
, col
)) return;
3864 row_button_set(sheet
, row
);
3865 column_button_set(sheet
, col
);
3867 gtk_sheet_draw_backing_pixmap(sheet
, sheet
->range
);
3868 gtk_sheet_draw_border(sheet
, sheet
->range
);
3874 gtk_sheet_make_backing_pixmap (GtkSheet
*sheet
, guint width
, guint height
)
3876 gint pixmap_width
, pixmap_height
;
3878 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return;
3880 if(width
== 0 && height
== 0){
3881 width
=sheet
->sheet_window_width
+80;
3882 height
=sheet
->sheet_window_height
+80;
3888 sheet
->pixmap
= gdk_pixmap_new (sheet
->sheet_window
,
3891 if(!GTK_SHEET_IS_FROZEN(sheet
)) gtk_sheet_range_draw(sheet
, NULL
);
3895 /* reallocate if sizes don't match */
3896 gdk_window_get_size (sheet
->pixmap
,
3897 &pixmap_width
, &pixmap_height
);
3898 if ((pixmap_width
!= width
) || (pixmap_height
!= height
))
3900 g_free(sheet
->pixmap
);
3901 sheet
->pixmap
= gdk_pixmap_new (sheet
->sheet_window
,
3904 if(!GTK_SHEET_IS_FROZEN(sheet
)) gtk_sheet_range_draw(sheet
, NULL
);
3910 gtk_sheet_new_selection(GtkSheet
*sheet
, GtkSheetRange
*range
)
3912 gint i
,j
, mask1
, mask2
;
3913 gint state
, selected
;
3914 gint x
,y
,width
,height
;
3915 GtkSheetRange new_range
, aux_range
;
3917 g_return_if_fail (sheet
!= NULL
);
3919 if(range
==NULL
) range
=&sheet
->range
;
3923 range
->row0
=MIN(range
->row0
, sheet
->range
.row0
);
3924 range
->rowi
=MAX(range
->rowi
, sheet
->range
.rowi
);
3925 range
->col0
=MIN(range
->col0
, sheet
->range
.col0
);
3926 range
->coli
=MAX(range
->coli
, sheet
->range
.coli
);
3928 range
->row0
=MAX(range
->row0
, MIN_VISIBLE_ROW(sheet
));
3929 range
->rowi
=MIN(range
->rowi
, MAX_VISIBLE_ROW(sheet
));
3930 range
->col0
=MAX(range
->col0
, MIN_VISIBLE_COLUMN(sheet
));
3931 range
->coli
=MIN(range
->coli
, MAX_VISIBLE_COLUMN(sheet
));
3933 aux_range
.row0
=MAX(new_range
.row0
, MIN_VISIBLE_ROW(sheet
));
3934 aux_range
.rowi
=MIN(new_range
.rowi
, MAX_VISIBLE_ROW(sheet
));
3935 aux_range
.col0
=MAX(new_range
.col0
, MIN_VISIBLE_COLUMN(sheet
));
3936 aux_range
.coli
=MIN(new_range
.coli
, MAX_VISIBLE_COLUMN(sheet
));
3938 for(i
=range
->row0
; i
<=range
->rowi
; i
++){
3939 for(j
=range
->col0
; j
<=range
->coli
; j
++){
3941 state
=gtk_sheet_cell_get_state(sheet
, i
, j
);
3942 selected
=(i
<=new_range
.rowi
&& i
>=new_range
.row0
&&
3943 j
<=new_range
.coli
&& j
>=new_range
.col0
) ? TRUE
: FALSE
;
3945 if(state
==GTK_STATE_SELECTED
&& selected
&&
3946 sheet
->column
[j
].is_visible
&& sheet
->row
[i
].is_visible
&&
3947 (i
==sheet
->range
.row0
|| i
==sheet
->range
.rowi
||
3948 j
==sheet
->range
.col0
|| j
==sheet
->range
.coli
||
3949 i
==new_range
.row0
|| i
==new_range
.rowi
||
3950 j
==new_range
.col0
|| j
==new_range
.coli
)){
3952 mask1
= i
==sheet
->range
.row0
? 1 : 0;
3953 mask1
= i
==sheet
->range
.rowi
? mask1
+2 : mask1
;
3954 mask1
= j
==sheet
->range
.col0
? mask1
+4 : mask1
;
3955 mask1
= j
==sheet
->range
.coli
? mask1
+8 : mask1
;
3957 mask2
= i
==new_range
.row0
? 1 : 0;
3958 mask2
= i
==new_range
.rowi
? mask2
+2 : mask2
;
3959 mask2
= j
==new_range
.col0
? mask2
+4 : mask2
;
3960 mask2
= j
==new_range
.coli
? mask2
+8 : mask2
;
3963 x
=COLUMN_LEFT_XPIXEL(sheet
,j
);
3964 y
=ROW_TOP_YPIXEL(sheet
, i
);
3965 width
=COLUMN_LEFT_XPIXEL(sheet
, j
)-x
+sheet
->column
[j
].width
;
3966 height
=ROW_TOP_YPIXEL(sheet
, i
)-y
+sheet
->row
[i
].height
;
3968 if(i
==sheet
->range
.row0
){
3972 if(i
==sheet
->range
.rowi
) height
=height
+3;
3973 if(j
==sheet
->range
.col0
){
3977 if(j
==sheet
->range
.coli
) width
=width
+3;
3979 gdk_draw_pixmap(sheet
->sheet_window
,
3980 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
3989 if(i
!= sheet
->active_cell
.row
|| j
!= sheet
->active_cell
.col
){
3990 x
=COLUMN_LEFT_XPIXEL(sheet
,j
);
3991 y
=ROW_TOP_YPIXEL(sheet
, i
);
3992 width
=COLUMN_LEFT_XPIXEL(sheet
, j
)-x
+sheet
->column
[j
].width
;
3993 height
=ROW_TOP_YPIXEL(sheet
, i
)-y
+sheet
->row
[i
].height
;
3995 if(i
==new_range
.row0
){
3999 if(i
==new_range
.rowi
) height
=height
-3;
4000 if(j
==new_range
.col0
){
4004 if(j
==new_range
.coli
) width
=width
-3;
4006 gdk_draw_rectangle (sheet
->sheet_window
,
4017 for(i
=range
->row0
; i
<=range
->rowi
; i
++){
4018 for(j
=range
->col0
; j
<=range
->coli
; j
++){
4020 state
=gtk_sheet_cell_get_state(sheet
, i
, j
);
4021 selected
=(i
<=new_range
.rowi
&& i
>=new_range
.row0
&&
4022 j
<=new_range
.coli
&& j
>=new_range
.col0
) ? TRUE
: FALSE
;
4024 if(state
==GTK_STATE_SELECTED
&& !selected
&&
4025 sheet
->column
[j
].is_visible
&& sheet
->row
[i
].is_visible
){
4027 x
=COLUMN_LEFT_XPIXEL(sheet
,j
);
4028 y
=ROW_TOP_YPIXEL(sheet
, i
);
4029 width
=COLUMN_LEFT_XPIXEL(sheet
, j
)-x
+sheet
->column
[j
].width
;
4030 height
=ROW_TOP_YPIXEL(sheet
, i
)-y
+sheet
->row
[i
].height
;
4032 if(i
==sheet
->range
.row0
){
4036 if(i
==sheet
->range
.rowi
) height
=height
+3;
4037 if(j
==sheet
->range
.col0
){
4041 if(j
==sheet
->range
.coli
) width
=width
+3;
4043 gdk_draw_pixmap(sheet
->sheet_window
,
4044 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
4056 for(i
=range
->row0
; i
<=range
->rowi
; i
++){
4057 for(j
=range
->col0
; j
<=range
->coli
; j
++){
4059 state
=gtk_sheet_cell_get_state(sheet
, i
, j
);
4060 selected
=(i
<=new_range
.rowi
&& i
>=new_range
.row0
&&
4061 j
<=new_range
.coli
&& j
>=new_range
.col0
) ? TRUE
: FALSE
;
4063 if(state
!=GTK_STATE_SELECTED
&& selected
&&
4064 sheet
->column
[j
].is_visible
&& sheet
->row
[i
].is_visible
&&
4065 (i
!= sheet
->active_cell
.row
|| j
!= sheet
->active_cell
.col
)){
4067 x
=COLUMN_LEFT_XPIXEL(sheet
,j
);
4068 y
=ROW_TOP_YPIXEL(sheet
, i
);
4069 width
=COLUMN_LEFT_XPIXEL(sheet
, j
)-x
+sheet
->column
[j
].width
;
4070 height
=ROW_TOP_YPIXEL(sheet
, i
)-y
+sheet
->row
[i
].height
;
4072 if(i
==new_range
.row0
){
4076 if(i
==new_range
.rowi
) height
=height
-3;
4077 if(j
==new_range
.col0
){
4081 if(j
==new_range
.coli
) width
=width
-3;
4083 gdk_draw_rectangle (sheet
->sheet_window
,
4094 for(i
=aux_range
.row0
; i
<=aux_range
.rowi
; i
++){
4095 for(j
=aux_range
.col0
; j
<=aux_range
.coli
; j
++){
4097 if(sheet
->column
[j
].is_visible
&& sheet
->row
[i
].is_visible
){
4099 state
=gtk_sheet_cell_get_state(sheet
, i
, j
);
4101 mask1
= i
==sheet
->range
.row0
? 1 : 0;
4102 mask1
= i
==sheet
->range
.rowi
? mask1
+2 : mask1
;
4103 mask1
= j
==sheet
->range
.col0
? mask1
+4 : mask1
;
4104 mask1
= j
==sheet
->range
.coli
? mask1
+8 : mask1
;
4106 mask2
= i
==new_range
.row0
? 1 : 0;
4107 mask2
= i
==new_range
.rowi
? mask2
+2 : mask2
;
4108 mask2
= j
==new_range
.col0
? mask2
+4 : mask2
;
4109 mask2
= j
==new_range
.coli
? mask2
+8 : mask2
;
4110 if(mask2
!=mask1
|| (mask2
==mask1
&& state
!=GTK_STATE_SELECTED
)){
4111 x
=COLUMN_LEFT_XPIXEL(sheet
,j
);
4112 y
=ROW_TOP_YPIXEL(sheet
, i
);
4113 width
=sheet
->column
[j
].width
;
4114 height
=sheet
->row
[i
].height
;
4116 gdk_draw_rectangle (sheet
->sheet_window
,
4124 gdk_draw_rectangle (sheet
->sheet_window
,
4131 gdk_draw_rectangle (sheet
->sheet_window
,
4139 gdk_draw_rectangle (sheet
->sheet_window
,
4156 gtk_sheet_draw_corners(sheet
, new_range
);
4161 gtk_sheet_draw_border (GtkSheet
*sheet
, GtkSheetRange new_range
)
4166 gint x
,y
,width
,height
;
4168 widget
= GTK_WIDGET(sheet
);
4170 x
=COLUMN_LEFT_XPIXEL(sheet
,new_range
.col0
);
4171 y
=ROW_TOP_YPIXEL(sheet
,new_range
.row0
);
4172 width
=COLUMN_LEFT_XPIXEL(sheet
,new_range
.coli
)-x
+
4173 sheet
->column
[new_range
.coli
].width
;
4174 height
=ROW_TOP_YPIXEL(sheet
,new_range
.rowi
)-y
+
4175 sheet
->row
[new_range
.rowi
].height
;
4177 area
.x
=COLUMN_LEFT_XPIXEL(sheet
, MIN_VISIBLE_COLUMN(sheet
));
4178 area
.y
=ROW_TOP_YPIXEL(sheet
, MIN_VISIBLE_ROW(sheet
));
4179 area
.width
=sheet
->sheet_window_width
;
4180 area
.height
=sheet
->sheet_window_height
;
4186 if(width
>area
.width
) width
=area
.width
+10;
4191 if(height
>area
.height
) height
=area
.height
+10;
4193 gdk_gc_set_clip_rectangle(sheet
->xor_gc
, &area
);
4195 for(i
=-1; i
<=1; i
++)
4196 gdk_draw_rectangle (sheet
->sheet_window
,
4200 width
-2*i
,height
-2*i
);
4202 gdk_gc_set_clip_rectangle(sheet
->xor_gc
, NULL
);
4204 gtk_sheet_draw_corners(sheet
, new_range
);
4209 gtk_sheet_draw_corners(GtkSheet
*sheet
, GtkSheetRange range
)
4214 if(gtk_sheet_cell_isvisible(sheet
, range
.row0
, range
.col0
)){
4215 x
=COLUMN_LEFT_XPIXEL(sheet
,range
.col0
);
4216 y
=ROW_TOP_YPIXEL(sheet
,range
.row0
);
4217 gdk_draw_pixmap(sheet
->sheet_window
,
4218 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
4226 gdk_draw_rectangle (sheet
->sheet_window
,
4233 if(gtk_sheet_cell_isvisible(sheet
, range
.row0
, range
.coli
) ||
4234 sheet
->state
== GTK_SHEET_COLUMN_SELECTED
){
4235 x
=COLUMN_LEFT_XPIXEL(sheet
,range
.coli
)+
4236 sheet
->column
[range
.coli
].width
;
4237 y
=ROW_TOP_YPIXEL(sheet
,range
.row0
);
4239 if(sheet
->state
== GTK_SHEET_COLUMN_SELECTED
)
4241 y
= ROW_TOP_YPIXEL(sheet
, sheet
->view
.row0
)+3;
4244 gdk_draw_pixmap(sheet
->sheet_window
,
4245 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
4253 gdk_draw_rectangle (sheet
->sheet_window
,
4256 x
-width
+width
/2,y
-width
+width
/2,
4260 if(gtk_sheet_cell_isvisible(sheet
, range
.rowi
, range
.col0
) ||
4261 sheet
->state
== GTK_SHEET_ROW_SELECTED
){
4262 x
=COLUMN_LEFT_XPIXEL(sheet
,range
.col0
);
4263 y
=ROW_TOP_YPIXEL(sheet
,range
.rowi
)+
4264 sheet
->row
[range
.rowi
].height
;
4266 if(sheet
->state
== GTK_SHEET_ROW_SELECTED
)
4268 x
= COLUMN_LEFT_XPIXEL(sheet
, sheet
->view
.col0
)+3;
4271 gdk_draw_pixmap(sheet
->sheet_window
,
4272 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
4280 gdk_draw_rectangle (sheet
->sheet_window
,
4283 x
-width
+width
/2,y
-width
+width
/2,
4287 if(gtk_sheet_cell_isvisible(sheet
, range
.rowi
, range
.coli
)){
4288 x
=COLUMN_LEFT_XPIXEL(sheet
,range
.coli
)+
4289 sheet
->column
[range
.coli
].width
;
4290 y
=ROW_TOP_YPIXEL(sheet
,range
.rowi
)+
4291 sheet
->row
[range
.rowi
].height
;
4293 if(sheet
->state
== GTK_SHEET_RANGE_SELECTED
) width
= 3;
4294 if(sheet
->state
== GTK_SHEET_NORMAL
) width
= 3;
4295 gdk_draw_pixmap(sheet
->sheet_window
,
4296 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
4304 gdk_draw_rectangle (sheet
->sheet_window
,
4307 x
-width
+width
/2,y
-width
+width
/2,
4316 gtk_sheet_real_select_range (GtkSheet
* sheet
,
4317 GtkSheetRange
* range
)
4322 g_return_if_fail (sheet
!= NULL
);
4324 if(range
==NULL
) range
=&sheet
->range
;
4326 if(range
->row0
< 0 || range
->rowi
< 0) return;
4327 if(range
->col0
< 0 || range
->coli
< 0) return;
4331 if(state
==GTK_SHEET_COLUMN_SELECTED
|| state
==GTK_SHEET_RANGE_SELECTED
){
4332 for(i
=sheet
->range
.col0
; i
< range
->col0
; i
++)
4333 column_button_release(sheet
, i
);
4334 for(i
=range
->coli
+1; i
<= sheet
->range
.coli
; i
++)
4335 column_button_release(sheet
, i
);
4336 for(i
=range
->col0
; i
<=range
->coli
; i
++){
4337 column_button_set(sheet
, i
);
4341 if(state
==GTK_SHEET_ROW_SELECTED
|| state
==GTK_SHEET_RANGE_SELECTED
){
4342 for(i
=sheet
->range
.row0
; i
< range
->row0
; i
++)
4343 row_button_release(sheet
, i
);
4344 for(i
=range
->rowi
+1; i
<= sheet
->range
.rowi
; i
++)
4345 row_button_release(sheet
, i
);
4346 for(i
=range
->row0
; i
<=range
->rowi
; i
++){
4347 row_button_set(sheet
, i
);
4351 if(range
->coli
!= sheet
->range
.coli
|| range
->col0
!= sheet
->range
.col0
||
4352 range
->rowi
!= sheet
->range
.rowi
|| range
->row0
!= sheet
->range
.row0
)
4355 gtk_sheet_new_selection(sheet
, range
);
4357 sheet
->range
.col0
=range
->col0
;
4358 sheet
->range
.coli
=range
->coli
;
4359 sheet
->range
.row0
=range
->row0
;
4360 sheet
->range
.rowi
=range
->rowi
;
4365 gtk_sheet_draw_backing_pixmap(sheet
, sheet
->range
);
4366 gtk_sheet_range_draw_selection(sheet
, sheet
->range
);
4369 gtk_signal_emit(GTK_OBJECT(sheet
), sheet_signals
[SELECT_RANGE
], range
);
4373 gtk_sheet_select_range(GtkSheet
* sheet
, const GtkSheetRange
*range
)
4375 g_return_if_fail (sheet
!= NULL
);
4377 if(range
==NULL
) range
=&sheet
->range
;
4379 if(range
->row0
< 0 || range
->rowi
< 0) return;
4380 if(range
->col0
< 0 || range
->coli
< 0) return;
4382 if(sheet
->state
!= GTK_SHEET_NORMAL
)
4383 gtk_sheet_real_unselect_range(sheet
, NULL
);
4387 veto
= gtk_sheet_deactivate_cell(sheet
);
4391 sheet
->range
.row0
=range
->row0
;
4392 sheet
->range
.rowi
=range
->rowi
;
4393 sheet
->range
.col0
=range
->col0
;
4394 sheet
->range
.coli
=range
->coli
;
4395 sheet
->active_cell
.row
=range
->row0
;
4396 sheet
->active_cell
.col
=range
->col0
;
4397 sheet
->selection_cell
.row
=range
->rowi
;
4398 sheet
->selection_cell
.col
=range
->coli
;
4400 sheet
->state
= GTK_SHEET_RANGE_SELECTED
;
4401 gtk_sheet_real_select_range(sheet
, NULL
);
4406 gtk_sheet_unselect_range (GtkSheet
* sheet
)
4408 gtk_sheet_real_unselect_range(sheet
, NULL
);
4409 sheet
->state
= GTK_STATE_NORMAL
;
4410 gtk_sheet_activate_cell(sheet
, sheet
->active_cell
.row
, sheet
->active_cell
.col
);
4415 gtk_sheet_real_unselect_range (GtkSheet
* sheet
,
4416 const GtkSheetRange
*range
)
4420 g_return_if_fail (sheet
!= NULL
);
4421 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
)));
4424 range
=&sheet
->range
;
4427 if(range
->row0
< 0 || range
->rowi
< 0) return;
4428 if(range
->col0
< 0 || range
->coli
< 0) return;
4430 if (gtk_sheet_range_isvisible (sheet
, *range
)){
4431 gtk_sheet_draw_backing_pixmap(sheet
, *range
);
4434 for(i
=range
->col0
; i
<=range
->coli
; i
++){
4435 column_button_release(sheet
, i
);
4438 for(i
=range
->row0
; i
<=range
->rowi
; i
++){
4439 row_button_release(sheet
, i
);
4446 gtk_sheet_draw (GtkWidget
* widget
,
4447 GdkRectangle
* area
)
4450 GtkSheetRange range
;
4451 GtkSheetChild
*child
;
4452 GdkRectangle child_area
;
4455 g_return_if_fail (widget
!= NULL
);
4456 g_return_if_fail (GTK_IS_SHEET (widget
));
4457 g_return_if_fail (area
!= NULL
);
4459 if (GTK_WIDGET_DRAWABLE (widget
))
4461 sheet
= GTK_SHEET (widget
);
4463 range
.row0
=ROW_FROM_YPIXEL(sheet
, area
->y
);
4464 range
.rowi
=ROW_FROM_YPIXEL(sheet
, area
->y
+area
->height
);
4465 range
.col0
=COLUMN_FROM_XPIXEL(sheet
, area
->x
);
4466 range
.coli
=COLUMN_FROM_XPIXEL(sheet
, area
->x
+area
->width
);
4468 gtk_sheet_range_draw (sheet
, &range
);
4470 if(sheet
->state
!= GTK_SHEET_NORMAL
&& gtk_sheet_range_isvisible(sheet
, sheet
->range
)){
4471 gtk_sheet_draw_backing_pixmap(sheet
, sheet
->range
);
4472 gtk_sheet_range_draw_selection(sheet
, sheet
->range
);
4475 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
4476 gdk_window_show(sheet
->row_title_window
);
4478 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
4479 gdk_window_show(sheet
->column_title_window
);
4481 children
= sheet
->children
;
4484 child
= children
->data
;
4485 children
= children
->next
;
4487 if (gtk_widget_intersect (child
->widget
, area
, &child_area
))
4488 gtk_widget_draw (child
->widget
, &child_area
);
4491 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)
4492 && GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
4493 gtk_widget_draw(sheet
->button
, NULL
);
4501 gtk_sheet_expose (GtkWidget
* widget
,
4502 GdkEventExpose
* event
)
4505 GtkSheetRange range
;
4506 GtkSheetChild
*child
;
4508 GdkEventExpose child_event
;
4510 g_return_val_if_fail (widget
!= NULL
, FALSE
);
4511 g_return_val_if_fail (GTK_IS_SHEET (widget
), FALSE
);
4512 g_return_val_if_fail (event
!= NULL
, FALSE
);
4514 sheet
= GTK_SHEET (widget
);
4516 if (GTK_WIDGET_DRAWABLE (widget
))
4518 range
.row0
=ROW_FROM_YPIXEL(sheet
,event
->area
.y
);
4519 range
.col0
=COLUMN_FROM_XPIXEL(sheet
,event
->area
.x
);
4520 range
.rowi
=ROW_FROM_YPIXEL(sheet
,event
->area
.y
+event
->area
.height
);
4521 range
.coli
=COLUMN_FROM_XPIXEL(sheet
,event
->area
.x
+event
->area
.width
);
4523 /* exposure events on the sheet */
4525 if(event
->window
== sheet
->row_title_window
){
4526 size_allocate_row_title_buttons(sheet
);
4527 gdk_window_show(sheet
->row_title_window
);
4530 if(event
->window
== sheet
->column_title_window
){
4531 size_allocate_column_title_buttons(sheet
);
4532 gdk_window_show(sheet
->column_title_window
);
4535 if (event
->window
== sheet
->sheet_window
){
4536 gtk_sheet_draw_backing_pixmap(sheet
, range
);
4538 if(sheet
->state
!= GTK_SHEET_NORMAL
){
4539 if(gtk_sheet_range_isvisible(sheet
, sheet
->range
))
4540 gtk_sheet_draw_backing_pixmap(sheet
, sheet
->range
);
4541 if(GTK_SHEET_IN_RESIZE(sheet
) || GTK_SHEET_IN_DRAG(sheet
))
4542 gtk_sheet_draw_backing_pixmap(sheet
, sheet
->drag_range
);
4544 if(gtk_sheet_range_isvisible(sheet
, sheet
->range
))
4545 gtk_sheet_range_draw_selection(sheet
, sheet
->range
);
4546 if(GTK_SHEET_IN_RESIZE(sheet
) || GTK_SHEET_IN_DRAG(sheet
))
4547 draw_xor_rectangle(sheet
, sheet
->drag_range
);
4550 if((!GTK_SHEET_IN_XDRAG(sheet
)) && (!GTK_SHEET_IN_YDRAG(sheet
))){
4551 if(sheet
->state
== GTK_SHEET_NORMAL
){
4552 gtk_sheet_draw_active_cell(sheet
);
4553 if(!GTK_SHEET_IN_SELECTION(sheet
))
4554 gtk_widget_queue_draw(sheet
->sheet_entry
);
4558 /* sheet children events */
4559 child_event
= *event
;
4560 children
= sheet
->children
;
4563 child
= children
->data
;
4564 children
= children
->next
;
4566 if (GTK_WIDGET_NO_WINDOW (child
->widget
))
4568 GdkRectangle child_area
;
4570 child_area
.x
= child
->x
;
4571 child_area
.y
= child
->y
;
4572 child_area
.width
= child
->widget
->allocation
.width
;
4573 child_area
.height
= child
->widget
->allocation
.height
;
4574 gdk_rectangle_intersect (&child_area
, &event
->area
, &child_event
.area
);
4575 child_event
.window
= event
->window
;
4576 if(child
->window
) child_event
.window
= child
->window
;
4577 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
4586 if(sheet
->state
!= GTK_SHEET_NORMAL
&& GTK_SHEET_IN_SELECTION(sheet
))
4587 gtk_widget_grab_focus(GTK_WIDGET(sheet
));
4594 gtk_sheet_forall (GtkContainer *container,
4595 gboolean include_internals,
4596 GtkCallback callback,
4597 gpointer callback_data)
4601 sheet = GTK_SHEET(container);
4603 (*callback) (sheet->button, callback_data);
4608 gtk_sheet_button_press (GtkWidget
* widget
,
4609 GdkEventButton
* event
)
4612 GdkModifierType mods
;
4613 gint x
, y
, row
, column
;
4616 g_return_val_if_fail (widget
!= NULL
, FALSE
);
4617 g_return_val_if_fail (GTK_IS_SHEET (widget
), FALSE
);
4618 g_return_val_if_fail (event
!= NULL
, FALSE
);
4620 if(event
->type
!= GDK_BUTTON_PRESS
) return TRUE
;
4621 gdk_window_get_pointer(widget
->window
, NULL
, NULL
, &mods
);
4622 if(!(mods
& GDK_BUTTON1_MASK
)) return TRUE
;
4624 sheet
= GTK_SHEET (widget
);
4626 /* press on resize windows */
4627 if (event
->window
== sheet
->column_title_window
&&
4628 !GTK_SHEET_COLUMN_FROZEN(sheet
))
4630 gtk_widget_get_pointer (widget
, &sheet
->x_drag
, NULL
);
4631 if(POSSIBLE_XDRAG(sheet
, sheet
->x_drag
, &sheet
->drag_cell
.col
)){
4633 GTK_SHEET_SET_FLAGS (sheet
, GTK_SHEET_IN_XDRAG
);
4634 gdk_pointer_grab (sheet
->column_title_window
, FALSE
,
4635 GDK_POINTER_MOTION_HINT_MASK
|
4636 GDK_BUTTON1_MOTION_MASK
|
4637 GDK_BUTTON_RELEASE_MASK
,
4638 NULL
, NULL
, event
->time
);
4640 draw_xor_vline (sheet
);
4645 if (event
->window
== sheet
->row_title_window
&& !GTK_SHEET_ROW_FROZEN(sheet
))
4647 gtk_widget_get_pointer (widget
, NULL
, &sheet
->y_drag
);
4649 if(POSSIBLE_YDRAG(sheet
, sheet
->y_drag
, &sheet
->drag_cell
.row
)){
4650 GTK_SHEET_SET_FLAGS (sheet
, GTK_SHEET_IN_YDRAG
);
4651 gdk_pointer_grab (sheet
->row_title_window
, FALSE
,
4652 GDK_POINTER_MOTION_HINT_MASK
|
4653 GDK_BUTTON1_MOTION_MASK
|
4654 GDK_BUTTON_RELEASE_MASK
,
4655 NULL
, NULL
, event
->time
);
4657 draw_xor_hline (sheet
);
4662 /* selections on the sheet */
4663 if(event
->window
== sheet
->sheet_window
){
4664 gtk_widget_get_pointer (widget
, &x
, &y
);
4665 gtk_sheet_get_pixel_info (sheet
, x
, y
, &row
, &column
);
4666 gdk_pointer_grab (sheet
->sheet_window
, FALSE
,
4667 GDK_POINTER_MOTION_HINT_MASK
|
4668 GDK_BUTTON1_MOTION_MASK
|
4669 GDK_BUTTON_RELEASE_MASK
,
4670 NULL
, NULL
, event
->time
);
4671 gtk_grab_add(GTK_WIDGET(sheet
));
4672 sheet
->timer
=gtk_timeout_add(TIMEOUT_SCROLL
, gtk_sheet_scroll
, (gpointer
) sheet
);
4673 GTK_WIDGET_UNSET_FLAGS(sheet
->sheet_entry
, GTK_HAS_FOCUS
);
4674 GTK_WIDGET_SET_FLAGS(GTK_SHEET(sheet
), GTK_HAS_FOCUS
);
4675 gtk_widget_grab_focus(GTK_WIDGET(sheet
));
4677 if(sheet
->selection_mode
!= GTK_SELECTION_SINGLE
&&
4678 sheet
->cursor_drag
->type
==GDK_SIZING
&&
4679 !GTK_SHEET_IN_SELECTION(sheet
) && !GTK_SHEET_IN_RESIZE(sheet
)){
4680 if(sheet
->state
==GTK_STATE_NORMAL
) {
4681 row
=sheet
->active_cell
.row
;
4682 column
=sheet
->active_cell
.col
;
4683 if(!gtk_sheet_deactivate_cell(sheet
)) return FALSE
;
4684 sheet
->active_cell
.row
=row
;
4685 sheet
->active_cell
.col
=column
;
4686 sheet
->drag_range
=sheet
->range
;
4687 sheet
->state
=GTK_SHEET_RANGE_SELECTED
;
4688 gtk_sheet_select_range(sheet
, &sheet
->drag_range
);
4692 if(row
> sheet
->range
.rowi
) row
--;
4693 if(column
> sheet
->range
.coli
) column
--;
4694 sheet
->drag_cell
.row
= row
;
4695 sheet
->drag_cell
.col
= column
;
4696 sheet
->drag_range
=sheet
->range
;
4697 draw_xor_rectangle(sheet
, sheet
->drag_range
);
4698 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_IN_RESIZE
);
4700 else if(sheet
->cursor_drag
->type
==GDK_TOP_LEFT_ARROW
&&
4701 !GTK_SHEET_IN_SELECTION(sheet
) && !GTK_SHEET_IN_DRAG(sheet
)) {
4702 if(sheet
->state
==GTK_STATE_NORMAL
) {
4703 row
=sheet
->active_cell
.row
;
4704 column
=sheet
->active_cell
.col
;
4705 if(!gtk_sheet_deactivate_cell(sheet
)) return FALSE
;
4706 sheet
->active_cell
.row
=row
;
4707 sheet
->active_cell
.col
=column
;
4708 sheet
->drag_range
=sheet
->range
;
4709 sheet
->state
=GTK_SHEET_RANGE_SELECTED
;
4710 gtk_sheet_select_range(sheet
, &sheet
->drag_range
);
4714 if(row
< sheet
->range
.row0
) row
++;
4715 if(row
> sheet
->range
.rowi
) row
--;
4716 if(column
< sheet
->range
.col0
) column
++;
4717 if(column
> sheet
->range
.coli
) column
--;
4718 sheet
->drag_cell
.row
=row
;
4719 sheet
->drag_cell
.col
=column
;
4720 sheet
->drag_range
=sheet
->range
;
4721 draw_xor_rectangle(sheet
, sheet
->drag_range
);
4722 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_IN_DRAG
);
4726 gtk_sheet_click_cell(sheet
, row
, column
, &veto
);
4727 if(veto
) GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_IN_SELECTION
);
4732 if(event
->window
== sheet
->column_title_window
){
4733 gtk_widget_get_pointer (widget
, &x
, &y
);
4734 column
= COLUMN_FROM_XPIXEL(sheet
, x
);
4735 if(sheet
->column
[column
].is_sensitive
){;
4736 gtk_sheet_click_cell(sheet
, -1, column
, &veto
);
4737 gtk_grab_add(GTK_WIDGET(sheet
));
4738 sheet
->timer
=gtk_timeout_add(TIMEOUT_SCROLL
, gtk_sheet_scroll
, (gpointer
) sheet
);
4739 GTK_WIDGET_UNSET_FLAGS(sheet
->sheet_entry
, GTK_HAS_FOCUS
);
4740 GTK_WIDGET_SET_FLAGS(GTK_SHEET(sheet
), GTK_HAS_FOCUS
);
4741 gtk_widget_grab_focus(GTK_WIDGET(sheet
));
4742 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_IN_SELECTION
);
4746 if(event
->window
== sheet
->row_title_window
){
4747 gtk_widget_get_pointer (widget
, &x
, &y
);
4748 row
= ROW_FROM_YPIXEL(sheet
, y
);
4749 if(sheet
->row
[row
].is_sensitive
){
4750 gtk_sheet_click_cell(sheet
, row
, -1, &veto
);
4751 gtk_grab_add(GTK_WIDGET(sheet
));
4752 sheet
->timer
=gtk_timeout_add(TIMEOUT_SCROLL
, gtk_sheet_scroll
, (gpointer
) sheet
);
4753 GTK_WIDGET_UNSET_FLAGS(sheet
->sheet_entry
, GTK_HAS_FOCUS
);
4754 GTK_WIDGET_SET_FLAGS(GTK_SHEET(sheet
), GTK_HAS_FOCUS
);
4755 gtk_widget_grab_focus(GTK_WIDGET(sheet
));
4756 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_IN_SELECTION
);
4764 gtk_sheet_scroll(gpointer data
)
4767 gint x
,y
,row
,column
;
4770 sheet
=GTK_SHEET(data
);
4772 GDK_THREADS_ENTER();
4774 gtk_widget_get_pointer (GTK_WIDGET(sheet
), &x
, &y
);
4775 gtk_sheet_get_pixel_info (sheet
, x
, y
, &row
, &column
);
4779 if(GTK_SHEET_IN_SELECTION(sheet
))
4780 gtk_sheet_extend_selection(sheet
, row
, column
);
4782 if(GTK_SHEET_IN_DRAG(sheet
) || GTK_SHEET_IN_RESIZE(sheet
)){
4783 move
=gtk_sheet_move_query(sheet
, row
, column
);
4784 if(move
) draw_xor_rectangle(sheet
, sheet
->drag_range
);
4787 GDK_THREADS_LEAVE();
4794 gtk_sheet_click_cell(GtkSheet
*sheet
, gint row
, gint column
, gboolean
*veto
)
4798 if(row
> sheet
->maxrow
|| column
> sheet
->maxcol
){
4803 if(column
>= 0 && row
>= 0)
4804 if(!sheet
->column
[column
].is_visible
|| !sheet
->row
[row
].is_visible
)
4810 gtk_signal_emit(GTK_OBJECT(sheet
), sheet_signals
[TRAVERSE
],
4811 sheet
->active_cell
.row
,
4812 sheet
->active_cell
.col
,
4817 if(sheet
->state
== GTK_STATE_NORMAL
) return;
4819 row
= sheet
->active_cell
.row
;
4820 column
= sheet
->active_cell
.col
;
4821 gtk_sheet_activate_cell(sheet
, row
, column
);
4825 if(row
== -1 && column
>= 0){
4826 if(GTK_SHEET_AUTO_SCROLL(sheet
))
4827 gtk_sheet_move_query(sheet
, row
, column
);
4828 gtk_sheet_select_column(sheet
, column
);
4831 if(column
== -1 && row
>= 0){
4832 if(GTK_SHEET_AUTO_SCROLL(sheet
))
4833 gtk_sheet_move_query(sheet
, row
, column
);
4834 gtk_sheet_select_row(sheet
, row
);
4838 if(row
!=-1 && column
!=-1){
4839 if(sheet
->state
!= GTK_SHEET_NORMAL
){
4840 sheet
->state
= GTK_SHEET_NORMAL
;
4841 gtk_sheet_real_unselect_range(sheet
, NULL
);
4845 if(!gtk_sheet_deactivate_cell(sheet
)){
4851 if(GTK_SHEET_AUTO_SCROLL(sheet
))
4852 gtk_sheet_move_query(sheet
, row
, column
);
4853 sheet
->active_cell
.row
=row
;
4854 sheet
->active_cell
.col
=column
;
4855 sheet
->selection_cell
.row
=row
;
4856 sheet
->selection_cell
.col
=column
;
4857 sheet
->range
.row0
=row
;
4858 sheet
->range
.col0
=column
;
4859 sheet
->range
.rowi
=row
;
4860 sheet
->range
.coli
=column
;
4861 sheet
->state
=GTK_SHEET_NORMAL
;
4862 GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_IN_SELECTION
);
4863 gtk_sheet_draw_active_cell(sheet
);
4867 if(row
==-1 && column
==-1){
4868 sheet
->state
=GTK_SHEET_RANGE_SELECTED
;
4869 sheet
->range
.row0
=0;
4870 sheet
->range
.col0
=0;
4871 sheet
->range
.rowi
=sheet
->maxrow
;
4872 sheet
->range
.coli
=sheet
->maxcol
;
4873 sheet
->active_cell
.row
=0;
4874 sheet
->active_cell
.col
=0;
4875 gtk_sheet_select_range(sheet
, NULL
);
4879 gtk_sheet_activate_cell(sheet
, sheet
->active_cell
.row
,
4880 sheet
->active_cell
.col
);
4884 gtk_sheet_button_release (GtkWidget
* widget
,
4885 GdkEventButton
* event
)
4890 sheet
=GTK_SHEET(widget
);
4892 /* release on resize windows */
4893 if (GTK_SHEET_IN_XDRAG (sheet
)){
4894 GTK_SHEET_UNSET_FLAGS (sheet
, GTK_SHEET_IN_XDRAG
);
4895 GTK_SHEET_UNSET_FLAGS (sheet
, GTK_SHEET_IN_SELECTION
);
4896 gtk_widget_get_pointer (widget
, &x
, NULL
);
4897 gdk_pointer_ungrab (event
->time
);
4898 draw_xor_vline (sheet
);
4900 gtk_sheet_set_column_width (sheet
, sheet
->drag_cell
.col
, new_column_width (sheet
, sheet
->drag_cell
.col
, &x
));
4901 sheet
->old_hadjustment
= -1.;
4902 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->hadjustment
), "value_changed");
4906 if (GTK_SHEET_IN_YDRAG (sheet
)){
4907 GTK_SHEET_UNSET_FLAGS (sheet
, GTK_SHEET_IN_YDRAG
);
4908 GTK_SHEET_UNSET_FLAGS (sheet
, GTK_SHEET_IN_SELECTION
);
4909 gtk_widget_get_pointer (widget
, NULL
, &y
);
4910 gdk_pointer_ungrab (event
->time
);
4911 draw_xor_hline (sheet
);
4913 gtk_sheet_set_row_height (sheet
, sheet
->drag_cell
.row
, new_row_height (sheet
, sheet
->drag_cell
.row
, &y
));
4914 sheet
->old_vadjustment
= -1.;
4915 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->vadjustment
), "value_changed");
4920 if (GTK_SHEET_IN_DRAG(sheet
)){
4921 GtkSheetRange old_range
;
4922 draw_xor_rectangle(sheet
, sheet
->drag_range
);
4923 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_IN_DRAG
);
4924 gdk_pointer_ungrab (event
->time
);
4926 gtk_sheet_real_unselect_range(sheet
, NULL
);
4928 sheet
->active_cell
.row
= sheet
->active_cell
.row
+
4929 (sheet
->drag_range
.row0
- sheet
->range
.row0
);
4930 sheet
->active_cell
.col
= sheet
->active_cell
.col
+
4931 (sheet
->drag_range
.col0
- sheet
->range
.col0
);
4932 sheet
->selection_cell
.row
= sheet
->selection_cell
.row
+
4933 (sheet
->drag_range
.row0
- sheet
->range
.row0
);
4934 sheet
->selection_cell
.col
= sheet
->selection_cell
.col
+
4935 (sheet
->drag_range
.col0
- sheet
->range
.col0
);
4936 old_range
=sheet
->range
;
4937 sheet
->range
=sheet
->drag_range
;
4938 sheet
->drag_range
=old_range
;
4939 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[MOVE_RANGE
],
4940 &sheet
->drag_range
, &sheet
->range
);
4941 gtk_sheet_select_range(sheet
, &sheet
->range
);
4944 if (GTK_SHEET_IN_RESIZE(sheet
)){
4945 GtkSheetRange old_range
;
4946 draw_xor_rectangle(sheet
, sheet
->drag_range
);
4947 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_IN_RESIZE
);
4948 gdk_pointer_ungrab (event
->time
);
4950 gtk_sheet_real_unselect_range(sheet
, NULL
);
4952 sheet
->active_cell
.row
= sheet
->active_cell
.row
+
4953 (sheet
->drag_range
.row0
- sheet
->range
.row0
);
4954 sheet
->active_cell
.col
= sheet
->active_cell
.col
+
4955 (sheet
->drag_range
.col0
- sheet
->range
.col0
);
4956 if(sheet
->drag_range
.row0
< sheet
->range
.row0
)
4957 sheet
->selection_cell
.row
= sheet
->drag_range
.row0
;
4958 if(sheet
->drag_range
.rowi
>= sheet
->range
.rowi
)
4959 sheet
->selection_cell
.row
= sheet
->drag_range
.rowi
;
4960 if(sheet
->drag_range
.col0
< sheet
->range
.col0
)
4961 sheet
->selection_cell
.col
= sheet
->drag_range
.col0
;
4962 if(sheet
->drag_range
.coli
>= sheet
->range
.coli
)
4963 sheet
->selection_cell
.col
= sheet
->drag_range
.coli
;
4964 old_range
= sheet
->range
;
4965 sheet
->range
= sheet
->drag_range
;
4966 sheet
->drag_range
= old_range
;
4968 if(sheet
->state
==GTK_STATE_NORMAL
) sheet
->state
=GTK_SHEET_RANGE_SELECTED
;
4969 gtk_signal_emit(GTK_OBJECT(sheet
),sheet_signals
[RESIZE_RANGE
],
4970 &sheet
->drag_range
, &sheet
->range
);
4971 gtk_sheet_select_range(sheet
, &sheet
->range
);
4974 if(sheet
->state
== GTK_SHEET_NORMAL
&& GTK_SHEET_IN_SELECTION(sheet
)){
4975 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_IN_SELECTION
);
4976 gdk_pointer_ungrab (event
->time
);
4977 gtk_sheet_activate_cell(sheet
, sheet
->active_cell
.row
,
4978 sheet
->active_cell
.col
);
4981 if(GTK_SHEET_IN_SELECTION
)
4982 gdk_pointer_ungrab (event
->time
);
4984 gtk_timeout_remove(sheet
->timer
);
4985 gtk_grab_remove(GTK_WIDGET(sheet
));
4987 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_IN_SELECTION
);
4993 gtk_sheet_motion (GtkWidget
* widget
,
4994 GdkEventMotion
* event
)
4997 GdkModifierType mods
;
4998 GdkCursorType new_cursor
;
4999 gint x
, y
, row
, column
;
5001 g_return_val_if_fail (widget
!= NULL
, FALSE
);
5002 g_return_val_if_fail (GTK_IS_SHEET (widget
), FALSE
);
5003 g_return_val_if_fail (event
!= NULL
, FALSE
);
5006 sheet
= GTK_SHEET (widget
);
5009 /* selections on the sheet */
5013 if(event
->window
== sheet
->column_title_window
&& !GTK_SHEET_COLUMN_FROZEN(sheet
)){
5014 gtk_widget_get_pointer(widget
, &x
, &y
);
5015 if(!GTK_SHEET_IN_SELECTION(sheet
) && POSSIBLE_XDRAG(sheet
, x
, &column
)){
5016 new_cursor
=GDK_SB_H_DOUBLE_ARROW
;
5017 if(new_cursor
!= sheet
->cursor_drag
->type
){
5018 gdk_cursor_destroy(sheet
->cursor_drag
);
5019 sheet
->cursor_drag
=gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW
);
5020 gdk_window_set_cursor(sheet
->column_title_window
,sheet
->cursor_drag
);
5023 new_cursor
=GDK_TOP_LEFT_ARROW
;
5024 if(!GTK_SHEET_IN_XDRAG(sheet
) && new_cursor
!= sheet
->cursor_drag
->type
){
5025 gdk_cursor_destroy(sheet
->cursor_drag
);
5026 sheet
->cursor_drag
=gdk_cursor_new(GDK_TOP_LEFT_ARROW
);
5027 gdk_window_set_cursor(sheet
->column_title_window
,sheet
->cursor_drag
);
5032 if(event
->window
== sheet
->row_title_window
&& !GTK_SHEET_ROW_FROZEN(sheet
)){
5033 gtk_widget_get_pointer(widget
, &x
, &y
);
5034 if(!GTK_SHEET_IN_SELECTION(sheet
) && POSSIBLE_YDRAG(sheet
,y
, &column
)){
5035 new_cursor
=GDK_SB_V_DOUBLE_ARROW
;
5036 if(new_cursor
!= sheet
->cursor_drag
->type
){
5037 gdk_cursor_destroy(sheet
->cursor_drag
);
5038 sheet
->cursor_drag
=gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW
);
5039 gdk_window_set_cursor(sheet
->row_title_window
,sheet
->cursor_drag
);
5042 new_cursor
=GDK_TOP_LEFT_ARROW
;
5043 if(!GTK_SHEET_IN_YDRAG(sheet
) && new_cursor
!= sheet
->cursor_drag
->type
){
5044 gdk_cursor_destroy(sheet
->cursor_drag
);
5045 sheet
->cursor_drag
=gdk_cursor_new(GDK_TOP_LEFT_ARROW
);
5046 gdk_window_set_cursor(sheet
->row_title_window
,sheet
->cursor_drag
);
5051 new_cursor
=GDK_PLUS
;
5052 if(!POSSIBLE_DRAG(sheet
,x
,y
,&row
,&column
) && !GTK_SHEET_IN_DRAG(sheet
) &&
5053 !POSSIBLE_RESIZE(sheet
,x
,y
,&row
,&column
) && !GTK_SHEET_IN_RESIZE(sheet
) &&
5054 event
->window
== sheet
->sheet_window
&&
5055 new_cursor
!= sheet
->cursor_drag
->type
){
5056 gdk_cursor_destroy(sheet
->cursor_drag
);
5057 sheet
->cursor_drag
=gdk_cursor_new(GDK_PLUS
);
5058 gdk_window_set_cursor(sheet
->sheet_window
,sheet
->cursor_drag
);
5061 new_cursor
=GDK_TOP_LEFT_ARROW
;
5062 if(!(POSSIBLE_RESIZE(sheet
,x
,y
,&row
,&column
) || GTK_SHEET_IN_RESIZE(sheet
)) &&
5063 (POSSIBLE_DRAG(sheet
, x
,y
,&row
,&column
) || GTK_SHEET_IN_DRAG(sheet
)) &&
5064 event
->window
== sheet
->sheet_window
&&
5065 new_cursor
!= sheet
->cursor_drag
->type
){
5066 gdk_cursor_destroy(sheet
->cursor_drag
);
5067 sheet
->cursor_drag
=gdk_cursor_new(GDK_TOP_LEFT_ARROW
);
5068 gdk_window_set_cursor(sheet
->sheet_window
,sheet
->cursor_drag
);
5071 new_cursor
=GDK_SIZING
;
5072 if(!GTK_SHEET_IN_DRAG(sheet
) &&
5073 (POSSIBLE_RESIZE(sheet
,x
,y
,&row
,&column
) || GTK_SHEET_IN_RESIZE(sheet
)) &&
5074 event
->window
== sheet
->sheet_window
&&
5075 new_cursor
!= sheet
->cursor_drag
->type
){
5076 gdk_cursor_destroy(sheet
->cursor_drag
);
5077 sheet
->cursor_drag
=gdk_cursor_new(GDK_SIZING
);
5078 gdk_window_set_cursor(sheet
->sheet_window
,sheet
->cursor_drag
);
5081 gdk_window_get_pointer (widget
->window
, &x
, &y
, &mods
);
5082 if(!(mods
& GDK_BUTTON1_MASK
)) return FALSE
;
5084 if (GTK_SHEET_IN_XDRAG (sheet
)){
5085 if (event
->is_hint
|| event
->window
!= widget
->window
)
5086 gtk_widget_get_pointer (widget
, &x
, NULL
);
5090 new_column_width (sheet
, sheet
->drag_cell
.col
, &x
);
5091 if (x
!= sheet
->x_drag
)
5093 draw_xor_vline (sheet
);
5095 draw_xor_vline (sheet
);
5100 if (GTK_SHEET_IN_YDRAG (sheet
)){
5101 if (event
->is_hint
|| event
->window
!= widget
->window
)
5102 gtk_widget_get_pointer (widget
, NULL
, &y
);
5106 new_row_height (sheet
, sheet
->drag_cell
.row
, &y
);
5107 if (y
!= sheet
->y_drag
)
5109 draw_xor_hline (sheet
);
5111 draw_xor_hline (sheet
);
5116 if (GTK_SHEET_IN_DRAG(sheet
)){
5118 column
=COLUMN_FROM_XPIXEL(sheet
,x
)-sheet
->drag_cell
.col
;
5119 row
=ROW_FROM_YPIXEL(sheet
,y
)-sheet
->drag_cell
.row
;
5120 if(sheet
->state
==GTK_SHEET_COLUMN_SELECTED
) row
=0;
5121 if(sheet
->state
==GTK_SHEET_ROW_SELECTED
) column
=0;
5125 if(aux
.row0
+row
>= 0 && aux
.rowi
+row
<= sheet
->maxrow
&&
5126 aux
.col0
+column
>= 0 && aux
.coli
+column
<= sheet
->maxcol
){
5127 aux
=sheet
->drag_range
;
5128 sheet
->drag_range
.row0
=sheet
->range
.row0
+row
;
5129 sheet
->drag_range
.col0
=sheet
->range
.col0
+column
;
5130 sheet
->drag_range
.rowi
=sheet
->range
.rowi
+row
;
5131 sheet
->drag_range
.coli
=sheet
->range
.coli
+column
;
5132 if(aux
.row0
!= sheet
->drag_range
.row0
||
5133 aux
.col0
!= sheet
->drag_range
.col0
){
5134 draw_xor_rectangle (sheet
, aux
);
5135 draw_xor_rectangle (sheet
, sheet
->drag_range
);
5141 if (GTK_SHEET_IN_RESIZE(sheet
)){
5145 if(abs(x
-COLUMN_LEFT_XPIXEL(sheet
,sheet
->drag_cell
.col
)) >
5146 abs(y
-ROW_TOP_YPIXEL(sheet
,sheet
->drag_cell
.row
))) v_h
=2;
5148 column
=COLUMN_FROM_XPIXEL(sheet
,x
)-sheet
->drag_cell
.col
;
5149 row
=ROW_FROM_YPIXEL(sheet
,y
)-sheet
->drag_cell
.row
;
5150 if(sheet
->state
==GTK_SHEET_COLUMN_SELECTED
) row
=0;
5151 if(sheet
->state
==GTK_SHEET_ROW_SELECTED
) column
=0;
5156 if(row
< sheet
->range
.row0
- sheet
->range
.rowi
- 1)
5157 row
=row
+(sheet
->range
.rowi
-sheet
->range
.row0
+ 1);
5158 else if(row
<0) row
=0;
5160 if(column
< sheet
->range
.col0
- sheet
->range
.coli
- 1)
5161 column
=column
+(sheet
->range
.coli
-sheet
->range
.col0
+ 1);
5162 else if(column
<0) column
=0;
5169 if(aux
.row0
+row
>= 0 && aux
.rowi
+row
<= sheet
->maxrow
&&
5170 aux
.col0
+column
>= 0 && aux
.coli
+column
<= sheet
->maxcol
){
5172 aux
=sheet
->drag_range
;
5173 sheet
->drag_range
=sheet
->range
;
5175 if(row
<0) sheet
->drag_range
.row0
=sheet
->range
.row0
+row
;
5176 if(row
>0) sheet
->drag_range
.rowi
=sheet
->range
.rowi
+row
;
5177 if(column
<0) sheet
->drag_range
.col0
=sheet
->range
.col0
+column
;
5178 if(column
>0) sheet
->drag_range
.coli
=sheet
->range
.coli
+column
;
5180 if(aux
.row0
!= sheet
->drag_range
.row0
||
5181 aux
.rowi
!= sheet
->drag_range
.rowi
||
5182 aux
.col0
!= sheet
->drag_range
.col0
||
5183 aux
.coli
!= sheet
->drag_range
.coli
){
5184 draw_xor_rectangle (sheet
, aux
);
5185 draw_xor_rectangle (sheet
, sheet
->drag_range
);
5193 gtk_sheet_get_pixel_info (sheet
, x
, y
, &row
, &column
);
5195 if(sheet
->state
==GTK_SHEET_NORMAL
&& row
==sheet
->active_cell
.row
&&
5196 column
==sheet
->active_cell
.col
) return TRUE
;
5198 if(GTK_SHEET_IN_SELECTION(sheet
) && mods
&GDK_BUTTON1_MASK
)
5199 gtk_sheet_extend_selection(sheet
, row
, column
);
5205 gtk_sheet_move_query(GtkSheet
*sheet
, gint row
, gint column
)
5207 gint row_move
, column_move
;
5208 gfloat row_align
, col_align
;
5209 guint height
, width
;
5211 gint new_col
= column
;
5218 height
= sheet
->sheet_window_height
;
5219 width
= sheet
->sheet_window_width
;
5221 if(row
>=MAX_VISIBLE_ROW(sheet
) && sheet
->state
!=GTK_SHEET_COLUMN_SELECTED
) {
5223 new_row
= MIN(sheet
->maxrow
, row
+ 1);
5225 if(MAX_VISIBLE_ROW(sheet
) == sheet
->maxrow
&&
5226 ROW_TOP_YPIXEL(sheet
, sheet
->maxrow
) +
5227 sheet
->row
[sheet
->maxrow
].height
< height
){
5232 if(row
<MIN_VISIBLE_ROW(sheet
) && sheet
->state
!=GTK_SHEET_COLUMN_SELECTED
) {
5236 if(column
>=MAX_VISIBLE_COLUMN(sheet
) && sheet
->state
!=GTK_SHEET_ROW_SELECTED
) {
5238 new_col
= MIN(sheet
->maxcol
, column
+ 1);
5240 if(MAX_VISIBLE_COLUMN(sheet
) == sheet
->maxcol
&&
5241 COLUMN_LEFT_XPIXEL(sheet
, sheet
->maxcol
) +
5242 sheet
->column
[sheet
->maxcol
].width
< width
){
5243 column_move
= FALSE
;
5247 if(column
<MIN_VISIBLE_COLUMN(sheet
) && sheet
->state
!=GTK_SHEET_ROW_SELECTED
) {
5252 if(row_move
|| column_move
){
5253 gtk_sheet_moveto(sheet
, new_row
, new_col
, row_align
, col_align
);
5256 return(row_move
|| column_move
);
5260 gtk_sheet_extend_selection(GtkSheet
*sheet
, gint row
, gint column
)
5262 GtkSheetRange range
;
5266 if(row
== sheet
->selection_cell
.row
&& column
== sheet
->selection_cell
.col
)
5269 if(sheet
->selection_mode
== GTK_SELECTION_SINGLE
) return;
5271 gtk_sheet_move_query(sheet
, row
, column
);
5272 gtk_widget_grab_focus(GTK_WIDGET(sheet
));
5274 if(GTK_SHEET_IN_DRAG(sheet
)) return;
5278 switch(sheet
->state
){
5279 case GTK_SHEET_ROW_SELECTED
:
5280 column
= sheet
->maxcol
;
5282 case GTK_SHEET_COLUMN_SELECTED
:
5283 row
= sheet
->maxrow
;
5285 case GTK_SHEET_NORMAL
:
5286 sheet
->state
=GTK_SHEET_RANGE_SELECTED
;
5287 r
=sheet
->active_cell
.row
;
5288 c
=sheet
->active_cell
.col
;
5289 sheet
->range
.col0
=c
;
5290 sheet
->range
.row0
=r
;
5291 sheet
->range
.coli
=c
;
5292 sheet
->range
.rowi
=r
;
5293 gdk_draw_pixmap(sheet
->sheet_window
,
5294 GTK_WIDGET(sheet
)->style
->fg_gc
[GTK_STATE_NORMAL
],
5296 COLUMN_LEFT_XPIXEL(sheet
,c
)-1,
5297 ROW_TOP_YPIXEL(sheet
,r
)-1,
5298 COLUMN_LEFT_XPIXEL(sheet
,c
)-1,
5299 ROW_TOP_YPIXEL(sheet
,r
)-1,
5300 sheet
->column
[c
].width
+4,
5301 sheet
->row
[r
].height
+4);
5302 gtk_sheet_range_draw_selection(sheet
, sheet
->range
);
5303 case GTK_SHEET_RANGE_SELECTED
:
5304 sheet
->state
=GTK_SHEET_RANGE_SELECTED
;
5307 sheet
->selection_cell
.row
= row
;
5308 sheet
->selection_cell
.col
= column
;
5310 range
.col0
=MIN(column
,sheet
->active_cell
.col
);
5311 range
.coli
=MAX(column
,sheet
->active_cell
.col
);
5312 range
.row0
=MIN(row
,sheet
->active_cell
.row
);
5313 range
.rowi
=MAX(row
,sheet
->active_cell
.row
);
5315 if(range
.row0
!= sheet
->range
.row0
|| range
.rowi
!= sheet
->range
.rowi
||
5316 range
.col0
!= sheet
->range
.col0
|| range
.coli
!= sheet
->range
.coli
||
5317 state
==GTK_SHEET_NORMAL
)
5318 gtk_sheet_real_select_range(sheet
, &range
);
5323 gtk_sheet_entry_key_press(GtkWidget
*widget
,
5327 gtk_signal_emit_by_name(GTK_OBJECT(widget
), "key_press_event", key
, &focus
);
5332 gtk_sheet_key_press(GtkWidget
*widget
,
5338 gboolean extend_selection
= FALSE
;
5339 gboolean force_move
= FALSE
;
5340 gboolean in_selection
= FALSE
;
5341 gboolean veto
= TRUE
;
5344 sheet
= GTK_SHEET(widget
);
5346 if(key
->state
& GDK_CONTROL_MASK
|| key
->keyval
==GDK_Control_L
||
5347 key
->keyval
==GDK_Control_R
) return FALSE
;
5351 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL)
5352 gtk_sheet_clip_range(sheet, sheet->range);
5353 if(key->keyval=='x' || key->keyval == 'X')
5354 gtk_sheet_unclip_range(sheet);
5359 extend_selection
= (key
->state
& GDK_SHIFT_MASK
) || key
->keyval
==GDK_Shift_L
5360 || key
->keyval
==GDK_Shift_R
;
5363 in_selection
= GTK_SHEET_IN_SELECTION(sheet
);
5364 GTK_SHEET_UNSET_FLAGS(sheet
, GTK_SHEET_IN_SELECTION
);
5366 switch(key
->keyval
){
5367 case GDK_Return
: case GDK_KP_Enter
:
5368 if(sheet
->state
== GTK_SHEET_NORMAL
&&
5369 !GTK_SHEET_IN_SELECTION(sheet
))
5370 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet
)),
5372 row
= sheet
->active_cell
.row
;
5373 col
= sheet
->active_cell
.col
;
5374 if(sheet
->state
== GTK_SHEET_COLUMN_SELECTED
)
5375 row
= MIN_VISIBLE_ROW(sheet
)-1;
5376 if(sheet
->state
== GTK_SHEET_ROW_SELECTED
)
5377 col
= MIN_VISIBLE_COLUMN(sheet
);
5378 if(row
< sheet
->maxrow
){
5380 while(!sheet
->row
[row
].is_visible
&& row
<sheet
->maxrow
) row
++;
5382 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5383 extend_selection
= FALSE
;
5385 case GDK_ISO_Left_Tab
:
5386 row
= sheet
->active_cell
.row
;
5387 col
= sheet
->active_cell
.col
;
5388 if(sheet
->state
== GTK_SHEET_ROW_SELECTED
)
5389 col
= MIN_VISIBLE_COLUMN(sheet
)-1;
5390 if(sheet
->state
== GTK_SHEET_COLUMN_SELECTED
)
5391 row
= MIN_VISIBLE_ROW(sheet
);
5394 while(!sheet
->column
[col
].is_visible
&& col
>0) col
--;
5397 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5398 extend_selection
= FALSE
;
5401 row
= sheet
->active_cell
.row
;
5402 col
= sheet
->active_cell
.col
;
5403 if(sheet
->state
== GTK_SHEET_ROW_SELECTED
)
5404 col
= MIN_VISIBLE_COLUMN(sheet
)-1;
5405 if(sheet
->state
== GTK_SHEET_COLUMN_SELECTED
)
5406 row
= MIN_VISIBLE_ROW(sheet
);
5407 if(col
< sheet
->maxcol
){
5409 while(!sheet
->column
[col
].is_visible
&& col
<sheet
->maxcol
) col
++;
5411 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5412 extend_selection
= FALSE
;
5414 /* case GDK_BackSpace:
5415 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){
5416 if(sheet->active_cell.col > 0){
5417 col = sheet->active_cell.col - scroll;
5418 row = sheet->active_cell.row;
5419 while(!sheet->column[col].is_visible && col > 0) col--;
5422 gtk_sheet_click_cell(sheet, row, col, &veto);
5423 extend_selection = FALSE;
5427 scroll
=MAX_VISIBLE_ROW(sheet
)-MIN_VISIBLE_ROW(sheet
)+1;
5429 if(extend_selection
){
5430 if(state
==GTK_STATE_NORMAL
){
5431 row
=sheet
->active_cell
.row
;
5432 col
=sheet
->active_cell
.col
;
5433 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5436 if(sheet
->selection_cell
.row
> 0){
5437 row
= sheet
->selection_cell
.row
- scroll
;
5438 while(!sheet
->row
[row
].is_visible
&& row
> 0) row
--;
5440 gtk_sheet_extend_selection(sheet
, row
, sheet
->selection_cell
.col
);
5444 col
= sheet
->active_cell
.col
;
5445 row
= sheet
->active_cell
.row
;
5446 if(state
==GTK_SHEET_COLUMN_SELECTED
)
5447 row
= MIN_VISIBLE_ROW(sheet
);
5448 if(state
==GTK_SHEET_ROW_SELECTED
)
5449 col
= MIN_VISIBLE_COLUMN(sheet
);
5451 while(!sheet
->row
[row
].is_visible
&& row
> 0) row
--;
5453 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5454 extend_selection
= FALSE
;
5457 scroll
=MAX_VISIBLE_ROW(sheet
)-MIN_VISIBLE_ROW(sheet
)+1;
5459 if(extend_selection
){
5460 if(state
==GTK_STATE_NORMAL
){
5461 row
=sheet
->active_cell
.row
;
5462 col
=sheet
->active_cell
.col
;
5463 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5466 if(sheet
->selection_cell
.row
< sheet
->maxrow
){
5467 row
= sheet
->selection_cell
.row
+ scroll
;
5468 while(!sheet
->row
[row
].is_visible
&& row
< sheet
->maxrow
) row
++;
5469 row
= MIN(sheet
->maxrow
, row
);
5470 gtk_sheet_extend_selection(sheet
, row
, sheet
->selection_cell
.col
);
5474 col
= sheet
->active_cell
.col
;
5475 row
= sheet
->active_cell
.row
;
5476 if(sheet
->active_cell
.row
< sheet
->maxrow
){
5477 if(state
==GTK_SHEET_COLUMN_SELECTED
)
5478 row
= MIN_VISIBLE_ROW(sheet
)-1;
5479 if(state
==GTK_SHEET_ROW_SELECTED
)
5480 col
= MIN_VISIBLE_COLUMN(sheet
);
5482 while(!sheet
->row
[row
].is_visible
&& row
< sheet
->maxrow
) row
++;
5483 row
= MIN(sheet
->maxrow
, row
);
5485 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5486 extend_selection
= FALSE
;
5489 if(extend_selection
){
5490 if(state
==GTK_STATE_NORMAL
){
5491 row
=sheet
->active_cell
.row
;
5492 col
=sheet
->active_cell
.col
;
5493 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5496 if(sheet
->selection_cell
.col
< sheet
->maxcol
){
5497 col
= sheet
->selection_cell
.col
+ 1;
5498 while(!sheet
->column
[col
].is_visible
&& col
< sheet
->maxcol
) col
++;
5499 gtk_sheet_extend_selection(sheet
, sheet
->selection_cell
.row
, col
);
5503 col
= sheet
->active_cell
.col
;
5504 row
= sheet
->active_cell
.row
;
5505 if(sheet
->active_cell
.col
< sheet
->maxcol
){
5507 if(state
==GTK_SHEET_ROW_SELECTED
)
5508 col
= MIN_VISIBLE_COLUMN(sheet
)-1;
5509 if(state
==GTK_SHEET_COLUMN_SELECTED
)
5510 row
= MIN_VISIBLE_ROW(sheet
);
5511 while(!sheet
->column
[col
].is_visible
&& col
< sheet
->maxcol
) col
++;
5512 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet
)))) == 0
5514 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5519 extend_selection
= FALSE
;
5522 if(extend_selection
){
5523 if(state
==GTK_STATE_NORMAL
){
5524 row
=sheet
->active_cell
.row
;
5525 col
=sheet
->active_cell
.col
;
5526 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5529 if(sheet
->selection_cell
.col
> 0){
5530 col
= sheet
->selection_cell
.col
- 1;
5531 while(!sheet
->column
[col
].is_visible
&& col
> 0) col
--;
5532 gtk_sheet_extend_selection(sheet
, sheet
->selection_cell
.row
, col
);
5536 col
= sheet
->active_cell
.col
- 1;
5537 row
= sheet
->active_cell
.row
;
5538 if(state
==GTK_SHEET_ROW_SELECTED
)
5539 col
= MIN_VISIBLE_COLUMN(sheet
)-1;
5540 if(state
==GTK_SHEET_COLUMN_SELECTED
)
5541 row
= MIN_VISIBLE_ROW(sheet
);
5542 while(!sheet
->column
[col
].is_visible
&& col
> 0) col
--;
5545 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet
)))) == 0
5547 gtk_sheet_click_cell(sheet
, row
, col
, &veto
);
5551 extend_selection
= FALSE
;
5555 while(!sheet
->row
[row
].is_visible
&& row
< sheet
->maxrow
) row
++;
5556 gtk_sheet_click_cell(sheet
, row
, sheet
->active_cell
.col
, &veto
);
5557 extend_selection
= FALSE
;
5561 while(!sheet
->row
[row
].is_visible
&& row
> 0) row
--;
5562 gtk_sheet_click_cell(sheet
, row
, sheet
->active_cell
.col
, &veto
);
5563 extend_selection
= FALSE
;
5566 if(in_selection
) GTK_SHEET_SET_FLAGS(sheet
, GTK_SHEET_IN_SELECTION
);
5567 if(extend_selection
) return TRUE
;
5568 if(state
== GTK_SHEET_ROW_SELECTED
)
5569 sheet
->active_cell
.col
=MIN_VISIBLE_COLUMN(sheet
);
5570 if(state
== GTK_SHEET_COLUMN_SELECTED
)
5571 sheet
->active_cell
.row
=MIN_VISIBLE_ROW(sheet
);
5575 if(extend_selection
) return TRUE
;
5577 gtk_sheet_activate_cell(sheet
, sheet
->active_cell
.row
,
5578 sheet
->active_cell
.col
);
5584 gtk_sheet_size_request (GtkWidget
* widget
,
5585 GtkRequisition
* requisition
)
5589 GtkSheetChild
*child
;
5590 GtkRequisition child_requisition
;
5592 g_return_if_fail (widget
!= NULL
);
5593 g_return_if_fail (GTK_IS_SHEET (widget
));
5594 g_return_if_fail (requisition
!= NULL
);
5596 sheet
= GTK_SHEET (widget
);
5598 requisition
->width
= 3*DEFAULT_COLUMN_WIDTH
;
5599 requisition
->height
= 3*DEFAULT_ROW_HEIGHT(widget
);
5601 /* compute the size of the column title area */
5602 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
5603 requisition
->height
+= sheet
->column_title_area
.height
;
5605 /* compute the size of the row title area */
5606 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
5607 requisition
->width
+= sheet
->row_title_area
.width
;
5609 sheet
->view
.row0
=ROW_FROM_YPIXEL(sheet
, sheet
->column_title_area
.height
+1);
5610 sheet
->view
.rowi
=ROW_FROM_YPIXEL(sheet
, sheet
->sheet_window_height
-1);
5611 sheet
->view
.col0
=COLUMN_FROM_XPIXEL(sheet
, sheet
->row_title_area
.width
+1);
5612 sheet
->view
.coli
=COLUMN_FROM_XPIXEL(sheet
, sheet
->sheet_window_width
);
5614 if(!GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
5615 sheet
->view
.row0
=ROW_FROM_YPIXEL(sheet
, 1);
5617 if(!GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
5618 sheet
->view
.col0
=COLUMN_FROM_XPIXEL(sheet
, 1);
5620 children
= sheet
->children
;
5623 child
= children
->data
;
5624 children
= children
->next
;
5626 gtk_widget_size_request(child
->widget
, &child_requisition
);
5632 gtk_sheet_size_allocate (GtkWidget
* widget
,
5633 GtkAllocation
* allocation
)
5636 GtkAllocation sheet_allocation
;
5639 g_return_if_fail (widget
!= NULL
);
5640 g_return_if_fail (GTK_IS_SHEET (widget
));
5641 g_return_if_fail (allocation
!= NULL
);
5643 sheet
= GTK_SHEET (widget
);
5644 widget
->allocation
= *allocation
;
5645 border_width
= GTK_CONTAINER(widget
)->border_width
;
5647 if (GTK_WIDGET_REALIZED (widget
))
5648 gdk_window_move_resize (widget
->window
,
5649 allocation
->x
+ border_width
,
5650 allocation
->y
+ border_width
,
5651 allocation
->width
- 2*border_width
,
5652 allocation
->height
- 2*border_width
);
5654 /* use internal allocation structure for all the math
5655 * because it's easier than always subtracting the container
5657 sheet
->internal_allocation
.x
= 0;
5658 sheet
->internal_allocation
.y
= 0;
5659 sheet
->internal_allocation
.width
= allocation
->width
- 2*border_width
;
5660 sheet
->internal_allocation
.height
= allocation
->height
- 2*border_width
;
5662 sheet_allocation
.x
= 0;
5663 sheet_allocation
.y
= 0;
5664 sheet_allocation
.width
= allocation
->width
- 2*border_width
;
5665 sheet_allocation
.height
= allocation
->height
- 2*border_width
;
5667 sheet
->sheet_window_width
= sheet_allocation
.width
;
5668 sheet
->sheet_window_height
= sheet_allocation
.height
;
5670 if (GTK_WIDGET_REALIZED (widget
))
5671 gdk_window_move_resize (sheet
->sheet_window
,
5674 sheet_allocation
.width
,
5675 sheet_allocation
.height
);
5677 /* position the window which holds the column title buttons */
5678 sheet
->column_title_area
.x
= 0;
5679 sheet
->column_title_area
.y
= 0;
5680 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
5681 sheet
->column_title_area
.x
= sheet
->row_title_area
.width
;
5682 sheet
->column_title_area
.width
= sheet_allocation
.width
-
5683 sheet
->column_title_area
.x
;
5684 if(GTK_WIDGET_REALIZED(widget
) && GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
5685 gdk_window_move_resize (sheet
->column_title_window
,
5686 sheet
->column_title_area
.x
,
5687 sheet
->column_title_area
.y
,
5688 sheet
->column_title_area
.width
,
5689 sheet
->column_title_area
.height
);
5691 sheet
->sheet_window_width
= sheet_allocation
.width
;
5692 sheet
->sheet_window_height
= sheet_allocation
.height
;
5694 /* column button allocation */
5695 size_allocate_column_title_buttons (sheet
);
5697 /* position the window which holds the row title buttons */
5698 sheet
->row_title_area
.x
= 0;
5699 sheet
->row_title_area
.y
= 0;
5700 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
5701 sheet
->row_title_area
.y
= sheet
->column_title_area
.height
;
5702 sheet
->row_title_area
.height
= sheet_allocation
.height
-
5703 sheet
->row_title_area
.y
;
5705 if(GTK_WIDGET_REALIZED(widget
) && GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
5706 gdk_window_move_resize (sheet
->row_title_window
,
5707 sheet
->row_title_area
.x
,
5708 sheet
->row_title_area
.y
,
5709 sheet
->row_title_area
.width
,
5710 sheet
->row_title_area
.height
);
5713 /* row button allocation */
5714 size_allocate_row_title_buttons (sheet
);
5716 sheet
->view
.row0
=ROW_FROM_YPIXEL(sheet
, sheet
->column_title_area
.height
+1);
5717 sheet
->view
.rowi
=ROW_FROM_YPIXEL(sheet
, sheet
->sheet_window_height
-1);
5718 sheet
->view
.col0
=COLUMN_FROM_XPIXEL(sheet
, sheet
->row_title_area
.width
+1);
5719 sheet
->view
.coli
=COLUMN_FROM_XPIXEL(sheet
, sheet
->sheet_window_width
);
5721 if(!GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
5722 sheet
->view
.row0
=ROW_FROM_YPIXEL(sheet
, 1);
5724 if(!GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
5725 sheet
->view
.col0
=COLUMN_FROM_XPIXEL(sheet
, 1);
5727 size_allocate_column_title_buttons(sheet
);
5728 size_allocate_row_title_buttons(sheet
);
5730 /* re-scale backing pixmap */
5731 gtk_sheet_make_backing_pixmap(sheet
, 0, 0);
5732 gtk_sheet_position_children(sheet
);
5734 /* set the scrollbars adjustments */
5735 adjust_scrollbars (sheet
);
5739 size_allocate_column_title_buttons (GtkSheet
* sheet
)
5744 if (!GTK_SHEET_COL_TITLES_VISIBLE(sheet
)) return;
5745 if (!GTK_WIDGET_REALIZED (sheet
))
5748 width
= sheet
->sheet_window_width
;
5751 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
5753 width
-= sheet
->row_title_area
.width
;
5754 x
= sheet
->row_title_area
.width
;
5757 if(sheet
->column_title_area
.width
!= width
|| sheet
->column_title_area
.x
!= x
)
5759 sheet
->column_title_area
.width
= width
;
5760 sheet
->column_title_area
.x
= x
;
5761 gdk_window_move_resize (sheet
->column_title_window
,
5762 sheet
->column_title_area
.x
,
5763 sheet
->column_title_area
.y
,
5764 sheet
->column_title_area
.width
,
5765 sheet
->column_title_area
.height
);
5769 if(MAX_VISIBLE_COLUMN(sheet
) == sheet
->maxcol
)
5770 gdk_window_clear_area (sheet
->column_title_window
,
5772 sheet
->column_title_area
.width
,
5773 sheet
->column_title_area
.height
);
5775 if(!GTK_WIDGET_DRAWABLE(sheet
)) return;
5777 for (i
= MIN_VISIBLE_COLUMN(sheet
); i
<= MAX_VISIBLE_COLUMN(sheet
); i
++)
5778 gtk_sheet_button_draw(sheet
,-1,i
);
5782 size_allocate_row_title_buttons (GtkSheet
* sheet
)
5787 if (!GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)) return;
5788 if (!GTK_WIDGET_REALIZED (sheet
))
5791 height
= sheet
->sheet_window_height
;
5794 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
5796 height
-= sheet
->column_title_area
.height
;
5797 y
= sheet
->column_title_area
.height
;
5800 if(sheet
->row_title_area
.height
!= height
|| sheet
->row_title_area
.y
!= y
){
5801 sheet
->row_title_area
.y
= y
;
5802 sheet
->row_title_area
.height
= height
;
5803 gdk_window_move_resize (sheet
->row_title_window
,
5804 sheet
->row_title_area
.x
,
5805 sheet
->row_title_area
.y
,
5806 sheet
->row_title_area
.width
,
5807 sheet
->row_title_area
.height
);
5809 if(MAX_VISIBLE_ROW(sheet
) == sheet
->maxrow
)
5810 gdk_window_clear_area (sheet
->row_title_window
,
5812 sheet
->row_title_area
.width
,
5813 sheet
->row_title_area
.height
);
5815 if(!GTK_WIDGET_DRAWABLE(sheet
)) return;
5817 for(i
= MIN_VISIBLE_ROW(sheet
); i
<= MAX_VISIBLE_ROW(sheet
); i
++)
5818 gtk_sheet_button_draw(sheet
,i
,-1);
5822 gtk_sheet_recalc_top_ypixels(GtkSheet
*sheet
, gint row
)
5826 cy
= sheet
->column_title_area
.height
;
5827 if(!GTK_SHEET_COL_TITLES_VISIBLE(sheet
)) cy
= 0;
5828 for(i
=0; i
<=sheet
->maxrow
; i
++){
5829 sheet
->row
[i
].top_ypixel
=cy
;
5830 if(sheet
->row
[i
].is_visible
) cy
+=sheet
->row
[i
].height
;
5835 gtk_sheet_recalc_left_xpixels(GtkSheet
*sheet
, gint column
)
5839 cx
= sheet
->row_title_area
.width
;
5840 if(!GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)) cx
= 0;
5841 for(i
=0; i
<=sheet
->maxcol
; i
++){
5842 sheet
->column
[i
].left_xpixel
=cx
;
5843 if(sheet
->column
[i
].is_visible
) cx
+=sheet
->column
[i
].width
;
5851 gtk_sheet_size_allocate_entry(GtkSheet
*sheet
)
5853 GtkAllocation shentry_allocation
;
5854 GtkSheetCellAttr attributes
;
5855 GtkEntry
*sheet_entry
;
5856 GtkStyle
*style
= NULL
, *previous_style
= NULL
;
5858 gint size
, max_size
, text_size
, column_width
;
5859 const gchar
*text
; /* Needed for Gtk-2.X */
5862 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return;
5863 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet
))) return;
5865 sheet_entry
= GTK_ENTRY(gtk_sheet_get_entry(sheet
));
5867 gtk_sheet_get_attributes(sheet
, sheet
->active_cell
.row
, sheet
->active_cell
.col
, &attributes
);
5869 if(GTK_WIDGET_REALIZED(sheet
->sheet_entry
)){
5871 if(!GTK_WIDGET(sheet_entry
)->style
)
5872 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry
));
5874 previous_style
= GTK_WIDGET(sheet_entry
)->style
;
5876 style
= gtk_style_copy(previous_style
);
5878 style
->bg
[GTK_STATE_NORMAL
] = attributes
.background
;
5879 style
->fg
[GTK_STATE_NORMAL
] = attributes
.foreground
;
5880 style
->text
[GTK_STATE_NORMAL
] = attributes
.foreground
;
5881 style
->bg
[GTK_STATE_ACTIVE
] = attributes
.background
;
5882 style
->fg
[GTK_STATE_ACTIVE
] = attributes
.foreground
;
5883 style
->text
[GTK_STATE_ACTIVE
] = attributes
.foreground
;
5885 if(style
->font
!= attributes
.font
) {
5886 gdk_font_unref(style
->font
);
5887 style
->font
= attributes
.font
;
5888 gdk_font_ref(style
->font
);
5891 /* I'm emulating gtk_widget_size_request to avoid the redraw */
5892 GTK_WIDGET(sheet_entry
)->style
= style
;
5893 gtk_widget_size_request(sheet
->sheet_entry
, NULL
);
5894 GTK_WIDGET(sheet_entry
)->style
= previous_style
;
5896 if(style
!= previous_style
)
5897 gtk_widget_set_style(GTK_WIDGET(sheet_entry
), style
);
5899 if(GTK_IS_ITEM_ENTRY(sheet_entry
)){
5900 gdk_gc_set_foreground(GTK_ITEM_ENTRY(sheet_entry
)->fg_gc
,
5901 &attributes
.foreground
);
5902 gdk_gc_set_foreground(GTK_ITEM_ENTRY(sheet_entry
)->bg_gc
,
5903 &attributes
.background
);
5906 gdk_window_set_background(GTK_ENTRY(sheet_entry
)->text_area
,
5907 &attributes
.background
);
5909 if(sheet
->sheet_entry_window
)
5910 gdk_window_set_background(sheet
->sheet_entry_window
,
5911 &attributes
.background
);
5913 gdk_window_set_background(GTK_WIDGET(sheet_entry
)->window
,
5914 &attributes
.background
);
5918 if(GTK_IS_ITEM_ENTRY(sheet_entry
))
5919 max_size
= GTK_ITEM_ENTRY(sheet_entry
)->text_max_size
;
5923 text_size
=GTK_ENTRY(sheet_entry
)->text
== NULL
? 0 :
5924 gdk_string_width(attributes
.font
,
5925 gtk_entry_get_text(GTK_ENTRY(sheet_entry
)));
5927 column_width
=sheet
->column
[sheet
->active_cell
.col
].width
;
5929 size
=MIN(text_size
, max_size
);
5930 size
=MAX(size
,column_width
);
5932 row
=sheet
->active_cell
.row
;
5933 col
=sheet
->active_cell
.col
;
5935 shentry_allocation
.x
=COLUMN_LEFT_XPIXEL(sheet
,sheet
->active_cell
.col
);
5936 shentry_allocation
.y
=ROW_TOP_YPIXEL(sheet
,sheet
->active_cell
.row
);
5937 shentry_allocation
.width
=column_width
;
5938 shentry_allocation
.height
=sheet
->row
[sheet
->active_cell
.row
].height
;
5940 /* SDB says: we may need to edit this for gtk-2 */
5941 if(GTK_IS_ITEM_ENTRY(sheet
->sheet_entry
) && !GTK_SHEET_CLIP_TEXT(sheet
)){
5942 switch(GTK_ITEM_ENTRY(sheet_entry
)->justification
){
5943 case GTK_JUSTIFY_CENTER
:
5944 shentry_allocation
.width
=size
;
5945 shentry_allocation
.x
=shentry_allocation
.x
+
5946 column_width
/2-size
/2;
5948 case GTK_JUSTIFY_RIGHT
:
5949 shentry_allocation
.x
=shentry_allocation
.x
+shentry_allocation
.width
-size
+1;
5950 shentry_allocation
.width
=size
;
5952 case GTK_JUSTIFY_LEFT
:
5953 case GTK_JUSTIFY_FILL
:
5954 shentry_allocation
.width
=size
;
5960 if(!GTK_IS_ITEM_ENTRY(sheet
->sheet_entry
)){
5961 shentry_allocation
.x
+= 2;
5962 shentry_allocation
.y
+= 2;
5963 shentry_allocation
.width
-= MIN(shentry_allocation
.width
, 3);
5964 shentry_allocation
.height
-= MIN(shentry_allocation
.height
, 3);
5967 /* SDB says: We may remove this (or rewrite it) for GTK22 */
5968 if(sheet
->sheet_entry_window
){
5969 gdk_window_move_resize(sheet
->sheet_entry_window
,
5970 shentry_allocation
.x
,
5971 shentry_allocation
.y
,
5972 shentry_allocation
.width
,
5973 shentry_allocation
.height
);
5974 shentry_allocation
.x
= 0;
5975 shentry_allocation
.y
= 0;
5976 gtk_widget_size_allocate(sheet
->sheet_entry
, &shentry_allocation
);
5978 gtk_widget_size_allocate(sheet
->sheet_entry
, &shentry_allocation
);
5982 if(previous_style
== style
) gtk_style_unref(previous_style
);
5988 gtk_sheet_entry_set_max_size(GtkSheet
*sheet
)
5992 gint sizel
=0, sizer
=0;
5994 GtkJustification justification
;
5996 row
=sheet
->active_cell
.row
;
5997 col
=sheet
->active_cell
.col
;
5999 if(!GTK_IS_ITEM_ENTRY(sheet
->sheet_entry
) || GTK_SHEET_CLIP_TEXT(sheet
)) return;
6001 justification
= GTK_ITEM_ENTRY(sheet
->sheet_entry
)->justification
;
6003 switch(justification
){
6004 case GTK_JUSTIFY_FILL
:
6005 case GTK_JUSTIFY_LEFT
:
6006 for(i
=col
+1; i
<=MAX_VISIBLE_COLUMN(sheet
); i
++){
6007 if(gtk_sheet_cell_get_text(sheet
, row
, i
)) break;
6008 size
+=sheet
->column
[i
].width
;
6010 size
= MIN(size
, sheet
->sheet_window_width
- COLUMN_LEFT_XPIXEL(sheet
, col
));
6012 case GTK_JUSTIFY_RIGHT
:
6013 for(i
=col
-1; i
>=MIN_VISIBLE_COLUMN(sheet
); i
--){
6014 if(gtk_sheet_cell_get_text(sheet
, row
, i
)) break;
6015 size
+=sheet
->column
[i
].width
;
6018 case GTK_JUSTIFY_CENTER
:
6019 for(i
=col
+1; i
<=MAX_VISIBLE_COLUMN(sheet
); i
++){
6020 /* if(gtk_sheet_cell_get_text(sheet, row, i)) break;
6022 sizer
+=sheet
->column
[i
].width
;
6024 for(i
=col
-1; i
>=MIN_VISIBLE_COLUMN(sheet
); i
--){
6025 if(gtk_sheet_cell_get_text(sheet
, row
, i
)) break;
6026 sizel
+=sheet
->column
[i
].width
;
6028 size
=2*MIN(sizel
, sizer
);
6032 if(size
!=0) size
+=sheet
->column
[col
].width
;
6033 GTK_ITEM_ENTRY(sheet
->sheet_entry
)->text_max_size
=size
;
6039 create_sheet_entry(GtkSheet
*sheet
)
6045 gint found_entry
= FALSE
;
6047 widget
= GTK_WIDGET(sheet
);
6049 style
= gtk_style_copy(GTK_WIDGET(sheet
)->style
);
6051 gtk_widget_push_style(style
);
6053 if(sheet
->sheet_entry
){
6054 if(sheet
->sheet_entry_window
){
6055 gdk_window_set_user_data(sheet
->sheet_entry_window
, NULL
);
6056 gdk_window_destroy(sheet
->sheet_entry_window
);
6057 sheet
->sheet_entry_window
= NULL
;
6059 /* avoids warnings */
6060 gtk_widget_ref(sheet
->sheet_entry
);
6061 gtk_widget_unparent(sheet
->sheet_entry
);
6062 gtk_widget_destroy(sheet
->sheet_entry
);
6065 if(sheet
->entry_type
){
6067 if(!gtk_type_is_a (sheet
->entry_type
, GTK_TYPE_ENTRY
)){
6069 parent
= GTK_WIDGET(gtk_type_new(sheet
->entry_type
));
6071 sheet
->sheet_entry
= parent
;
6073 entry
= gtk_sheet_get_entry (sheet
);
6074 if(GTK_IS_ENTRY(entry
)) found_entry
= TRUE
;
6078 parent
= GTK_WIDGET(gtk_type_new(sheet
->entry_type
));
6086 g_warning ("Entry type must be GtkEntry subclass, using default");
6087 entry
=GTK_WIDGET(gtk_type_new(GTK_TYPE_ITEM_ENTRY
));
6088 sheet
->sheet_entry
= entry
;
6092 sheet
->sheet_entry
= parent
;
6099 entry
=GTK_WIDGET(gtk_type_new(GTK_TYPE_ITEM_ENTRY
));
6100 sheet
->sheet_entry
= entry
;
6104 gtk_widget_size_request(sheet
->sheet_entry
, NULL
);
6106 /* --- SDB says: This doesn't appear in the Gtk-2.X version --- */
6107 if (GTK_WIDGET_REALIZED(sheet
) && GTK_WIDGET_NO_WINDOW (sheet
->sheet_entry
))
6109 GdkWindowAttr attributes
;
6110 gint attributes_mask
;
6112 attributes
.window_type
= GDK_WINDOW_CHILD
;
6115 attributes
.width
= sheet
->sheet_entry
->requisition
.width
;
6116 attributes
.height
= sheet
->sheet_entry
->requisition
.height
;
6117 attributes
.wclass
= GDK_INPUT_OUTPUT
;
6118 attributes
.visual
= gtk_widget_get_visual (widget
);
6119 attributes
.colormap
= gtk_widget_get_colormap (widget
);
6120 attributes
.event_mask
= GDK_EXPOSURE_MASK
;
6122 attributes_mask
= GDK_WA_X
| GDK_WA_Y
| GDK_WA_VISUAL
| GDK_WA_COLORMAP
;
6123 sheet
->sheet_entry_window
= gdk_window_new (sheet
->sheet_window
,
6124 &attributes
, attributes_mask
);
6125 gdk_window_set_user_data (sheet
->sheet_entry_window
, widget
);
6127 if (sheet
->sheet_entry_window
)
6128 gtk_style_set_background (widget
->style
,
6129 sheet
->sheet_entry_window
,
6133 if(GTK_WIDGET_REALIZED(sheet
))
6135 gtk_widget_set_parent(sheet
->sheet_entry
, GTK_WIDGET(sheet
));
6136 gtk_widget_set_parent_window (sheet
->sheet_entry
,
6137 sheet
->sheet_entry_window
?
6138 sheet
->sheet_entry_window
:
6139 sheet
->sheet_window
);
6140 gtk_widget_realize(sheet
->sheet_entry
);
6143 gtk_signal_connect_object(GTK_OBJECT(entry
),"key_press_event",
6144 (GtkSignalFunc
) gtk_sheet_entry_key_press
,
6147 gtk_widget_show (sheet
->sheet_entry
);
6152 gtk_sheet_get_entry(GtkSheet
*sheet
)
6155 GtkWidget
*entry
= NULL
;
6156 GtkTableChild
*table_child
;
6157 GtkBoxChild
*box_child
;
6158 GList
*children
= NULL
;
6160 g_return_val_if_fail (sheet
!= NULL
, NULL
);
6161 g_return_val_if_fail (GTK_IS_SHEET (sheet
), NULL
);
6162 g_return_val_if_fail (sheet
->sheet_entry
!= NULL
, NULL
);
6164 if(GTK_IS_ENTRY(sheet
->sheet_entry
)) return (sheet
->sheet_entry
);
6166 parent
= GTK_WIDGET(sheet
->sheet_entry
);
6168 if(GTK_IS_TABLE(parent
)) children
= GTK_TABLE(parent
)->children
;
6169 if(GTK_IS_BOX(parent
)) children
= GTK_BOX(parent
)->children
;
6171 if(!children
) return NULL
;
6174 if(GTK_IS_TABLE(parent
)) {
6175 table_child
= children
->data
;
6176 entry
= table_child
->widget
;
6178 if(GTK_IS_BOX(parent
)){
6179 box_child
= children
->data
;
6180 entry
= box_child
->widget
;
6183 if(GTK_IS_ENTRY(entry
))
6185 children
= children
->next
;
6189 if(!GTK_IS_ENTRY(entry
)) return NULL
;
6196 gtk_sheet_get_entry_widget(GtkSheet
*sheet
)
6198 g_return_val_if_fail (sheet
!= NULL
, NULL
);
6199 g_return_val_if_fail (GTK_IS_SHEET (sheet
), NULL
);
6200 g_return_val_if_fail (sheet
->sheet_entry
!= NULL
, NULL
);
6202 return (sheet
->sheet_entry
);
6207 row_button_set (GtkSheet
*sheet
, gint row
)
6209 if(sheet
->row
[row
].button
.state
== GTK_STATE_ACTIVE
) return;
6211 sheet
->row
[row
].button
.state
= GTK_STATE_ACTIVE
;
6212 gtk_sheet_button_draw(sheet
, row
, -1);
6217 column_button_set (GtkSheet
*sheet
, gint column
)
6219 if(sheet
->column
[column
].button
.state
== GTK_STATE_ACTIVE
) return;
6221 sheet
->column
[column
].button
.state
= GTK_STATE_ACTIVE
;
6222 gtk_sheet_button_draw(sheet
, -1, column
);
6227 row_button_release (GtkSheet
*sheet
, gint row
)
6229 if(sheet
->row
[row
].button
.state
== GTK_STATE_NORMAL
) return;
6231 sheet
->row
[row
].button
.state
= GTK_STATE_NORMAL
;
6232 gtk_sheet_button_draw(sheet
, row
, -1);
6236 column_button_release (GtkSheet
*sheet
, gint column
)
6238 if(sheet
->column
[column
].button
.state
== GTK_STATE_NORMAL
) return;
6240 sheet
->column
[column
].button
.state
= GTK_STATE_NORMAL
;
6241 gtk_sheet_button_draw(sheet
, -1, column
);
6245 gtk_sheet_button_draw (GtkSheet
*sheet
, gint row
, gint column
)
6247 GdkWindow
*window
= NULL
;
6248 GtkShadowType shadow_type
;
6249 guint width
= 0, height
= 0;
6252 gint text_width
= 0, text_height
= 0;
6253 GtkSheetButton
*button
= NULL
;
6254 GtkSheetChild
*child
= NULL
;
6255 GdkRectangle allocation
;
6256 gboolean is_sensitive
= FALSE
;
6263 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))) return;
6265 if(row
>= 0 && !sheet
->row
[row
].is_visible
) return;
6266 if(column
>= 0 && !sheet
->column
[column
].is_visible
) return;
6267 if(row
>= 0 && !GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)) return;
6268 if(column
>= 0 && !GTK_SHEET_COL_TITLES_VISIBLE(sheet
)) return;
6269 if(column
>=0 && column
<MIN_VISIBLE_COLUMN(sheet
)) return;
6270 if(column
>=0 && column
>MAX_VISIBLE_COLUMN(sheet
)) return;
6271 if(row
>=0 && row
<MIN_VISIBLE_ROW(sheet
)) return;
6272 if(row
>=0 && row
>MAX_VISIBLE_ROW(sheet
)) return;
6273 if( (row
== -1) && (column
== -1) ) return; //This seems to cause a crash.
6276 window
=sheet
->column_title_window
;
6277 button
=&sheet
->column
[column
].button
;
6279 x
= COLUMN_LEFT_XPIXEL(sheet
, column
)+CELL_SPACING
;
6280 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)) x
-= sheet
->row_title_area
.width
;
6282 width
= sheet
->column
[column
].width
;
6283 height
= sheet
->column_title_area
.height
;
6284 is_sensitive
=sheet
->column
[column
].is_sensitive
;
6286 else if(column
==-1){
6287 window
=sheet
->row_title_window
;
6288 button
=&sheet
->row
[row
].button
;
6291 y
= ROW_TOP_YPIXEL(sheet
, row
)+CELL_SPACING
;
6292 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
)) y
-=sheet
->column_title_area
.height
;
6293 width
= sheet
->row_title_area
.width
;
6294 height
= sheet
->row
[row
].height
;
6295 is_sensitive
=sheet
->row
[row
].is_sensitive
;
6300 allocation
.width
= width
;
6301 allocation
.height
= height
;
6303 gdk_window_clear_area (window
,
6307 gtk_paint_box (sheet
->button
->style
, window
,
6308 GTK_STATE_NORMAL
, GTK_SHADOW_OUT
,
6309 &allocation
, GTK_WIDGET(sheet
),
6310 "buttondefault", x
, y
, width
, height
);
6312 state
= button
->state
;
6313 if(!is_sensitive
) state
=GTK_STATE_INSENSITIVE
;
6315 if (state
== GTK_STATE_ACTIVE
)
6316 shadow_type
= GTK_SHADOW_IN
;
6318 shadow_type
= GTK_SHADOW_OUT
;
6320 if(state
!= GTK_STATE_NORMAL
&& state
!= GTK_STATE_INSENSITIVE
)
6321 gtk_paint_box (sheet
->button
->style
, window
,
6322 button
->state
, shadow_type
,
6323 &allocation
, GTK_WIDGET(sheet
),
6324 "button", x
, y
, width
, height
);
6326 if(button
->label_visible
){
6328 text_height
=DEFAULT_LABEL_HEIGHT(GTK_WIDGET(sheet
));
6330 y
+= DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet
))/2+
6331 DEFAULT_FONT_ASCENT(GTK_WIDGET(sheet
))/2;
6333 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet
)->style
->fg_gc
[button
->state
],
6335 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet
)->style
->white_gc
, &allocation
);
6337 if(button
->label
&& strlen(button
->label
)>0){
6338 words
=button
->label
;
6339 line
= g_new(gchar
, 1);
6342 while(words
&& *words
!= '\0'){
6345 line
=g_realloc(line
, len
+2);
6349 if(*words
== '\n' || *(words
+1) == '\0'){
6350 text_width
= gdk_string_width (GTK_WIDGET (sheet
)->style
->font
, line
);
6352 switch(button
->justification
){
6353 case GTK_JUSTIFY_LEFT
:
6354 gtk_paint_string (GTK_WIDGET(sheet
)->style
, window
, state
,
6355 &allocation
, GTK_WIDGET(sheet
), "label",
6359 case GTK_JUSTIFY_RIGHT
:
6360 gtk_paint_string (GTK_WIDGET(sheet
)->style
, window
, state
,
6361 &allocation
, GTK_WIDGET(sheet
), "label",
6362 x
+ width
- text_width
- CELLOFFSET
, y
,
6365 case GTK_JUSTIFY_CENTER
:
6367 gtk_paint_string (GTK_WIDGET(sheet
)->style
, window
, state
,
6368 &allocation
, GTK_WIDGET(sheet
), "label",
6369 x
+ (width
- text_width
) /2, y
,
6373 y
+= DEFAULT_FONT_ASCENT(GTK_WIDGET(sheet
))+
6374 DEFAULT_FONT_DESCENT(GTK_WIDGET(sheet
)) + 2;
6377 line
= g_new(gchar
, 1);
6384 sprintf(label
,"%d",index
);
6386 text_width
= gdk_string_width (GTK_WIDGET (sheet
)->style
->font
, label
);
6388 switch(button
->justification
){
6389 case GTK_JUSTIFY_LEFT
:
6390 gtk_paint_string (GTK_WIDGET(sheet
)->style
, window
, state
,
6391 &allocation
, GTK_WIDGET(sheet
), "label",
6395 case GTK_JUSTIFY_RIGHT
:
6396 gtk_paint_string (GTK_WIDGET(sheet
)->style
, window
, state
,
6397 &allocation
, GTK_WIDGET(sheet
), "label",
6398 x
+ width
- text_width
- CELLOFFSET
, y
,
6401 case GTK_JUSTIFY_CENTER
:
6403 gtk_paint_string (GTK_WIDGET(sheet
)->style
, window
, state
,
6404 &allocation
, GTK_WIDGET(sheet
), "label",
6405 x
+ (width
- text_width
) /2, y
,
6411 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet
)->style
->fg_gc
[button
->state
],
6413 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet
)->style
->white_gc
, NULL
);
6417 if((child
= button
->child
) && (child
->widget
)){
6418 child
->x
= allocation
.x
;
6419 child
->y
= allocation
.y
;
6421 child
->x
+= (width
- child
->widget
->requisition
.width
) * child
->x_align
;
6422 child
->y
+= (height
- child
->widget
->requisition
.height
) * child
->y_align
;
6423 child
->widget
->allocation
.width
= child
->widget
->requisition
.width
;
6424 child
->widget
->allocation
.height
= child
->widget
->requisition
.height
;
6429 gtk_widget_set_state(child
->widget
, button
->state
);
6430 if(GTK_WIDGET_NO_WINDOW(child
->widget
))
6432 child
->widget
->allocation
.x
= 0;
6433 child
->widget
->allocation
.y
= 0;
6436 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
)) &&
6437 GTK_WIDGET_MAPPED(child
->widget
))
6439 gtk_widget_size_allocate(child
->widget
,
6440 &child
->widget
->allocation
);
6441 if(GTK_WIDGET_NO_WINDOW(child
->widget
) && child
->window
)
6443 gdk_window_move_resize(child
->window
,
6445 child
->widget
->allocation
.width
,
6446 child
->widget
->allocation
.height
);
6447 gtk_widget_draw(child
->widget
, NULL
);
6460 * vadjustment_changed
6461 * hadjustment_changed
6462 * vadjustment_value_changed
6463 * hadjustment_value_changed */
6466 adjust_scrollbars (GtkSheet
* sheet
)
6469 if(sheet
->vadjustment
){
6470 sheet
->vadjustment
->page_size
= sheet
->sheet_window_height
;
6471 sheet
->vadjustment
->page_increment
= sheet
->sheet_window_height
/ 2;
6472 sheet
->vadjustment
->step_increment
= DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet
));
6473 sheet
->vadjustment
->lower
= 0;
6474 sheet
->vadjustment
->upper
= SHEET_HEIGHT (sheet
) + 80;
6476 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet))
6478 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) -
6479 sheet->sheet_window_height);
6480 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment),
6484 gtk_signal_emit_by_name (GTK_OBJECT(sheet
->vadjustment
), "changed");
6488 if(sheet
->hadjustment
){
6489 sheet
->hadjustment
->page_size
= sheet
->sheet_window_width
;
6490 sheet
->hadjustment
->page_increment
= sheet
->sheet_window_width
/ 2;
6491 sheet
->hadjustment
->step_increment
= DEFAULT_COLUMN_WIDTH
;
6492 sheet
->hadjustment
->lower
= 0;
6493 sheet
->hadjustment
->upper
= SHEET_WIDTH (sheet
)+ 80;
6495 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet))
6497 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) -
6498 sheet->sheet_window_width);
6499 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment),
6503 gtk_signal_emit_by_name (GTK_OBJECT(sheet
->hadjustment
), "changed");
6507 if(GTK_WIDGET_REALIZED(sheet))
6509 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet)){
6510 size_allocate_row_title_buttons(sheet);
6511 gdk_window_show(sheet->row_title_window);
6514 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet)){
6515 size_allocate_column_title_buttons(sheet);
6516 gdk_window_show(sheet->column_title_window);
6519 gtk_sheet_range_draw(sheet, NULL);
6526 vadjustment_changed (GtkAdjustment
* adjustment
,
6531 g_return_if_fail (adjustment
!= NULL
);
6532 g_return_if_fail (data
!= NULL
);
6534 sheet
= GTK_SHEET (data
);
6539 hadjustment_changed (GtkAdjustment
* adjustment
,
6544 g_return_if_fail (adjustment
!= NULL
);
6545 g_return_if_fail (data
!= NULL
);
6547 sheet
= GTK_SHEET (data
);
6553 vadjustment_value_changed (GtkAdjustment
* adjustment
,
6557 gint diff
, value
, old_value
;
6562 g_return_if_fail (adjustment
!= NULL
);
6563 g_return_if_fail (data
!= NULL
);
6564 g_return_if_fail (GTK_IS_SHEET (data
));
6566 sheet
= GTK_SHEET (data
);
6568 if(GTK_SHEET_IS_FROZEN(sheet
)) return;
6570 row
=ROW_FROM_YPIXEL(sheet
,sheet
->column_title_area
.height
+ CELL_SPACING
);
6571 if(!GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
6572 row
=ROW_FROM_YPIXEL(sheet
,CELL_SPACING
);
6574 old_value
= -sheet
->voffset
;
6576 for(i
=0; i
<= sheet
->maxrow
; i
++){
6577 if(sheet
->row
[i
].is_visible
) y
+=sheet
->row
[i
].height
;
6578 if(y
> adjustment
->value
) break;
6580 y
-=sheet
->row
[i
].height
;
6583 if (adjustment
->value
> sheet
->old_vadjustment
&& sheet
->old_vadjustment
> 0. &&
6584 sheet
->row
[i
].height
> sheet
->vadjustment
->step_increment
){
6585 /* This avoids embarrassing twitching */
6586 if(row
== new_row
&& row
!= sheet
->maxrow
&&
6587 adjustment
->value
- sheet
->old_vadjustment
>=
6588 sheet
->vadjustment
->step_increment
&&
6589 new_row
+ 1 != MIN_VISIBLE_ROW(sheet
)){
6591 y
=y
+sheet
->row
[row
].height
;
6595 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6596 if(sheet
->old_vadjustment
>= 0. && row
== new_row
){
6597 sheet
->old_vadjustment
= sheet
->vadjustment
->value
;
6601 sheet
->old_vadjustment
= sheet
->vadjustment
->value
;
6602 adjustment
->value
=y
;
6606 sheet
->vadjustment
->step_increment
=
6607 sheet
->row
[0].height
;
6609 sheet
->vadjustment
->step_increment
=
6610 MIN(sheet
->row
[new_row
].height
, sheet
->row
[new_row
-1].height
);
6613 sheet
->vadjustment
->value
=adjustment
->value
;
6615 value
= adjustment
->value
;
6617 if (value
>= -sheet
->voffset
)
6620 diff
= value
+ sheet
->voffset
;
6625 diff
= -sheet
->voffset
- value
;
6628 sheet
->voffset
= -value
;
6630 sheet
->view
.row0
=ROW_FROM_YPIXEL(sheet
, sheet
->column_title_area
.height
+1);
6631 sheet
->view
.rowi
=ROW_FROM_YPIXEL(sheet
, sheet
->sheet_window_height
-1);
6632 if(!GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
6633 sheet
->view
.row0
=ROW_FROM_YPIXEL(sheet
, 1);
6635 if(GTK_WIDGET_REALIZED(sheet
->sheet_entry
) &&
6636 sheet
->state
== GTK_SHEET_NORMAL
&&
6637 sheet
->active_cell
.row
>= 0 && sheet
->active_cell
.col
>= 0 &&
6638 !gtk_sheet_cell_isvisible(sheet
, sheet
->active_cell
.row
,
6639 sheet
->active_cell
.col
))
6643 text
= (gchar
*) gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet
)));
6645 if(!text
|| strlen(text
)==0)
6646 gtk_sheet_cell_clear(sheet
,
6647 sheet
->active_cell
.row
,
6648 sheet
->active_cell
.col
);
6650 if(sheet
->sheet_entry_window
)
6651 gdk_window_hide(sheet
->sheet_entry_window
);
6653 gdk_window_hide(sheet
->sheet_entry
->window
);
6656 gtk_sheet_position_children(sheet
);
6658 gtk_sheet_range_draw(sheet
, NULL
);
6659 size_allocate_row_title_buttons(sheet
);
6660 size_allocate_global_button(sheet
);
6664 hadjustment_value_changed (GtkAdjustment
* adjustment
,
6668 gint i
, diff
, value
, old_value
;
6669 gint column
, new_column
;
6672 g_return_if_fail (adjustment
!= NULL
);
6673 g_return_if_fail (data
!= NULL
);
6674 g_return_if_fail (GTK_IS_SHEET (data
));
6676 sheet
= GTK_SHEET (data
);
6678 if(GTK_SHEET_IS_FROZEN(sheet
)) return;
6680 column
=COLUMN_FROM_XPIXEL(sheet
,sheet
->row_title_area
.width
+ CELL_SPACING
);
6681 if(!GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
6682 column
=COLUMN_FROM_XPIXEL(sheet
, CELL_SPACING
);
6684 old_value
= -sheet
->hoffset
;
6686 for(i
=0; i
<= sheet
->maxcol
; i
++){
6687 if(sheet
->column
[i
].is_visible
) x
+=sheet
->column
[i
].width
;
6688 if(x
> adjustment
->value
) break;
6690 x
-=sheet
->column
[i
].width
;
6693 if (adjustment
->value
> sheet
->old_hadjustment
&& sheet
->old_hadjustment
> 0 &&
6694 sheet
->column
[i
].width
> sheet
->hadjustment
->step_increment
){
6695 /* This avoids embarrassing twitching */
6696 if(column
== new_column
&& column
!= sheet
->maxcol
&&
6697 adjustment
->value
- sheet
->old_hadjustment
>=
6698 sheet
->hadjustment
->step_increment
&&
6699 new_column
+ 1 != MIN_VISIBLE_COLUMN(sheet
)){
6701 x
=x
+sheet
->column
[column
].width
;
6705 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
6706 if(sheet
->old_hadjustment
>= 0. && new_column
== column
){
6707 sheet
->old_hadjustment
= sheet
->hadjustment
->value
;
6711 sheet
->old_hadjustment
= sheet
->hadjustment
->value
;
6712 adjustment
->value
=x
;
6714 if(new_column
== 0){
6715 sheet
->hadjustment
->step_increment
=
6716 sheet
->column
[0].width
;
6718 sheet
->hadjustment
->step_increment
=
6719 MIN(sheet
->column
[new_column
].width
, sheet
->column
[new_column
-1].width
);
6723 sheet
->hadjustment
->value
=adjustment
->value
;
6725 value
= adjustment
->value
;
6727 if (value
>= -sheet
->hoffset
)
6730 diff
= value
+ sheet
->hoffset
;
6735 diff
= -sheet
->hoffset
- value
;
6738 sheet
->hoffset
= -value
;
6740 sheet
->view
.col0
=COLUMN_FROM_XPIXEL(sheet
, sheet
->row_title_area
.width
+1);
6741 sheet
->view
.coli
=COLUMN_FROM_XPIXEL(sheet
, sheet
->sheet_window_width
);
6742 if(!GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
6743 sheet
->view
.col0
=COLUMN_FROM_XPIXEL(sheet
, 1);
6745 if(GTK_WIDGET_REALIZED(sheet
->sheet_entry
) &&
6746 sheet
->state
== GTK_SHEET_NORMAL
&&
6747 sheet
->active_cell
.row
>= 0 && sheet
->active_cell
.col
>= 0 &&
6748 !gtk_sheet_cell_isvisible(sheet
, sheet
->active_cell
.row
,
6749 sheet
->active_cell
.col
))
6753 text
= (gchar
*) gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet
)));
6754 if(!text
|| strlen(text
)==0)
6755 gtk_sheet_cell_clear(sheet
,
6756 sheet
->active_cell
.row
,
6757 sheet
->active_cell
.col
);
6759 if(sheet
->sheet_entry_window
)
6760 gdk_window_hide(sheet
->sheet_entry_window
);
6762 gdk_window_hide(sheet
->sheet_entry
->window
);
6765 gtk_sheet_position_children(sheet
);
6767 gtk_sheet_range_draw(sheet
, NULL
);
6768 size_allocate_column_title_buttons(sheet
);
6772 /* COLUMN RESIZING */
6774 draw_xor_vline (GtkSheet
* sheet
)
6778 g_return_if_fail (sheet
!= NULL
);
6780 widget
= GTK_WIDGET (sheet
);
6782 gdk_draw_line (widget
->window
, sheet
->xor_gc
,
6784 sheet
->column_title_area
.height
,
6786 sheet
->sheet_window_height
+ 1);
6791 draw_xor_hline (GtkSheet
* sheet
)
6795 g_return_if_fail (sheet
!= NULL
);
6797 widget
= GTK_WIDGET (sheet
);
6799 gdk_draw_line (widget
->window
, sheet
->xor_gc
,
6800 sheet
->row_title_area
.width
,
6803 sheet
->sheet_window_width
+ 1,
6807 /* SELECTED RANGE */
6809 draw_xor_rectangle(GtkSheet
*sheet
, GtkSheetRange range
)
6812 GdkRectangle clip_area
, area
;
6815 area
.x
=COLUMN_LEFT_XPIXEL(sheet
, range
.col0
);
6816 area
.y
=ROW_TOP_YPIXEL(sheet
, range
.row0
);
6817 area
.width
=COLUMN_LEFT_XPIXEL(sheet
, range
.coli
)-area
.x
+
6818 sheet
->column
[range
.coli
].width
;
6819 area
.height
=ROW_TOP_YPIXEL(sheet
, range
.rowi
)-area
.y
+
6820 sheet
->row
[range
.rowi
].height
;
6822 clip_area
.x
=sheet
->row_title_area
.width
;
6823 clip_area
.y
=sheet
->column_title_area
.height
;
6824 clip_area
.width
=sheet
->sheet_window_width
;
6825 clip_area
.height
=sheet
->sheet_window_height
;
6827 if(!GTK_SHEET_ROW_TITLES_VISIBLE(sheet
)) clip_area
.x
= 0;
6828 if(!GTK_SHEET_COL_TITLES_VISIBLE(sheet
)) clip_area
.y
= 0;
6831 area
.width
=area
.width
+area
.x
;
6834 if(area
.width
>clip_area
.width
) area
.width
=clip_area
.width
+10;
6836 area
.height
=area
.height
+area
.y
;
6839 if(area
.height
>clip_area
.height
) area
.height
=clip_area
.height
+10;
6844 clip_area
.height
+=3;
6846 gdk_gc_get_values(sheet
->xor_gc
, &values
);
6848 gdk_gc_set_clip_rectangle(sheet
->xor_gc
, &clip_area
);
6850 for(i
=-1; i
<=1; i
++)
6851 gdk_draw_rectangle(sheet
->sheet_window
,
6855 area
.width
-2*i
, area
.height
-2*i
);
6858 gdk_gc_set_clip_rectangle(sheet
->xor_gc
, NULL
);
6860 gdk_gc_set_foreground(sheet
->xor_gc
, &values
.foreground
);
6865 /* this function returns the new width of the column being resized given
6866 * the column and x position of the cursor; the x cursor position is passed
6867 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
6869 new_column_width (GtkSheet
* sheet
,
6874 GtkRequisition requisition
;
6878 gtk_sheet_button_size_request(sheet
, &sheet
->column
[column
].button
,
6881 /* you can't shrink a column to less than its minimum width */
6882 if (cx
< COLUMN_LEFT_XPIXEL (sheet
, column
) + requisition
.width
)
6884 *x
= cx
= COLUMN_LEFT_XPIXEL (sheet
, column
) + requisition
.width
;
6887 /* don't grow past the end of the window */
6889 if (cx > sheet->sheet_window_width)
6891 *x = cx = sheet->sheet_window_width;
6894 /* calculate new column width making sure it doesn't end up
6895 * less than the minimum width */
6896 width
= cx
- COLUMN_LEFT_XPIXEL (sheet
, column
);
6897 if (width
< requisition
.width
)
6898 width
= requisition
.width
;
6900 sheet
->column
[column
].width
= width
;
6901 gtk_sheet_recalc_left_xpixels(sheet
, column
+1);
6902 sheet
->view
.coli
=COLUMN_FROM_XPIXEL(sheet
, sheet
->sheet_window_width
);
6903 size_allocate_column_title_buttons (sheet
);
6908 /* this function returns the new height of the row being resized given
6909 * the row and y position of the cursor; the y cursor position is passed
6910 * in as a pointer and automaticaly corrected if it's beyond min/max limits */
6912 new_row_height (GtkSheet
* sheet
,
6916 GtkRequisition requisition
;
6921 gtk_sheet_button_size_request(sheet
, &sheet
->row
[row
].button
,
6924 /* you can't shrink a row to less than its minimum height */
6925 if (cy
< ROW_TOP_YPIXEL (sheet
, row
) + requisition
.height
)
6928 *y
= cy
= ROW_TOP_YPIXEL (sheet
, row
) + requisition
.height
;
6931 /* don't grow past the end of the window */
6933 if (cy > sheet->sheet_window_height)
6935 *y = cy = sheet->sheet_window_height;
6938 /* calculate new row height making sure it doesn't end up
6939 * less than the minimum height */
6940 height
= (cy
- ROW_TOP_YPIXEL (sheet
, row
));
6941 if (height
< requisition
.height
)
6942 height
= requisition
.height
;
6944 sheet
->row
[row
].height
= height
;
6945 gtk_sheet_recalc_top_ypixels(sheet
, row
);
6946 sheet
->view
.rowi
=ROW_FROM_YPIXEL(sheet
, sheet
->sheet_window_height
-1);
6947 size_allocate_row_title_buttons (sheet
);
6953 gtk_sheet_set_column_width (GtkSheet
* sheet
,
6957 g_return_if_fail (sheet
!= NULL
);
6958 g_return_if_fail (GTK_IS_SHEET (sheet
));
6960 if (column
< 0 || column
> sheet
->maxcol
)
6963 sheet
->column
[column
].width
= width
;
6965 gtk_sheet_recalc_left_xpixels(sheet
, column
+1);
6967 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
)) && !GTK_SHEET_IS_FROZEN(sheet
)){
6968 size_allocate_column_title_buttons (sheet
);
6969 adjust_scrollbars (sheet
);
6970 gtk_sheet_size_allocate_entry(sheet
);
6971 gtk_sheet_range_draw (sheet
, NULL
);
6974 gtk_signal_emit(GTK_OBJECT(sheet
), sheet_signals
[CHANGED
], -1, column
);
6975 gtk_signal_emit(GTK_OBJECT(sheet
), sheet_signals
[NEW_COL_WIDTH
], column
, width
);
6980 gtk_sheet_set_row_height (GtkSheet
* sheet
,
6984 g_return_if_fail (sheet
!= NULL
);
6985 g_return_if_fail (GTK_IS_SHEET (sheet
));
6987 if (row
< 0 || row
> sheet
->maxrow
)
6990 sheet
->row
[row
].height
= height
;
6992 gtk_sheet_recalc_top_ypixels(sheet
, row
+1);
6994 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
)) && !GTK_SHEET_IS_FROZEN(sheet
)){
6995 size_allocate_row_title_buttons (sheet
);
6996 adjust_scrollbars (sheet
);
6997 gtk_sheet_size_allocate_entry(sheet
);
6998 gtk_sheet_range_draw (sheet
, NULL
);
7001 gtk_signal_emit(GTK_OBJECT(sheet
), sheet_signals
[CHANGED
], row
, -1);
7002 gtk_signal_emit(GTK_OBJECT(sheet
), sheet_signals
[NEW_ROW_HEIGHT
], row
, height
);
7008 gtk_sheet_add_column(GtkSheet
*sheet
, guint ncols
)
7011 g_return_if_fail (sheet
!= NULL
);
7012 g_return_if_fail (GTK_IS_SHEET (sheet
));
7014 AddColumn(sheet
, ncols
);
7016 if(!GTK_WIDGET_REALIZED(sheet
)) return;
7018 adjust_scrollbars(sheet
);
7020 if(sheet
->state
==GTK_SHEET_ROW_SELECTED
) sheet
->range
.coli
+=ncols
;
7022 sheet
->old_hadjustment
= -1.;
7023 if(!GTK_SHEET_IS_FROZEN(sheet
) && sheet
->hadjustment
)
7024 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->hadjustment
),
7029 gtk_sheet_add_row(GtkSheet
*sheet
, guint nrows
)
7032 g_return_if_fail (sheet
!= NULL
);
7033 g_return_if_fail (GTK_IS_SHEET (sheet
));
7035 AddRow(sheet
, nrows
);
7037 if(!GTK_WIDGET_REALIZED(sheet
)) return;
7039 if(sheet
->state
==GTK_SHEET_COLUMN_SELECTED
) sheet
->range
.rowi
+=nrows
;
7041 adjust_scrollbars(sheet
);
7043 sheet
->old_vadjustment
= -1.;
7044 if(!GTK_SHEET_IS_FROZEN(sheet
) && sheet
->vadjustment
)
7045 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->vadjustment
),
7050 gtk_sheet_insert_rows(GtkSheet
*sheet
, guint row
, guint nrows
)
7053 GtkSheetChild
*child
;
7055 g_return_if_fail (sheet
!= NULL
);
7056 g_return_if_fail (GTK_IS_SHEET (sheet
));
7058 if(GTK_WIDGET_REALIZED(sheet
))
7059 gtk_sheet_real_unselect_range(sheet
, NULL
);
7061 InsertRow(sheet
, row
, nrows
);
7063 children
= sheet
->children
;
7066 child
= (GtkSheetChild
*)children
->data
;
7068 if(child
->attached_to_cell
)
7069 if(child
->row
>= row
) child
->row
+= nrows
;
7071 children
= children
->next
;
7074 if(!GTK_WIDGET_REALIZED(sheet
)) return;
7076 if(sheet
->state
==GTK_SHEET_COLUMN_SELECTED
) sheet
->range
.rowi
+=nrows
;
7077 adjust_scrollbars(sheet
);
7079 sheet
->old_vadjustment
= -1.;
7080 if(!GTK_SHEET_IS_FROZEN(sheet
) && sheet
->vadjustment
)
7081 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->vadjustment
),
7087 gtk_sheet_insert_columns(GtkSheet
*sheet
, guint col
, guint ncols
)
7090 GtkSheetChild
*child
;
7092 g_return_if_fail (sheet
!= NULL
);
7093 g_return_if_fail (GTK_IS_SHEET (sheet
));
7095 if(GTK_WIDGET_REALIZED(sheet
))
7096 gtk_sheet_real_unselect_range(sheet
, NULL
);
7098 InsertColumn(sheet
, col
, ncols
);
7100 children
= sheet
->children
;
7103 child
= (GtkSheetChild
*)children
->data
;
7105 if(child
->attached_to_cell
)
7106 if(child
->col
>= col
) child
->col
+= ncols
;
7108 children
= children
->next
;
7111 if(!GTK_WIDGET_REALIZED(sheet
)) return;
7113 if(sheet
->state
==GTK_SHEET_ROW_SELECTED
) sheet
->range
.coli
+=ncols
;
7114 adjust_scrollbars(sheet
);
7116 sheet
->old_hadjustment
= -1.;
7117 if(!GTK_SHEET_IS_FROZEN(sheet
) && sheet
->hadjustment
)
7118 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->hadjustment
),
7124 gtk_sheet_delete_rows(GtkSheet
*sheet
, guint row
, guint nrows
)
7127 GtkSheetChild
*child
;
7131 g_return_if_fail (sheet
!= NULL
);
7132 g_return_if_fail (GTK_IS_SHEET (sheet
));
7134 nrows
= MIN(nrows
, sheet
->maxrow
-row
+1);
7136 if(GTK_WIDGET_REALIZED(sheet
))
7137 gtk_sheet_real_unselect_range(sheet
, NULL
);
7139 DeleteRow(sheet
, row
, nrows
);
7141 children
= sheet
->children
;
7144 child
= (GtkSheetChild
*)children
->data
;
7146 if(child
->attached_to_cell
){
7147 if(child
->row
>= row
&& child
->row
< row
+nrows
){
7148 gtk_container_remove(GTK_CONTAINER(sheet
), child
->widget
);
7149 children
= sheet
->children
;
7153 if(child
->row
>= row
) child
->row
-= nrows
;
7154 children
= children
->next
;
7158 children
= children
->next
;
7162 if(!GTK_WIDGET_REALIZED(sheet
)) return;
7164 irow
= sheet
->active_cell
.row
;
7165 icol
= sheet
->active_cell
.col
;
7167 sheet
->active_cell
.row
= -1;
7168 sheet
->active_cell
.col
= -1;
7170 /* if(sheet->state == GTK_SHEET_ROW_SELECTED)
7173 irow
= MIN(irow
, sheet
->maxrow
);
7174 irow
= MAX(irow
, 0);
7175 gtk_sheet_click_cell(sheet
, irow
, icol
, &veto
);
7177 gtk_sheet_activate_cell(sheet
, sheet
->active_cell
.row
,
7178 sheet
->active_cell
.col
);
7180 adjust_scrollbars(sheet
);
7182 sheet
->old_vadjustment
= -1.;
7183 if(!GTK_SHEET_IS_FROZEN(sheet
) && sheet
->vadjustment
)
7184 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->vadjustment
),
7190 gtk_sheet_delete_columns(GtkSheet
*sheet
, guint col
, guint ncols
)
7193 GtkSheetChild
*child
;
7197 g_return_if_fail (sheet
!= NULL
);
7198 g_return_if_fail (GTK_IS_SHEET (sheet
));
7200 ncols
= MIN(ncols
, sheet
->maxcol
-col
+1);
7202 if(GTK_WIDGET_REALIZED(sheet
))
7203 gtk_sheet_real_unselect_range(sheet
, NULL
);
7205 DeleteColumn(sheet
, col
, ncols
);
7207 children
= sheet
->children
;
7210 child
= (GtkSheetChild
*)children
->data
;
7212 if(child
->attached_to_cell
){
7213 if(child
->col
>= col
&& child
->col
< col
+ncols
){
7214 gtk_container_remove(GTK_CONTAINER(sheet
), child
->widget
);
7215 children
= sheet
->children
;
7219 if(child
->col
>= col
) child
->col
-= ncols
;
7220 children
= children
->next
;
7224 children
= children
->next
;
7228 if(!GTK_WIDGET_REALIZED(sheet
)) return;
7230 irow
= sheet
->active_cell
.row
;
7231 icol
= sheet
->active_cell
.col
;
7233 sheet
->active_cell
.row
= -1;
7234 sheet
->active_cell
.col
= -1;
7236 /* if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
7239 icol
= MIN(icol
, sheet
->maxcol
);
7240 icol
= MAX(icol
, 0);
7241 gtk_sheet_click_cell(sheet
, irow
, icol
, &veto
);
7243 gtk_sheet_activate_cell(sheet
, sheet
->active_cell
.row
,
7244 sheet
->active_cell
.col
);
7246 adjust_scrollbars(sheet
);
7248 sheet
->old_hadjustment
= -1.;
7249 if(!GTK_SHEET_IS_FROZEN(sheet
) && sheet
->hadjustment
)
7250 gtk_signal_emit_by_name (GTK_OBJECT (sheet
->hadjustment
),
7256 gtk_sheet_range_set_background(GtkSheet
*sheet
, const GtkSheetRange
*urange
, const GdkColor
*color
)
7259 GtkSheetCellAttr attributes
;
7260 GtkSheetRange range
;
7262 g_return_if_fail (sheet
!= NULL
);
7263 g_return_if_fail (GTK_IS_SHEET (sheet
));
7266 range
= sheet
->range
;
7270 for (i
=range
.row0
; i
<=range
.rowi
; i
++)
7271 for (j
=range
.col0
; j
<=range
.coli
; j
++){
7272 gtk_sheet_get_attributes(sheet
, i
, j
, &attributes
);
7274 attributes
.background
= *color
;
7276 attributes
.background
= sheet
->bg_color
;
7278 gtk_sheet_set_cell_attributes(sheet
, i
, j
, attributes
);
7286 if(!GTK_SHEET_IS_FROZEN(sheet
))
7287 gtk_sheet_range_draw(sheet
, &range
);
7292 gtk_sheet_range_set_foreground(GtkSheet
*sheet
, const GtkSheetRange
*urange
, const GdkColor
*color
)
7295 GtkSheetCellAttr attributes
;
7296 GtkSheetRange range
;
7298 g_return_if_fail (sheet
!= NULL
);
7299 g_return_if_fail (GTK_IS_SHEET (sheet
));
7302 range
= sheet
->range
;
7306 for (i
=range
.row0
; i
<=range
.rowi
; i
++)
7307 for (j
=range
.col0
; j
<=range
.coli
; j
++){
7308 gtk_sheet_get_attributes(sheet
, i
, j
, &attributes
);
7311 attributes
.foreground
= *color
;
7313 gdk_color_black(gdk_colormap_get_system(), &attributes
.foreground
);
7315 gtk_sheet_set_cell_attributes(sheet
, i
, j
, attributes
);
7318 if(!GTK_SHEET_IS_FROZEN(sheet
))
7319 gtk_sheet_range_draw(sheet
, &range
);
7324 gtk_sheet_range_set_justification(GtkSheet
*sheet
, const GtkSheetRange
*urange
,
7325 GtkJustification just
)
7328 GtkSheetCellAttr attributes
;
7329 GtkSheetRange range
;
7331 g_return_if_fail (sheet
!= NULL
);
7332 g_return_if_fail (GTK_IS_SHEET (sheet
));
7335 range
= sheet
->range
;
7339 for (i
=range
.row0
; i
<=range
.rowi
; i
++)
7340 for (j
=range
.col0
; j
<=range
.coli
; j
++){
7341 gtk_sheet_get_attributes(sheet
, i
, j
, &attributes
);
7342 attributes
.justification
= just
;
7343 gtk_sheet_set_cell_attributes(sheet
, i
, j
, attributes
);
7346 range
.col0
= sheet
->view
.col0
;
7347 range
.coli
= sheet
->view
.coli
;
7349 if(!GTK_SHEET_IS_FROZEN(sheet
))
7350 gtk_sheet_range_draw(sheet
, &range
);
7355 gtk_sheet_column_set_justification(GtkSheet
*sheet
, gint col
,
7356 GtkJustification justification
)
7358 g_return_if_fail (sheet
!= NULL
);
7359 g_return_if_fail (GTK_IS_SHEET (sheet
));
7361 if(col
> sheet
->maxcol
) return;
7363 sheet
->column
[col
].justification
= justification
;
7365 if(GTK_WIDGET_REALIZED(sheet
) && !GTK_SHEET_IS_FROZEN(sheet
) &&
7366 col
>= MIN_VISIBLE_COLUMN(sheet
) && col
<= MAX_VISIBLE_COLUMN(sheet
))
7367 gtk_sheet_range_draw(sheet
, NULL
);
7372 gtk_sheet_range_set_editable(GtkSheet
*sheet
, const GtkSheetRange
*urange
, gboolean editable
)
7375 GtkSheetCellAttr attributes
;
7376 GtkSheetRange range
;
7378 g_return_if_fail (sheet
!= NULL
);
7379 g_return_if_fail (GTK_IS_SHEET (sheet
));
7382 range
= sheet
->range
;
7386 for (i
=range
.row0
; i
<=range
.rowi
; i
++)
7387 for (j
=range
.col0
; j
<=range
.coli
; j
++){
7388 gtk_sheet_get_attributes(sheet
, i
, j
, &attributes
);
7389 attributes
.is_editable
= editable
;
7390 gtk_sheet_set_cell_attributes(sheet
, i
, j
, attributes
);
7393 if(!GTK_SHEET_IS_FROZEN(sheet
))
7394 gtk_sheet_range_draw(sheet
, &range
);
7399 gtk_sheet_range_set_visible(GtkSheet
*sheet
, const GtkSheetRange
*urange
, gboolean visible
)
7402 GtkSheetCellAttr attributes
;
7403 GtkSheetRange range
;
7405 g_return_if_fail (sheet
!= NULL
);
7406 g_return_if_fail (GTK_IS_SHEET (sheet
));
7409 range
= sheet
->range
;
7413 for (i
=range
.row0
; i
<=range
.rowi
; i
++)
7414 for (j
=range
.col0
; j
<=range
.coli
; j
++){
7415 gtk_sheet_get_attributes(sheet
, i
, j
, &attributes
);
7416 attributes
.is_visible
=visible
;
7417 gtk_sheet_set_cell_attributes(sheet
, i
, j
, attributes
);
7420 if(!GTK_SHEET_IS_FROZEN(sheet
))
7421 gtk_sheet_range_draw(sheet
, &range
);
7426 gtk_sheet_range_set_border(GtkSheet
*sheet
, const GtkSheetRange
*urange
, gint mask
,
7427 guint width
, gint line_style
)
7430 GtkSheetCellAttr attributes
;
7431 GtkSheetRange range
;
7433 g_return_if_fail (sheet
!= NULL
);
7434 g_return_if_fail (GTK_IS_SHEET (sheet
));
7437 range
= sheet
->range
;
7441 for (i
=range
.row0
; i
<=range
.rowi
; i
++)
7442 for (j
=range
.col0
; j
<=range
.coli
; j
++){
7443 gtk_sheet_get_attributes(sheet
, i
, j
, &attributes
);
7444 attributes
.border
.mask
= mask
;
7445 attributes
.border
.width
= width
;
7446 attributes
.border
.line_style
=line_style
;
7447 attributes
.border
.cap_style
=GDK_CAP_NOT_LAST
;
7448 attributes
.border
.join_style
=GDK_JOIN_MITER
;
7449 gtk_sheet_set_cell_attributes(sheet
, i
, j
, attributes
);
7457 if(!GTK_SHEET_IS_FROZEN(sheet
))
7458 gtk_sheet_range_draw(sheet
, &range
);
7463 gtk_sheet_range_set_border_color(GtkSheet
*sheet
, const GtkSheetRange
*urange
, const GdkColor
*color
)
7466 GtkSheetCellAttr attributes
;
7467 GtkSheetRange range
;
7469 g_return_if_fail (sheet
!= NULL
);
7470 g_return_if_fail (GTK_IS_SHEET (sheet
));
7473 range
= sheet
->range
;
7477 for (i
=range
.row0
; i
<=range
.rowi
; i
++)
7478 for (j
=range
.col0
; j
<=range
.coli
; j
++){
7479 gtk_sheet_get_attributes(sheet
, i
, j
, &attributes
);
7480 attributes
.border
.color
= *color
;
7481 gtk_sheet_set_cell_attributes(sheet
, i
, j
, attributes
);
7484 if(!GTK_SHEET_IS_FROZEN(sheet
))
7485 gtk_sheet_range_draw(sheet
, &range
);
7489 /* TODO: Should this really store the font pointer instead of the font value.
7493 /* SDB says: Remove this . . . . . */
7495 gtk_sheet_range_set_font(GtkSheet
*sheet
, const GtkSheetRange
*urange
, GdkFont
*font
)
7499 GtkSheetCellAttr attributes
;
7500 GtkSheetRange range
;
7502 g_return_if_fail (sheet
!= NULL
);
7503 g_return_if_fail (GTK_IS_SHEET (sheet
));
7506 range
= sheet
->range
;
7510 gtk_sheet_freeze(sheet
);
7512 for (i
=range
.row0
; i
<=range
.rowi
; i
++)
7513 for (j
=range
.col0
; j
<=range
.coli
; j
++){
7514 gtk_sheet_get_attributes(sheet
, i
, j
, &attributes
);
7515 attributes
.font
= font
; /* TODO: See comment above this function.*/
7516 font_height
=attributes
.font
->ascent
+
7517 2 * attributes
.font
->descent
+ 2*CELLOFFSET
;
7518 if(font_height
> sheet
->row
[i
].height
){
7519 sheet
->row
[i
].height
= font_height
;
7520 gtk_sheet_recalc_top_ypixels(sheet
, i
);
7523 gtk_sheet_set_cell_attributes(sheet
, i
, j
, attributes
);
7526 gtk_sheet_thaw(sheet
);
7531 gtk_sheet_set_cell_attributes(GtkSheet
*sheet
, gint row
, gint col
, GtkSheetCellAttr attributes
)
7533 GtkSheetCell
**cell
;
7535 if(row
> sheet
->maxrow
|| col
>sheet
->maxcol
) return;
7537 CheckBounds(sheet
, row
, col
);
7539 cell
= &sheet
->data
[row
][col
];
7542 (*cell
) = gtk_sheet_cell_new();
7547 if((*cell
)->attributes
== NULL
)
7548 (*cell
)->attributes
= g_new(GtkSheetCellAttr
, 1);
7550 *((*cell
)->attributes
) = attributes
;
7554 gtk_sheet_get_attributes(GtkSheet
*sheet
, gint row
, gint col
, GtkSheetCellAttr
*attributes
)
7556 GtkSheetCell
**cell
= NULL
;
7558 g_return_val_if_fail (sheet
!= NULL
, FALSE
);
7559 g_return_val_if_fail (GTK_IS_SHEET (sheet
), FALSE
);
7561 if(row
< 0 || col
< 0) return FALSE
;
7563 if(row
> sheet
->maxallocrow
|| col
> sheet
->maxalloccol
){
7564 init_attributes(sheet
, col
, attributes
);
7568 if(row
<= sheet
->maxallocrow
&& col
<= sheet
->maxalloccol
){
7569 if(sheet
->data
[row
] && sheet
->data
[row
][col
])
7570 cell
= &sheet
->data
[row
][col
];
7571 if(cell
== NULL
|| *cell
== NULL
){
7572 init_attributes(sheet
, col
, attributes
);
7575 if((*cell
)->attributes
== NULL
){
7576 init_attributes(sheet
, col
, attributes
);
7579 *attributes
= *(sheet
->data
[row
][col
]->attributes
);
7580 if(sheet
->column
[col
].justification
!= GTK_JUSTIFY_FILL
)
7581 attributes
->justification
= sheet
->column
[col
].justification
;
7589 init_attributes(GtkSheet
*sheet
, gint col
, GtkSheetCellAttr
*attributes
)
7591 /* DEFAULT VALUES */
7592 attributes
->foreground
= GTK_WIDGET(sheet
)->style
->black
;
7593 attributes
->background
= sheet
->bg_color
;
7594 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
))){
7595 GdkColormap
*colormap
;
7596 colormap
=gdk_colormap_get_system();
7597 gdk_color_black(colormap
, &attributes
->foreground
);
7598 attributes
->background
= sheet
->bg_color
;
7600 attributes
->justification
= sheet
->column
[col
].justification
;
7601 attributes
->border
.width
= 0;
7602 attributes
->border
.line_style
= GDK_LINE_SOLID
;
7603 attributes
->border
.cap_style
= GDK_CAP_NOT_LAST
;
7604 attributes
->border
.join_style
= GDK_JOIN_MITER
;
7605 attributes
->border
.mask
= 0;
7606 attributes
->border
.color
= GTK_WIDGET(sheet
)->style
->black
;
7607 attributes
->is_editable
= TRUE
;
7608 attributes
->is_visible
= TRUE
;
7609 attributes
->font
= GTK_WIDGET(sheet
)->style
->font
;
7613 /**********************************************************************
7614 * Memory allocation routines:
7615 * AddRow & AddColumn allocate memory for GtkSheetColumn & GtkSheetRow structs.
7620 * GrowSheet allocates memory for the sheet cells contents using an array of
7621 * pointers. Alternative to this could be a linked list or a hash table.
7622 * CheckBounds checks whether the given cell is currently allocated or not.
7623 * If not, it calls to GrowSheet.
7624 **********************************************************************/
7627 AddColumn(GtkSheet
*tbl
, gint ncols
)
7631 if(ncols
== -1 && tbl
->maxcol
== 0)
7637 tbl
->maxcol
+= ncols
;
7638 tbl
->column
= (GtkSheetColumn
*)g_realloc(tbl
->column
,(tbl
->maxcol
+1)*
7639 sizeof(GtkSheetColumn
));
7642 for(i
=tbl
->maxcol
-ncols
+1; i
<= tbl
->maxcol
; i
++){
7643 tbl
->column
[i
].width
=DEFAULT_COLUMN_WIDTH
;
7644 tbl
->column
[i
].button
.label
=NULL
;
7645 tbl
->column
[i
].button
.child
=NULL
;
7646 tbl
->column
[i
].button
.state
=GTK_STATE_NORMAL
;
7647 tbl
->column
[i
].button
.justification
=GTK_JUSTIFY_CENTER
;
7648 tbl
->column
[i
].button
.label_visible
= TRUE
;
7649 tbl
->column
[i
].name
=NULL
;
7650 tbl
->column
[i
].is_visible
=TRUE
;
7651 tbl
->column
[i
].is_sensitive
=TRUE
;
7652 tbl
->column
[i
].left_text_column
=i
;
7653 tbl
->column
[i
].right_text_column
=i
;
7654 tbl
->column
[i
].justification
=GTK_JUSTIFY_FILL
;
7657 tbl
->column
[i
].left_text_column
=tbl
->column
[i
-1].left_text_column
;
7658 tbl
->column
[i
].left_xpixel
=tbl
->column
[i
-1].left_xpixel
+
7659 tbl
->column
[i
-1].width
;
7663 tbl
->column
[i
].left_xpixel
=tbl
->row_title_area
.width
;
7664 if(!GTK_SHEET_ROW_TITLES_VISIBLE(tbl
))
7665 tbl
->column
[i
].left_xpixel
=0;
7672 AddRow(GtkSheet
*tbl
, gint nrows
)
7676 if(nrows
== -1 && tbl
->maxrow
== 0)
7682 tbl
->maxrow
+= nrows
;
7683 tbl
->row
= (GtkSheetRow
*)g_realloc(tbl
->row
,(tbl
->maxrow
+1)*
7684 sizeof(GtkSheetRow
));
7687 for(i
=tbl
->maxrow
-nrows
+1; i
<= tbl
->maxrow
; i
++){
7688 tbl
->row
[i
].height
=DEFAULT_ROW_HEIGHT(GTK_WIDGET(tbl
));
7689 tbl
->row
[i
].button
.label
=NULL
;
7690 tbl
->row
[i
].button
.child
=NULL
;
7691 tbl
->row
[i
].button
.state
=GTK_STATE_NORMAL
;
7692 tbl
->row
[i
].button
.justification
=GTK_JUSTIFY_CENTER
;
7693 tbl
->row
[i
].button
.label_visible
= TRUE
;
7694 tbl
->row
[i
].name
=NULL
;
7695 tbl
->row
[i
].is_visible
=TRUE
;
7696 tbl
->row
[i
].is_sensitive
=TRUE
;
7698 tbl
->row
[i
].top_ypixel
=tbl
->row
[i
-1].top_ypixel
+tbl
->row
[i
-1].height
;
7701 tbl
->row
[i
].top_ypixel
=tbl
->column_title_area
.height
;
7702 if(!GTK_SHEET_COL_TITLES_VISIBLE(tbl
))
7703 tbl
->row
[i
].top_ypixel
=0;
7710 InsertRow(GtkSheet
*tbl
, gint row
, gint nrows
)
7714 GtkSheetCell
**auxdata
;
7719 for(i
=tbl
->maxrow
; i
>=row
+nrows
; i
--){
7720 auxrow
= tbl
->row
[i
];
7721 tbl
->row
[i
]=tbl
->row
[i
-nrows
];
7722 tbl
->row
[i
].is_visible
=tbl
->row
[i
-nrows
].is_visible
;
7723 tbl
->row
[i
].is_sensitive
=tbl
->row
[i
-nrows
].is_sensitive
;
7724 if(auxrow
.is_visible
)
7725 tbl
->row
[i
].top_ypixel
+=nrows
*DEFAULT_ROW_HEIGHT(GTK_WIDGET(tbl
));
7726 tbl
->row
[i
-nrows
]=auxrow
;
7729 if(row
<= tbl
->maxallocrow
){
7731 GrowSheet(tbl
,nrows
,0);
7733 for(i
=tbl
->maxallocrow
; i
>=row
+nrows
; i
--){
7734 auxdata
= tbl
->data
[i
];
7735 tbl
->data
[i
]=tbl
->data
[i
-nrows
];
7738 for(j
=0; j
<=tbl
->maxalloccol
; j
++,pp
++){
7739 if(*pp
!=(GtkSheetCell
*)NULL
)
7743 tbl
->data
[i
-nrows
]=auxdata
;
7746 gtk_sheet_recalc_top_ypixels(tbl
, 0);
7751 InsertColumn(GtkSheet
*tbl
, gint col
, gint ncols
)
7754 GtkSheetColumn auxcol
;
7756 AddColumn(tbl
,ncols
);
7758 for(i
=tbl
->maxcol
; i
>=col
+ncols
; i
--){
7759 auxcol
= tbl
->column
[i
];
7760 tbl
->column
[i
]=tbl
->column
[i
-ncols
];
7761 tbl
->column
[i
].is_visible
=tbl
->column
[i
-ncols
].is_visible
;
7762 tbl
->column
[i
].is_sensitive
=tbl
->column
[i
-ncols
].is_sensitive
;
7763 tbl
->column
[i
].left_text_column
=tbl
->column
[i
-ncols
].left_text_column
;
7764 tbl
->column
[i
].right_text_column
=tbl
->column
[i
-ncols
].right_text_column
;
7765 tbl
->column
[i
].justification
=tbl
->column
[i
-ncols
].justification
;
7766 if(auxcol
.is_visible
) tbl
->column
[i
].left_xpixel
+=ncols
*DEFAULT_COLUMN_WIDTH
;
7767 tbl
->column
[i
-ncols
]=auxcol
;
7770 if(col
<= tbl
->maxalloccol
){
7772 GrowSheet(tbl
,0,ncols
);
7774 for(i
=0; i
<=tbl
->maxallocrow
; i
++){
7775 for(j
=tbl
->maxalloccol
; j
>=col
+ncols
; j
--){
7776 gtk_sheet_real_cell_clear(tbl
, i
, j
, TRUE
);
7777 tbl
->data
[i
][j
]=tbl
->data
[i
][j
-ncols
];
7778 if(tbl
->data
[i
][j
]) tbl
->data
[i
][j
]->col
=j
;
7779 tbl
->data
[i
][j
-ncols
]=NULL
;
7783 gtk_sheet_recalc_left_xpixels(tbl
, 0);
7788 DeleteRow(GtkSheet
*tbl
, gint row
, gint nrows
)
7790 GtkSheetCell
**auxdata
= NULL
;
7793 if(nrows
<= 0 || row
> tbl
->maxrow
) return TRUE
;
7795 nrows
=MIN(nrows
,tbl
->maxrow
-row
+1);
7797 for(i
=row
; i
<row
+nrows
; i
++){
7798 if(tbl
->row
[i
].name
){
7799 g_free(tbl
->row
[i
].name
);
7800 tbl
->row
[i
].name
= NULL
;
7802 if(tbl
->row
[i
].button
.label
){
7803 g_free(tbl
->row
[i
].button
.label
);
7804 tbl
->row
[i
].button
.label
= NULL
;
7808 for(i
=row
; i
<=tbl
->maxrow
-nrows
; i
++){
7809 if(i
+nrows
<= tbl
->maxrow
){
7810 tbl
->row
[i
]=tbl
->row
[i
+nrows
];
7814 if(row
<= tbl
->maxallocrow
){
7816 for(i
=row
; i
<=tbl
->maxrow
-nrows
; i
++){
7817 if(i
<=tbl
->maxallocrow
){
7818 auxdata
=tbl
->data
[i
];
7819 for(j
=0; j
<=tbl
->maxalloccol
; j
++){
7820 gtk_sheet_real_cell_clear(tbl
, i
, j
, TRUE
);
7823 if(i
+nrows
<=tbl
->maxallocrow
){
7824 tbl
->data
[i
]=tbl
->data
[i
+nrows
];
7825 tbl
->data
[i
+nrows
]=auxdata
;
7826 for(j
=0; j
<=tbl
->maxalloccol
; j
++){
7827 if(tbl
->data
[i
][j
]) tbl
->data
[i
][j
]->row
=i
;
7832 for(i
=tbl
->maxrow
-nrows
+1; i
<=tbl
->maxallocrow
; i
++){
7833 if(i
> 0 && tbl
->data
[i
]){
7834 g_free(tbl
->data
[i
]);
7835 tbl
->data
[i
] = NULL
;
7839 tbl
->maxallocrow
-=MIN(nrows
,tbl
->maxallocrow
-row
+1);
7840 tbl
->maxallocrow
= MIN(tbl
->maxallocrow
, tbl
->maxrow
);
7845 gtk_sheet_recalc_top_ypixels(tbl
, 0);
7850 DeleteColumn(GtkSheet
*tbl
, gint column
, gint ncols
)
7853 GtkSheetColumn auxcol
;
7855 ncols
= MIN(ncols
,tbl
->maxcol
-column
+1);
7857 if(ncols
<= 0 || column
> tbl
->maxcol
) return TRUE
;
7859 for(i
=column
; i
<column
+ncols
; i
++){
7860 auxcol
=tbl
->column
[i
];
7861 if(tbl
->column
[i
].name
){
7862 g_free(tbl
->column
[i
].name
);
7863 tbl
->column
[i
].name
= NULL
;
7865 if(tbl
->column
[i
].button
.label
){
7866 g_free(tbl
->column
[i
].button
.label
);
7867 tbl
->column
[i
].button
.label
= NULL
;
7871 for(i
=column
; i
<=tbl
->maxcol
-ncols
; i
++){
7872 if(i
+ncols
<= tbl
->maxcol
){
7873 tbl
->column
[i
]=tbl
->column
[i
+ncols
];
7877 if(column
<= tbl
->maxalloccol
){
7879 for(i
=column
; i
<=tbl
->maxcol
-ncols
; i
++){
7880 if(i
<=tbl
->maxalloccol
){
7881 for(j
=0; j
<=tbl
->maxallocrow
; j
++){
7882 gtk_sheet_real_cell_clear(tbl
, j
, i
, TRUE
);
7883 if(i
+ncols
<= tbl
->maxalloccol
){
7884 tbl
->data
[j
][i
] = tbl
->data
[j
][i
+ncols
];
7885 tbl
->data
[j
][i
+ncols
] = NULL
;
7886 if(tbl
->data
[j
][i
]) tbl
->data
[j
][i
]->col
=i
;
7893 tbl
->maxalloccol
-=MIN(ncols
,tbl
->maxalloccol
-column
+1);
7894 tbl
->maxalloccol
= MIN(tbl
->maxalloccol
, tbl
->maxcol
);
7897 gtk_sheet_recalc_left_xpixels(tbl
, 0);
7902 GrowSheet(GtkSheet
*tbl
, gint newrows
, gint newcols
)
7905 gint inirow
, inicol
;
7907 inirow
= tbl
->maxallocrow
+ 1;
7908 inicol
= tbl
->maxalloccol
+ 1;
7910 tbl
->maxalloccol
= tbl
->maxalloccol
+ newcols
;
7911 tbl
->maxallocrow
= tbl
->maxallocrow
+ newrows
;
7914 tbl
->data
= (GtkSheetCell
***)
7915 g_realloc(tbl
->data
,(tbl
->maxallocrow
+1)*sizeof(GtkSheetCell
**)+sizeof(double));
7917 for(i
=inirow
; i
<= tbl
->maxallocrow
; i
++){
7918 tbl
->data
[i
] = (GtkSheetCell
**) \
7919 g_malloc((tbl
->maxcol
+1)*sizeof(GtkSheetCell
*)+sizeof(double));
7920 for(j
=0; j
<inicol
; j
++) {
7921 tbl
->data
[i
][j
] = NULL
;
7928 for(i
=0; i
<= tbl
->maxallocrow
; i
++) {
7929 tbl
->data
[i
] = (GtkSheetCell
**) \
7930 g_realloc(tbl
->data
[i
],(tbl
->maxalloccol
+1)*sizeof(GtkSheetCell
*)+sizeof(double));
7931 for(j
=inicol
; j
<= tbl
->maxalloccol
; j
++) {
7932 tbl
->data
[i
][j
] = NULL
;
7941 CheckBounds(GtkSheet
*tbl
, gint row
, gint col
)
7943 gint newrows
=0,newcols
=0;
7945 if(col
>tbl
->maxalloccol
) newcols
=col
-tbl
->maxalloccol
;
7946 if(row
>tbl
->maxallocrow
) newrows
=row
-tbl
->maxallocrow
;
7947 if(newrows
>0 || newcols
>0) GrowSheet(tbl
, newrows
, newcols
);
7951 /********************************************************************
7952 * Container Functions:
7957 * gtk_sheet_move_child
7958 * gtk_sheet_position_child
7959 * gtk_sheet_position_children
7960 * gtk_sheet_realize_child
7961 * gtk_sheet_get_child_at
7962 ********************************************************************/
7965 gtk_sheet_put(GtkSheet
*sheet
, GtkWidget
*child
, gint x
, gint y
)
7967 GtkRequisition child_requisition
;
7968 GtkSheetChild
*child_info
;
7970 g_return_val_if_fail(sheet
!= NULL
, NULL
);
7971 g_return_val_if_fail(GTK_IS_SHEET(sheet
), NULL
);
7972 g_return_val_if_fail(child
!= NULL
, NULL
);
7973 g_return_val_if_fail(child
->parent
== NULL
, NULL
);
7975 child_info
= g_new (GtkSheetChild
, 1);
7976 child_info
->widget
= child
;
7979 child_info
->window
= NULL
;
7980 child_info
->attached_to_cell
= FALSE
;
7982 sheet
->children
= g_list_append(sheet
->children
, child_info
);
7984 gtk_widget_set_parent (child
, GTK_WIDGET(sheet
));
7986 gtk_widget_size_request(child
, &child_requisition
);
7988 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet
)))
7991 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
)) &&
7992 !GTK_WIDGET_REALIZED(child
))
7993 gtk_sheet_realize_child(sheet
, child_info
);
7995 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet
)) &&
7996 !GTK_WIDGET_MAPPED(child
))
7997 gtk_widget_map(child
);
8000 gtk_sheet_position_child(sheet
, child_info
);
8002 /* This will avoid drawing on the titles */
8004 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
)))
8006 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
8007 gdk_window_show(sheet
->row_title_window
);
8008 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
8009 gdk_window_show(sheet
->column_title_window
);
8012 return (child_info
);
8016 gtk_sheet_attach (GtkSheet
*sheet
,
8019 gfloat x_align
, gfloat y_align
)
8022 GtkSheetChild
*child
;
8024 if(row
< 0 || col
< 0){
8025 gtk_sheet_button_attach(sheet
, widget
, row
, col
, x_align
, y_align
);
8029 gtk_sheet_get_cell_area(sheet
, row
, col
, &area
);
8031 child
= gtk_sheet_put(sheet
, widget
, area
.x
, area
.y
);
8033 child
->attached_to_cell
= TRUE
;
8036 child
->x_align
= x_align
;
8037 child
->y_align
= y_align
;
8041 gtk_sheet_button_attach (GtkSheet
*sheet
,
8044 gfloat x_align
, gfloat y_align
)
8046 GtkSheetButton
*button
;
8047 GtkSheetChild
*child
;
8048 GtkRequisition button_requisition
;
8050 if(row
>= 0 && col
>= 0) return;
8051 if(row
< 0 && col
< 0) return;
8053 child
= g_new (GtkSheetChild
, 1);
8054 child
->widget
= widget
;
8057 child
->window
= NULL
;
8058 child
->attached_to_cell
= TRUE
;
8061 child
->x_align
= x_align
;
8062 child
->y_align
= y_align
;
8065 button
= &sheet
->column
[col
].button
;
8066 button
->child
= child
;
8070 button
= &sheet
->row
[row
].button
;
8071 button
->child
= child
;
8074 sheet
->children
= g_list_append(sheet
->children
, child
);
8076 gtk_widget_set_parent (widget
, GTK_WIDGET(sheet
));
8077 gtk_sheet_button_size_request(sheet
, button
, &button_requisition
);
8080 if(button_requisition
.height
> sheet
->column_title_area
.height
)
8081 sheet
->column_title_area
.height
= button_requisition
.height
;
8082 if(button_requisition
.width
> sheet
->column
[col
].width
)
8083 sheet
->column
[col
].width
= button_requisition
.width
;
8087 if(button_requisition
.width
> sheet
->row_title_area
.width
)
8088 sheet
->row_title_area
.width
= button_requisition
.width
;
8089 if(button_requisition
.height
> sheet
->row
[row
].height
)
8090 sheet
->row
[row
].height
= button_requisition
.height
;
8093 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet
)))
8096 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
)) &&
8097 !GTK_WIDGET_REALIZED(widget
))
8098 gtk_sheet_realize_child(sheet
, child
);
8100 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet
)) &&
8101 !GTK_WIDGET_MAPPED(widget
))
8102 gtk_widget_map(widget
);
8105 if(row
== -1) size_allocate_column_title_buttons(sheet
);
8106 if(col
== -1) size_allocate_row_title_buttons(sheet
);
8112 label_size_request(GtkSheet
*sheet
, gchar
*label
, GtkRequisition
*req
)
8117 gint row_height
= DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet
)) - 2*CELLOFFSET
+ 2;
8123 while(words
&& *words
!= '\0'){
8124 if(*words
== '\n' || *(words
+1) == '\0'){
8125 req
->height
+= row_height
;
8128 req
->width
= MAX( req
->width
, gdk_string_width (GTK_WIDGET (sheet
)->style
->font
, word
) );
8136 if(n
> 0) req
->height
-= 2;
8142 gtk_sheet_button_size_request (GtkSheet
*sheet
,
8143 GtkSheetButton
*button
,
8144 GtkRequisition
*button_requisition
)
8146 GtkRequisition requisition
;
8147 GtkRequisition label_requisition
;
8149 /* Taken from 2.2 */
8150 if(GTK_SHEET_AUTORESIZE(sheet
) && button
->label
&& strlen(button
->label
) > 0){
8151 label_size_request(sheet
, button
->label
, &label_requisition
);
8152 label_requisition
.width
+= 2*CELLOFFSET
;
8153 label_requisition
.height
+= 2*CELLOFFSET
;
8155 label_requisition
.height
= DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet
));
8156 label_requisition
.width
= COLUMN_MIN_WIDTH
;
8161 gtk_widget_size_request(button
->child
->widget
, &requisition
);
8162 /* taken from 2.2 */
8163 requisition
.width
+= 2; /* 2*button->child->xpadding; */
8164 requisition
.height
+= 2; /* 2*button->child->ypadding; */
8165 requisition
.width
+= 2*sheet
->button
->style
->klass
->xthickness
;
8166 requisition
.height
+= 2*sheet
->button
->style
->klass
->ythickness
;
8168 requisition
.height
= DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet
));
8169 requisition
.width
= COLUMN_MIN_WIDTH
;
8172 *button_requisition
= requisition
;
8174 button_requisition
->width
+= sheet
->button
->style
->klass
->xthickness
;
8175 button_requisition
->height
+= sheet
->button
->style
->klass
->ythickness
;
8179 gtk_sheet_move_child(GtkSheet
*sheet
, GtkWidget
*widget
, gint x
, gint y
)
8181 GtkSheetChild
*child
;
8184 g_return_if_fail(sheet
!= NULL
);
8185 g_return_if_fail(GTK_IS_SHEET(sheet
));
8187 children
= sheet
->children
;
8190 child
= children
->data
;
8192 if(child
->widget
== widget
){
8195 child
->row
= ROW_FROM_YPIXEL(sheet
, y
);
8196 child
->col
= COLUMN_FROM_XPIXEL(sheet
, x
);
8197 gtk_sheet_position_child(sheet
, child
);
8201 children
= children
->next
;
8204 g_warning("Widget must be a GtkSheet child");
8209 gtk_sheet_position_child(GtkSheet
*sheet
, GtkSheetChild
*child
)
8211 GtkRequisition child_requisition
;
8217 gtk_widget_get_child_requisition(child
->widget
, &child_requisition
);
8219 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet
))
8220 yoffset
= sheet
->column_title_area
.height
;
8222 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet
))
8223 xoffset
= sheet
->row_title_area
.width
;
8225 if(child
->attached_to_cell
){
8227 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col);
8228 child->y = ROW_TOP_YPIXEL(sheet, child->row);
8230 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet))
8231 child->x-=sheet->row_title_area.width;
8232 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet))
8233 child->y-=sheet->column_title_area.height;
8235 width = sheet->column[child->col].width;
8236 height = sheet->row[child->row].height;
8239 gtk_sheet_get_cell_area(sheet
, child
->row
, child
->col
, &area
);
8242 child
->x
+= (area
.width
- child_requisition
.width
) * child
->x_align
;
8243 child
->y
+= (area
.height
- child_requisition
.height
) * child
->y_align
;
8244 x
= child
->widget
->allocation
.x
= child
->x
+ xoffset
;
8245 y
= child
->widget
->allocation
.y
= child
->y
+ yoffset
;
8249 x
= child
->widget
->allocation
.x
= child
->x
+ sheet
->hoffset
+ xoffset
;
8250 x
= child
->widget
->allocation
.x
= child
->x
+ xoffset
;
8251 y
= child
->widget
->allocation
.y
= child
->y
+ sheet
->voffset
+ yoffset
;
8252 y
= child
->widget
->allocation
.y
= child
->y
+ yoffset
;
8255 child
->widget
->allocation
.width
= child_requisition
.width
;
8256 child
->widget
->allocation
.height
= child_requisition
.height
;
8258 if(GTK_WIDGET_NO_WINDOW(child
->widget
))
8260 child
->widget
->allocation
.x
= 0;
8261 child
->widget
->allocation
.y
= 0;
8264 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet
)) &&
8265 GTK_WIDGET_MAPPED(child
->widget
))
8267 gtk_widget_size_allocate(child
->widget
,
8268 &child
->widget
->allocation
);
8269 if(GTK_WIDGET_NO_WINDOW(child
->widget
) && child
->window
)
8271 gdk_window_move_resize(child
->window
,
8273 child
->widget
->allocation
.width
,
8274 child
->widget
->allocation
.height
);
8275 gtk_widget_draw(child
->widget
, NULL
);
8282 gtk_sheet_position_children(GtkSheet
*sheet
)
8285 GtkSheetChild
*child
;
8287 children
= sheet
->children
;
8291 child
= (GtkSheetChild
*)children
->data
;
8293 if(child
->col
!=-1 && child
->row
!= -1)
8294 gtk_sheet_position_child(sheet
, child
);
8296 if(child
->row
== -1){
8297 if(child
->col
< MIN_VISIBLE_COLUMN(sheet
) ||
8298 child
->col
> MAX_VISIBLE_COLUMN(sheet
))
8299 gtk_sheet_child_hide(child
);
8301 gtk_sheet_child_show(child
);
8303 if(child
->col
== -1){
8304 if(child
->row
< MIN_VISIBLE_ROW(sheet
) ||
8305 child
->row
> MAX_VISIBLE_ROW(sheet
))
8306 gtk_sheet_child_hide(child
);
8308 gtk_sheet_child_show(child
);
8311 children
= children
->next
;
8317 gtk_sheet_remove (GtkContainer
*container
, GtkWidget
*widget
)
8321 GtkSheetChild
*child
= 0;
8323 g_return_if_fail(container
!= NULL
);
8324 g_return_if_fail(GTK_IS_SHEET(container
));
8326 sheet
= GTK_SHEET(container
);
8328 children
= sheet
->children
;
8332 child
= (GtkSheetChild
*)children
->data
;
8334 if(child
->widget
== widget
) break;
8336 children
= children
->next
;
8341 if(child
->row
== -1)
8342 sheet
->row
[child
->col
].button
.child
= NULL
;
8344 if(child
->col
== -1)
8345 sheet
->column
[child
->row
].button
.child
= NULL
;
8348 gdk_window_hide(child
->window
);
8349 gdk_window_unref(child
->window
);
8352 gtk_widget_unparent (widget
);
8353 child
->widget
= NULL
;
8355 sheet
->children
= g_list_remove_link (sheet
->children
, children
);
8356 g_list_free_1 (children
);
8362 gtk_sheet_realize_child(GtkSheet
*sheet
, GtkSheetChild
*child
)
8364 gint attributes_mask
;
8367 widget
= GTK_WIDGET(sheet
);
8369 if (GTK_WIDGET_NO_WINDOW (child
->widget
))
8371 GdkWindowAttr attributes
;
8373 gint x
= child
->x
- sheet
->hoffset
;
8374 gint y
= child
->y
- sheet
->voffset
;
8376 attributes
.window_type
= GDK_WINDOW_CHILD
;
8379 attributes
.width
= child
->widget
->requisition
.width
;
8380 attributes
.height
= child
->widget
->requisition
.height
;
8381 attributes
.wclass
= GDK_INPUT_OUTPUT
;
8382 attributes
.visual
= gtk_widget_get_visual (widget
);
8383 attributes
.colormap
= gtk_widget_get_colormap (widget
);
8384 attributes
.event_mask
= GDK_EXPOSURE_MASK
;
8386 attributes_mask
= GDK_WA_X
| GDK_WA_Y
| GDK_WA_VISUAL
| GDK_WA_COLORMAP
;
8388 if(child
->row
== -1)
8389 child
->window
= gdk_window_new (sheet
->column_title_window
,
8390 &attributes
, attributes_mask
);
8391 else if(child
->col
== -1)
8392 child
->window
= gdk_window_new (sheet
->row_title_window
,
8393 &attributes
, attributes_mask
);
8395 child
->window
= gdk_window_new (widget
->window
,
8396 &attributes
, attributes_mask
);
8398 if(GTK_IS_PIXMAP(child
->widget
)){
8399 gdk_window_shape_combine_mask(child
->window
,
8400 GTK_PIXMAP(child
->widget
)->mask
,
8404 gdk_window_set_user_data (child
->window
, widget
);
8407 gtk_style_set_background (widget
->style
,
8411 gtk_widget_set_parent_window(child
->widget
, child
->window
);
8412 gdk_window_show(child
->window
);
8416 gtk_widget_realize(child
->widget
);
8423 gtk_sheet_get_child_at(GtkSheet
*sheet
, gint row
, gint col
)
8426 GtkSheetChild
*child
= 0;
8428 g_return_val_if_fail(sheet
!= NULL
, NULL
);
8429 g_return_val_if_fail(GTK_IS_SHEET(sheet
), NULL
);
8431 children
= sheet
->children
;
8435 child
= (GtkSheetChild
*)children
->data
;
8437 if(child
->attached_to_cell
)
8438 if(child
->row
== row
&& child
->col
== col
) break;
8440 children
= children
->next
;
8443 if(children
) return child
;
8449 gtk_sheet_child_hide(GtkSheetChild
*child
)
8451 g_return_if_fail(child
!= NULL
);
8452 gtk_widget_hide(child
->widget
);
8454 gdk_window_hide(child
->window
);
8458 gtk_sheet_child_show(GtkSheetChild
*child
)
8460 g_return_if_fail(child
!= NULL
);
8462 gtk_widget_show(child
->widget
);
8464 gdk_window_show(child
->window
);