gattrib
|
00001 /* GtkSheet widget for Gtk+. 00002 * Copyright (C) 1999-2001 Adrian E. Feiguin <adrian@ifir.ifir.edu.ar> 00003 * 00004 * Based on GtkClist widget by Jay Painter, but major changes. 00005 * Memory allocation routines inspired on SC (Spreadsheet Calculator) 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Library General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Library General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Library General Public 00018 * License along with this library; if not, write to the 00019 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 * Boston, MA 02110-1301 USA 00021 */ 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include "config.h" 00025 #endif 00026 00027 #include <string.h> 00028 #include <stdio.h> 00029 #include <stdlib.h> 00030 #include <glib.h> 00031 #include <glib-object.h> 00032 #include <gobject/gvaluecollector.h> 00033 #include <gdk/gdk.h> 00034 #include <gdk/gdkkeysyms.h> 00035 #include <gtk/gtksignal.h> 00036 #include <gtk/gtklabel.h> 00037 #include <gtk/gtkbutton.h> 00038 #include <gtk/gtkadjustment.h> 00039 #include <gtk/gtktable.h> 00040 #include <gtk/gtkbox.h> 00041 #include <gtk/gtkmain.h> 00042 #include <gtk/gtktypeutils.h> 00043 #include <gtk/gtkentry.h> 00044 #include <gtk/gtkcontainer.h> 00045 #include <gtk/gtkpixmap.h> 00046 #include <pango/pango.h> 00047 #include "gtksheet_2_2.h" 00048 #include "gtkextra-marshal.h" 00049 00050 /*------------------------------------------------------------------ 00051 * Gattrib specific includes -- stuff dealing with gattrib data structs. 00052 * Included here in order to grab sheet_head->CHANGED, which is set 00053 * when the user puts a new value in a cell. 00054 *------------------------------------------------------------------*/ 00055 #include <libgeda/libgeda.h> /* geda library fcns */ 00056 #include "../include/struct.h" /* typdef and struct declarations */ 00057 #include "../include/prototype.h" /* function prototypes */ 00058 #include "../include/globals.h" 00059 00060 #ifdef HAVE_LIBDMALLOC 00061 #include <dmalloc.h> 00062 #endif 00063 00064 00065 /* sheet flags */ 00066 enum 00067 { 00068 GTK_SHEET_IS_LOCKED = 1 << 0, 00069 GTK_SHEET_IS_FROZEN = 1 << 1, 00070 GTK_SHEET_IN_XDRAG = 1 << 2, 00071 GTK_SHEET_IN_YDRAG = 1 << 3, 00072 GTK_SHEET_IN_DRAG = 1 << 4, 00073 GTK_SHEET_IN_SELECTION = 1 << 5, 00074 GTK_SHEET_IN_RESIZE = 1 << 6, 00075 GTK_SHEET_IN_CLIP = 1 << 7, 00076 GTK_SHEET_REDRAW_PENDING = 1 << 8, 00077 }; 00078 00079 #define GTK_SHEET_FLAGS(sheet) (GTK_SHEET (sheet)->flags) 00080 #define GTK_SHEET_SET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) |= (flag)) 00081 #define GTK_SHEET_UNSET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) &= ~(flag)) 00082 00083 #define GTK_SHEET_IS_FROZEN(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN) 00084 #define GTK_SHEET_IN_XDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG) 00085 #define GTK_SHEET_IN_YDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG) 00086 #define GTK_SHEET_IN_DRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_DRAG) 00087 #define GTK_SHEET_IN_SELECTION(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_SELECTION) 00088 #define GTK_SHEET_IN_RESIZE(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_RESIZE) 00089 #define GTK_SHEET_IN_CLIP(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_CLIP) 00090 #define GTK_SHEET_REDRAW_PENDING(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_REDRAW_PENDING) 00091 00092 #define CELL_SPACING 1 00093 #define DRAG_WIDTH 6 00094 #define TIMEOUT_SCROLL 20 00095 #define TIMEOUT_FLASH 200 00096 #define TIME_INTERVAL 8 00097 #define COLUMN_MIN_WIDTH 10 00098 #define MINROWS 1 00099 #define MINCOLS 1 00100 #define MAXLENGTH 30 00101 #define CELLOFFSET 4 00102 #define DEFAULT_COLUMN_WIDTH 80 00103 00104 static inline guint DEFAULT_ROW_HEIGHT(GtkWidget *widget) 00105 { 00106 if(!widget->style->font_desc) return 24; 00107 else { 00108 PangoContext *context = gtk_widget_get_pango_context(widget); 00109 PangoFontMetrics *metrics = pango_context_get_metrics(context, 00110 widget->style->font_desc, 00111 pango_context_get_language(context)); 00112 guint val = pango_font_metrics_get_descent(metrics) + 00113 pango_font_metrics_get_ascent(metrics); 00114 pango_font_metrics_unref(metrics); 00115 return PANGO_PIXELS(val)+2*CELLOFFSET; 00116 } 00117 } 00118 static inline guint DEFAULT_FONT_ASCENT(GtkWidget *widget) 00119 { 00120 if(!widget->style->font_desc) return 12; 00121 else { 00122 PangoContext *context = gtk_widget_get_pango_context(widget); 00123 PangoFontMetrics *metrics = pango_context_get_metrics(context, 00124 widget->style->font_desc, 00125 pango_context_get_language(context)); 00126 guint val = pango_font_metrics_get_ascent(metrics); 00127 pango_font_metrics_unref(metrics); 00128 return PANGO_PIXELS(val); 00129 } 00130 } 00131 static inline guint STRING_WIDTH(GtkWidget *widget, 00132 PangoFontDescription *font, const gchar *text) 00133 { 00134 PangoRectangle rect; 00135 PangoLayout *layout; 00136 00137 layout = gtk_widget_create_pango_layout (widget, text); 00138 pango_layout_set_font_description (layout, font); 00139 00140 pango_layout_get_extents (layout, NULL, &rect); 00141 00142 g_object_unref(G_OBJECT(layout)); 00143 return PANGO_PIXELS(rect.width); 00144 } 00145 00146 static inline guint DEFAULT_FONT_DESCENT(GtkWidget *widget) 00147 { 00148 if(!widget->style->font_desc) return 12; 00149 else { 00150 PangoContext *context = gtk_widget_get_pango_context(widget); 00151 PangoFontMetrics *metrics = pango_context_get_metrics(context, 00152 widget->style->font_desc, 00153 pango_context_get_language(context)); 00154 guint val = pango_font_metrics_get_descent(metrics); 00155 pango_font_metrics_unref(metrics); 00156 return PANGO_PIXELS(val); 00157 } 00158 } 00159 00164 static inline gint 00165 ROW_TOP_YPIXEL(GtkSheet *sheet, gint nrow) 00166 { 00167 return (sheet->voffset + sheet->row[nrow].top_ypixel); 00168 } 00169 00170 00175 static inline gint 00176 ROW_FROM_YPIXEL(GtkSheet *sheet, gint y) 00177 { 00178 gint i, cy; 00179 00180 cy = sheet->voffset; 00181 if(sheet->column_titles_visible) cy += sheet->column_title_area.height; 00182 if(y < cy) return 0; 00183 for (i = 0; i <= sheet->maxrow; i++) 00184 { 00185 if (y >= cy && y <= (cy + sheet->row[i].height) && sheet->row[i].is_visible) 00186 return i; 00187 if(sheet->row[i].is_visible) cy += sheet->row[i].height; 00188 00189 } 00190 00191 /* no match */ 00192 return sheet->maxrow; 00193 } 00194 00195 00200 static inline gint 00201 COLUMN_LEFT_XPIXEL(GtkSheet *sheet, gint ncol) 00202 { 00203 return (sheet->hoffset + sheet->column[ncol].left_xpixel); 00204 } 00205 00210 static inline gint 00211 COLUMN_FROM_XPIXEL (GtkSheet * sheet, 00212 gint x) 00213 { 00214 gint i, cx; 00215 00216 cx = sheet->hoffset; 00217 if(sheet->row_titles_visible) cx += sheet->row_title_area.width; 00218 if(x < cx) return 0; 00219 for (i = 0; i <= sheet->maxcol; i++) 00220 { 00221 if (x >= cx && x <= (cx + sheet->column[i].width) && sheet->column[i].is_visible) 00222 return i; 00223 if(sheet->column[i].is_visible) cx += sheet->column[i].width; 00224 00225 } 00226 00227 /* no match */ 00228 return sheet->maxcol; 00229 } 00230 00234 static inline gint SHEET_HEIGHT(GtkSheet *sheet) 00235 { 00236 gint i,cx; 00237 00238 cx = 0; 00239 if(sheet->column_titles_visible) cx += sheet->column_title_area.height; 00240 for (i=0;i<=sheet->maxrow; i++) 00241 if(sheet->row[i].is_visible) cx += sheet->row[i].height; 00242 00243 return cx; 00244 } 00245 00246 00250 static inline gint SHEET_WIDTH(GtkSheet *sheet) 00251 { 00252 gint i,cx; 00253 00254 cx = 0; 00255 if(sheet->row_titles_visible) cx += sheet->row_title_area.width; 00256 for (i=0;i<=sheet->maxcol; i++) 00257 if(sheet->column[i].is_visible) cx += sheet->column[i].width; 00258 00259 return cx; 00260 } 00261 00262 #define MIN_VISIBLE_ROW(sheet) sheet->view.row0 00263 #define MAX_VISIBLE_ROW(sheet) sheet->view.rowi 00264 #define MIN_VISIBLE_COLUMN(sheet) sheet->view.col0 00265 #define MAX_VISIBLE_COLUMN(sheet) sheet->view.coli 00266 00267 00268 static inline gint 00269 POSSIBLE_XDRAG(GtkSheet *sheet, gint x, gint *drag_column) 00270 { 00271 gint column, xdrag; 00272 00273 column=COLUMN_FROM_XPIXEL(sheet, x); 00274 *drag_column=column; 00275 00276 xdrag=COLUMN_LEFT_XPIXEL(sheet,column)+CELL_SPACING; 00277 if(x <= xdrag+DRAG_WIDTH/2 && column != 0){ 00278 while(!sheet->column[column-1].is_visible && column>0) column--; 00279 *drag_column=column-1; 00280 return sheet->column[column-1].is_sensitive; 00281 } 00282 00283 xdrag+=sheet->column[column].width; 00284 if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag+DRAG_WIDTH/2) 00285 return sheet->column[column].is_sensitive; 00286 00287 return FALSE; 00288 } 00289 00290 static inline gint 00291 POSSIBLE_YDRAG(GtkSheet *sheet, gint y, gint *drag_row) 00292 { 00293 gint row, ydrag; 00294 00295 row=ROW_FROM_YPIXEL(sheet, y); 00296 *drag_row=row; 00297 00298 ydrag=ROW_TOP_YPIXEL(sheet,row)+CELL_SPACING; 00299 if(y <= ydrag+DRAG_WIDTH/2 && row != 0){ 00300 while(!sheet->row[row-1].is_visible && row>0) row--; 00301 *drag_row=row-1; 00302 return sheet->row[row-1].is_sensitive; 00303 } 00304 00305 ydrag+=sheet->row[row].height; 00306 00307 if(y >= ydrag-DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2) 00308 return sheet->row[row].is_sensitive; 00309 00310 00311 return FALSE; 00312 } 00313 00314 static inline gint POSSIBLE_DRAG(GtkSheet *sheet, gint x, gint y, 00315 gint *drag_row, gint *drag_column) 00316 { 00317 gint ydrag, xdrag; 00318 00319 *drag_column=COLUMN_FROM_XPIXEL(sheet,x); 00320 *drag_row=ROW_FROM_YPIXEL(sheet,y); 00321 00322 if(x>=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0)-DRAG_WIDTH/2 && 00323 x<=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+ 00324 sheet->column[sheet->range.coli].width+DRAG_WIDTH/2){ 00325 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.row0); 00326 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){ 00327 *drag_row=sheet->range.row0; 00328 return TRUE; 00329 } 00330 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+ 00331 sheet->row[sheet->range.rowi].height; 00332 if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){ 00333 *drag_row=sheet->range.rowi; 00334 return TRUE; 00335 } 00336 } 00337 00338 if(y>=ROW_TOP_YPIXEL(sheet,sheet->range.row0)-DRAG_WIDTH/2 && 00339 y<=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+ 00340 sheet->row[sheet->range.rowi].height+DRAG_WIDTH/2){ 00341 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0); 00342 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){ 00343 *drag_column=sheet->range.col0; 00344 return TRUE; 00345 } 00346 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+ 00347 sheet->column[sheet->range.coli].width; 00348 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){ 00349 *drag_column=sheet->range.coli; 00350 return TRUE; 00351 } 00352 } 00353 return FALSE; 00354 } 00355 00356 static inline gint POSSIBLE_RESIZE(GtkSheet *sheet, gint x, gint y, 00357 gint *drag_row, gint *drag_column) 00358 { 00359 gint xdrag, ydrag; 00360 00361 xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+ 00362 sheet->column[sheet->range.coli].width; 00363 00364 ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+ 00365 sheet->row[sheet->range.rowi].height; 00366 00367 if(sheet->state == GTK_SHEET_COLUMN_SELECTED) 00368 ydrag = ROW_TOP_YPIXEL(sheet, sheet->view.row0); 00369 00370 if(sheet->state == GTK_SHEET_ROW_SELECTED) 00371 xdrag = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0); 00372 00373 *drag_column=COLUMN_FROM_XPIXEL(sheet,x); 00374 *drag_row=ROW_FROM_YPIXEL(sheet,y); 00375 00376 if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2 && 00377 y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2) return TRUE; 00378 00379 return FALSE; 00380 } 00381 00382 static void gtk_sheet_class_init (GtkSheetClass * klass); 00383 static void gtk_sheet_init (GtkSheet * sheet); 00384 static void gtk_sheet_destroy (GtkObject * object); 00385 static void gtk_sheet_finalize (GObject * object); 00386 static void gtk_sheet_style_set (GtkWidget *widget, 00387 GtkStyle *previous_style); 00388 static void gtk_sheet_realize (GtkWidget * widget); 00389 static void gtk_sheet_unrealize (GtkWidget * widget); 00390 static void gtk_sheet_map (GtkWidget * widget); 00391 static void gtk_sheet_unmap (GtkWidget * widget); 00392 static gint gtk_sheet_expose (GtkWidget * widget, 00393 GdkEventExpose * event); 00394 static void gtk_sheet_forall (GtkContainer *container, 00395 gboolean include_internals, 00396 GtkCallback callback, 00397 gpointer callback_data); 00398 00399 static void gtk_sheet_set_scroll_adjustments (GtkSheet *sheet, 00400 GtkAdjustment *hadjustment, 00401 GtkAdjustment *vadjustment); 00402 00403 static gint gtk_sheet_button_press (GtkWidget * widget, 00404 GdkEventButton * event); 00405 static gint gtk_sheet_button_release (GtkWidget * widget, 00406 GdkEventButton * event); 00407 static gint gtk_sheet_motion (GtkWidget * widget, 00408 GdkEventMotion * event); 00409 00410 #if 0 00411 static gint gtk_sheet_entry_key_press (GtkWidget *widget, 00412 GdkEventKey *key); 00413 #endif 00414 00415 static gint gtk_sheet_key_press (GtkWidget *widget, 00416 GdkEventKey *key); 00417 00418 static void gtk_sheet_size_request (GtkWidget * widget, 00419 GtkRequisition * requisition); 00420 static void gtk_sheet_size_allocate (GtkWidget * widget, 00421 GtkAllocation * allocation); 00422 00423 /* Sheet queries */ 00424 00425 static gint gtk_sheet_range_isvisible (GtkSheet * sheet, 00426 GtkSheetRange range); 00427 static gint gtk_sheet_cell_isvisible (GtkSheet * sheet, 00428 gint row, gint column); 00429 /* Clipped Range */ 00430 00431 static gint gtk_sheet_scroll (gpointer data); 00432 static gint gtk_sheet_flash (gpointer data); 00433 00434 /* Drawing Routines */ 00435 00436 /* draw cell background and frame */ 00437 static void gtk_sheet_cell_draw_default (GtkSheet *sheet, 00438 gint row, gint column); 00439 00440 /* draw cell border */ 00441 static void gtk_sheet_cell_draw_border (GtkSheet *sheet, 00442 gint row, gint column, 00443 gint mask); 00444 00445 /* draw cell contents */ 00446 static void gtk_sheet_cell_draw_label (GtkSheet *sheet, 00447 gint row, gint column); 00448 00449 /* draw visible part of range. If range==NULL then draw the whole screen */ 00450 static void gtk_sheet_range_draw (GtkSheet *sheet, 00451 const GtkSheetRange *range); 00452 00453 /* highlight the visible part of the selected range */ 00454 static void gtk_sheet_range_draw_selection (GtkSheet *sheet, 00455 GtkSheetRange range); 00456 00457 /* Selection */ 00458 00459 static gint gtk_sheet_move_query (GtkSheet *sheet, 00460 gint row, gint column); 00461 static void gtk_sheet_real_select_range (GtkSheet * sheet, 00462 GtkSheetRange * range); 00463 static void gtk_sheet_real_unselect_range (GtkSheet * sheet, 00464 const GtkSheetRange * range); 00465 static void gtk_sheet_extend_selection (GtkSheet *sheet, 00466 gint row, gint column); 00467 static void gtk_sheet_new_selection (GtkSheet *sheet, 00468 GtkSheetRange *range); 00469 static void gtk_sheet_draw_border (GtkSheet *sheet, 00470 GtkSheetRange range); 00471 static void gtk_sheet_draw_corners (GtkSheet *sheet, 00472 GtkSheetRange range); 00473 00474 00475 /* Active Cell handling */ 00476 00477 static void gtk_sheet_entry_changed (GtkWidget *widget, 00478 gpointer data); 00479 static gboolean gtk_sheet_deactivate_cell (GtkSheet *sheet); 00480 static void gtk_sheet_hide_active_cell (GtkSheet *sheet); 00481 static gboolean gtk_sheet_activate_cell (GtkSheet *sheet, 00482 gint row, gint col); 00483 static void gtk_sheet_draw_active_cell (GtkSheet *sheet); 00484 static void gtk_sheet_show_active_cell (GtkSheet *sheet); 00485 static void gtk_sheet_click_cell (GtkSheet *sheet, 00486 gint row, 00487 gint column, 00488 gboolean *veto); 00489 00490 /* Backing Pixmap */ 00491 00492 static void gtk_sheet_make_backing_pixmap (GtkSheet *sheet, 00493 guint width, guint height); 00494 static void gtk_sheet_draw_backing_pixmap (GtkSheet *sheet, 00495 GtkSheetRange range); 00496 /* Scrollbars */ 00497 00498 static void adjust_scrollbars (GtkSheet * sheet); 00499 static void vadjustment_changed (GtkAdjustment * adjustment, 00500 gpointer data); 00501 static void hadjustment_changed (GtkAdjustment * adjustment, 00502 gpointer data); 00503 static void vadjustment_value_changed (GtkAdjustment * adjustment, 00504 gpointer data); 00505 static void hadjustment_value_changed (GtkAdjustment * adjustment, 00506 gpointer data); 00507 00508 00509 static void draw_xor_vline (GtkSheet * sheet); 00510 static void draw_xor_hline (GtkSheet * sheet); 00511 static void draw_xor_rectangle (GtkSheet *sheet, 00512 GtkSheetRange range); 00513 static void gtk_sheet_draw_flashing_range (GtkSheet *sheet, 00514 GtkSheetRange range); 00515 static guint new_column_width (GtkSheet * sheet, 00516 gint column, 00517 gint * x); 00518 static guint new_row_height (GtkSheet * sheet, 00519 gint row, 00520 gint * y); 00521 /* Sheet Button */ 00522 00523 static void create_global_button (GtkSheet *sheet); 00524 static void global_button_clicked (GtkWidget *widget, 00525 gpointer data); 00526 /* Sheet Entry */ 00527 00528 static void create_sheet_entry (GtkSheet *sheet); 00529 static void gtk_sheet_size_allocate_entry (GtkSheet *sheet); 00530 00531 /* Sheet button gadgets */ 00532 00533 static void size_allocate_column_title_buttons (GtkSheet * sheet); 00534 static void size_allocate_row_title_buttons (GtkSheet * sheet); 00535 static void gtk_sheet_recalc_top_ypixels (GtkSheet *sheet, 00536 gint row); 00537 static void gtk_sheet_recalc_left_xpixels (GtkSheet *sheet, 00538 gint column); 00539 static void row_button_set (GtkSheet *sheet, 00540 gint row); 00541 static void column_button_set (GtkSheet *sheet, 00542 gint column); 00543 static void row_button_release (GtkSheet *sheet, 00544 gint row); 00545 static void column_button_release (GtkSheet *sheet, 00546 gint column); 00547 static void gtk_sheet_button_draw (GtkSheet *sheet, 00548 gint row, gint column); 00549 static void size_allocate_global_button (GtkSheet *sheet); 00550 static void gtk_sheet_button_size_request (GtkSheet *sheet, 00551 GtkSheetButton *button, 00552 GtkRequisition *requisition); 00553 00554 /* Attributes routines */ 00555 00556 static void gtk_sheet_set_cell_attributes (GtkSheet *sheet, 00557 gint row, gint col, 00558 GtkSheetCellAttr attributes); 00559 00560 static void init_attributes (GtkSheet *sheet, gint col, 00561 GtkSheetCellAttr *attributes); 00562 /* Memory allocation routines */ 00563 static void gtk_sheet_real_range_clear (GtkSheet *sheet, 00564 const GtkSheetRange *range, 00565 gboolean delete); 00566 static void gtk_sheet_real_cell_clear (GtkSheet *sheet, 00567 gint row, 00568 gint column, 00569 gboolean delete); 00570 static GtkSheetCell * gtk_sheet_cell_new (void); 00571 static gint AddRow (GtkSheet *sheet, gint nrows); 00572 static gint AddColumn (GtkSheet *sheet, gint ncols); 00573 static gint InsertRow (GtkSheet *sheet, gint row, gint nrows); 00574 static gint InsertColumn (GtkSheet *sheet, gint col, gint ncols); 00575 static gint DeleteRow (GtkSheet *sheet, gint row, gint nrows); 00576 static gint DeleteColumn (GtkSheet *sheet, gint col, gint ncols); 00577 static gint GrowSheet (GtkSheet *sheet, 00578 gint newrows, gint newcols); 00579 static gint CheckBounds (GtkSheet *sheet, 00580 gint row, gint col); 00581 00582 /* Container Functions */ 00583 static void gtk_sheet_remove (GtkContainer *container, 00584 GtkWidget *widget); 00585 static void gtk_sheet_realize_child (GtkSheet *sheet, 00586 GtkSheetChild *child); 00587 static void gtk_sheet_position_child (GtkSheet *sheet, 00588 GtkSheetChild *child); 00589 static void gtk_sheet_position_children (GtkSheet *sheet); 00590 static void gtk_sheet_child_show (GtkSheetChild *child); 00591 static void gtk_sheet_child_hide (GtkSheetChild *child); 00592 static void gtk_sheet_column_size_request (GtkSheet *sheet, 00593 gint col, 00594 guint *requisition); 00595 static void gtk_sheet_row_size_request (GtkSheet *sheet, 00596 gint row, 00597 guint *requisition); 00598 00599 00600 /* Signals */ 00601 00602 /* \brief Imported from gtkextra.c by SDB 7.22.2004 00603 * 00604 */ 00605 void 00606 _gtkextra_signal_emit(GtkObject *object, guint signal_id, ...) 00607 { 00608 gboolean *result; 00609 GValue ret = { 0, }; 00610 GValue instance_and_params [10] = { {0, }, }; 00611 va_list var_args; 00612 GSignalQuery query; 00613 gchar *error; 00614 int i; 00615 00616 va_start (var_args, signal_id); 00617 00618 g_value_init(instance_and_params + 0, GTK_OBJECT_TYPE(object)); 00619 g_value_set_instance (instance_and_params + 0, G_OBJECT(object)); 00620 00621 g_signal_query(signal_id, &query); 00622 00623 for (i = 0; i < query.n_params; i++) 00624 { 00625 gboolean static_scope = query.param_types[i]&~G_SIGNAL_TYPE_STATIC_SCOPE; 00626 g_value_init(instance_and_params + i + 1, query.param_types[i]); 00627 00628 00629 G_VALUE_COLLECT (instance_and_params + i + 1, 00630 var_args, 00631 static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, 00632 &error); 00633 00634 if (error) 00635 { 00636 g_warning ("%s: %s", G_STRLOC, error); 00637 g_free (error); 00638 while (i-- > 0) 00639 g_value_unset (instance_and_params + i); 00640 00641 va_end (var_args); 00642 return; 00643 } 00644 00645 00646 } 00647 00648 g_value_init(&ret, query.return_type); 00649 result = va_arg(var_args,gboolean *); 00650 g_value_set_boolean(&ret, *result); 00651 g_signal_emitv(instance_and_params, signal_id, 0, &ret); 00652 *result = g_value_get_boolean(&ret); 00653 g_value_unset (&ret); 00654 00655 for (i = 0; i < query.n_params; i++) 00656 g_value_unset (instance_and_params + 1 + i); 00657 g_value_unset (instance_and_params + 0); 00658 00659 va_end (var_args); 00660 } 00661 00662 00663 enum { 00664 SELECT_ROW, 00665 SELECT_COLUMN, 00666 SELECT_RANGE, 00667 CLIP_RANGE, 00668 RESIZE_RANGE, 00669 MOVE_RANGE, 00670 TRAVERSE, 00671 DEACTIVATE, 00672 ACTIVATE, 00673 SET_CELL, 00674 CLEAR_CELL, 00675 CHANGED, 00676 NEW_COL_WIDTH, 00677 NEW_ROW_HEIGHT, 00678 LAST_SIGNAL 00679 }; 00680 00681 static GtkContainerClass *parent_class = NULL; 00682 static guint sheet_signals[LAST_SIGNAL] = {0}; 00683 00684 00685 GType 00686 gtk_sheet_get_type () 00687 { 00688 static GType sheet_type = 0; 00689 00690 if (!sheet_type) 00691 { 00692 static const GTypeInfo sheet_info = 00693 { 00694 sizeof (GtkSheetClass), 00695 NULL, 00696 NULL, 00697 (GClassInitFunc) gtk_sheet_class_init, 00698 NULL, 00699 NULL, 00700 sizeof (GtkSheet), 00701 0, 00702 (GInstanceInitFunc) gtk_sheet_init, 00703 NULL, 00704 }; 00705 sheet_type = 00706 g_type_register_static (GTK_TYPE_CONTAINER, "GtkSheet", 00707 &sheet_info, 0); 00708 } 00709 return sheet_type; 00710 } 00711 00712 static GtkSheetRange* 00713 gtk_sheet_range_copy (const GtkSheetRange *range) 00714 { 00715 GtkSheetRange *new_range; 00716 00717 g_return_val_if_fail (range != NULL, NULL); 00718 00719 new_range = g_new (GtkSheetRange, 1); 00720 00721 *new_range = *range; 00722 00723 return new_range; 00724 } 00725 00726 static void 00727 gtk_sheet_range_free (GtkSheetRange *range) 00728 { 00729 g_return_if_fail (range != NULL); 00730 00731 g_free (range); 00732 } 00733 00734 GType 00735 gtk_sheet_range_get_type (void) 00736 { 00737 static GType sheet_range_type; 00738 00739 if(!sheet_range_type) 00740 { 00741 sheet_range_type = g_boxed_type_register_static("GtkSheetRange", (GBoxedCopyFunc)gtk_sheet_range_copy, (GBoxedFreeFunc)gtk_sheet_range_free); 00742 } 00743 return sheet_range_type; 00744 00745 } 00746 00747 static void 00748 gtk_sheet_class_init (GtkSheetClass * klass) 00749 { 00750 GtkObjectClass *object_class; 00751 GtkWidgetClass *widget_class; 00752 GtkContainerClass *container_class; 00753 GObjectClass *gobject_class = G_OBJECT_CLASS (klass); 00754 00755 object_class = (GtkObjectClass *) klass; 00756 widget_class = (GtkWidgetClass *) klass; 00757 container_class = (GtkContainerClass *) klass; 00758 00759 parent_class = g_type_class_peek_parent (klass); 00760 00761 sheet_signals[SELECT_ROW] = 00762 gtk_signal_new ("select_row", 00763 GTK_RUN_LAST, 00764 GTK_CLASS_TYPE(object_class), 00765 GTK_SIGNAL_OFFSET (GtkSheetClass, select_row), 00766 gtkextra_VOID__INT, 00767 GTK_TYPE_NONE, 1, GTK_TYPE_INT); 00768 00769 sheet_signals[SELECT_COLUMN] = 00770 gtk_signal_new ("select_column", 00771 GTK_RUN_LAST, 00772 GTK_CLASS_TYPE(object_class), 00773 GTK_SIGNAL_OFFSET (GtkSheetClass, select_column), 00774 gtkextra_VOID__INT, 00775 GTK_TYPE_NONE, 1, GTK_TYPE_INT); 00776 00777 sheet_signals[SELECT_RANGE] = 00778 gtk_signal_new ("select_range", 00779 GTK_RUN_LAST, 00780 GTK_CLASS_TYPE(object_class), 00781 GTK_SIGNAL_OFFSET (GtkSheetClass, select_range), 00782 gtkextra_VOID__BOXED, 00783 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE); 00784 00785 sheet_signals[CLIP_RANGE] = 00786 gtk_signal_new ("clip_range", 00787 GTK_RUN_LAST, 00788 GTK_CLASS_TYPE(object_class), 00789 GTK_SIGNAL_OFFSET (GtkSheetClass, clip_range), 00790 gtkextra_VOID__BOXED, 00791 GTK_TYPE_NONE, 1, GTK_TYPE_SHEET_RANGE); 00792 00793 sheet_signals[RESIZE_RANGE] = 00794 gtk_signal_new ("resize_range", 00795 GTK_RUN_LAST, 00796 GTK_CLASS_TYPE(object_class), 00797 GTK_SIGNAL_OFFSET (GtkSheetClass, resize_range), 00798 gtkextra_VOID__BOXED_BOXED, 00799 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE); 00800 sheet_signals[MOVE_RANGE] = 00801 gtk_signal_new ("move_range", 00802 GTK_RUN_LAST, 00803 GTK_CLASS_TYPE(object_class), 00804 GTK_SIGNAL_OFFSET (GtkSheetClass, move_range), 00805 gtkextra_VOID__BOXED_BOXED, 00806 GTK_TYPE_NONE, 2, GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE); 00807 sheet_signals[TRAVERSE] = 00808 gtk_signal_new ("traverse", 00809 GTK_RUN_LAST, 00810 GTK_CLASS_TYPE(object_class), 00811 GTK_SIGNAL_OFFSET (GtkSheetClass, traverse), 00812 gtkextra_BOOLEAN__INT_INT_POINTER_POINTER, 00813 GTK_TYPE_BOOL, 4, GTK_TYPE_INT, GTK_TYPE_INT, 00814 GTK_TYPE_POINTER, GTK_TYPE_POINTER); 00815 00816 sheet_signals[DEACTIVATE] = 00817 gtk_signal_new ("deactivate", 00818 GTK_RUN_LAST, 00819 GTK_CLASS_TYPE(object_class), 00820 GTK_SIGNAL_OFFSET (GtkSheetClass, deactivate), 00821 gtkextra_BOOLEAN__INT_INT, 00822 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT); 00823 00824 sheet_signals[ACTIVATE] = 00825 gtk_signal_new ("activate", 00826 GTK_RUN_LAST, 00827 GTK_CLASS_TYPE(object_class), 00828 GTK_SIGNAL_OFFSET (GtkSheetClass, activate), 00829 gtkextra_BOOLEAN__INT_INT, 00830 GTK_TYPE_BOOL, 2, GTK_TYPE_INT, GTK_TYPE_INT); 00831 00832 sheet_signals[SET_CELL] = 00833 gtk_signal_new ("set_cell", 00834 GTK_RUN_LAST, 00835 GTK_CLASS_TYPE(object_class), 00836 GTK_SIGNAL_OFFSET (GtkSheetClass, set_cell), 00837 gtkextra_VOID__INT_INT, 00838 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); 00839 00840 sheet_signals[CLEAR_CELL] = 00841 gtk_signal_new ("clear_cell", 00842 GTK_RUN_LAST, 00843 GTK_CLASS_TYPE(object_class), 00844 GTK_SIGNAL_OFFSET (GtkSheetClass, clear_cell), 00845 gtkextra_VOID__INT_INT, 00846 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); 00847 00848 sheet_signals[CHANGED] = 00849 gtk_signal_new ("changed", 00850 GTK_RUN_LAST, 00851 GTK_CLASS_TYPE(object_class), 00852 GTK_SIGNAL_OFFSET (GtkSheetClass, changed), 00853 gtkextra_VOID__INT_INT, 00854 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); 00855 00856 sheet_signals[NEW_COL_WIDTH] = 00857 gtk_signal_new ("new_column_width", 00858 GTK_RUN_LAST, 00859 GTK_CLASS_TYPE(object_class), 00860 GTK_SIGNAL_OFFSET (GtkSheetClass, changed), 00861 gtkextra_VOID__INT_INT, 00862 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); 00863 00864 sheet_signals[NEW_ROW_HEIGHT] = 00865 gtk_signal_new ("new_row_height", 00866 GTK_RUN_LAST, 00867 GTK_CLASS_TYPE(object_class), 00868 GTK_SIGNAL_OFFSET (GtkSheetClass, changed), 00869 gtkextra_VOID__INT_INT, 00870 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); 00871 00872 00873 00874 widget_class->set_scroll_adjustments_signal = 00875 gtk_signal_new ("set_scroll_adjustments", 00876 GTK_RUN_LAST, 00877 GTK_CLASS_TYPE(object_class), 00878 GTK_SIGNAL_OFFSET (GtkSheetClass, set_scroll_adjustments), 00879 gtkextra_VOID__OBJECT_OBJECT, 00880 GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); 00881 00882 00883 container_class->add = NULL; 00884 container_class->remove = gtk_sheet_remove; 00885 container_class->forall = gtk_sheet_forall; 00886 00887 object_class->destroy = gtk_sheet_destroy; 00888 gobject_class->finalize = gtk_sheet_finalize; 00889 00890 widget_class->realize = gtk_sheet_realize; 00891 widget_class->unrealize = gtk_sheet_unrealize; 00892 widget_class->map = gtk_sheet_map; 00893 widget_class->unmap = gtk_sheet_unmap; 00894 widget_class->style_set = gtk_sheet_style_set; 00895 widget_class->button_press_event = gtk_sheet_button_press; 00896 widget_class->button_release_event = gtk_sheet_button_release; 00897 widget_class->motion_notify_event = gtk_sheet_motion; 00898 widget_class->key_press_event = gtk_sheet_key_press; 00899 widget_class->expose_event = gtk_sheet_expose; 00900 widget_class->size_request = gtk_sheet_size_request; 00901 widget_class->size_allocate = gtk_sheet_size_allocate; 00902 widget_class->focus_in_event = NULL; 00903 widget_class->focus_out_event = NULL; 00904 00905 klass->set_scroll_adjustments = gtk_sheet_set_scroll_adjustments; 00906 klass->select_row = NULL; 00907 klass->select_column = NULL; 00908 klass->select_range = NULL; 00909 klass->clip_range = NULL; 00910 klass->resize_range = NULL; 00911 klass->move_range = NULL; 00912 klass->traverse = NULL; 00913 klass->deactivate = NULL; 00914 klass->activate = NULL; 00915 klass->set_cell = NULL; 00916 klass->clear_cell = NULL; 00917 klass->changed = NULL; 00918 00919 gtk_widget_class_install_style_property (widget_class, 00920 g_param_spec_boxed ("default-border", 00921 NULL, /* P_("Default Spacing"),*/ 00922 NULL, /* P_("Extra space to add for CAN_DEFAULT buttons"), */ 00923 GTK_TYPE_BORDER, 00924 G_PARAM_READABLE)); 00925 00926 gtk_widget_class_install_style_property (widget_class, 00927 g_param_spec_boxed ("default-outside-border", 00928 NULL, /* P_("Default Outside Spacing"), */ 00929 NULL, /* P_("Extra space to add for CAN_DEFAULT buttons that is always drawn outside the border"), */ 00930 GTK_TYPE_BORDER, 00931 G_PARAM_READABLE)); 00932 } 00933 00934 static void 00935 gtk_sheet_init (GtkSheet *sheet) 00936 { 00937 sheet->children = NULL; 00938 00939 sheet->flags = 0; 00940 sheet->selection_mode = GTK_SELECTION_BROWSE; 00941 sheet->freeze_count = 0; 00942 sheet->state = GTK_SHEET_NORMAL; 00943 00944 GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW); 00945 GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS); 00946 00947 sheet->maxrow = 0; 00948 sheet->maxcol = 0; 00949 00950 sheet->view.row0 = 0; 00951 sheet->view.col0 = 0; 00952 sheet->view.rowi = 0; 00953 sheet->view.coli = 0; 00954 00955 sheet->maxallocrow = 0; 00956 sheet->maxalloccol = 0; 00957 00958 sheet->column_title_window=NULL; 00959 sheet->column_title_area.x=0; 00960 sheet->column_title_area.y=0; 00961 sheet->column_title_area.width=0; 00962 sheet->column_title_area.height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)); 00963 00964 sheet->row_title_window=NULL; 00965 sheet->row_title_area.x=0; 00966 sheet->row_title_area.y=0; 00967 sheet->row_title_area.width=DEFAULT_COLUMN_WIDTH; 00968 sheet->row_title_area.height=0; 00969 00970 sheet->active_cell.row=0; 00971 sheet->active_cell.col=0; 00972 sheet->selection_cell.row=0; 00973 sheet->selection_cell.col=0; 00974 00975 sheet->sheet_entry=NULL; 00976 sheet->pixmap=NULL; 00977 00978 sheet->range.row0=0; 00979 sheet->range.rowi=0; 00980 sheet->range.col0=0; 00981 sheet->range.coli=0; 00982 00983 sheet->state=GTK_SHEET_NORMAL; 00984 00985 sheet->sheet_window = NULL; 00986 sheet->sheet_window_width = 0; 00987 sheet->sheet_window_height = 0; 00988 sheet->sheet_entry = NULL; 00989 sheet->button = NULL; 00990 00991 sheet->hoffset = 0; 00992 sheet->voffset = 0; 00993 00994 sheet->hadjustment = NULL; 00995 sheet->vadjustment = NULL; 00996 00997 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS); 00998 sheet->xor_gc = NULL; 00999 sheet->fg_gc = NULL; 01000 sheet->bg_gc = NULL; 01001 sheet->x_drag = 0; 01002 sheet->y_drag = 0; 01003 01004 gdk_color_white(gdk_colormap_get_system(), &sheet->bg_color); 01005 gdk_color_parse("gray", &sheet->grid_color); 01006 gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color); 01007 sheet->show_grid = TRUE; 01008 } 01009 01010 GtkWidget * 01011 gtk_sheet_new (guint rows, guint columns, const gchar *title) 01012 { 01013 GtkWidget *widget; 01014 01015 /* sanity check */ 01016 g_return_val_if_fail (columns >= MINCOLS, NULL); 01017 g_return_val_if_fail (rows >= MINROWS, NULL); 01018 01019 widget = gtk_type_new (gtk_sheet_get_type ()); 01020 01021 gtk_sheet_construct(GTK_SHEET(widget), rows, columns, title); 01022 01023 return widget; 01024 } 01025 01026 void 01027 gtk_sheet_construct (GtkSheet *sheet, guint rows, guint columns, const gchar *title) 01028 { 01029 sheet->row=(GtkSheetRow *)g_malloc(sizeof(GtkSheetRow)); 01030 sheet->column=(GtkSheetColumn *)g_malloc(sizeof(GtkSheetColumn)); 01031 sheet->data=(GtkSheetCell ***)g_malloc(sizeof(GtkSheetCell **)); 01032 01033 sheet->data[0] = (GtkSheetCell **)g_malloc(sizeof(GtkSheetCell *)+sizeof(gdouble)); 01034 sheet->data[0][0] = NULL; 01035 01036 sheet->columns_resizable = TRUE; 01037 sheet->rows_resizable = TRUE; 01038 sheet->row_titles_visible = TRUE; 01039 sheet->column_titles_visible = TRUE; 01040 sheet->autoscroll = TRUE; 01041 sheet->justify_entry = TRUE; 01042 sheet->locked = FALSE; 01043 01044 /* set number of rows and columns */ 01045 GrowSheet(sheet, MINROWS, MINCOLS); 01046 01047 /* Init row an column zero */ 01048 AddRow(sheet,-1); 01049 AddColumn(sheet,-1); 01050 01051 /* Add rows and columns */ 01052 AddRow(sheet,rows-1); 01053 AddColumn(sheet,columns-1); 01054 01055 /* create sheet entry */ 01056 sheet->entry_type = 0; 01057 create_sheet_entry (sheet); 01058 01059 /* create global selection button */ 01060 create_global_button(sheet); 01061 01062 if(title) 01063 sheet->name = g_strdup(title); 01064 01065 } 01066 01067 01068 GtkWidget * 01069 gtk_sheet_new_browser(guint rows, guint columns, const gchar *title) 01070 { 01071 GtkWidget *widget; 01072 01073 widget = gtk_type_new (gtk_sheet_get_type ()); 01074 01075 gtk_sheet_construct_browser(GTK_SHEET(widget), rows, columns, title); 01076 01077 return widget; 01078 } 01079 01080 void 01081 gtk_sheet_construct_browser(GtkSheet *sheet, guint rows, guint columns, 01082 const gchar *title) 01083 { 01084 gtk_sheet_construct(sheet, rows, columns, title); 01085 01086 gtk_sheet_set_locked(sheet, TRUE); 01087 sheet->autoresize = TRUE; 01088 } 01089 01090 GtkWidget * 01091 gtk_sheet_new_with_custom_entry (guint rows, guint columns, const gchar *title, 01092 GtkType entry_type) 01093 { 01094 GtkWidget *widget; 01095 01096 widget = gtk_type_new (gtk_sheet_get_type ()); 01097 01098 gtk_sheet_construct_with_custom_entry(GTK_SHEET(widget), 01099 rows, columns, title, entry_type); 01100 01101 return widget; 01102 } 01103 01104 void 01105 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet, 01106 guint rows, guint columns, 01107 const gchar *title, 01108 GtkType entry_type) 01109 { 01110 gtk_sheet_construct(sheet, rows, columns, title); 01111 01112 sheet->entry_type = entry_type; 01113 create_sheet_entry(sheet); 01114 } 01115 01116 01117 void 01118 gtk_sheet_change_entry(GtkSheet *sheet, GtkType entry_type) 01119 { 01120 gint state; 01121 01122 g_return_if_fail (sheet != NULL); 01123 g_return_if_fail (GTK_IS_SHEET (sheet)); 01124 01125 state = sheet->state; 01126 01127 if(sheet->state == GTK_SHEET_NORMAL) 01128 gtk_sheet_hide_active_cell(sheet); 01129 01130 sheet->entry_type = entry_type; 01131 01132 create_sheet_entry(sheet); 01133 01134 if(state == GTK_SHEET_NORMAL) 01135 { 01136 gtk_sheet_show_active_cell(sheet); 01137 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)), 01138 "changed", 01139 (GtkSignalFunc)gtk_sheet_entry_changed, 01140 GTK_OBJECT(GTK_WIDGET(sheet))); 01141 } 01142 01143 } 01144 01145 void 01146 gtk_sheet_show_grid(GtkSheet *sheet, gboolean show) 01147 { 01148 g_return_if_fail (sheet != NULL); 01149 g_return_if_fail (GTK_IS_SHEET (sheet)); 01150 01151 if(show == sheet->show_grid) return; 01152 01153 sheet->show_grid = show; 01154 01155 if(!GTK_SHEET_IS_FROZEN(sheet)) 01156 gtk_sheet_range_draw(sheet, NULL); 01157 } 01158 01159 gboolean 01160 gtk_sheet_grid_visible(GtkSheet *sheet) 01161 { 01162 g_return_val_if_fail (sheet != NULL, 0); 01163 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0); 01164 01165 return sheet->show_grid; 01166 } 01167 01168 void 01169 gtk_sheet_set_background(GtkSheet *sheet, GdkColor *color) 01170 { 01171 g_return_if_fail (sheet != NULL); 01172 g_return_if_fail (GTK_IS_SHEET (sheet)); 01173 01174 if(!color) 01175 gdk_color_white(gdk_colormap_get_system(), &sheet->bg_color); 01176 else 01177 sheet->bg_color = *color; 01178 01179 if(!GTK_SHEET_IS_FROZEN(sheet)) 01180 gtk_sheet_range_draw(sheet, NULL); 01181 } 01182 01183 void 01184 gtk_sheet_set_grid(GtkSheet *sheet, GdkColor *color) 01185 { 01186 g_return_if_fail (sheet != NULL); 01187 g_return_if_fail (GTK_IS_SHEET (sheet)); 01188 01189 if(!color) 01190 gdk_color_black(gdk_colormap_get_system(), &sheet->grid_color); 01191 else 01192 sheet->grid_color = *color; 01193 01194 if(!GTK_SHEET_IS_FROZEN(sheet)) 01195 gtk_sheet_range_draw(sheet, NULL); 01196 } 01197 01198 guint 01199 gtk_sheet_get_columns_count(GtkSheet *sheet) 01200 { 01201 g_return_val_if_fail (sheet != NULL, 0); 01202 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0); 01203 01204 return sheet->maxcol + 1; 01205 } 01206 01207 guint 01208 gtk_sheet_get_rows_count(GtkSheet *sheet) 01209 { 01210 g_return_val_if_fail (sheet != NULL, 0); 01211 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0); 01212 01213 return sheet->maxrow + 1; 01214 } 01215 01216 gint 01217 gtk_sheet_get_state(GtkSheet *sheet) 01218 { 01219 g_return_val_if_fail (sheet != NULL, 0); 01220 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0); 01221 01222 return (sheet->state); 01223 } 01224 01225 void 01226 gtk_sheet_set_selection_mode(GtkSheet *sheet, gint mode) 01227 { 01228 g_return_if_fail (sheet != NULL); 01229 g_return_if_fail (GTK_IS_SHEET (sheet)); 01230 01231 if(GTK_WIDGET_REALIZED(sheet)) 01232 gtk_sheet_real_unselect_range(sheet, NULL); 01233 01234 sheet->selection_mode = mode; 01235 } 01236 01237 void 01238 gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize) 01239 { 01240 g_return_if_fail (sheet != NULL); 01241 g_return_if_fail (GTK_IS_SHEET (sheet)); 01242 01243 sheet->autoresize = autoresize; 01244 } 01245 01246 gboolean 01247 gtk_sheet_autoresize (GtkSheet *sheet) 01248 { 01249 g_return_val_if_fail (sheet != NULL, FALSE); 01250 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 01251 01252 return sheet->autoresize; 01253 } 01254 01255 void 01256 gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll) 01257 { 01258 g_return_if_fail (sheet != NULL); 01259 g_return_if_fail (GTK_IS_SHEET (sheet)); 01260 01261 sheet->autoscroll = autoscroll; 01262 } 01263 01264 gboolean 01265 gtk_sheet_autoscroll (GtkSheet *sheet) 01266 { 01267 g_return_val_if_fail (sheet != NULL, FALSE); 01268 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 01269 01270 return sheet->autoscroll; 01271 } 01272 01273 void 01274 gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text) 01275 { 01276 g_return_if_fail (sheet != NULL); 01277 g_return_if_fail (GTK_IS_SHEET (sheet)); 01278 01279 sheet->clip_text = clip_text; 01280 } 01281 01282 gboolean 01283 gtk_sheet_clip_text (GtkSheet *sheet) 01284 { 01285 g_return_val_if_fail (sheet != NULL, FALSE); 01286 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 01287 01288 return sheet->clip_text; 01289 } 01290 01291 void 01292 gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify) 01293 { 01294 g_return_if_fail (sheet != NULL); 01295 g_return_if_fail (GTK_IS_SHEET (sheet)); 01296 01297 sheet->justify_entry = justify; 01298 } 01299 01300 gboolean 01301 gtk_sheet_justify_entry (GtkSheet *sheet) 01302 { 01303 g_return_val_if_fail (sheet != NULL, FALSE); 01304 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 01305 01306 return sheet->justify_entry; 01307 } 01308 01309 void 01310 gtk_sheet_set_locked (GtkSheet *sheet, gboolean locked) 01311 { 01312 g_return_if_fail (sheet != NULL); 01313 g_return_if_fail (GTK_IS_SHEET (sheet)); 01314 01315 sheet->locked = locked; 01316 } 01317 01318 gboolean 01319 gtk_sheet_locked (GtkSheet *sheet) 01320 { 01321 g_return_val_if_fail (sheet != NULL, FALSE); 01322 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 01323 01324 return sheet->locked; 01325 } 01326 01327 /* This routine has problems with gtk+-1.2 related with the 01328 * label/button drawing - I think it's a bug in gtk+-1.2 */ 01329 01330 void 01331 gtk_sheet_set_title(GtkSheet *sheet, const gchar *title) 01332 { 01333 /* GtkWidget *old_widget; 01334 */ GtkWidget *label; 01335 01336 g_return_if_fail (sheet != NULL); 01337 g_return_if_fail (title != NULL); 01338 g_return_if_fail (GTK_IS_SHEET (sheet)); 01339 01340 if (sheet->name) 01341 g_free (sheet->name); 01342 01343 sheet->name = g_strdup (title); 01344 01345 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) || !title) return; 01346 01347 if(GTK_BIN(sheet->button)->child) 01348 label = GTK_BIN(sheet->button)->child; 01349 /* 01350 gtk_label_set_text(GTK_LABEL(label), title); 01351 */ 01352 size_allocate_global_button(sheet); 01353 01354 /* remove and destroy the old widget */ 01355 /* 01356 old_widget = GTK_BIN (sheet->button)->child; 01357 if (old_widget) 01358 { 01359 gtk_container_remove (GTK_CONTAINER (sheet->button), old_widget); 01360 } 01361 01362 label = gtk_label_new (title); 01363 gtk_misc_set_alignment(GTK_MISC(label), 0.5 , 0.5 ); 01364 01365 gtk_container_add (GTK_CONTAINER (sheet->button), label); 01366 gtk_widget_show (label); 01367 01368 size_allocate_global_button(sheet); 01369 01370 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, -1); 01371 01372 if(old_widget) 01373 gtk_widget_destroy (old_widget); 01374 */ 01375 } 01376 01377 void 01378 gtk_sheet_freeze (GtkSheet *sheet) 01379 { 01380 g_return_if_fail (sheet != NULL); 01381 g_return_if_fail (GTK_IS_SHEET (sheet)); 01382 01383 sheet->freeze_count++; 01384 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN); 01385 } 01386 01387 void 01388 gtk_sheet_thaw(GtkSheet *sheet) 01389 { 01390 g_return_if_fail (sheet != NULL); 01391 g_return_if_fail (GTK_IS_SHEET (sheet)); 01392 01393 if(sheet->freeze_count == 0) return; 01394 01395 sheet->freeze_count--; 01396 if(sheet->freeze_count > 0) return; 01397 01398 adjust_scrollbars(sheet); 01399 01400 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN); 01401 01402 sheet->old_vadjustment = -1.; 01403 sheet->old_hadjustment = -1.; 01404 01405 if(sheet->hadjustment) 01406 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 01407 "value_changed"); 01408 if(sheet->vadjustment) 01409 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 01410 "value_changed"); 01411 01412 if(sheet->state == GTK_STATE_NORMAL) 01413 if(sheet->sheet_entry && GTK_WIDGET_MAPPED(sheet->sheet_entry)){ 01414 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col); 01415 /* 01416 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)), 01417 "changed", 01418 (GtkSignalFunc)gtk_sheet_entry_changed, 01419 GTK_OBJECT(GTK_WIDGET(sheet))); 01420 gtk_sheet_show_active_cell(sheet); 01421 */ 01422 } 01423 01424 } 01425 01426 void 01427 gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width) 01428 { 01429 if(width < COLUMN_MIN_WIDTH) return; 01430 01431 sheet->row_title_area.width = width; 01432 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1); 01433 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width); 01434 gtk_sheet_recalc_top_ypixels(sheet, 0); 01435 gtk_sheet_recalc_left_xpixels(sheet, 0); 01436 adjust_scrollbars(sheet); 01437 01438 sheet->old_hadjustment = -1.; 01439 if(sheet->hadjustment) 01440 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 01441 "value_changed"); 01442 size_allocate_global_button(sheet); 01443 } 01444 01445 void 01446 gtk_sheet_set_column_titles_height(GtkSheet *sheet, guint height) 01447 { 01448 if(height < DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))) return; 01449 01450 sheet->column_title_area.height = height; 01451 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1); 01452 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1); 01453 gtk_sheet_recalc_top_ypixels(sheet, 0); 01454 gtk_sheet_recalc_left_xpixels(sheet, 0); 01455 adjust_scrollbars(sheet); 01456 01457 sheet->old_vadjustment = -1.; 01458 if(sheet->vadjustment) 01459 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 01460 "value_changed"); 01461 size_allocate_global_button(sheet); 01462 } 01463 01464 void 01465 gtk_sheet_show_column_titles(GtkSheet *sheet) 01466 { 01467 gint col; 01468 01469 if(sheet->column_titles_visible) return; 01470 01471 sheet->column_titles_visible = TRUE; 01472 gtk_sheet_recalc_top_ypixels(sheet, 0); 01473 gtk_sheet_recalc_left_xpixels(sheet, 0); 01474 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){ 01475 gdk_window_show(sheet->column_title_window); 01476 gdk_window_move_resize (sheet->column_title_window, 01477 sheet->column_title_area.x, 01478 sheet->column_title_area.y, 01479 sheet->column_title_area.width, 01480 sheet->column_title_area.height); 01481 01482 for(col = MIN_VISIBLE_COLUMN(sheet); col <= MAX_VISIBLE_COLUMN(sheet); col++){ 01483 GtkSheetChild *child; 01484 child = sheet->column[col].button.child; 01485 if(child){ 01486 gtk_sheet_child_show(child); 01487 } 01488 } 01489 adjust_scrollbars(sheet); 01490 } 01491 01492 sheet->old_vadjustment = -1.; 01493 if(sheet->vadjustment) 01494 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 01495 "value_changed"); 01496 size_allocate_global_button(sheet); 01497 } 01498 01499 void 01500 gtk_sheet_show_row_titles(GtkSheet *sheet) 01501 { 01502 gint row; 01503 01504 if(sheet->row_titles_visible) return; 01505 01506 sheet->row_titles_visible = TRUE; 01507 gtk_sheet_recalc_top_ypixels(sheet, 0); 01508 gtk_sheet_recalc_left_xpixels(sheet, 0); 01509 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){ 01510 gdk_window_show(sheet->row_title_window); 01511 gdk_window_move_resize (sheet->row_title_window, 01512 sheet->row_title_area.x, 01513 sheet->row_title_area.y, 01514 sheet->row_title_area.width, 01515 sheet->row_title_area.height); 01516 01517 for(row = MIN_VISIBLE_ROW(sheet); row <= MAX_VISIBLE_ROW(sheet); row++){ 01518 GtkSheetChild *child; 01519 child = sheet->row[row].button.child; 01520 if(child){ 01521 gtk_sheet_child_show(child); 01522 } 01523 } 01524 adjust_scrollbars(sheet); 01525 } 01526 01527 sheet->old_hadjustment = -1.; 01528 if(sheet->hadjustment) 01529 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 01530 "value_changed"); 01531 size_allocate_global_button(sheet); 01532 } 01533 01534 void 01535 gtk_sheet_hide_column_titles(GtkSheet *sheet) 01536 { 01537 gint col; 01538 01539 if(!sheet->column_titles_visible) return; 01540 01541 sheet->column_titles_visible = FALSE; 01542 gtk_sheet_recalc_top_ypixels(sheet, 0); 01543 gtk_sheet_recalc_left_xpixels(sheet, 0); 01544 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){ 01545 if(sheet->column_title_window) 01546 gdk_window_hide(sheet->column_title_window); 01547 if(GTK_WIDGET_VISIBLE(sheet->button)) 01548 gtk_widget_hide(sheet->button); 01549 01550 for(col = MIN_VISIBLE_COLUMN(sheet); col <= MAX_VISIBLE_COLUMN(sheet); col++){ 01551 GtkSheetChild *child; 01552 child = sheet->column[col].button.child; 01553 if(child){ 01554 gtk_sheet_child_hide(child); 01555 } 01556 } 01557 adjust_scrollbars(sheet); 01558 } 01559 01560 sheet->old_vadjustment = -1.; 01561 if(sheet->vadjustment) 01562 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 01563 "value_changed"); 01564 } 01565 01566 void 01567 gtk_sheet_hide_row_titles(GtkSheet *sheet) 01568 { 01569 gint row; 01570 01571 if(!sheet->row_titles_visible) return; 01572 01573 sheet->row_titles_visible = FALSE; 01574 gtk_sheet_recalc_top_ypixels(sheet, 0); 01575 gtk_sheet_recalc_left_xpixels(sheet, 0); 01576 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){ 01577 if(sheet->row_title_window) 01578 gdk_window_hide(sheet->row_title_window); 01579 if(GTK_WIDGET_VISIBLE(sheet->button)) 01580 gtk_widget_hide(sheet->button); 01581 for(row = MIN_VISIBLE_ROW(sheet); row <= MAX_VISIBLE_ROW(sheet); row++){ 01582 GtkSheetChild *child; 01583 child = sheet->row[row].button.child; 01584 if(child){ 01585 gtk_sheet_child_hide(child); 01586 } 01587 } 01588 adjust_scrollbars(sheet); 01589 } 01590 01591 sheet->old_hadjustment = -1.; 01592 if(sheet->hadjustment) 01593 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 01594 "value_changed"); 01595 } 01596 01597 gboolean 01598 gtk_sheet_column_titles_visible(GtkSheet *sheet) 01599 { 01600 g_return_val_if_fail (sheet != NULL, FALSE); 01601 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 01602 return sheet->column_titles_visible; 01603 } 01604 01605 gboolean 01606 gtk_sheet_row_titles_visible(GtkSheet *sheet) 01607 { 01608 g_return_val_if_fail (sheet != NULL, FALSE); 01609 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 01610 return sheet->row_titles_visible; 01611 } 01612 01613 void 01614 gtk_sheet_set_column_title (GtkSheet * sheet, 01615 gint column, 01616 const gchar * title) 01617 { 01618 g_return_if_fail (sheet != NULL); 01619 g_return_if_fail (GTK_IS_SHEET (sheet)); 01620 01621 if (sheet->column[column].name) 01622 g_free (sheet->column[column].name); 01623 01624 sheet->column[column].name = g_strdup(title); 01625 } 01626 01627 void 01628 gtk_sheet_set_row_title (GtkSheet * sheet, 01629 gint row, 01630 const gchar * title) 01631 { 01632 g_return_if_fail (sheet != NULL); 01633 g_return_if_fail (GTK_IS_SHEET (sheet)); 01634 01635 if (sheet->row[row].name) 01636 g_free (sheet->row[row].name); 01637 01638 sheet->row[row].name = g_strdup (title); 01639 } 01640 01641 const gchar * 01642 gtk_sheet_get_row_title (GtkSheet * sheet, 01643 gint row) 01644 { 01645 g_return_val_if_fail (sheet != NULL, NULL); 01646 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL); 01647 01648 return(sheet->row[row].name); 01649 } 01650 01651 const gchar * 01652 gtk_sheet_get_column_title (GtkSheet * sheet, 01653 gint column) 01654 { 01655 g_return_val_if_fail (sheet != NULL, NULL); 01656 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL); 01657 01658 return(sheet->column[column].name); 01659 } 01660 01661 void 01662 gtk_sheet_row_button_add_label(GtkSheet *sheet, gint row, const gchar *label) 01663 { 01664 GtkSheetButton *button; 01665 GtkRequisition req; 01666 gboolean aux; 01667 01668 g_return_if_fail (sheet != NULL); 01669 g_return_if_fail (GTK_IS_SHEET (sheet)); 01670 01671 if(row < 0 || row > sheet->maxrow) return; 01672 01673 button = &sheet->row[row].button; 01674 if (button->label) g_free (button->label); 01675 button->label = g_strdup (label); 01676 01677 aux = gtk_sheet_autoresize(sheet); 01678 gtk_sheet_set_autoresize(sheet, TRUE); 01679 gtk_sheet_button_size_request(sheet, button, &req); 01680 gtk_sheet_set_autoresize(sheet, aux); 01681 01682 if(req.height > sheet->row[row].height) 01683 gtk_sheet_set_row_height(sheet, row, req.height); 01684 01685 if(req.width > sheet->row_title_area.width){ 01686 gtk_sheet_set_row_titles_width(sheet, req.width); 01687 } 01688 01689 if(!GTK_SHEET_IS_FROZEN(sheet)){ 01690 gtk_sheet_button_draw(sheet, row, -1); 01691 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, -1); 01692 } 01693 } 01694 01695 const gchar * 01696 gtk_sheet_row_button_get_label(GtkSheet *sheet, gint row) 01697 { 01698 g_return_val_if_fail (sheet != NULL, NULL); 01699 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL); 01700 01701 if(row < 0 || row > sheet->maxrow) return NULL; 01702 01703 return (sheet->row[row].button.label); 01704 } 01705 01706 void 01707 gtk_sheet_row_label_set_visibility(GtkSheet *sheet, gint row, gboolean visible) 01708 { 01709 g_return_if_fail (sheet != NULL); 01710 g_return_if_fail (GTK_IS_SHEET (sheet)); 01711 01712 if(row < 0 || row > sheet->maxrow) return; 01713 01714 sheet->row[row].button.label_visible = visible; 01715 01716 if(!GTK_SHEET_IS_FROZEN(sheet)){ 01717 gtk_sheet_button_draw(sheet, row, -1); 01718 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, -1); 01719 } 01720 } 01721 01722 void 01723 gtk_sheet_rows_labels_set_visibility(GtkSheet *sheet, gboolean visible) 01724 { 01725 gint i; 01726 01727 g_return_if_fail (sheet != NULL); 01728 g_return_if_fail (GTK_IS_SHEET (sheet)); 01729 01730 for(i = 0; i <= sheet->maxrow; i++) 01731 gtk_sheet_row_label_set_visibility(sheet, i, visible); 01732 } 01733 01734 01735 void 01736 gtk_sheet_column_button_add_label(GtkSheet *sheet, gint column, const gchar *label) 01737 { 01738 GtkSheetButton *button; 01739 GtkRequisition req; 01740 gboolean aux; 01741 01742 g_return_if_fail (sheet != NULL); 01743 g_return_if_fail (GTK_IS_SHEET (sheet)); 01744 01745 if(column < 0 || column >sheet->maxcol) return; 01746 01747 button = &sheet->column[column].button; 01748 if (button->label) g_free (button->label); 01749 button->label = g_strdup (label); 01750 01751 aux = gtk_sheet_autoresize(sheet); 01752 gtk_sheet_set_autoresize(sheet, TRUE); 01753 gtk_sheet_button_size_request(sheet, button, &req); 01754 gtk_sheet_set_autoresize(sheet, aux); 01755 01756 if(req.width > sheet->column[column].width) 01757 gtk_sheet_set_column_width(sheet, column, req.width); 01758 01759 if(req.height > sheet->column_title_area.height) 01760 gtk_sheet_set_column_titles_height(sheet, req.height); 01761 01762 if(!GTK_SHEET_IS_FROZEN(sheet)){ 01763 gtk_sheet_button_draw(sheet, -1, column); 01764 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, column); 01765 } 01766 } 01767 01768 const gchar * 01769 gtk_sheet_column_button_get_label(GtkSheet *sheet, gint column) 01770 { 01771 g_return_val_if_fail (sheet != NULL, NULL); 01772 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL); 01773 01774 if(column < 0 || column >sheet->maxcol) return NULL; 01775 01776 return(sheet->column[column].button.label); 01777 } 01778 01779 void 01780 gtk_sheet_column_label_set_visibility(GtkSheet *sheet, gint col, gboolean visible) 01781 { 01782 g_return_if_fail (sheet != NULL); 01783 g_return_if_fail (GTK_IS_SHEET (sheet)); 01784 01785 if(col < 0 || col > sheet->maxcol) return; 01786 01787 sheet->column[col].button.label_visible = visible; 01788 01789 if(!GTK_SHEET_IS_FROZEN(sheet)){ 01790 gtk_sheet_button_draw(sheet, -1, col); 01791 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, col); 01792 } 01793 } 01794 01795 void 01796 gtk_sheet_columns_labels_set_visibility(GtkSheet *sheet, gboolean visible) 01797 { 01798 gint i; 01799 01800 g_return_if_fail (sheet != NULL); 01801 g_return_if_fail (GTK_IS_SHEET (sheet)); 01802 01803 for(i = 0; i <= sheet->maxcol; i++) 01804 gtk_sheet_column_label_set_visibility(sheet, i, visible); 01805 } 01806 01807 void 01808 gtk_sheet_row_button_justify(GtkSheet *sheet, gint row, 01809 GtkJustification justification) 01810 { 01811 GtkSheetButton *button; 01812 01813 g_return_if_fail (sheet != NULL); 01814 g_return_if_fail (GTK_IS_SHEET (sheet)); 01815 01816 if(row < 0 || row > sheet->maxrow) return; 01817 01818 button = &sheet->row[row].button; 01819 button->justification = justification; 01820 01821 if(!GTK_SHEET_IS_FROZEN(sheet)){ 01822 gtk_sheet_button_draw(sheet, row, -1); 01823 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, -1); 01824 } 01825 } 01826 01827 void 01828 gtk_sheet_column_button_justify(GtkSheet *sheet, gint column, 01829 GtkJustification justification) 01830 { 01831 GtkSheetButton *button; 01832 01833 g_return_if_fail (sheet != NULL); 01834 g_return_if_fail (GTK_IS_SHEET (sheet)); 01835 01836 if(column < 0 || column > sheet->maxcol) return; 01837 01838 button = &sheet->column[column].button; 01839 button->justification = justification; 01840 01841 if(!GTK_SHEET_IS_FROZEN(sheet)){ 01842 gtk_sheet_button_draw(sheet, -1, column); 01843 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, column); 01844 } 01845 } 01846 01847 01848 void 01849 gtk_sheet_moveto (GtkSheet * sheet, 01850 gint row, 01851 gint column, 01852 gfloat row_align, 01853 gfloat col_align) 01854 { 01855 gint x, y; 01856 guint width, height; 01857 gint adjust; 01858 gint min_row, min_col; 01859 01860 g_return_if_fail (sheet != NULL); 01861 g_return_if_fail (GTK_IS_SHEET (sheet)); 01862 g_return_if_fail (sheet->hadjustment != NULL); 01863 g_return_if_fail (sheet->vadjustment != NULL); 01864 01865 if (row < 0 || row > sheet->maxrow) 01866 return; 01867 if (column < 0 || column > sheet->maxcol) 01868 return; 01869 01870 height = sheet->sheet_window_height; 01871 width = sheet->sheet_window_width; 01872 01873 /* adjust vertical scrollbar */ 01874 01875 if (row >= 0 && row_align >=0.) 01876 { 01877 y = ROW_TOP_YPIXEL(sheet, row) - sheet->voffset - 01878 row_align*height- 01879 (1.-row_align)*sheet->row[row].height; 01880 01881 /* This forces the sheet to scroll when you don't see the entire cell */ 01882 min_row = row; 01883 adjust = 0; 01884 if(row_align == 1.){ 01885 while(min_row >= 0 && min_row > MIN_VISIBLE_ROW(sheet)){ 01886 if(sheet->row[min_row].is_visible) 01887 adjust += sheet->row[min_row].height; 01888 if(adjust >= height){ 01889 break; 01890 } 01891 min_row--; 01892 } 01893 min_row = MAX(min_row, 0); 01894 y = ROW_TOP_YPIXEL(sheet, min_row) - sheet->voffset + 01895 sheet->row[min_row].height - 1; 01896 } 01897 01898 if (y < 0) 01899 sheet->vadjustment->value = 0.0; 01900 else 01901 sheet->vadjustment->value = y; 01902 01903 sheet->old_vadjustment = -1.; 01904 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 01905 "value_changed"); 01906 01907 } 01908 01909 /* adjust horizontal scrollbar */ 01910 if (column >= 0 && col_align >= 0.) 01911 { 01912 x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset - 01913 col_align*width - 01914 (1.-col_align)*sheet->column[column].width; 01915 01916 /* This forces the sheet to scroll when you don't see the entire cell */ 01917 min_col = column; 01918 adjust = 0; 01919 if(col_align == 1.){ 01920 while(min_col >= 0 && min_col > MIN_VISIBLE_COLUMN(sheet)){ 01921 if(sheet->column[min_col].is_visible) 01922 adjust += sheet->column[min_col].width; 01923 if(adjust >= width){ 01924 break; 01925 } 01926 min_col--; 01927 } 01928 min_col = MAX(min_col, 0); 01929 x = COLUMN_LEFT_XPIXEL(sheet, min_col) - sheet->hoffset + 01930 sheet->column[min_col].width - 1; 01931 } 01932 01933 if (x < 0) 01934 sheet->hadjustment->value = 0.0; 01935 else 01936 sheet->hadjustment->value = x; 01937 01938 sheet->old_vadjustment = -1.; 01939 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 01940 "value_changed"); 01941 01942 } 01943 } 01944 01945 void 01946 gtk_sheet_column_set_sensitivity(GtkSheet *sheet, gint column, gboolean sensitive) 01947 { 01948 g_return_if_fail (sheet != NULL); 01949 g_return_if_fail (GTK_IS_SHEET (sheet)); 01950 01951 if(column < 0 || column > sheet->maxcol) return; 01952 01953 sheet->column[column].is_sensitive=sensitive; 01954 if(!sensitive) 01955 sheet->column[column].button.state=GTK_STATE_INSENSITIVE; 01956 else 01957 sheet->column[column].button.state=GTK_STATE_NORMAL; 01958 01959 if(GTK_WIDGET_REALIZED(sheet) && !GTK_SHEET_IS_FROZEN(sheet)) 01960 gtk_sheet_button_draw(sheet, -1, column); 01961 } 01962 01963 01964 void 01965 gtk_sheet_columns_set_sensitivity(GtkSheet *sheet, gboolean sensitive) 01966 { 01967 gint i; 01968 01969 g_return_if_fail (sheet != NULL); 01970 g_return_if_fail (GTK_IS_SHEET (sheet)); 01971 01972 for(i=0; i<=sheet->maxcol; i++) 01973 gtk_sheet_column_set_sensitivity(sheet, i, sensitive); 01974 } 01975 01976 void 01977 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable) 01978 { 01979 g_return_if_fail (sheet != NULL); 01980 g_return_if_fail (GTK_IS_SHEET (sheet)); 01981 01982 sheet->columns_resizable = resizable; 01983 } 01984 01985 gboolean 01986 gtk_sheet_columns_resizable (GtkSheet *sheet) 01987 { 01988 g_return_val_if_fail (sheet != NULL, FALSE); 01989 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 01990 01991 return sheet->columns_resizable; 01992 } 01993 01994 void 01995 gtk_sheet_row_set_sensitivity(GtkSheet *sheet, gint row, gboolean sensitive) 01996 { 01997 01998 g_return_if_fail (sheet != NULL); 01999 g_return_if_fail (GTK_IS_SHEET (sheet)); 02000 02001 if(row < 0 || row > sheet->maxrow) return; 02002 02003 sheet->row[row].is_sensitive=sensitive; 02004 if(!sensitive) 02005 sheet->row[row].button.state=GTK_STATE_INSENSITIVE; 02006 else 02007 sheet->row[row].button.state=GTK_STATE_NORMAL; 02008 02009 if(GTK_WIDGET_REALIZED(sheet) && !GTK_SHEET_IS_FROZEN(sheet)) 02010 gtk_sheet_button_draw(sheet, row, -1); 02011 } 02012 02013 void 02014 gtk_sheet_rows_set_sensitivity(GtkSheet *sheet, gboolean sensitive) 02015 { 02016 gint i; 02017 02018 g_return_if_fail (sheet != NULL); 02019 g_return_if_fail (GTK_IS_SHEET (sheet)); 02020 02021 for(i=0; i<=sheet->maxrow; i++) 02022 gtk_sheet_row_set_sensitivity(sheet, i, sensitive); 02023 } 02024 02025 02026 void 02027 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable) 02028 { 02029 g_return_if_fail (sheet != NULL); 02030 g_return_if_fail (GTK_IS_SHEET (sheet)); 02031 02032 sheet->rows_resizable = resizable; 02033 } 02034 02035 gboolean 02036 gtk_sheet_rows_resizable (GtkSheet *sheet) 02037 { 02038 g_return_val_if_fail (sheet != NULL, FALSE); 02039 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 02040 02041 return sheet->rows_resizable; 02042 } 02043 02044 void 02045 gtk_sheet_column_set_visibility(GtkSheet *sheet, gint column, gboolean visible) 02046 { 02047 g_return_if_fail (sheet != NULL); 02048 g_return_if_fail (GTK_IS_SHEET (sheet)); 02049 02050 if(column < 0 || column > sheet->maxcol) return; 02051 if(sheet->column[column].is_visible == visible) return; 02052 02053 sheet->column[column].is_visible = visible; 02054 02055 gtk_sheet_recalc_left_xpixels(sheet, column); 02056 02057 if(!GTK_SHEET_IS_FROZEN(sheet) && 02058 gtk_sheet_cell_isvisible(sheet, MIN_VISIBLE_ROW(sheet), column)){ 02059 gtk_sheet_range_draw(sheet, NULL); 02060 size_allocate_column_title_buttons(sheet); 02061 } 02062 } 02063 02064 void 02065 gtk_sheet_row_set_visibility(GtkSheet *sheet, gint row, gboolean visible) 02066 { 02067 g_return_if_fail (sheet != NULL); 02068 g_return_if_fail (GTK_IS_SHEET (sheet)); 02069 02070 if(row < 0 || row > sheet->maxrow) return; 02071 if(sheet->row[row].is_visible == visible) return; 02072 02073 sheet->row[row].is_visible = visible; 02074 02075 gtk_sheet_recalc_top_ypixels(sheet, row); 02076 02077 if(!GTK_SHEET_IS_FROZEN(sheet) && 02078 gtk_sheet_cell_isvisible(sheet, row, MIN_VISIBLE_COLUMN(sheet))){ 02079 gtk_sheet_range_draw(sheet, NULL); 02080 size_allocate_row_title_buttons(sheet); 02081 } 02082 } 02083 02084 void 02085 gtk_sheet_select_row (GtkSheet * sheet, 02086 gint row) 02087 { 02088 g_return_if_fail (sheet != NULL); 02089 g_return_if_fail (GTK_IS_SHEET (sheet)); 02090 02091 if (row < 0 || row > sheet->maxrow) 02092 return; 02093 02094 if(sheet->state != GTK_SHEET_NORMAL) 02095 gtk_sheet_real_unselect_range(sheet, NULL); 02096 else 02097 { 02098 gboolean veto = TRUE; 02099 veto = gtk_sheet_deactivate_cell(sheet); 02100 if(!veto) return; 02101 } 02102 02103 sheet->state=GTK_SHEET_ROW_SELECTED; 02104 sheet->range.row0=row; 02105 sheet->range.col0=0; 02106 sheet->range.rowi=row; 02107 sheet->range.coli=sheet->maxcol; 02108 sheet->active_cell.row=row; 02109 sheet->active_cell.col=0; 02110 02111 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_ROW], row); 02112 gtk_sheet_real_select_range(sheet, NULL); 02113 02114 } 02115 02116 02117 void 02118 gtk_sheet_select_column (GtkSheet * sheet, 02119 gint column) 02120 { 02121 02122 g_return_if_fail (sheet != NULL); 02123 g_return_if_fail (GTK_IS_SHEET (sheet)); 02124 02125 if (column < 0 || column > sheet->maxcol) 02126 return; 02127 02128 if(sheet->state != GTK_SHEET_NORMAL) 02129 gtk_sheet_real_unselect_range(sheet, NULL); 02130 else 02131 { 02132 gboolean veto = TRUE; 02133 veto = gtk_sheet_deactivate_cell(sheet); 02134 if(!veto) return; 02135 } 02136 02137 sheet->state=GTK_SHEET_COLUMN_SELECTED; 02138 sheet->range.row0=0; 02139 sheet->range.col0=column; 02140 sheet->range.rowi=sheet->maxrow; 02141 sheet->range.coli=column; 02142 sheet->active_cell.row=0; 02143 sheet->active_cell.col=column; 02144 02145 gtk_signal_emit (GTK_OBJECT (sheet), sheet_signals[SELECT_COLUMN], column); 02146 gtk_sheet_real_select_range(sheet, NULL); 02147 02148 } 02149 02150 void 02151 gtk_sheet_clip_range (GtkSheet *sheet, const GtkSheetRange *range) 02152 { 02153 02154 g_return_if_fail (sheet != NULL); 02155 g_return_if_fail (GTK_IS_SHEET (sheet)); 02156 02157 if(GTK_SHEET_IN_CLIP(sheet)) return; 02158 02159 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_CLIP); 02160 02161 if(range == NULL) 02162 sheet->clip_range = sheet->range; 02163 else 02164 sheet->clip_range=*range; 02165 02166 sheet->interval=0; 02167 sheet->clip_timer=gtk_timeout_add(TIMEOUT_FLASH, gtk_sheet_flash, sheet); 02168 02169 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CLIP_RANGE], 02170 &sheet->clip_range); 02171 02172 } 02173 02174 void 02175 gtk_sheet_unclip_range(GtkSheet *sheet) 02176 { 02177 02178 g_return_if_fail (sheet != NULL); 02179 g_return_if_fail (GTK_IS_SHEET (sheet)); 02180 02181 if(!GTK_SHEET_IN_CLIP(sheet)) return; 02182 02183 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_CLIP); 02184 gtk_timeout_remove(sheet->clip_timer); 02185 gtk_sheet_range_draw(sheet, &sheet->clip_range); 02186 02187 if(gtk_sheet_range_isvisible(sheet, sheet->range)) 02188 gtk_sheet_range_draw(sheet, &sheet->range); 02189 } 02190 02191 gboolean 02192 gtk_sheet_in_clip (GtkSheet *sheet) 02193 { 02194 g_return_val_if_fail (sheet != NULL, FALSE); 02195 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 02196 02197 return GTK_SHEET_IN_CLIP(sheet); 02198 } 02199 02200 static gint 02201 gtk_sheet_flash(gpointer data) 02202 { 02203 GtkSheet *sheet; 02204 gint x,y,width,height; 02205 GdkRectangle clip_area; 02206 02207 sheet=GTK_SHEET(data); 02208 02209 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return TRUE; 02210 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return TRUE; 02211 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return TRUE; 02212 if(GTK_SHEET_IN_XDRAG(sheet)) return TRUE; 02213 if(GTK_SHEET_IN_YDRAG(sheet)) return TRUE; 02214 02215 GDK_THREADS_ENTER(); 02216 02217 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1; 02218 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1; 02219 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+ 02220 sheet->column[sheet->clip_range.coli].width-1; 02221 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+ 02222 sheet->row[sheet->clip_range.rowi].height-1; 02223 02224 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet)); 02225 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet)); 02226 clip_area.width=sheet->sheet_window_width; 02227 clip_area.height=sheet->sheet_window_height; 02228 02229 if(x<0) { 02230 width=width+x+1; 02231 x=-1; 02232 } 02233 if(width>clip_area.width) width=clip_area.width+10; 02234 if(y<0) { 02235 height=height+y+1; 02236 y=-1; 02237 } 02238 if(height>clip_area.height) height=clip_area.height+10; 02239 02240 gdk_draw_pixmap(sheet->sheet_window, 02241 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 02242 sheet->pixmap, 02243 x, y, 02244 x, y, 02245 1, height); 02246 02247 gdk_draw_pixmap(sheet->sheet_window, 02248 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 02249 sheet->pixmap, 02250 x, y, 02251 x, y, 02252 width, 1); 02253 02254 gdk_draw_pixmap(sheet->sheet_window, 02255 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 02256 sheet->pixmap, 02257 x, y+height, 02258 x, y+height, 02259 width, 1); 02260 02261 gdk_draw_pixmap(sheet->sheet_window, 02262 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 02263 sheet->pixmap, 02264 x+width, y, 02265 x+width, y, 02266 1, height); 02267 02268 02269 sheet->interval=sheet->interval+1; 02270 if(sheet->interval==TIME_INTERVAL) sheet->interval=0; 02271 02272 gdk_gc_set_dashes(sheet->xor_gc, sheet->interval, (gint8*)"\4\4", 2); 02273 gtk_sheet_draw_flashing_range(sheet,sheet->clip_range); 02274 gdk_gc_set_dashes(sheet->xor_gc, 0, (gint8*)"\4\4", 2); 02275 02276 GDK_THREADS_LEAVE(); 02277 02278 return TRUE; 02279 02280 } 02281 02282 static void 02283 gtk_sheet_draw_flashing_range(GtkSheet *sheet, GtkSheetRange range) 02284 { 02285 GdkRectangle clip_area; 02286 gint x,y,width,height; 02287 02288 if(!gtk_sheet_range_isvisible(sheet, sheet->clip_range)) return; 02289 02290 clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet)); 02291 clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet)); 02292 clip_area.width=sheet->sheet_window_width; 02293 clip_area.height=sheet->sheet_window_height; 02294 02295 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area); 02296 02297 x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1; 02298 y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1; 02299 width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+ 02300 sheet->column[sheet->clip_range.coli].width-1; 02301 height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+ 02302 sheet->row[sheet->clip_range.rowi].height-1; 02303 02304 if(x<0) { 02305 width=width+x+1; 02306 x=-1; 02307 } 02308 if(width>clip_area.width) width=clip_area.width+10; 02309 if(y<0) { 02310 height=height+y+1; 02311 y=-1; 02312 } 02313 if(height>clip_area.height) height=clip_area.height+10; 02314 02315 gdk_gc_set_line_attributes(sheet->xor_gc, 1, 1, 0 ,0 ); 02316 02317 gdk_draw_rectangle(sheet->sheet_window, sheet->xor_gc, FALSE, 02318 x, y, 02319 width, height); 02320 02321 gdk_gc_set_line_attributes (sheet->xor_gc, 1, 0, 0, 0); 02322 02323 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL); 02324 02325 } 02326 02327 static gint 02328 gtk_sheet_range_isvisible (GtkSheet * sheet, 02329 GtkSheetRange range) 02330 { 02331 g_return_val_if_fail (sheet != NULL, FALSE); 02332 02333 if (range.row0 < 0 || range.row0 > sheet->maxrow) 02334 return FALSE; 02335 02336 if (range.rowi < 0 || range.rowi > sheet->maxrow) 02337 return FALSE; 02338 02339 if (range.col0 < 0 || range.col0 > sheet->maxcol) 02340 return FALSE; 02341 02342 if (range.coli < 0 || range.coli > sheet->maxcol) 02343 return FALSE; 02344 02345 if (range.rowi < MIN_VISIBLE_ROW (sheet)) 02346 return FALSE; 02347 02348 if (range.row0 > MAX_VISIBLE_ROW (sheet)) 02349 return FALSE; 02350 02351 if (range.coli < MIN_VISIBLE_COLUMN (sheet)) 02352 return FALSE; 02353 02354 if (range.col0 > MAX_VISIBLE_COLUMN (sheet)) 02355 return FALSE; 02356 02357 return TRUE; 02358 } 02359 02360 static gint 02361 gtk_sheet_cell_isvisible (GtkSheet * sheet, 02362 gint row, gint column) 02363 { 02364 GtkSheetRange range; 02365 02366 range.row0 = row; 02367 range.col0 = column; 02368 range.rowi = row; 02369 range.coli = column; 02370 02371 return gtk_sheet_range_isvisible(sheet, range); 02372 } 02373 02374 void 02375 gtk_sheet_get_visible_range(GtkSheet *sheet, GtkSheetRange *range) 02376 { 02377 02378 g_return_if_fail (sheet != NULL); 02379 g_return_if_fail (GTK_IS_SHEET (sheet)) ; 02380 g_return_if_fail (range != NULL); 02381 02382 range->row0 = MIN_VISIBLE_ROW(sheet); 02383 range->col0 = MIN_VISIBLE_COLUMN(sheet); 02384 range->rowi = MAX_VISIBLE_ROW(sheet); 02385 range->coli = MAX_VISIBLE_COLUMN(sheet); 02386 02387 } 02388 02389 GtkAdjustment * 02390 gtk_sheet_get_vadjustment (GtkSheet * sheet) 02391 { 02392 g_return_val_if_fail (sheet != NULL, NULL); 02393 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL); 02394 02395 return sheet->vadjustment; 02396 } 02397 02398 GtkAdjustment * 02399 gtk_sheet_get_hadjustment (GtkSheet * sheet) 02400 { 02401 g_return_val_if_fail (sheet != NULL, NULL); 02402 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL); 02403 02404 return sheet->hadjustment; 02405 } 02406 02407 void 02408 gtk_sheet_set_vadjustment (GtkSheet *sheet, 02409 GtkAdjustment *adjustment) 02410 { 02411 GtkAdjustment *old_adjustment; 02412 02413 g_return_if_fail (sheet != NULL); 02414 g_return_if_fail (GTK_IS_SHEET (sheet)); 02415 if (adjustment) 02416 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment)); 02417 02418 if (sheet->vadjustment == adjustment) 02419 return; 02420 02421 old_adjustment = sheet->vadjustment; 02422 02423 if (sheet->vadjustment) 02424 { 02425 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet); 02426 gtk_object_unref (GTK_OBJECT (sheet->vadjustment)); 02427 } 02428 02429 sheet->vadjustment = adjustment; 02430 02431 if (sheet->vadjustment) 02432 { 02433 gtk_object_ref (GTK_OBJECT (sheet->vadjustment)); 02434 gtk_object_sink (GTK_OBJECT (sheet->vadjustment)); 02435 02436 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "changed", 02437 (GtkSignalFunc) vadjustment_changed, 02438 (gpointer) sheet); 02439 gtk_signal_connect (GTK_OBJECT (sheet->vadjustment), "value_changed", 02440 (GtkSignalFunc) vadjustment_value_changed, 02441 (gpointer) sheet); 02442 } 02443 02444 if (!sheet->vadjustment || !old_adjustment) 02445 { 02446 gtk_widget_queue_resize (GTK_WIDGET (sheet)); 02447 return; 02448 } 02449 02450 sheet->old_vadjustment = sheet->vadjustment->value; 02451 } 02452 02453 void 02454 gtk_sheet_set_hadjustment (GtkSheet *sheet, 02455 GtkAdjustment *adjustment) 02456 { 02457 GtkAdjustment *old_adjustment; 02458 02459 g_return_if_fail (sheet != NULL); 02460 g_return_if_fail (GTK_IS_SHEET (sheet)); 02461 if (adjustment) 02462 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment)); 02463 02464 if (sheet->hadjustment == adjustment) 02465 return; 02466 02467 old_adjustment = sheet->hadjustment; 02468 02469 if (sheet->hadjustment) 02470 { 02471 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet); 02472 gtk_object_unref (GTK_OBJECT (sheet->hadjustment)); 02473 } 02474 02475 sheet->hadjustment = adjustment; 02476 02477 if (sheet->hadjustment) 02478 { 02479 gtk_object_ref (GTK_OBJECT (sheet->hadjustment)); 02480 gtk_object_sink (GTK_OBJECT (sheet->hadjustment)); 02481 02482 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "changed", 02483 (GtkSignalFunc) hadjustment_changed, 02484 (gpointer) sheet); 02485 gtk_signal_connect (GTK_OBJECT (sheet->hadjustment), "value_changed", 02486 (GtkSignalFunc) hadjustment_value_changed, 02487 (gpointer) sheet); 02488 } 02489 02490 if (!sheet->hadjustment || !old_adjustment) 02491 { 02492 gtk_widget_queue_resize (GTK_WIDGET (sheet)); 02493 return; 02494 } 02495 02496 sheet->old_hadjustment = sheet->hadjustment->value; 02497 } 02498 02499 static void 02500 gtk_sheet_set_scroll_adjustments (GtkSheet *sheet, 02501 GtkAdjustment *hadjustment, 02502 GtkAdjustment *vadjustment) 02503 { 02504 if(sheet->hadjustment != hadjustment) 02505 gtk_sheet_set_hadjustment (sheet, hadjustment); 02506 if(sheet->vadjustment != vadjustment) 02507 gtk_sheet_set_vadjustment (sheet, vadjustment); 02508 } 02509 02510 static void 02511 gtk_sheet_finalize (GObject * object) 02512 { 02513 GtkSheet *sheet; 02514 02515 g_return_if_fail (object != NULL); 02516 g_return_if_fail (GTK_IS_SHEET (object)); 02517 02518 sheet = GTK_SHEET (object); 02519 02520 /* get rid of all the cells */ 02521 gtk_sheet_range_clear (sheet, NULL); 02522 gtk_sheet_range_delete(sheet, NULL); 02523 02524 gtk_sheet_delete_rows (sheet, 0, sheet->maxrow + 1); 02525 gtk_sheet_delete_columns (sheet, 0, sheet->maxcol + 1); 02526 02527 DeleteRow (sheet, 0, sheet->maxrow + 1); 02528 DeleteColumn (sheet, 0, sheet->maxcol + 1); 02529 02530 g_free(sheet->row); 02531 sheet->row = NULL; 02532 g_free(sheet->column); 02533 sheet->column = NULL; 02534 g_free(sheet->data); 02535 sheet->data = NULL; 02536 02537 if(sheet->name){ 02538 g_free(sheet->name); 02539 sheet->name = NULL; 02540 } 02541 02542 if (G_OBJECT_CLASS (parent_class)->finalize) 02543 (*G_OBJECT_CLASS (parent_class)->finalize) (object); 02544 } 02545 02546 static void 02547 gtk_sheet_destroy (GtkObject * object) 02548 { 02549 GtkSheet *sheet; 02550 GList *children; 02551 02552 g_return_if_fail (object != NULL); 02553 g_return_if_fail (GTK_IS_SHEET (object)); 02554 02555 sheet = GTK_SHEET (object); 02556 02557 /* destroy the entry */ 02558 if(sheet->sheet_entry && GTK_IS_WIDGET(sheet->sheet_entry)){ 02559 gtk_widget_destroy (sheet->sheet_entry); 02560 sheet->sheet_entry = NULL; 02561 } 02562 02563 /* destroy the global selection button */ 02564 if(sheet->button && GTK_IS_WIDGET(sheet->button)){ 02565 gtk_widget_destroy (sheet->button); 02566 sheet->button = NULL; 02567 } 02568 02569 if(sheet->timer){ 02570 gtk_timeout_remove(sheet->timer); 02571 sheet->timer = 0; 02572 } 02573 02574 if(sheet->clip_timer){ 02575 gtk_timeout_remove(sheet->clip_timer); 02576 sheet->clip_timer = 0; 02577 } 02578 02579 /* unref adjustments */ 02580 if (sheet->hadjustment) 02581 { 02582 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->hadjustment), sheet); 02583 gtk_object_unref (GTK_OBJECT (sheet->hadjustment)); 02584 sheet->hadjustment = NULL; 02585 } 02586 if (sheet->vadjustment) 02587 { 02588 gtk_signal_disconnect_by_data (GTK_OBJECT (sheet->vadjustment), sheet); 02589 gtk_object_unref (GTK_OBJECT (sheet->vadjustment)); 02590 sheet->vadjustment = NULL; 02591 } 02592 02593 children = sheet->children; 02594 while(children){ 02595 GtkSheetChild *child = (GtkSheetChild *)children->data; 02596 if(child && child->widget) 02597 gtk_sheet_remove(GTK_CONTAINER(sheet), child->widget); 02598 children = sheet->children; 02599 } 02600 sheet->children = NULL; 02601 02602 if (GTK_OBJECT_CLASS (parent_class)->destroy) 02603 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object); 02604 } 02605 02606 static void 02607 gtk_sheet_style_set (GtkWidget *widget, 02608 GtkStyle *previous_style) 02609 { 02610 GtkSheet *sheet; 02611 02612 g_return_if_fail (widget != NULL); 02613 g_return_if_fail (GTK_IS_SHEET (widget)); 02614 02615 if (GTK_WIDGET_CLASS (parent_class)->style_set) 02616 (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style); 02617 02618 sheet = GTK_SHEET (widget); 02619 02620 if(GTK_WIDGET_REALIZED(widget)) 02621 { 02622 gtk_style_set_background (widget->style, widget->window, widget->state); 02623 } 02624 02625 } 02626 02627 static void 02628 gtk_sheet_realize (GtkWidget * widget) 02629 { 02630 GtkSheet *sheet; 02631 GdkWindowAttr attributes; 02632 gint attributes_mask; 02633 GdkGCValues values, auxvalues; 02634 GdkColormap *colormap; 02635 gchar *name; 02636 GtkSheetChild *child; 02637 GList *children; 02638 02639 g_return_if_fail (widget != NULL); 02640 g_return_if_fail (GTK_IS_SHEET (widget)); 02641 02642 sheet = GTK_SHEET (widget); 02643 02644 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); 02645 02646 attributes.window_type = GDK_WINDOW_CHILD; 02647 attributes.x = widget->allocation.x; 02648 attributes.y = widget->allocation.y; 02649 attributes.width = widget->allocation.width; 02650 attributes.height = widget->allocation.height; 02651 attributes.wclass = GDK_INPUT_OUTPUT; 02652 02653 attributes.visual = gtk_widget_get_visual (widget); 02654 attributes.colormap = gtk_widget_get_colormap (widget); 02655 02656 attributes.event_mask = gtk_widget_get_events (widget); 02657 attributes.event_mask |= (GDK_EXPOSURE_MASK | 02658 GDK_BUTTON_PRESS_MASK | 02659 GDK_BUTTON_RELEASE_MASK | 02660 GDK_KEY_PRESS_MASK | 02661 GDK_POINTER_MOTION_MASK | 02662 GDK_POINTER_MOTION_HINT_MASK); 02663 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | 02664 GDK_WA_CURSOR; 02665 02666 attributes.cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW); 02667 02668 /* main window */ 02669 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); 02670 02671 gdk_window_set_user_data (widget->window, sheet); 02672 02673 widget->style = gtk_style_attach (widget->style, widget->window); 02674 02675 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); 02676 02677 attributes.x = 0; 02678 if(sheet->row_titles_visible) 02679 attributes.x = sheet->row_title_area.width; 02680 attributes.y = 0; 02681 attributes.width = sheet->column_title_area.width; 02682 attributes.height = sheet->column_title_area.height; 02683 02684 /* column-title window */ 02685 sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask); 02686 gdk_window_set_user_data (sheet->column_title_window, sheet); 02687 gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL); 02688 02689 attributes.x = 0; 02690 attributes.y = 0; 02691 if(sheet->column_titles_visible) 02692 attributes.y = sheet->column_title_area.height; 02693 attributes.width = sheet->row_title_area.width; 02694 attributes.height = sheet->row_title_area.height; 02695 02696 /* row-title window */ 02697 sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask); 02698 gdk_window_set_user_data (sheet->row_title_window, sheet); 02699 gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL); 02700 02701 /* sheet-window */ 02702 attributes.cursor = gdk_cursor_new(GDK_PLUS); 02703 02704 attributes.x = 0; 02705 attributes.y = 0; 02706 attributes.width = sheet->sheet_window_width, 02707 attributes.height = sheet->sheet_window_height; 02708 02709 sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask); 02710 gdk_window_set_user_data (sheet->sheet_window, sheet); 02711 02712 gdk_window_set_background (sheet->sheet_window, &widget->style->white); 02713 gdk_window_show (sheet->sheet_window); 02714 02715 /* backing_pixmap */ 02716 gtk_sheet_make_backing_pixmap(sheet, 0, 0); 02717 02718 /* GCs */ 02719 if(sheet->fg_gc) 02720 gdk_gc_unref(sheet->fg_gc); 02721 if(sheet->bg_gc) 02722 gdk_gc_unref(sheet->bg_gc); 02723 sheet->fg_gc = gdk_gc_new (widget->window); 02724 sheet->bg_gc = gdk_gc_new (widget->window); 02725 02726 colormap = gtk_widget_get_colormap(widget); 02727 02728 gdk_color_white(colormap, &widget->style->white); 02729 gdk_color_black(colormap, &widget->style->black); 02730 02731 gdk_gc_get_values(sheet->fg_gc, &auxvalues); 02732 02733 values.foreground = widget->style->white; 02734 values.function = GDK_INVERT; 02735 values.subwindow_mode = GDK_INCLUDE_INFERIORS; 02736 if(sheet->xor_gc) 02737 gdk_gc_unref(sheet->xor_gc); 02738 sheet->xor_gc = gdk_gc_new_with_values (widget->window, 02739 &values, 02740 GDK_GC_FOREGROUND | 02741 GDK_GC_FUNCTION | 02742 GDK_GC_SUBWINDOW); 02743 02744 if(sheet->sheet_entry->parent){ 02745 gtk_widget_ref(sheet->sheet_entry); 02746 gtk_widget_unparent(sheet->sheet_entry); 02747 } 02748 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window); 02749 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet)); 02750 02751 if(sheet->button && sheet->button->parent){ 02752 gtk_widget_ref(sheet->button); 02753 gtk_widget_unparent(sheet->button); 02754 } 02755 gtk_widget_set_parent_window(sheet->button, sheet->sheet_window); 02756 gtk_widget_set_parent(sheet->button, GTK_WIDGET(sheet)); 02757 02758 /* 02759 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col); 02760 */ 02761 if(!sheet->cursor_drag) 02762 sheet->cursor_drag = gdk_cursor_new(GDK_PLUS); 02763 02764 if(sheet->column_titles_visible) 02765 gdk_window_show(sheet->column_title_window); 02766 if(sheet->row_titles_visible) 02767 gdk_window_show(sheet->row_title_window); 02768 02769 size_allocate_row_title_buttons(sheet); 02770 size_allocate_column_title_buttons(sheet); 02771 02772 name = g_strdup(sheet->name); 02773 gtk_sheet_set_title(sheet, name); 02774 02775 g_free(name); 02776 02777 children = sheet->children; 02778 while(children) 02779 { 02780 child = children->data; 02781 children = g_list_next(children); 02782 02783 gtk_sheet_realize_child(sheet, child); 02784 } 02785 } 02786 02787 static void 02788 create_global_button(GtkSheet *sheet) 02789 { 02790 sheet->button = gtk_button_new_with_label(" "); 02791 02792 gtk_signal_connect (GTK_OBJECT (sheet->button), 02793 "pressed", 02794 (GtkSignalFunc) global_button_clicked, 02795 (gpointer) sheet); 02796 } 02797 02798 static void 02799 size_allocate_global_button(GtkSheet *sheet) 02800 { 02801 GtkAllocation allocation; 02802 02803 if(!sheet->column_titles_visible) return; 02804 if(!sheet->row_titles_visible) return; 02805 02806 gtk_widget_size_request(sheet->button, NULL); 02807 02808 allocation.x=0; 02809 allocation.y=0; 02810 allocation.width=sheet->row_title_area.width; 02811 allocation.height=sheet->column_title_area.height; 02812 02813 gtk_widget_size_allocate(sheet->button, &allocation); 02814 gtk_widget_show(sheet->button); 02815 } 02816 02817 static void 02818 global_button_clicked(GtkWidget *widget, gpointer data) 02819 { 02820 gboolean veto; 02821 02822 gtk_sheet_click_cell(GTK_SHEET(data), -1, -1, &veto); 02823 gtk_widget_grab_focus(GTK_WIDGET(data)); 02824 } 02825 02826 02827 static void 02828 gtk_sheet_unrealize (GtkWidget * widget) 02829 { 02830 GtkSheet *sheet; 02831 02832 g_return_if_fail (widget != NULL); 02833 g_return_if_fail (GTK_IS_SHEET (widget)); 02834 02835 sheet = GTK_SHEET (widget); 02836 02837 gdk_cursor_destroy (sheet->cursor_drag); 02838 02839 gdk_gc_destroy (sheet->xor_gc); 02840 gdk_gc_destroy (sheet->fg_gc); 02841 gdk_gc_destroy (sheet->bg_gc); 02842 02843 gdk_window_destroy (sheet->sheet_window); 02844 gdk_window_destroy (sheet->column_title_window); 02845 gdk_window_destroy (sheet->row_title_window); 02846 02847 if (sheet->pixmap){ 02848 g_object_unref (sheet->pixmap); 02849 sheet->pixmap = NULL; 02850 } 02851 02852 sheet->column_title_window=NULL; 02853 sheet->sheet_window = NULL; 02854 sheet->cursor_drag = NULL; 02855 sheet->xor_gc = NULL; 02856 sheet->fg_gc = NULL; 02857 sheet->bg_gc = NULL; 02858 02859 if (GTK_WIDGET_CLASS (parent_class)->unrealize) 02860 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); 02861 } 02862 02863 static void 02864 gtk_sheet_map (GtkWidget * widget) 02865 { 02866 GtkSheet *sheet; 02867 GtkSheetChild *child; 02868 GList *children; 02869 02870 g_return_if_fail (widget != NULL); 02871 g_return_if_fail (GTK_IS_SHEET (widget)); 02872 02873 sheet = GTK_SHEET (widget); 02874 02875 if (!GTK_WIDGET_MAPPED (widget)) 02876 { 02877 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); 02878 02879 if(!sheet->cursor_drag) sheet->cursor_drag=gdk_cursor_new(GDK_PLUS); 02880 02881 gdk_window_show (widget->window); 02882 02883 gdk_window_show (sheet->sheet_window); 02884 02885 if(sheet->column_titles_visible){ 02886 gdk_window_show (sheet->column_title_window); 02887 } 02888 if(sheet->row_titles_visible){ 02889 gdk_window_show (sheet->row_title_window); 02890 } 02891 02892 if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)){ 02893 gtk_widget_show (sheet->sheet_entry); 02894 gtk_widget_map (sheet->sheet_entry); 02895 } 02896 02897 if (GTK_WIDGET_VISIBLE (sheet->button) && 02898 !GTK_WIDGET_MAPPED (sheet->button)){ 02899 gtk_widget_show(sheet->button); 02900 gtk_widget_map (sheet->button); 02901 } 02902 02903 if(GTK_BIN(sheet->button)->child) 02904 if (GTK_WIDGET_VISIBLE (GTK_BIN(sheet->button)->child) && 02905 !GTK_WIDGET_MAPPED (GTK_BIN(sheet->button)->child)) 02906 gtk_widget_map (GTK_BIN(sheet->button)->child); 02907 02908 gtk_sheet_range_draw(sheet, NULL); 02909 gtk_sheet_activate_cell(sheet, 02910 sheet->active_cell.row, 02911 sheet->active_cell.col); 02912 02913 children = sheet->children; 02914 while (children) 02915 { 02916 child = children->data; 02917 children = g_list_next(children); 02918 02919 if (GTK_WIDGET_VISIBLE (child->widget) && 02920 !GTK_WIDGET_MAPPED (child->widget)){ 02921 gtk_widget_map (child->widget); 02922 gtk_sheet_position_child(sheet, child); 02923 } 02924 } 02925 02926 } 02927 } 02928 02929 static void 02930 gtk_sheet_unmap (GtkWidget * widget) 02931 { 02932 GtkSheet *sheet; 02933 GtkSheetChild *child; 02934 GList *children; 02935 02936 g_return_if_fail (widget != NULL); 02937 g_return_if_fail (GTK_IS_SHEET (widget)); 02938 02939 sheet = GTK_SHEET (widget); 02940 02941 if (GTK_WIDGET_MAPPED (widget)) 02942 { 02943 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); 02944 02945 gdk_window_hide (sheet->sheet_window); 02946 if(sheet->column_titles_visible) 02947 gdk_window_hide (sheet->column_title_window); 02948 if(sheet->row_titles_visible) 02949 gdk_window_hide (sheet->row_title_window); 02950 gdk_window_hide (widget->window); 02951 02952 if (GTK_WIDGET_MAPPED (sheet->sheet_entry)) 02953 gtk_widget_unmap (sheet->sheet_entry); 02954 02955 if (GTK_WIDGET_MAPPED (sheet->button)) 02956 gtk_widget_unmap (sheet->button); 02957 02958 children = sheet->children; 02959 while (children) 02960 { 02961 child = children->data; 02962 children = g_list_next(children); 02963 02964 if (GTK_WIDGET_VISIBLE (child->widget) && 02965 GTK_WIDGET_MAPPED (child->widget)) 02966 { 02967 gtk_widget_unmap (child->widget); 02968 } 02969 } 02970 02971 } 02972 } 02973 02974 02975 static void 02976 gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col) 02977 { 02978 GtkWidget *widget; 02979 GdkGC *fg_gc, *bg_gc; 02980 GtkSheetCellAttr attributes; 02981 GdkRectangle area; 02982 02983 g_return_if_fail (sheet != NULL); 02984 02985 /* bail now if we arn't drawable yet */ 02986 if (!GTK_WIDGET_DRAWABLE (sheet)) return; 02987 02988 if (row < 0 || row > sheet->maxrow) return; 02989 if (col < 0 || col > sheet->maxcol) return; 02990 if (!sheet->column[col].is_visible) return; 02991 if (!sheet->row[row].is_visible) return; 02992 02993 widget = GTK_WIDGET (sheet); 02994 02995 gtk_sheet_get_attributes(sheet, row, col, &attributes); 02996 02997 /* select GC for background rectangle */ 02998 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground); 02999 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background); 03000 03001 fg_gc = sheet->fg_gc; 03002 bg_gc = sheet->bg_gc; 03003 03004 area.x=COLUMN_LEFT_XPIXEL(sheet,col); 03005 area.y=ROW_TOP_YPIXEL(sheet,row); 03006 area.width=sheet->column[col].width; 03007 area.height=sheet->row[row].height; 03008 03009 gdk_draw_rectangle (sheet->pixmap, 03010 bg_gc, 03011 TRUE, 03012 area.x, 03013 area.y, 03014 area.width, 03015 area.height); 03016 03017 gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0); 03018 03019 if(sheet->show_grid){ 03020 gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color); 03021 03022 gdk_draw_rectangle (sheet->pixmap, 03023 sheet->bg_gc, 03024 FALSE, 03025 area.x, area.y, 03026 area.width, area.height); 03027 } 03028 } 03029 03030 static void 03031 gtk_sheet_cell_draw_border (GtkSheet *sheet, gint row, gint col, gint mask) 03032 { 03033 GtkWidget *widget; 03034 GdkGC *fg_gc, *bg_gc; 03035 GtkSheetCellAttr attributes; 03036 GdkRectangle area; 03037 guint width; 03038 03039 g_return_if_fail (sheet != NULL); 03040 03041 /* bail now if we arn't drawable yet */ 03042 if (!GTK_WIDGET_DRAWABLE (sheet)) return; 03043 03044 if (row < 0 || row > sheet->maxrow) return; 03045 if (col < 0 || col > sheet->maxcol) return; 03046 if (!sheet->column[col].is_visible) return; 03047 if (!sheet->row[row].is_visible) return; 03048 03049 widget = GTK_WIDGET (sheet); 03050 03051 gtk_sheet_get_attributes(sheet, row, col, &attributes); 03052 03053 /* select GC for background rectangle */ 03054 gdk_gc_set_foreground (sheet->fg_gc, &attributes.border.color); 03055 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background); 03056 03057 fg_gc = sheet->fg_gc; 03058 bg_gc = sheet->bg_gc; 03059 03060 area.x=COLUMN_LEFT_XPIXEL(sheet,col); 03061 area.y=ROW_TOP_YPIXEL(sheet,row); 03062 area.width=sheet->column[col].width; 03063 area.height=sheet->row[row].height; 03064 03065 width = attributes.border.width; 03066 gdk_gc_set_line_attributes(sheet->fg_gc, attributes.border.width, 03067 attributes.border.line_style, 03068 attributes.border.cap_style, 03069 attributes.border.join_style); 03070 if(width>0){ 03071 03072 if(attributes.border.mask & GTK_SHEET_LEFT_BORDER & mask) 03073 gdk_draw_line(sheet->pixmap, sheet->fg_gc, 03074 area.x, area.y-width/2, 03075 area.x, area.y+area.height+width/2+1); 03076 03077 if(attributes.border.mask & GTK_SHEET_RIGHT_BORDER & mask) 03078 gdk_draw_line(sheet->pixmap, sheet->fg_gc, 03079 area.x+area.width, area.y-width/2, 03080 area.x+area.width, 03081 area.y+area.height+width/2+1); 03082 03083 if(attributes.border.mask & GTK_SHEET_TOP_BORDER & mask) 03084 gdk_draw_line(sheet->pixmap, sheet->fg_gc, 03085 area.x-width/2,area.y, 03086 area.x+area.width+width/2+1, 03087 area.y); 03088 03089 if(attributes.border.mask & GTK_SHEET_BOTTOM_BORDER & mask) 03090 gdk_draw_line(sheet->pixmap, sheet->fg_gc, 03091 area.x-width/2, area.y+area.height, 03092 area.x+area.width+width/2+1, 03093 area.y+area.height); 03094 } 03095 03096 } 03097 03098 03099 static void 03100 gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col) 03101 { 03102 GtkWidget *widget; 03103 GdkRectangle area, clip_area; 03104 gint i; 03105 gint text_width, text_height, y; 03106 gint xoffset=0; 03107 gint size, sizel, sizer; 03108 GdkGC *fg_gc, *bg_gc; 03109 GtkSheetCellAttr attributes; 03110 PangoLayout *layout; 03111 PangoRectangle rect; 03112 PangoRectangle logical_rect; 03113 PangoLayoutLine *line; 03114 PangoFontMetrics *metrics; 03115 PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet)); 03116 gint ascent, descent, y_pos; 03117 03118 char *label; 03119 03120 g_return_if_fail (sheet != NULL); 03121 03122 /* bail now if we aren't drawable yet */ 03123 if (!GTK_WIDGET_DRAWABLE (sheet)) 03124 return; 03125 03126 if (row > sheet->maxallocrow) return; 03127 if (col > sheet->maxalloccol) return; 03128 if (!sheet->data[row]) return; 03129 if (!sheet->data[row][col]) return; 03130 if (!sheet->data[row][col]->text || strlen(sheet->data[row][col]->text)==0) 03131 return; 03132 03133 if (row < 0 || row > sheet->maxrow) return; 03134 if (col < 0 || col > sheet->maxcol) return; 03135 if (!sheet->column[col].is_visible) return; 03136 if (!sheet->row[row].is_visible) return; 03137 03138 03139 widget = GTK_WIDGET(sheet); 03140 03141 label = sheet->data[row][col]->text; 03142 03143 gtk_sheet_get_attributes(sheet, row, col, &attributes); 03144 03145 /* select GC for background rectangle */ 03146 gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground); 03147 gdk_gc_set_foreground (sheet->bg_gc, &attributes.background); 03148 03149 fg_gc = sheet->fg_gc; 03150 bg_gc = sheet->bg_gc; 03151 03152 area.x=COLUMN_LEFT_XPIXEL(sheet,col); 03153 area.y=ROW_TOP_YPIXEL(sheet,row); 03154 area.width=sheet->column[col].width; 03155 area.height=sheet->row[row].height; 03156 03157 clip_area = area; 03158 03159 layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label); 03160 pango_layout_set_font_description (layout, attributes.font_desc); 03161 03162 pango_layout_get_pixel_extents (layout, NULL, &rect); 03163 03164 line = pango_layout_get_lines (layout)->data; 03165 pango_layout_line_get_extents (line, NULL, &logical_rect); 03166 03167 metrics = pango_context_get_metrics(context, 03168 attributes.font_desc, 03169 pango_context_get_language(context)); 03170 03171 ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE; 03172 descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE; 03173 03174 pango_font_metrics_unref(metrics); 03175 03176 /* Align primarily for locale's ascent/descent */ 03177 03178 logical_rect.height /= PANGO_SCALE; 03179 logical_rect.y /= PANGO_SCALE; 03180 y_pos = area.height - logical_rect.height; 03181 03182 if (logical_rect.height > area.height) 03183 y_pos = (logical_rect.height - area.height - 2*CELLOFFSET) / 2; 03184 else if (y_pos < 0) 03185 y_pos = 0; 03186 else if (y_pos + logical_rect.height > area.height) 03187 y_pos = area.height - logical_rect.height; 03188 03189 text_width = rect.width; 03190 text_height = rect.height; 03191 y = area.y + y_pos - CELLOFFSET; 03192 03193 switch(attributes.justification){ 03194 case GTK_JUSTIFY_RIGHT: 03195 size=area.width; 03196 area.x+=area.width; 03197 if(!gtk_sheet_clip_text(sheet)){ 03198 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){ 03199 if(gtk_sheet_cell_get_text(sheet, row, i)) break; 03200 if(size>=text_width+CELLOFFSET) break; 03201 size+=sheet->column[i].width; 03202 sheet->column[i].right_text_column = MAX(col, sheet->column[i].right_text_column); 03203 } 03204 area.width=size; 03205 } 03206 area.x-=size; 03207 xoffset+=area.width-text_width - 2 * CELLOFFSET - 03208 attributes.border.width/2; 03209 break; 03210 case GTK_JUSTIFY_CENTER: 03211 sizel=area.width/2; 03212 sizer=area.width/2; 03213 area.x+=area.width/2; 03214 if(!gtk_sheet_clip_text(sheet)){ 03215 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){ 03216 if(gtk_sheet_cell_get_text(sheet, row, i)) break; 03217 if(sizer>=text_width/2) break; 03218 sizer+=sheet->column[i].width; 03219 sheet->column[i].left_text_column = MIN(col, sheet->column[i].left_text_column); 03220 } 03221 for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){ 03222 if(gtk_sheet_cell_get_text(sheet, row, i)) break; 03223 if(sizel>=text_width/2) break; 03224 sizel+=sheet->column[i].width; 03225 sheet->column[i].right_text_column = MAX(col, sheet->column[i].right_text_column); 03226 } 03227 size=MIN(sizel, sizer); 03228 } 03229 area.x-=sizel; 03230 xoffset+= sizel - text_width/2 - CELLOFFSET; 03231 area.width=sizel+sizer; 03232 break; 03233 case GTK_JUSTIFY_LEFT: 03234 default: 03235 size=area.width; 03236 if(!gtk_sheet_clip_text(sheet)){ 03237 for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){ 03238 if(gtk_sheet_cell_get_text(sheet, row, i)) break; 03239 if(size>=text_width+CELLOFFSET) break; 03240 size+=sheet->column[i].width; 03241 sheet->column[i].left_text_column = MIN(col, sheet->column[i].left_text_column); 03242 } 03243 area.width=size; 03244 } 03245 xoffset += attributes.border.width/2; 03246 break; 03247 } 03248 03249 if(!gtk_sheet_clip_text(sheet)) clip_area = area; 03250 gdk_gc_set_clip_rectangle(fg_gc, &clip_area); 03251 03252 03253 gdk_draw_layout (sheet->pixmap, fg_gc, 03254 area.x + xoffset + CELLOFFSET, 03255 y, 03256 layout); 03257 03258 gdk_gc_set_clip_rectangle(fg_gc, NULL); 03259 g_object_unref(G_OBJECT(layout)); 03260 03261 gdk_draw_pixmap(sheet->sheet_window, 03262 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 03263 sheet->pixmap, 03264 area.x, 03265 area.y, 03266 area.x, 03267 area.y, 03268 area.width, 03269 area.height); 03270 03271 } 03272 03273 03274 03275 static void 03276 gtk_sheet_range_draw(GtkSheet *sheet, const GtkSheetRange *range) 03277 { 03278 gint i,j; 03279 GtkSheetRange drawing_range; 03280 GdkRectangle area; 03281 03282 g_return_if_fail(sheet != NULL); 03283 g_return_if_fail(GTK_SHEET(sheet)); 03284 03285 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return; 03286 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return; 03287 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return; 03288 03289 if(range == NULL) 03290 { 03291 drawing_range.row0=MIN_VISIBLE_ROW(sheet); 03292 drawing_range.col0=MIN_VISIBLE_COLUMN(sheet); 03293 drawing_range.rowi=MAX_VISIBLE_ROW(sheet); 03294 drawing_range.coli=MAX_VISIBLE_COLUMN(sheet); 03295 /* 03296 gdk_draw_rectangle (sheet->pixmap, 03297 GTK_WIDGET(sheet)->style->white_gc, 03298 TRUE, 03299 0,0, 03300 sheet->sheet_window_width,sheet->sheet_window_height); 03301 */ 03302 } 03303 else 03304 { 03305 drawing_range.row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet)); 03306 drawing_range.col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet)); 03307 drawing_range.rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet)); 03308 drawing_range.coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet)); 03309 } 03310 03311 if(drawing_range.coli == sheet->maxcol){ 03312 area.x=COLUMN_LEFT_XPIXEL(sheet,sheet->maxcol)+ 03313 sheet->column[sheet->maxcol].width+1; 03314 area.y=0; 03315 03316 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color); 03317 03318 gdk_draw_rectangle (sheet->pixmap, 03319 sheet->fg_gc, 03320 TRUE, 03321 area.x,area.y, 03322 sheet->sheet_window_width - area.x, 03323 sheet->sheet_window_height); 03324 03325 gdk_draw_pixmap(sheet->sheet_window, 03326 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 03327 sheet->pixmap, 03328 area.x, 03329 area.y, 03330 area.x, 03331 area.y, 03332 sheet->sheet_window_width - area.x, 03333 sheet->sheet_window_height); 03334 } 03335 if(drawing_range.rowi == sheet->maxrow){ 03336 area.x=0; 03337 area.y=ROW_TOP_YPIXEL(sheet,sheet->maxrow)+sheet->row[sheet->maxrow].height+1; 03338 03339 gdk_gc_set_foreground(sheet->fg_gc, &sheet->bg_color); 03340 03341 gdk_draw_rectangle (sheet->pixmap, 03342 sheet->fg_gc, 03343 TRUE, 03344 area.x,area.y, 03345 sheet->sheet_window_width, 03346 sheet->sheet_window_height - area.y); 03347 03348 gdk_draw_pixmap(sheet->sheet_window, 03349 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 03350 sheet->pixmap, 03351 area.x, 03352 area.y, 03353 area.x, 03354 area.y, 03355 sheet->sheet_window_width, 03356 sheet->sheet_window_height - area.y); 03357 } 03358 03359 for(i=drawing_range.row0; i<=drawing_range.rowi; i++) 03360 for(j=drawing_range.col0; j<=drawing_range.coli; j++){ 03361 gtk_sheet_cell_draw_default(sheet, i, j); 03362 } 03363 03364 for(i=drawing_range.row0; i<=drawing_range.rowi; i++) 03365 for(j=drawing_range.col0; j<=drawing_range.coli; j++){ 03366 gtk_sheet_cell_draw_border(sheet, i-1, j, GTK_SHEET_BOTTOM_BORDER); 03367 gtk_sheet_cell_draw_border(sheet, i+1, j, GTK_SHEET_TOP_BORDER); 03368 gtk_sheet_cell_draw_border(sheet, i, j-1, GTK_SHEET_RIGHT_BORDER); 03369 gtk_sheet_cell_draw_border(sheet, i, j+1, GTK_SHEET_LEFT_BORDER); 03370 gtk_sheet_cell_draw_border(sheet, i, j, 15); 03371 } 03372 03373 for(i=drawing_range.row0; i<=drawing_range.rowi; i++) 03374 for(j=drawing_range.col0; j<=drawing_range.coli; j++) 03375 if(i<=sheet->maxallocrow && j<=sheet->maxalloccol && 03376 sheet->data[i] && sheet->data[i][j]) 03377 gtk_sheet_cell_draw_label (sheet, i, j); 03378 03379 for(i=drawing_range.row0; i<=drawing_range.rowi; i++) 03380 for(j=sheet->column[drawing_range.col0].left_text_column; j<drawing_range.col0; j++) 03381 if(i<=sheet->maxallocrow && j<=sheet->maxalloccol && 03382 sheet->data[i] && sheet->data[i][j]) 03383 gtk_sheet_cell_draw_label (sheet, i, j); 03384 03385 for(i=drawing_range.row0; i<=drawing_range.rowi; i++) 03386 for(j=drawing_range.coli+1; j<=sheet->column[drawing_range.coli].right_text_column; j++) 03387 if(i<=sheet->maxallocrow && j<=sheet->maxalloccol && 03388 sheet->data[i] && sheet->data[i][j]) 03389 gtk_sheet_cell_draw_label (sheet, i, j); 03390 03391 gtk_sheet_draw_backing_pixmap(sheet, drawing_range); 03392 03393 if(sheet->state != GTK_SHEET_NORMAL && gtk_sheet_range_isvisible(sheet, sheet->range)) 03394 gtk_sheet_range_draw_selection(sheet, drawing_range); 03395 03396 if(sheet->state == GTK_STATE_NORMAL && 03397 sheet->active_cell.row >= drawing_range.row0 && 03398 sheet->active_cell.row <= drawing_range.rowi && 03399 sheet->active_cell.col >= drawing_range.col0 && 03400 sheet->active_cell.col <= drawing_range.coli) 03401 gtk_sheet_show_active_cell(sheet); 03402 03403 } 03404 03405 static void 03406 gtk_sheet_range_draw_selection(GtkSheet *sheet, GtkSheetRange range) 03407 { 03408 GdkRectangle area; 03409 gint i,j; 03410 GtkSheetRange aux; 03411 03412 if(range.col0 > sheet->range.coli || range.coli < sheet->range.col0 || 03413 range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0) 03414 return; 03415 03416 if(!gtk_sheet_range_isvisible(sheet, range)) return; 03417 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return; 03418 03419 aux=range; 03420 03421 range.col0=MAX(sheet->range.col0, range.col0); 03422 range.coli=MIN(sheet->range.coli, range.coli); 03423 range.row0=MAX(sheet->range.row0, range.row0); 03424 range.rowi=MIN(sheet->range.rowi, range.rowi); 03425 03426 range.col0=MAX(range.col0, MIN_VISIBLE_COLUMN(sheet)); 03427 range.coli=MIN(range.coli, MAX_VISIBLE_COLUMN(sheet)); 03428 range.row0=MAX(range.row0, MIN_VISIBLE_ROW(sheet)); 03429 range.rowi=MIN(range.rowi, MAX_VISIBLE_ROW(sheet)); 03430 03431 for(i=range.row0; i<=range.rowi; i++){ 03432 for(j=range.col0; j<=range.coli; j++){ 03433 03434 if(gtk_sheet_cell_get_state(sheet, i, j)==GTK_STATE_SELECTED && 03435 sheet->column[j].is_visible && sheet->row[i].is_visible){ 03436 03437 row_button_set(sheet, i); 03438 column_button_set(sheet, j); 03439 03440 area.x=COLUMN_LEFT_XPIXEL(sheet,j); 03441 area.y=ROW_TOP_YPIXEL(sheet,i); 03442 area.width=sheet->column[j].width; 03443 area.height=sheet->row[i].height; 03444 03445 if(i==sheet->range.row0){ 03446 area.y=area.y+2; 03447 area.height=area.height-2; 03448 } 03449 if(i==sheet->range.rowi) area.height=area.height-3; 03450 if(j==sheet->range.col0){ 03451 area.x=area.x+2; 03452 area.width=area.width-2; 03453 } 03454 if(j==sheet->range.coli) area.width=area.width-3; 03455 03456 if(i!=sheet->active_cell.row || j!=sheet->active_cell.col){ 03457 gdk_draw_rectangle (sheet->sheet_window, 03458 sheet->xor_gc, 03459 TRUE, 03460 area.x+1,area.y+1, 03461 area.width,area.height); 03462 } 03463 } 03464 03465 } 03466 } 03467 03468 gtk_sheet_draw_border(sheet, sheet->range); 03469 03470 } 03471 03472 static void 03473 gtk_sheet_draw_backing_pixmap(GtkSheet *sheet, GtkSheetRange range) 03474 { 03475 gint x,y,width,height; 03476 03477 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return; 03478 03479 x=COLUMN_LEFT_XPIXEL(sheet,range.col0); 03480 y=ROW_TOP_YPIXEL(sheet, range.row0); 03481 width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-x+sheet->column[range.coli].width; 03482 height=ROW_TOP_YPIXEL(sheet, range.rowi)-y+sheet->row[range.rowi].height; 03483 03484 if(range.row0==sheet->range.row0){ 03485 y=y-5; 03486 height=height+5; 03487 } 03488 if(range.rowi==sheet->range.rowi) height=height+5; 03489 if(range.col0==sheet->range.col0){ 03490 x=x-5; 03491 width=width+5; 03492 } 03493 if(range.coli==sheet->range.coli) width=width+5; 03494 03495 03496 width=MIN(width, sheet->sheet_window_width-x); 03497 height=MIN(height, sheet->sheet_window_height-y); 03498 03499 x--; 03500 y--; 03501 width+=2; 03502 height+=2; 03503 03504 x = (sheet->row_titles_visible) 03505 ? MAX(x, sheet->row_title_area.width) : MAX(x, 0); 03506 y = (sheet->column_titles_visible) 03507 ? MAX(y, sheet->column_title_area.height) : MAX(y, 0); 03508 03509 if(range.coli==sheet->maxcol) width=sheet->sheet_window_width-x; 03510 if(range.rowi==sheet->maxrow) height=sheet->sheet_window_height-y; 03511 03512 gdk_draw_pixmap(sheet->sheet_window, 03513 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 03514 sheet->pixmap, 03515 x, 03516 y, 03517 x, 03518 y, 03519 width+1, 03520 height+1); 03521 } 03522 03523 static GtkSheetCell * 03524 gtk_sheet_cell_new() 03525 { 03526 GtkSheetCell *cell; 03527 cell = g_new(GtkSheetCell, 1); 03528 cell->text = NULL; 03529 cell->link = NULL; 03530 cell->attributes = NULL; 03531 return cell; 03532 } 03533 03534 void 03535 gtk_sheet_set_cell_text(GtkSheet *sheet, gint row, gint col, const gchar *text) 03536 { 03537 GtkSheetCellAttr attributes; 03538 03539 g_return_if_fail (sheet != NULL); 03540 g_return_if_fail (GTK_IS_SHEET (sheet)); 03541 if (col > sheet->maxcol || row > sheet->maxrow) return; 03542 if (col < 0 || row < 0) return; 03543 03544 gtk_sheet_get_attributes(sheet, row, col, &attributes); 03545 gtk_sheet_set_cell(sheet, row, col, attributes.justification, text); 03546 } 03547 03548 void 03549 gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col, 03550 GtkJustification justification, 03551 const gchar *text) 03552 { 03553 GtkSheetCell **cell; 03554 GtkSheetRange range; 03555 gint text_width; 03556 GtkSheetCellAttr attributes; 03557 03558 g_return_if_fail (sheet != NULL); 03559 g_return_if_fail (GTK_IS_SHEET (sheet)); 03560 if (col > sheet->maxcol || row > sheet->maxrow) return; 03561 if (col < 0 || row < 0) return; 03562 03563 CheckBounds(sheet, row, col); 03564 03565 cell=&sheet->data[row][col]; 03566 03567 if(*cell==NULL) 03568 (*cell) = gtk_sheet_cell_new(); 03569 03570 gtk_sheet_get_attributes(sheet, row, col, &attributes); 03571 03572 (*cell)->row = row; 03573 (*cell)->col = col; 03574 03575 attributes.justification = justification; 03576 gtk_sheet_set_cell_attributes(sheet, row, col, attributes); 03577 03578 if((*cell)->text){ 03579 g_free((*cell)->text); 03580 (*cell)->text = NULL; 03581 } 03582 03583 if(text) 03584 (*cell)->text=g_strdup(text); 03585 03586 if(attributes.is_visible){ 03587 03588 text_width = 0; 03589 if((*cell)->text && strlen((*cell)->text) > 0) { 03590 text_width = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, (*cell)->text); 03591 } 03592 03593 range.row0 = row; 03594 range.rowi = row; 03595 range.col0 = sheet->view.col0; 03596 range.coli = sheet->view.coli; 03597 03598 if(gtk_sheet_autoresize(sheet) && 03599 text_width > sheet->column[col].width-2*CELLOFFSET-attributes.border.width){ 03600 gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width); 03601 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING); 03602 } 03603 else 03604 if(!GTK_SHEET_IS_FROZEN(sheet)) 03605 gtk_sheet_range_draw(sheet, &range); 03606 } 03607 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col); 03608 03609 03610 } 03611 03612 void 03613 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column) 03614 { 03615 GtkSheetRange range; 03616 03617 g_return_if_fail (sheet != NULL); 03618 g_return_if_fail (GTK_IS_SHEET (sheet)); 03619 if (column > sheet->maxcol || row > sheet->maxrow) return; 03620 if (column > sheet->maxalloccol || row > sheet->maxallocrow) return; 03621 if (column < 0 || row < 0) return; 03622 03623 range.row0 = row; 03624 range.rowi = row; 03625 range.col0 = sheet->view.col0; 03626 range.coli = sheet->view.coli; 03627 03628 gtk_sheet_real_cell_clear(sheet, row, column, FALSE); 03629 03630 if(!GTK_SHEET_IS_FROZEN(sheet)){ 03631 gtk_sheet_range_draw(sheet, &range); 03632 } 03633 } 03634 03635 void 03636 gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column) 03637 { 03638 GtkSheetRange range; 03639 03640 g_return_if_fail (sheet != NULL); 03641 g_return_if_fail (GTK_IS_SHEET (sheet)); 03642 if (column > sheet->maxcol || row > sheet->maxrow) return; 03643 if (column > sheet->maxalloccol || row > sheet->maxallocrow) return; 03644 if (column < 0 || row < 0) return; 03645 03646 range.row0 = row; 03647 range.rowi = row; 03648 range.col0 = sheet->view.col0; 03649 range.coli = sheet->view.coli; 03650 03651 gtk_sheet_real_cell_clear(sheet, row, column, TRUE); 03652 03653 if(!GTK_SHEET_IS_FROZEN(sheet)){ 03654 gtk_sheet_range_draw(sheet, &range); 03655 } 03656 } 03657 03658 static void 03659 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete) 03660 { 03661 gchar *text; 03662 gpointer link; 03663 03664 if(row > sheet->maxallocrow || column > sheet->maxalloccol) return; 03665 if(!sheet->data[row]) return; 03666 if(!sheet->data[row][column]) return; 03667 03668 text = gtk_sheet_cell_get_text(sheet, row, column); 03669 link = gtk_sheet_get_link(sheet, row, column); 03670 03671 if(text){ 03672 g_free(sheet->data[row][column]->text); 03673 sheet->data[row][column]->text = NULL; 03674 03675 if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0) 03676 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL], row, column); 03677 03678 sheet_head->CHANGED = 1; 03679 } 03680 03681 if(delete){ 03682 if(sheet->data[row][column]->attributes){ 03683 g_free(sheet->data[row][column]->attributes); 03684 sheet->data[row][column]->attributes = NULL; 03685 } 03686 sheet->data[row][column]->link = NULL; 03687 03688 if(sheet->data[row][column]) g_free(sheet->data[row][column]); 03689 03690 sheet->data[row][column] = NULL; 03691 } 03692 03693 } 03694 03695 void 03696 gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range) 03697 { 03698 g_return_if_fail (sheet != NULL); 03699 g_return_if_fail (GTK_IS_SHEET (sheet)); 03700 03701 gtk_sheet_real_range_clear(sheet, range, FALSE); 03702 } 03703 03704 void 03705 gtk_sheet_range_delete (GtkSheet *sheet, const GtkSheetRange *range) 03706 { 03707 g_return_if_fail (sheet != NULL); 03708 g_return_if_fail (GTK_IS_SHEET (sheet)); 03709 03710 gtk_sheet_real_range_clear(sheet, range, TRUE); 03711 } 03712 03713 static void 03714 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range, 03715 gboolean delete) 03716 { 03717 gint i, j; 03718 GtkSheetRange clear; 03719 03720 if(!range){ 03721 clear.row0=0; 03722 clear.rowi=sheet->maxallocrow; 03723 clear.col0=0; 03724 clear.coli=sheet->maxalloccol; 03725 }else 03726 clear=*range; 03727 03728 clear.row0=MAX(clear.row0, 0); 03729 clear.col0=MAX(clear.col0, 0); 03730 clear.rowi=MIN(clear.rowi, sheet->maxallocrow); 03731 clear.coli=MIN(clear.coli, sheet->maxalloccol); 03732 03733 for(i=clear.row0; i<=clear.rowi; i++) 03734 for(j=clear.col0; j<=clear.coli; j++){ 03735 gtk_sheet_real_cell_clear(sheet, i, j, delete); 03736 } 03737 03738 gtk_sheet_range_draw(sheet, NULL); 03739 } 03740 03741 03742 gchar * 03743 gtk_sheet_cell_get_text (GtkSheet *sheet, gint row, gint col) 03744 { 03745 g_return_val_if_fail (sheet != NULL, NULL); 03746 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL); 03747 03748 if(col > sheet->maxcol || row > sheet->maxrow) return NULL; 03749 if(col < 0 || row < 0) return NULL; 03750 if(row > sheet->maxallocrow || col > sheet->maxalloccol) return NULL; 03751 if(!sheet->data[row]) return NULL; 03752 if(!sheet->data[row][col]) return NULL; 03753 if(!sheet->data[row][col]->text) return NULL; 03754 if(strlen(sheet->data[row][col]->text) == 0) return NULL; 03755 03756 return (sheet->data[row][col]->text); 03757 } 03758 03759 void 03760 gtk_sheet_link_cell(GtkSheet *sheet, gint row, gint col, gpointer link) 03761 { 03762 g_return_if_fail (sheet != NULL); 03763 g_return_if_fail (GTK_IS_SHEET (sheet)); 03764 if(col > sheet->maxcol || row > sheet->maxrow) return; 03765 if(col < 0 || row < 0) return; 03766 03767 if(row > sheet->maxallocrow || col > sheet->maxalloccol || 03768 !sheet->data[row] || !sheet->data[row][col]) 03769 gtk_sheet_set_cell_text(sheet, row, col, ""); 03770 03771 sheet->data[row][col]->link = link; 03772 } 03773 03774 gpointer 03775 gtk_sheet_get_link(GtkSheet *sheet, gint row, gint col) 03776 { 03777 g_return_val_if_fail (sheet != NULL, NULL); 03778 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL); 03779 if(col > sheet->maxcol || row > sheet->maxrow) return NULL; 03780 if(col < 0 || row < 0) return NULL; 03781 03782 if (row > sheet->maxallocrow || col > sheet->maxalloccol) return NULL; 03783 if (!sheet->data[row]) return NULL; /* Added by Chris Howell */ 03784 if (!sheet->data[row][col]) return NULL; /* Added by Bob Lissner */ 03785 03786 return(sheet->data[row][col]->link); 03787 } 03788 03789 void 03790 gtk_sheet_remove_link(GtkSheet *sheet, gint row, gint col) 03791 { 03792 g_return_if_fail (sheet != NULL); 03793 g_return_if_fail (GTK_IS_SHEET (sheet)); 03794 if(col > sheet->maxcol || row > sheet->maxrow) return; 03795 if(col < 0 || row < 0) return; 03796 03797 /* Fixed by Andreas Voegele */ 03798 if(row < sheet->maxallocrow && col < sheet->maxalloccol && 03799 sheet->data[row] && sheet->data[row][col] && 03800 sheet->data[row][col]->link) 03801 sheet->data[row][col]->link = NULL; 03802 } 03803 03804 03805 GtkStateType 03806 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col) 03807 { 03808 gint state; 03809 GtkSheetRange *range; 03810 03811 g_return_val_if_fail (sheet != NULL, 0); 03812 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0); 03813 if(col > sheet->maxcol || row > sheet->maxrow) return 0; 03814 if(col < 0 || row < 0) return 0; 03815 03816 state = sheet->state; 03817 range = &sheet->range; 03818 03819 switch (state){ 03820 case GTK_SHEET_NORMAL: 03821 return GTK_STATE_NORMAL; 03822 break; 03823 case GTK_SHEET_ROW_SELECTED: 03824 if(row>=range->row0 && row<=range->rowi) 03825 return GTK_STATE_SELECTED; 03826 break; 03827 case GTK_SHEET_COLUMN_SELECTED: 03828 if(col>=range->col0 && col<=range->coli) 03829 return GTK_STATE_SELECTED; 03830 break; 03831 case GTK_SHEET_RANGE_SELECTED: 03832 if(row >= range->row0 && row <= range->rowi && \ 03833 col >= range->col0 && col <= range->coli) 03834 return GTK_STATE_SELECTED; 03835 break; 03836 } 03837 return GTK_STATE_NORMAL; 03838 } 03839 03840 gboolean 03841 gtk_sheet_get_pixel_info (GtkSheet * sheet, 03842 gint x, 03843 gint y, 03844 gint * row, 03845 gint * column) 03846 { 03847 gint trow, tcol; 03848 03849 g_return_val_if_fail (sheet != NULL, 0); 03850 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0); 03851 03852 /* bounds checking, return false if the user clicked 03853 * on a blank area */ 03854 trow = ROW_FROM_YPIXEL (sheet, y); 03855 if (trow > sheet->maxrow) 03856 return FALSE; 03857 03858 *row = trow; 03859 03860 tcol = COLUMN_FROM_XPIXEL (sheet, x); 03861 if (tcol > sheet->maxcol) 03862 return FALSE; 03863 03864 *column = tcol; 03865 03866 return TRUE; 03867 } 03868 03869 gboolean 03870 gtk_sheet_get_cell_area (GtkSheet * sheet, 03871 gint row, 03872 gint column, 03873 GdkRectangle *area) 03874 { 03875 g_return_val_if_fail (sheet != NULL, 0); 03876 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0); 03877 03878 if(row > sheet->maxrow || column > sheet->maxcol) return FALSE; 03879 03880 area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) - 03881 (sheet->row_titles_visible 03882 ? sheet->row_title_area.width 03883 : 0)); 03884 area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL(sheet, row) - 03885 (sheet->column_titles_visible 03886 ? sheet->column_title_area.height 03887 : 0)); 03888 area->width= (column == -1) ? sheet->row_title_area.width 03889 : sheet->column[column].width; 03890 area->height= (row == -1) ? sheet->column_title_area.height 03891 : sheet->row[row].height; 03892 03893 /* 03894 if(row < 0 || column < 0) return FALSE; 03895 03896 area->x = COLUMN_LEFT_XPIXEL(sheet, column); 03897 area->y = ROW_TOP_YPIXEL(sheet, row); 03898 if(sheet->row_titles_visible) 03899 area->x -= sheet->row_title_area.width; 03900 if(sheet->column_titles_visible) 03901 area->y -= sheet->column_title_area.height; 03902 03903 area->width=sheet->column[column].width; 03904 area->height=sheet->row[row].height; 03905 */ 03906 return TRUE; 03907 } 03908 03909 gboolean 03910 gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column) 03911 { 03912 g_return_val_if_fail (sheet != NULL, 0); 03913 g_return_val_if_fail (GTK_IS_SHEET (sheet), 0); 03914 03915 if(row < 0 || column < 0) return FALSE; 03916 if(row > sheet->maxrow || column > sheet->maxcol) return FALSE; 03917 03918 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) 03919 { 03920 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE; 03921 } 03922 03923 sheet->active_cell.row=row; 03924 sheet->active_cell.col=column; 03925 03926 if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE; 03927 03928 return TRUE; 03929 } 03930 03931 void 03932 gtk_sheet_get_active_cell (GtkSheet *sheet, gint *row, gint *column) 03933 { 03934 g_return_if_fail (sheet != NULL); 03935 g_return_if_fail (GTK_IS_SHEET (sheet)); 03936 03937 *row = sheet->active_cell.row; 03938 *column = sheet->active_cell.col; 03939 } 03940 03941 static void 03942 gtk_sheet_entry_changed(GtkWidget *widget, gpointer data) 03943 { 03944 GtkSheet *sheet; 03945 gint row,col; 03946 const char *text; 03947 GtkJustification justification; 03948 GtkSheetCellAttr attributes; 03949 03950 g_return_if_fail (data != NULL); 03951 g_return_if_fail (GTK_IS_SHEET (data)); 03952 03953 sheet=GTK_SHEET(data); 03954 03955 if(!GTK_WIDGET_VISIBLE(widget)) return; 03956 if(sheet->state != GTK_STATE_NORMAL) return; 03957 03958 row=sheet->active_cell.row; 03959 col=sheet->active_cell.col; 03960 03961 if(row<0 || col<0) return; 03962 03963 sheet->active_cell.row=-1; 03964 sheet->active_cell.col=-1; 03965 03966 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet))); 03967 03968 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN); 03969 03970 if(text && strlen(text)!=0){ 03971 gtk_sheet_get_attributes(sheet, row, col, &attributes); 03972 justification=attributes.justification; 03973 gtk_sheet_set_cell(sheet, row, col, justification, text); 03974 } 03975 else 03976 { 03977 /* Added by Matias Mutchinick */ 03978 gtk_sheet_cell_clear(sheet, row, col); 03979 } 03980 03981 sheet_head->CHANGED = 1; 03982 03983 if(sheet->freeze_count == 0) 03984 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN); 03985 03986 sheet->active_cell.row=row;; 03987 sheet->active_cell.col=col; 03988 03989 } 03990 03991 03992 static gboolean 03993 gtk_sheet_deactivate_cell(GtkSheet *sheet) 03994 { 03995 gboolean veto = TRUE; 03996 03997 g_return_val_if_fail (sheet != NULL, FALSE); 03998 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 03999 04000 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return FALSE; 04001 if(sheet->state != GTK_SHEET_NORMAL) return FALSE; 04002 04003 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[DEACTIVATE], 04004 sheet->active_cell.row, 04005 sheet->active_cell.col, &veto); 04006 04007 if(!veto) return FALSE; 04008 04009 gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)), 04010 (GtkSignalFunc) gtk_sheet_entry_changed, 04011 GTK_OBJECT(GTK_WIDGET(sheet))); 04012 04013 gtk_sheet_hide_active_cell(sheet); 04014 sheet->active_cell.row=-1; 04015 sheet->active_cell.col=-1; 04016 04017 if(GTK_SHEET_REDRAW_PENDING(sheet)){ 04018 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING); 04019 gtk_sheet_range_draw(sheet, NULL); 04020 } 04021 04022 return TRUE; 04023 } 04024 04025 static void 04026 gtk_sheet_hide_active_cell(GtkSheet *sheet) 04027 { 04028 const char *text; 04029 gint row,col; 04030 GtkJustification justification; 04031 GtkSheetCellAttr attributes; 04032 04033 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return; 04034 04035 row=sheet->active_cell.row; 04036 col=sheet->active_cell.col; 04037 04038 if(row < 0 || col < 0) return; 04039 04040 if(sheet->freeze_count == 0) 04041 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN); 04042 04043 text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet))); 04044 04045 gtk_sheet_get_attributes(sheet, row, col, &attributes); 04046 justification=attributes.justification; 04047 04048 if(text && strlen(text)!=0){ 04049 gtk_sheet_set_cell(sheet, row, col, justification, text); 04050 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col); 04051 } 04052 else 04053 { 04054 gtk_sheet_cell_clear(sheet, row, col); 04055 } 04056 04057 row=sheet->active_cell.row; 04058 col=sheet->active_cell.col; 04059 04060 column_button_release(sheet, col); 04061 row_button_release(sheet, row); 04062 04063 gtk_widget_unmap(sheet->sheet_entry); 04064 04065 if(row != -1 && col != -1) 04066 gdk_draw_pixmap(sheet->sheet_window, 04067 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 04068 sheet->pixmap, 04069 COLUMN_LEFT_XPIXEL(sheet,col)-1, 04070 ROW_TOP_YPIXEL(sheet,row)-1, 04071 COLUMN_LEFT_XPIXEL(sheet,col)-1, 04072 ROW_TOP_YPIXEL(sheet,row)-1, 04073 sheet->column[col].width+4, 04074 sheet->row[row].height+4); 04075 04076 GTK_WIDGET_UNSET_FLAGS(sheet->sheet_entry, GTK_HAS_FOCUS); 04077 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet), GTK_HAS_FOCUS); 04078 gtk_widget_grab_focus(GTK_WIDGET(sheet)); 04079 04080 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE); 04081 04082 } 04083 04084 static gboolean 04085 gtk_sheet_activate_cell(GtkSheet *sheet, gint row, gint col) 04086 { 04087 gboolean veto = TRUE; 04088 04089 g_return_val_if_fail (sheet != NULL, FALSE); 04090 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 04091 04092 if(row < 0 || col < 0) return FALSE; 04093 if(row > sheet->maxrow || col > sheet->maxcol) return FALSE; 04094 04095 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto); 04096 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto; 04097 */ 04098 04099 if(!veto) return FALSE; 04100 if(sheet->state != GTK_SHEET_NORMAL){ 04101 sheet->state=GTK_SHEET_NORMAL; 04102 gtk_sheet_real_unselect_range(sheet, NULL); 04103 } 04104 04105 sheet->range.row0=row; 04106 sheet->range.col0=col; 04107 sheet->range.rowi=row; 04108 sheet->range.coli=col; 04109 sheet->active_cell.row=row; 04110 sheet->active_cell.col=col; 04111 sheet->selection_cell.row=row; 04112 sheet->selection_cell.col=col; 04113 row_button_set(sheet, row); 04114 column_button_set(sheet, col); 04115 04116 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); 04117 gtk_sheet_show_active_cell(sheet); 04118 04119 gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)), 04120 "changed", 04121 (GtkSignalFunc)gtk_sheet_entry_changed, 04122 GTK_OBJECT(GTK_WIDGET(sheet))); 04123 04124 _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, &veto); 04125 04126 return TRUE; 04127 } 04128 04129 static void 04130 gtk_sheet_show_active_cell(GtkSheet *sheet) 04131 { 04132 GtkSheetCell *cell; 04133 GtkEntry *sheet_entry; 04134 GtkSheetCellAttr attributes; 04135 gchar *text = NULL; 04136 GtkJustification justification; 04137 gint row, col; 04138 04139 g_return_if_fail (sheet != NULL); 04140 g_return_if_fail (GTK_IS_SHEET (sheet)); 04141 04142 row = sheet->active_cell.row; 04143 col = sheet->active_cell.col; 04144 04145 /* Don't show the active cell, if there is no active cell: */ 04146 if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */ 04147 return; 04148 04149 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return; 04150 if(sheet->state != GTK_SHEET_NORMAL) return; 04151 if(GTK_SHEET_IN_SELECTION(sheet)) return; 04152 04153 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE); 04154 04155 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet)); 04156 04157 gtk_sheet_get_attributes(sheet, row, col, &attributes); 04158 04159 justification = GTK_JUSTIFY_LEFT; 04160 04161 if(gtk_sheet_justify_entry(sheet)) 04162 justification = attributes.justification; 04163 04164 if(row <= sheet->maxallocrow && col <= sheet->maxalloccol) { 04165 if(sheet->data[row]) { 04166 if(sheet->data[row][col]) { 04167 cell = sheet->data[row][col]; 04168 if(cell->text) 04169 text = g_strdup(cell->text); 04170 } 04171 } 04172 } 04173 04174 if(!text) text = g_strdup(""); 04175 04176 gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible); 04177 04178 if(gtk_sheet_locked(sheet) || !attributes.is_editable){ 04179 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE); 04180 }else{ 04181 gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE); 04182 } 04183 04184 04185 gtk_entry_set_text(GTK_ENTRY(sheet_entry), text); 04186 04187 04188 gtk_sheet_size_allocate_entry(sheet); 04189 04190 gtk_widget_map(sheet->sheet_entry); 04191 gtk_sheet_draw_active_cell(sheet); 04192 04193 gtk_widget_grab_focus(GTK_WIDGET(sheet_entry)); 04194 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet_entry), GTK_HAS_FOCUS); 04195 GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet), GTK_HAS_FOCUS); 04196 04197 g_free(text); 04198 } 04199 04200 static void 04201 gtk_sheet_draw_active_cell(GtkSheet *sheet) 04202 { 04203 gint row, col; 04204 04205 if(!GTK_WIDGET_DRAWABLE(GTK_WIDGET(sheet))) return; 04206 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return; 04207 04208 row = sheet->active_cell.row; 04209 col = sheet->active_cell.col; 04210 04211 if(row<0 || col<0) return; 04212 04213 if(!gtk_sheet_cell_isvisible(sheet, row, col)) return; 04214 04215 row_button_set(sheet, row); 04216 column_button_set(sheet, col); 04217 04218 gtk_sheet_draw_backing_pixmap(sheet, sheet->range); 04219 gtk_sheet_draw_border(sheet, sheet->range); 04220 04221 } 04222 04223 04224 static void 04225 gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height) 04226 { 04227 gint pixmap_width, pixmap_height; 04228 04229 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return; 04230 04231 if(width == 0 && height == 0){ 04232 width=sheet->sheet_window_width+80; 04233 height=sheet->sheet_window_height+80; 04234 } 04235 04236 if (!sheet->pixmap) 04237 { 04238 /* allocate */ 04239 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window, 04240 width, height, 04241 -1); 04242 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL); 04243 } 04244 else 04245 { 04246 /* reallocate if sizes don't match */ 04247 gdk_window_get_size (sheet->pixmap, 04248 &pixmap_width, &pixmap_height); 04249 if ((pixmap_width != width) || (pixmap_height != height)) 04250 { 04251 gdk_pixmap_unref(sheet->pixmap); /* replaced by SDB on 7.31.2006 */ 04252 /* g_free(sheet->pixmap); */ 04253 sheet->pixmap = gdk_pixmap_new (sheet->sheet_window, 04254 width, height, 04255 -1); 04256 if(!GTK_SHEET_IS_FROZEN(sheet)) gtk_sheet_range_draw(sheet, NULL); 04257 } 04258 } 04259 } 04260 04261 static void 04262 gtk_sheet_new_selection(GtkSheet *sheet, GtkSheetRange *range) 04263 { 04264 gint i,j, mask1, mask2; 04265 gint state, selected; 04266 gint x,y,width,height; 04267 GtkSheetRange new_range, aux_range; 04268 04269 g_return_if_fail (sheet != NULL); 04270 04271 if(range==NULL) range=&sheet->range; 04272 04273 new_range=*range; 04274 04275 range->row0=MIN(range->row0, sheet->range.row0); 04276 range->rowi=MAX(range->rowi, sheet->range.rowi); 04277 range->col0=MIN(range->col0, sheet->range.col0); 04278 range->coli=MAX(range->coli, sheet->range.coli); 04279 04280 range->row0=MAX(range->row0, MIN_VISIBLE_ROW(sheet)); 04281 range->rowi=MIN(range->rowi, MAX_VISIBLE_ROW(sheet)); 04282 range->col0=MAX(range->col0, MIN_VISIBLE_COLUMN(sheet)); 04283 range->coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet)); 04284 04285 aux_range.row0=MAX(new_range.row0, MIN_VISIBLE_ROW(sheet)); 04286 aux_range.rowi=MIN(new_range.rowi, MAX_VISIBLE_ROW(sheet)); 04287 aux_range.col0=MAX(new_range.col0, MIN_VISIBLE_COLUMN(sheet)); 04288 aux_range.coli=MIN(new_range.coli, MAX_VISIBLE_COLUMN(sheet)); 04289 04290 for(i=range->row0; i<=range->rowi; i++){ 04291 for(j=range->col0; j<=range->coli; j++){ 04292 04293 state=gtk_sheet_cell_get_state(sheet, i, j); 04294 selected=(i<=new_range.rowi && i>=new_range.row0 && 04295 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE; 04296 04297 if(state==GTK_STATE_SELECTED && selected && 04298 sheet->column[j].is_visible && sheet->row[i].is_visible && 04299 (i==sheet->range.row0 || i==sheet->range.rowi || 04300 j==sheet->range.col0 || j==sheet->range.coli || 04301 i==new_range.row0 || i==new_range.rowi || 04302 j==new_range.col0 || j==new_range.coli)){ 04303 04304 mask1 = i==sheet->range.row0 ? 1 : 0; 04305 mask1 = i==sheet->range.rowi ? mask1+2 : mask1; 04306 mask1 = j==sheet->range.col0 ? mask1+4 : mask1; 04307 mask1 = j==sheet->range.coli ? mask1+8 : mask1; 04308 04309 mask2 = i==new_range.row0 ? 1 : 0; 04310 mask2 = i==new_range.rowi ? mask2+2 : mask2; 04311 mask2 = j==new_range.col0 ? mask2+4 : mask2; 04312 mask2 = j==new_range.coli ? mask2+8 : mask2; 04313 04314 if(mask1 != mask2){ 04315 x=COLUMN_LEFT_XPIXEL(sheet,j); 04316 y=ROW_TOP_YPIXEL(sheet, i); 04317 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+sheet->column[j].width; 04318 height=ROW_TOP_YPIXEL(sheet, i)-y+sheet->row[i].height; 04319 04320 if(i==sheet->range.row0){ 04321 y=y-3; 04322 height=height+3; 04323 } 04324 if(i==sheet->range.rowi) height=height+3; 04325 if(j==sheet->range.col0){ 04326 x=x-3; 04327 width=width+3; 04328 } 04329 if(j==sheet->range.coli) width=width+3; 04330 04331 gdk_draw_pixmap(sheet->sheet_window, 04332 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 04333 sheet->pixmap, 04334 x+1, 04335 y+1, 04336 x+1, 04337 y+1, 04338 width, 04339 height); 04340 04341 if(i != sheet->active_cell.row || j != sheet->active_cell.col){ 04342 x=COLUMN_LEFT_XPIXEL(sheet,j); 04343 y=ROW_TOP_YPIXEL(sheet, i); 04344 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+sheet->column[j].width; 04345 height=ROW_TOP_YPIXEL(sheet, i)-y+sheet->row[i].height; 04346 04347 if(i==new_range.row0){ 04348 y=y+2; 04349 height=height-2; 04350 } 04351 if(i==new_range.rowi) height=height-3; 04352 if(j==new_range.col0){ 04353 x=x+2; 04354 width=width-2; 04355 } 04356 if(j==new_range.coli) width=width-3; 04357 04358 gdk_draw_rectangle (sheet->sheet_window, 04359 sheet->xor_gc, 04360 TRUE, 04361 x+1,y+1, 04362 width,height); 04363 } 04364 } 04365 } 04366 } 04367 } 04368 04369 for(i=range->row0; i<=range->rowi; i++){ 04370 for(j=range->col0; j<=range->coli; j++){ 04371 04372 state=gtk_sheet_cell_get_state(sheet, i, j); 04373 selected=(i<=new_range.rowi && i>=new_range.row0 && 04374 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE; 04375 04376 if(state==GTK_STATE_SELECTED && !selected && 04377 sheet->column[j].is_visible && sheet->row[i].is_visible){ 04378 04379 x=COLUMN_LEFT_XPIXEL(sheet,j); 04380 y=ROW_TOP_YPIXEL(sheet, i); 04381 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+sheet->column[j].width; 04382 height=ROW_TOP_YPIXEL(sheet, i)-y+sheet->row[i].height; 04383 04384 if(i==sheet->range.row0){ 04385 y=y-3; 04386 height=height+3; 04387 } 04388 if(i==sheet->range.rowi) height=height+3; 04389 if(j==sheet->range.col0){ 04390 x=x-3; 04391 width=width+3; 04392 } 04393 if(j==sheet->range.coli) width=width+3; 04394 04395 gdk_draw_pixmap(sheet->sheet_window, 04396 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 04397 sheet->pixmap, 04398 x+1, 04399 y+1, 04400 x+1, 04401 y+1, 04402 width, 04403 height); 04404 } 04405 } 04406 } 04407 04408 for(i=range->row0; i<=range->rowi; i++){ 04409 for(j=range->col0; j<=range->coli; j++){ 04410 04411 state=gtk_sheet_cell_get_state(sheet, i, j); 04412 selected=(i<=new_range.rowi && i>=new_range.row0 && 04413 j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE; 04414 04415 if(state!=GTK_STATE_SELECTED && selected && 04416 sheet->column[j].is_visible && sheet->row[i].is_visible && 04417 (i != sheet->active_cell.row || j != sheet->active_cell.col)){ 04418 04419 x=COLUMN_LEFT_XPIXEL(sheet,j); 04420 y=ROW_TOP_YPIXEL(sheet, i); 04421 width=COLUMN_LEFT_XPIXEL(sheet, j)-x+sheet->column[j].width; 04422 height=ROW_TOP_YPIXEL(sheet, i)-y+sheet->row[i].height; 04423 04424 if(i==new_range.row0){ 04425 y=y+2; 04426 height=height-2; 04427 } 04428 if(i==new_range.rowi) height=height-3; 04429 if(j==new_range.col0){ 04430 x=x+2; 04431 width=width-2; 04432 } 04433 if(j==new_range.coli) width=width-3; 04434 04435 gdk_draw_rectangle (sheet->sheet_window, 04436 sheet->xor_gc, 04437 TRUE, 04438 x+1,y+1, 04439 width,height); 04440 04441 } 04442 04443 } 04444 } 04445 04446 for(i=aux_range.row0; i<=aux_range.rowi; i++){ 04447 for(j=aux_range.col0; j<=aux_range.coli; j++){ 04448 04449 if(sheet->column[j].is_visible && sheet->row[i].is_visible){ 04450 04451 state=gtk_sheet_cell_get_state(sheet, i, j); 04452 04453 mask1 = i==sheet->range.row0 ? 1 : 0; 04454 mask1 = i==sheet->range.rowi ? mask1+2 : mask1; 04455 mask1 = j==sheet->range.col0 ? mask1+4 : mask1; 04456 mask1 = j==sheet->range.coli ? mask1+8 : mask1; 04457 04458 mask2 = i==new_range.row0 ? 1 : 0; 04459 mask2 = i==new_range.rowi ? mask2+2 : mask2; 04460 mask2 = j==new_range.col0 ? mask2+4 : mask2; 04461 mask2 = j==new_range.coli ? mask2+8 : mask2; 04462 if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){ 04463 x=COLUMN_LEFT_XPIXEL(sheet,j); 04464 y=ROW_TOP_YPIXEL(sheet, i); 04465 width=sheet->column[j].width; 04466 height=sheet->row[i].height; 04467 if(mask2 & 1) 04468 gdk_draw_rectangle (sheet->sheet_window, 04469 sheet->xor_gc, 04470 TRUE, 04471 x+1,y-1, 04472 width,3); 04473 04474 04475 if(mask2 & 2) 04476 gdk_draw_rectangle (sheet->sheet_window, 04477 sheet->xor_gc, 04478 TRUE, 04479 x+1,y+height-1, 04480 width,3); 04481 04482 if(mask2 & 4) 04483 gdk_draw_rectangle (sheet->sheet_window, 04484 sheet->xor_gc, 04485 TRUE, 04486 x-1,y+1, 04487 3,height); 04488 04489 04490 if(mask2 & 8) 04491 gdk_draw_rectangle (sheet->sheet_window, 04492 sheet->xor_gc, 04493 TRUE, 04494 x+width-1,y+1, 04495 3,height); 04496 04497 04498 04499 } 04500 04501 } 04502 04503 } 04504 } 04505 04506 04507 *range=new_range; 04508 gtk_sheet_draw_corners(sheet, new_range); 04509 04510 } 04511 04512 static void 04513 gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range) 04514 { 04515 GtkWidget *widget; 04516 GdkRectangle area; 04517 gint i; 04518 gint x,y,width,height; 04519 04520 widget = GTK_WIDGET(sheet); 04521 04522 x=COLUMN_LEFT_XPIXEL(sheet,new_range.col0); 04523 y=ROW_TOP_YPIXEL(sheet,new_range.row0); 04524 width=COLUMN_LEFT_XPIXEL(sheet,new_range.coli)-x+ 04525 sheet->column[new_range.coli].width; 04526 height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+ 04527 sheet->row[new_range.rowi].height; 04528 04529 area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet)); 04530 area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet)); 04531 area.width=sheet->sheet_window_width; 04532 area.height=sheet->sheet_window_height; 04533 04534 if(x<0) { 04535 width=width+x; 04536 x=0; 04537 } 04538 if(width>area.width) width=area.width+10; 04539 if(y<0) { 04540 height=height+y; 04541 y=0; 04542 } 04543 if(height>area.height) height=area.height+10; 04544 04545 gdk_gc_set_clip_rectangle(sheet->xor_gc, &area); 04546 04547 for(i=-1; i<=1; ++i) 04548 gdk_draw_rectangle (sheet->sheet_window, 04549 sheet->xor_gc, 04550 FALSE, 04551 x+i,y+i, 04552 width-2*i,height-2*i); 04553 04554 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL); 04555 04556 gtk_sheet_draw_corners(sheet, new_range); 04557 04558 } 04559 04560 static void 04561 gtk_sheet_draw_corners(GtkSheet *sheet, GtkSheetRange range) 04562 { 04563 gint x,y; 04564 guint width = 1; 04565 04566 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.col0)){ 04567 x=COLUMN_LEFT_XPIXEL(sheet,range.col0); 04568 y=ROW_TOP_YPIXEL(sheet,range.row0); 04569 gdk_draw_pixmap(sheet->sheet_window, 04570 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 04571 sheet->pixmap, 04572 x-1, 04573 y-1, 04574 x-1, 04575 y-1, 04576 3, 04577 3); 04578 gdk_draw_rectangle (sheet->sheet_window, 04579 sheet->xor_gc, 04580 TRUE, 04581 x-1,y-1, 04582 3,3); 04583 } 04584 04585 if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) || 04586 sheet->state == GTK_SHEET_COLUMN_SELECTED){ 04587 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+ 04588 sheet->column[range.coli].width; 04589 y=ROW_TOP_YPIXEL(sheet,range.row0); 04590 width = 1; 04591 if(sheet->state == GTK_SHEET_COLUMN_SELECTED) 04592 { 04593 y = ROW_TOP_YPIXEL(sheet, sheet->view.row0)+3; 04594 width = 3; 04595 } 04596 gdk_draw_pixmap(sheet->sheet_window, 04597 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 04598 sheet->pixmap, 04599 x-width, 04600 y-width, 04601 x-width, 04602 y-width, 04603 2*width+1, 04604 2*width+1); 04605 gdk_draw_rectangle (sheet->sheet_window, 04606 sheet->xor_gc, 04607 TRUE, 04608 x-width+width/2,y-width+width/2, 04609 2+width,2+width); 04610 } 04611 04612 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.col0) || 04613 sheet->state == GTK_SHEET_ROW_SELECTED){ 04614 x=COLUMN_LEFT_XPIXEL(sheet,range.col0); 04615 y=ROW_TOP_YPIXEL(sheet,range.rowi)+ 04616 sheet->row[range.rowi].height; 04617 width = 1; 04618 if(sheet->state == GTK_SHEET_ROW_SELECTED) 04619 { 04620 x = COLUMN_LEFT_XPIXEL(sheet, sheet->view.col0)+3; 04621 width = 3; 04622 } 04623 gdk_draw_pixmap(sheet->sheet_window, 04624 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 04625 sheet->pixmap, 04626 x-width, 04627 y-width, 04628 x-width, 04629 y-width, 04630 2*width+1, 04631 2*width+1); 04632 gdk_draw_rectangle (sheet->sheet_window, 04633 sheet->xor_gc, 04634 TRUE, 04635 x-width+width/2,y-width+width/2, 04636 2+width,2+width); 04637 } 04638 04639 if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){ 04640 x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+ 04641 sheet->column[range.coli].width; 04642 y=ROW_TOP_YPIXEL(sheet,range.rowi)+ 04643 sheet->row[range.rowi].height; 04644 width = 1; 04645 if(sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3; 04646 if(sheet->state == GTK_SHEET_NORMAL) width = 3; 04647 gdk_draw_pixmap(sheet->sheet_window, 04648 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 04649 sheet->pixmap, 04650 x-width, 04651 y-width, 04652 x-width, 04653 y-width, 04654 2*width+1, 04655 2*width+1); 04656 gdk_draw_rectangle (sheet->sheet_window, 04657 sheet->xor_gc, 04658 TRUE, 04659 x-width+width/2,y-width+width/2, 04660 2+width,2+width); 04661 04662 } 04663 04664 } 04665 04666 04667 static void 04668 gtk_sheet_real_select_range (GtkSheet * sheet, 04669 GtkSheetRange * range) 04670 { 04671 gint i; 04672 gint state; 04673 04674 g_return_if_fail (sheet != NULL); 04675 04676 if(range==NULL) range=&sheet->range; 04677 04678 if(range->row0 < 0 || range->rowi < 0) return; 04679 if(range->col0 < 0 || range->coli < 0) return; 04680 04681 state=sheet->state; 04682 04683 if(state==GTK_SHEET_COLUMN_SELECTED || state==GTK_SHEET_RANGE_SELECTED){ 04684 for(i=sheet->range.col0; i< range->col0; i++) 04685 column_button_release(sheet, i); 04686 for(i=range->coli+1; i<= sheet->range.coli; i++) 04687 column_button_release(sheet, i); 04688 for(i=range->col0; i<=range->coli; i++){ 04689 column_button_set(sheet, i); 04690 } 04691 } 04692 04693 if(state==GTK_SHEET_ROW_SELECTED || state==GTK_SHEET_RANGE_SELECTED){ 04694 for(i=sheet->range.row0; i< range->row0; i++) 04695 row_button_release(sheet, i); 04696 for(i=range->rowi+1; i<= sheet->range.rowi; i++) 04697 row_button_release(sheet, i); 04698 for(i=range->row0; i<=range->rowi; i++){ 04699 row_button_set(sheet, i); 04700 } 04701 } 04702 04703 if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 || 04704 range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0) 04705 { 04706 04707 gtk_sheet_new_selection(sheet, range); 04708 04709 sheet->range.col0=range->col0; 04710 sheet->range.coli=range->coli; 04711 sheet->range.row0=range->row0; 04712 sheet->range.rowi=range->rowi; 04713 04714 } 04715 else 04716 { 04717 gtk_sheet_draw_backing_pixmap(sheet, sheet->range); 04718 gtk_sheet_range_draw_selection(sheet, sheet->range); 04719 } 04720 04721 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[SELECT_RANGE], range); 04722 } 04723 04724 void 04725 gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range) 04726 { 04727 g_return_if_fail (sheet != NULL); 04728 04729 if(range==NULL) range=&sheet->range; 04730 04731 if(range->row0 < 0 || range->rowi < 0) return; 04732 if(range->col0 < 0 || range->coli < 0) return; 04733 04734 if(sheet->state != GTK_SHEET_NORMAL) 04735 gtk_sheet_real_unselect_range(sheet, NULL); 04736 else 04737 { 04738 gboolean veto = TRUE; 04739 veto = gtk_sheet_deactivate_cell(sheet); 04740 if(!veto) return; 04741 } 04742 04743 sheet->range.row0=range->row0; 04744 sheet->range.rowi=range->rowi; 04745 sheet->range.col0=range->col0; 04746 sheet->range.coli=range->coli; 04747 sheet->active_cell.row=range->row0; 04748 sheet->active_cell.col=range->col0; 04749 sheet->selection_cell.row=range->rowi; 04750 sheet->selection_cell.col=range->coli; 04751 04752 sheet->state = GTK_SHEET_RANGE_SELECTED; 04753 gtk_sheet_real_select_range(sheet, NULL); 04754 04755 } 04756 04757 void 04758 gtk_sheet_unselect_range (GtkSheet * sheet) 04759 { 04760 gtk_sheet_real_unselect_range(sheet, NULL); 04761 sheet->state = GTK_STATE_NORMAL; 04762 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, sheet->active_cell.col); 04763 } 04764 04765 04766 static void 04767 gtk_sheet_real_unselect_range (GtkSheet * sheet, 04768 const GtkSheetRange *range) 04769 { 04770 gint i; 04771 04772 g_return_if_fail (sheet != NULL); 04773 g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))); 04774 04775 if(range==NULL){ 04776 range=&sheet->range; 04777 } 04778 04779 if(range->row0 < 0 || range->rowi < 0) return; 04780 if(range->col0 < 0 || range->coli < 0) return; 04781 04782 if (gtk_sheet_range_isvisible (sheet, *range)){ 04783 gtk_sheet_draw_backing_pixmap(sheet, *range); 04784 } 04785 04786 for(i=range->col0; i<=range->coli; i++){ 04787 column_button_release(sheet, i); 04788 } 04789 04790 for(i=range->row0; i<=range->rowi; i++){ 04791 row_button_release(sheet, i); 04792 } 04793 04794 } 04795 04796 04797 static gint 04798 gtk_sheet_expose (GtkWidget * widget, 04799 GdkEventExpose * event) 04800 { 04801 GtkSheet *sheet; 04802 GtkSheetRange range; 04803 04804 #ifdef DEBUG 04805 printf("---> Entered gtk_sheet_expose ... must have received expose_event\n"); 04806 #endif 04807 04808 g_return_val_if_fail (widget != NULL, FALSE); 04809 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE); 04810 g_return_val_if_fail (event != NULL, FALSE); 04811 04812 sheet = GTK_SHEET (widget); 04813 04814 if (GTK_WIDGET_DRAWABLE (widget)) 04815 { 04816 range.row0=ROW_FROM_YPIXEL(sheet,event->area.y); 04817 range.col0=COLUMN_FROM_XPIXEL(sheet,event->area.x); 04818 range.rowi=ROW_FROM_YPIXEL(sheet,event->area.y+event->area.height); 04819 range.coli=COLUMN_FROM_XPIXEL(sheet,event->area.x+event->area.width); 04820 04821 /* exposure events on the sheet */ 04822 04823 if( (event->window == sheet->row_title_window) && sheet->row_titles_visible){ 04824 size_allocate_row_title_buttons(sheet); 04825 } 04826 04827 if( (event->window == sheet->column_title_window) && sheet->column_titles_visible){ 04828 size_allocate_column_title_buttons(sheet); 04829 } 04830 04831 if (event->window == sheet->sheet_window){ 04832 gtk_sheet_draw_backing_pixmap(sheet, range); 04833 04834 if(sheet->state != GTK_SHEET_NORMAL){ 04835 if(gtk_sheet_range_isvisible(sheet, sheet->range)) 04836 gtk_sheet_draw_backing_pixmap(sheet, sheet->range); 04837 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet)) 04838 gtk_sheet_draw_backing_pixmap(sheet, sheet->drag_range); 04839 04840 if(gtk_sheet_range_isvisible(sheet, sheet->range)) 04841 gtk_sheet_range_draw_selection(sheet, sheet->range); 04842 if(GTK_SHEET_IN_RESIZE(sheet) || GTK_SHEET_IN_DRAG(sheet)) 04843 draw_xor_rectangle(sheet, sheet->drag_range); 04844 } 04845 04846 if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet))){ 04847 if(sheet->state == GTK_SHEET_NORMAL){ 04848 gtk_sheet_draw_active_cell(sheet); 04849 if(!GTK_SHEET_IN_SELECTION(sheet)) 04850 gtk_widget_queue_draw(sheet->sheet_entry); 04851 } 04852 } 04853 04854 04855 } 04856 04857 } 04858 04859 if(sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)) 04860 gtk_widget_grab_focus(GTK_WIDGET(sheet)); 04861 04862 (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event); 04863 04864 #ifdef DEBUG 04865 printf("<--- Leaving gtk_sheet_expose\n"); 04866 #endif 04867 04868 return FALSE; 04869 } 04870 04871 04872 static gint 04873 gtk_sheet_button_press (GtkWidget * widget, 04874 GdkEventButton * event) 04875 { 04876 GtkSheet *sheet; 04877 GdkModifierType mods; 04878 gint x, y, row, column; 04879 gboolean veto; 04880 04881 g_return_val_if_fail (widget != NULL, FALSE); 04882 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE); 04883 g_return_val_if_fail (event != NULL, FALSE); 04884 04885 if(event->type != GDK_BUTTON_PRESS) return TRUE; 04886 gdk_window_get_pointer(widget->window, NULL, NULL, &mods); 04887 if(!(mods & GDK_BUTTON1_MASK)) return TRUE; 04888 04889 sheet = GTK_SHEET (widget); 04890 04891 /* press on resize windows */ 04892 if (event->window == sheet->column_title_window && 04893 gtk_sheet_columns_resizable(sheet)) 04894 { 04895 gtk_widget_get_pointer (widget, &sheet->x_drag, NULL); 04896 if(POSSIBLE_XDRAG(sheet, sheet->x_drag, &sheet->drag_cell.col)){ 04897 guint req; 04898 gtk_sheet_column_size_request(sheet, sheet->drag_cell.col, &req); 04899 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG); 04900 gdk_pointer_grab (sheet->column_title_window, FALSE, 04901 GDK_POINTER_MOTION_HINT_MASK | 04902 GDK_BUTTON1_MOTION_MASK | 04903 GDK_BUTTON_RELEASE_MASK, 04904 NULL, NULL, event->time); 04905 04906 draw_xor_vline (sheet); 04907 return TRUE; 04908 } 04909 } 04910 04911 if (event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet)) 04912 { 04913 gtk_widget_get_pointer (widget, NULL, &sheet->y_drag); 04914 04915 if(POSSIBLE_YDRAG(sheet, sheet->y_drag, &sheet->drag_cell.row)){ 04916 guint req; 04917 gtk_sheet_row_size_request(sheet, sheet->drag_cell.row, &req); 04918 GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_YDRAG); 04919 gdk_pointer_grab (sheet->row_title_window, FALSE, 04920 GDK_POINTER_MOTION_HINT_MASK | 04921 GDK_BUTTON1_MOTION_MASK | 04922 GDK_BUTTON_RELEASE_MASK, 04923 NULL, NULL, event->time); 04924 04925 draw_xor_hline (sheet); 04926 return TRUE; 04927 } 04928 } 04929 04930 /* selections on the sheet */ 04931 if(event->window == sheet->sheet_window){ 04932 gtk_widget_get_pointer (widget, &x, &y); 04933 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column); 04934 gdk_pointer_grab (sheet->sheet_window, FALSE, 04935 GDK_POINTER_MOTION_HINT_MASK | 04936 GDK_BUTTON1_MOTION_MASK | 04937 GDK_BUTTON_RELEASE_MASK, 04938 NULL, NULL, event->time); 04939 gtk_grab_add(GTK_WIDGET(sheet)); 04940 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet); 04941 GTK_WIDGET_UNSET_FLAGS(sheet->sheet_entry, GTK_HAS_FOCUS); 04942 GTK_WIDGET_SET_FLAGS(GTK_SHEET(sheet), GTK_HAS_FOCUS); 04943 gtk_widget_grab_focus(GTK_WIDGET(sheet)); 04944 04945 if(sheet->selection_mode != GTK_SELECTION_SINGLE && 04946 sheet->cursor_drag->type==GDK_SIZING && 04947 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_RESIZE(sheet)){ 04948 if(sheet->state==GTK_STATE_NORMAL) { 04949 row=sheet->active_cell.row; 04950 column=sheet->active_cell.col; 04951 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE; 04952 sheet->active_cell.row=row; 04953 sheet->active_cell.col=column; 04954 sheet->drag_range=sheet->range; 04955 sheet->state=GTK_SHEET_RANGE_SELECTED; 04956 gtk_sheet_select_range(sheet, &sheet->drag_range); 04957 } 04958 sheet->x_drag=x; 04959 sheet->y_drag=y; 04960 if(row > sheet->range.rowi) row--; 04961 if(column > sheet->range.coli) column--; 04962 sheet->drag_cell.row = row; 04963 sheet->drag_cell.col = column; 04964 sheet->drag_range=sheet->range; 04965 draw_xor_rectangle(sheet, sheet->drag_range); 04966 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE); 04967 } 04968 else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW && 04969 !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_DRAG(sheet)) { 04970 if(sheet->state==GTK_STATE_NORMAL) { 04971 row=sheet->active_cell.row; 04972 column=sheet->active_cell.col; 04973 if(!gtk_sheet_deactivate_cell(sheet)) return FALSE; 04974 sheet->active_cell.row=row; 04975 sheet->active_cell.col=column; 04976 sheet->drag_range=sheet->range; 04977 sheet->state=GTK_SHEET_RANGE_SELECTED; 04978 gtk_sheet_select_range(sheet, &sheet->drag_range); 04979 } 04980 sheet->x_drag=x; 04981 sheet->y_drag=y; 04982 if(row < sheet->range.row0) row++; 04983 if(row > sheet->range.rowi) row--; 04984 if(column < sheet->range.col0) column++; 04985 if(column > sheet->range.coli) column--; 04986 sheet->drag_cell.row=row; 04987 sheet->drag_cell.col=column; 04988 sheet->drag_range=sheet->range; 04989 draw_xor_rectangle(sheet, sheet->drag_range); 04990 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG); 04991 } 04992 else 04993 { 04994 gtk_sheet_click_cell(sheet, row, column, &veto); 04995 if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); 04996 } 04997 04998 } 04999 05000 if(event->window == sheet->column_title_window){ 05001 gtk_widget_get_pointer (widget, &x, &y); 05002 column = COLUMN_FROM_XPIXEL(sheet, x); 05003 if(sheet->column[column].is_sensitive){; 05004 gtk_sheet_click_cell(sheet, -1, column, &veto); 05005 gtk_grab_add(GTK_WIDGET(sheet)); 05006 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet); 05007 GTK_WIDGET_UNSET_FLAGS(sheet->sheet_entry, GTK_HAS_FOCUS); 05008 GTK_WIDGET_SET_FLAGS(GTK_SHEET(sheet), GTK_HAS_FOCUS); 05009 gtk_widget_grab_focus(GTK_WIDGET(sheet)); 05010 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); 05011 } 05012 } 05013 05014 if(event->window == sheet->row_title_window){ 05015 gtk_widget_get_pointer (widget, &x, &y); 05016 row = ROW_FROM_YPIXEL(sheet, y); 05017 if(sheet->row[row].is_sensitive){ 05018 gtk_sheet_click_cell(sheet, row, -1, &veto); 05019 gtk_grab_add(GTK_WIDGET(sheet)); 05020 sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet); 05021 GTK_WIDGET_UNSET_FLAGS(sheet->sheet_entry, GTK_HAS_FOCUS); 05022 GTK_WIDGET_SET_FLAGS(GTK_SHEET(sheet), GTK_HAS_FOCUS); 05023 gtk_widget_grab_focus(GTK_WIDGET(sheet)); 05024 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); 05025 } 05026 } 05027 05028 return TRUE; 05029 } 05030 05031 static gint 05032 gtk_sheet_scroll(gpointer data) 05033 { 05034 GtkSheet *sheet; 05035 gint x,y,row,column; 05036 gint move; 05037 05038 sheet=GTK_SHEET(data); 05039 05040 GDK_THREADS_ENTER(); 05041 05042 gtk_widget_get_pointer (GTK_WIDGET(sheet), &x, &y); 05043 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column); 05044 05045 move=TRUE; 05046 05047 if(GTK_SHEET_IN_SELECTION(sheet)) 05048 gtk_sheet_extend_selection(sheet, row, column); 05049 05050 if(GTK_SHEET_IN_DRAG(sheet) || GTK_SHEET_IN_RESIZE(sheet)){ 05051 move=gtk_sheet_move_query(sheet, row, column); 05052 if(move) draw_xor_rectangle(sheet, sheet->drag_range); 05053 } 05054 05055 GDK_THREADS_LEAVE(); 05056 05057 return TRUE; 05058 05059 } 05060 05061 static void 05062 gtk_sheet_click_cell(GtkSheet *sheet, gint row, gint column, gboolean *veto) 05063 { 05064 *veto = TRUE; 05065 05066 if(row > sheet->maxrow || column > sheet->maxcol){ 05067 *veto = FALSE; 05068 return; 05069 } 05070 05071 if(column >= 0 && row >= 0) 05072 if(!sheet->column[column].is_visible || !sheet->row[row].is_visible) 05073 { 05074 *veto = FALSE; 05075 return; 05076 } 05077 05078 _gtkextra_signal_emit(GTK_OBJECT(sheet), sheet_signals[TRAVERSE], 05079 sheet->active_cell.row, sheet->active_cell.col, 05080 &row, &column, veto); 05081 05082 if(!*veto){ 05083 if(sheet->state == GTK_STATE_NORMAL) return; 05084 05085 row = sheet->active_cell.row; 05086 column = sheet->active_cell.col; 05087 gtk_sheet_activate_cell(sheet, row, column); 05088 return; 05089 } 05090 05091 if(row == -1 && column >= 0){ 05092 if(gtk_sheet_autoscroll(sheet)) 05093 gtk_sheet_move_query(sheet, row, column); 05094 gtk_sheet_select_column(sheet, column); 05095 return; 05096 } 05097 if(column == -1 && row >= 0){ 05098 if(gtk_sheet_autoscroll(sheet)) 05099 gtk_sheet_move_query(sheet, row, column); 05100 gtk_sheet_select_row(sheet, row); 05101 return; 05102 } 05103 05104 if(row==-1 && column ==-1){ 05105 sheet->range.row0=0; 05106 sheet->range.col0=0; 05107 sheet->range.rowi=sheet->maxrow; 05108 sheet->range.coli=sheet->maxcol; 05109 sheet->active_cell.row=0; 05110 sheet->active_cell.col=0; 05111 gtk_sheet_select_range(sheet, NULL); 05112 return; 05113 } 05114 05115 if(row!=-1 && column !=-1){ 05116 if(sheet->state != GTK_SHEET_NORMAL){ 05117 sheet->state = GTK_SHEET_NORMAL; 05118 gtk_sheet_real_unselect_range(sheet, NULL); 05119 } 05120 else 05121 { 05122 if(!gtk_sheet_deactivate_cell(sheet)){ 05123 *veto = FALSE; 05124 return; 05125 } 05126 } 05127 05128 if(gtk_sheet_autoscroll(sheet)) 05129 gtk_sheet_move_query(sheet, row, column); 05130 sheet->active_cell.row=row; 05131 sheet->active_cell.col=column; 05132 sheet->selection_cell.row=row; 05133 sheet->selection_cell.col=column; 05134 sheet->range.row0=row; 05135 sheet->range.col0=column; 05136 sheet->range.rowi=row; 05137 sheet->range.coli=column; 05138 sheet->state=GTK_SHEET_NORMAL; 05139 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); 05140 gtk_sheet_draw_active_cell(sheet); 05141 return; 05142 } 05143 05144 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, 05145 sheet->active_cell.col); 05146 } 05147 05148 static gint 05149 gtk_sheet_button_release (GtkWidget * widget, 05150 GdkEventButton * event) 05151 { 05152 GtkSheet *sheet; 05153 gint x,y; 05154 05155 sheet=GTK_SHEET(widget); 05156 05157 /* release on resize windows */ 05158 if (GTK_SHEET_IN_XDRAG (sheet)){ 05159 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG); 05160 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION); 05161 gtk_widget_get_pointer (widget, &x, NULL); 05162 gdk_pointer_ungrab (event->time); 05163 draw_xor_vline (sheet); 05164 05165 gtk_sheet_set_column_width (sheet, sheet->drag_cell.col, new_column_width (sheet, sheet->drag_cell.col, &x)); 05166 sheet->old_hadjustment = -1.; 05167 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), "value_changed"); 05168 return TRUE; 05169 } 05170 05171 if (GTK_SHEET_IN_YDRAG (sheet)){ 05172 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG); 05173 GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION); 05174 gtk_widget_get_pointer (widget, NULL, &y); 05175 gdk_pointer_ungrab (event->time); 05176 draw_xor_hline (sheet); 05177 05178 gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y)); 05179 sheet->old_vadjustment = -1.; 05180 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), "value_changed"); 05181 return TRUE; 05182 } 05183 05184 05185 if (GTK_SHEET_IN_DRAG(sheet)){ 05186 GtkSheetRange old_range; 05187 draw_xor_rectangle(sheet, sheet->drag_range); 05188 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_DRAG); 05189 gdk_pointer_ungrab (event->time); 05190 05191 gtk_sheet_real_unselect_range(sheet, NULL); 05192 05193 sheet->active_cell.row = sheet->active_cell.row + 05194 (sheet->drag_range.row0 - sheet->range.row0); 05195 sheet->active_cell.col = sheet->active_cell.col + 05196 (sheet->drag_range.col0 - sheet->range.col0); 05197 sheet->selection_cell.row = sheet->selection_cell.row + 05198 (sheet->drag_range.row0 - sheet->range.row0); 05199 sheet->selection_cell.col = sheet->selection_cell.col + 05200 (sheet->drag_range.col0 - sheet->range.col0); 05201 old_range=sheet->range; 05202 sheet->range=sheet->drag_range; 05203 sheet->drag_range=old_range; 05204 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[MOVE_RANGE], 05205 &sheet->drag_range, &sheet->range); 05206 gtk_sheet_select_range(sheet, &sheet->range); 05207 } 05208 05209 if (GTK_SHEET_IN_RESIZE(sheet)){ 05210 GtkSheetRange old_range; 05211 draw_xor_rectangle(sheet, sheet->drag_range); 05212 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_RESIZE); 05213 gdk_pointer_ungrab (event->time); 05214 05215 gtk_sheet_real_unselect_range(sheet, NULL); 05216 05217 sheet->active_cell.row = sheet->active_cell.row + 05218 (sheet->drag_range.row0 - sheet->range.row0); 05219 sheet->active_cell.col = sheet->active_cell.col + 05220 (sheet->drag_range.col0 - sheet->range.col0); 05221 if(sheet->drag_range.row0 < sheet->range.row0) 05222 sheet->selection_cell.row = sheet->drag_range.row0; 05223 if(sheet->drag_range.rowi >= sheet->range.rowi) 05224 sheet->selection_cell.row = sheet->drag_range.rowi; 05225 if(sheet->drag_range.col0 < sheet->range.col0) 05226 sheet->selection_cell.col = sheet->drag_range.col0; 05227 if(sheet->drag_range.coli >= sheet->range.coli) 05228 sheet->selection_cell.col = sheet->drag_range.coli; 05229 old_range = sheet->range; 05230 sheet->range = sheet->drag_range; 05231 sheet->drag_range = old_range; 05232 05233 if(sheet->state==GTK_STATE_NORMAL) sheet->state=GTK_SHEET_RANGE_SELECTED; 05234 gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[RESIZE_RANGE], 05235 &sheet->drag_range, &sheet->range); 05236 gtk_sheet_select_range(sheet, &sheet->range); 05237 } 05238 05239 if(sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION(sheet)){ 05240 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); 05241 gdk_pointer_ungrab (event->time); 05242 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, 05243 sheet->active_cell.col); 05244 } 05245 05246 if(GTK_SHEET_IN_SELECTION) 05247 gdk_pointer_ungrab (event->time); 05248 if(sheet->timer) 05249 gtk_timeout_remove(sheet->timer); 05250 gtk_grab_remove(GTK_WIDGET(sheet)); 05251 05252 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); 05253 05254 return TRUE; 05255 } 05256 05257 static gint 05258 gtk_sheet_motion (GtkWidget * widget, 05259 GdkEventMotion * event) 05260 { 05261 GtkSheet *sheet; 05262 GdkModifierType mods; 05263 GdkCursorType new_cursor; 05264 gint x, y, row, column; 05265 05266 g_return_val_if_fail (widget != NULL, FALSE); 05267 g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE); 05268 g_return_val_if_fail (event != NULL, FALSE); 05269 05270 05271 sheet = GTK_SHEET (widget); 05272 05273 05274 /* selections on the sheet */ 05275 x = event->x; 05276 y = event->y; 05277 05278 if(event->window == sheet->column_title_window && gtk_sheet_columns_resizable(sheet)){ 05279 gtk_widget_get_pointer(widget, &x, &y); 05280 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_XDRAG(sheet, x, &column)){ 05281 new_cursor=GDK_SB_H_DOUBLE_ARROW; 05282 if(new_cursor != sheet->cursor_drag->type){ 05283 gdk_cursor_destroy(sheet->cursor_drag); 05284 sheet->cursor_drag=gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW); 05285 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag); 05286 } 05287 }else{ 05288 new_cursor=GDK_TOP_LEFT_ARROW; 05289 if(!GTK_SHEET_IN_XDRAG(sheet) && new_cursor != sheet->cursor_drag->type){ 05290 gdk_cursor_destroy(sheet->cursor_drag); 05291 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW); 05292 gdk_window_set_cursor(sheet->column_title_window,sheet->cursor_drag); 05293 } 05294 } 05295 } 05296 05297 if(event->window == sheet->row_title_window && gtk_sheet_rows_resizable(sheet)){ 05298 gtk_widget_get_pointer(widget, &x, &y); 05299 if(!GTK_SHEET_IN_SELECTION(sheet) && POSSIBLE_YDRAG(sheet,y, &column)){ 05300 new_cursor=GDK_SB_V_DOUBLE_ARROW; 05301 if(new_cursor != sheet->cursor_drag->type){ 05302 gdk_cursor_destroy(sheet->cursor_drag); 05303 sheet->cursor_drag=gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW); 05304 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag); 05305 } 05306 }else{ 05307 new_cursor=GDK_TOP_LEFT_ARROW; 05308 if(!GTK_SHEET_IN_YDRAG(sheet) && new_cursor != sheet->cursor_drag->type){ 05309 gdk_cursor_destroy(sheet->cursor_drag); 05310 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW); 05311 gdk_window_set_cursor(sheet->row_title_window,sheet->cursor_drag); 05312 } 05313 } 05314 } 05315 05316 new_cursor=GDK_PLUS; 05317 if(!POSSIBLE_DRAG(sheet,x,y,&row,&column) && !GTK_SHEET_IN_DRAG(sheet) && 05318 !POSSIBLE_RESIZE(sheet,x,y,&row,&column) && !GTK_SHEET_IN_RESIZE(sheet) && 05319 event->window == sheet->sheet_window && 05320 new_cursor != sheet->cursor_drag->type){ 05321 gdk_cursor_destroy(sheet->cursor_drag); 05322 sheet->cursor_drag=gdk_cursor_new(GDK_PLUS); 05323 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag); 05324 } 05325 05326 new_cursor=GDK_TOP_LEFT_ARROW; 05327 if(!(POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) && 05328 (POSSIBLE_DRAG(sheet, x,y,&row,&column) || GTK_SHEET_IN_DRAG(sheet)) && 05329 event->window == sheet->sheet_window && 05330 new_cursor != sheet->cursor_drag->type){ 05331 gdk_cursor_destroy(sheet->cursor_drag); 05332 sheet->cursor_drag=gdk_cursor_new(GDK_TOP_LEFT_ARROW); 05333 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag); 05334 } 05335 05336 new_cursor=GDK_SIZING; 05337 if(!GTK_SHEET_IN_DRAG(sheet) && 05338 (POSSIBLE_RESIZE(sheet,x,y,&row,&column) || GTK_SHEET_IN_RESIZE(sheet)) && 05339 event->window == sheet->sheet_window && 05340 new_cursor != sheet->cursor_drag->type){ 05341 gdk_cursor_destroy(sheet->cursor_drag); 05342 sheet->cursor_drag=gdk_cursor_new(GDK_SIZING); 05343 gdk_window_set_cursor(sheet->sheet_window,sheet->cursor_drag); 05344 } 05345 05346 gdk_window_get_pointer (widget->window, &x, &y, &mods); 05347 if(!(mods & GDK_BUTTON1_MASK)) return FALSE; 05348 05349 if (GTK_SHEET_IN_XDRAG (sheet)){ 05350 if (event->is_hint || event->window != widget->window) 05351 gtk_widget_get_pointer (widget, &x, NULL); 05352 else 05353 x = event->x; 05354 05355 new_column_width (sheet, sheet->drag_cell.col, &x); 05356 if (x != sheet->x_drag) 05357 { 05358 draw_xor_vline (sheet); 05359 sheet->x_drag = x; 05360 draw_xor_vline (sheet); 05361 } 05362 return TRUE; 05363 } 05364 05365 if (GTK_SHEET_IN_YDRAG (sheet)){ 05366 if (event->is_hint || event->window != widget->window) 05367 gtk_widget_get_pointer (widget, NULL, &y); 05368 else 05369 y = event->y; 05370 05371 new_row_height (sheet, sheet->drag_cell.row, &y); 05372 if (y != sheet->y_drag) 05373 { 05374 draw_xor_hline (sheet); 05375 sheet->y_drag = y; 05376 draw_xor_hline (sheet); 05377 } 05378 return TRUE; 05379 } 05380 05381 if (GTK_SHEET_IN_DRAG(sheet)){ 05382 GtkSheetRange aux; 05383 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col; 05384 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row; 05385 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0; 05386 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0; 05387 sheet->x_drag=x; 05388 sheet->y_drag=y; 05389 aux=sheet->range; 05390 if(aux.row0+row >= 0 && aux.rowi+row <= sheet->maxrow && 05391 aux.col0+column >= 0 && aux.coli+column <= sheet->maxcol){ 05392 aux=sheet->drag_range; 05393 sheet->drag_range.row0=sheet->range.row0+row; 05394 sheet->drag_range.col0=sheet->range.col0+column; 05395 sheet->drag_range.rowi=sheet->range.rowi+row; 05396 sheet->drag_range.coli=sheet->range.coli+column; 05397 if(aux.row0 != sheet->drag_range.row0 || 05398 aux.col0 != sheet->drag_range.col0){ 05399 draw_xor_rectangle (sheet, aux); 05400 draw_xor_rectangle (sheet, sheet->drag_range); 05401 } 05402 } 05403 return TRUE; 05404 } 05405 05406 if (GTK_SHEET_IN_RESIZE(sheet)){ 05407 GtkSheetRange aux; 05408 gint v_h; 05409 v_h=1; 05410 if(abs(x-COLUMN_LEFT_XPIXEL(sheet,sheet->drag_cell.col)) > 05411 abs(y-ROW_TOP_YPIXEL(sheet,sheet->drag_cell.row))) v_h=2; 05412 05413 column=COLUMN_FROM_XPIXEL(sheet,x)-sheet->drag_cell.col; 05414 row=ROW_FROM_YPIXEL(sheet,y)-sheet->drag_cell.row; 05415 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) row=0; 05416 if(sheet->state==GTK_SHEET_ROW_SELECTED) column=0; 05417 sheet->x_drag=x; 05418 sheet->y_drag=y; 05419 aux=sheet->range; 05420 05421 if(row < sheet->range.row0 - sheet->range.rowi - 1) 05422 row=row+(sheet->range.rowi-sheet->range.row0 + 1); 05423 else if(row<0) row=0; 05424 05425 if(column < sheet->range.col0 - sheet->range.coli - 1) 05426 column=column+(sheet->range.coli-sheet->range.col0 + 1); 05427 else if(column<0) column=0; 05428 05429 if(v_h==1) 05430 column=0; 05431 else 05432 row=0; 05433 05434 if(aux.row0+row >= 0 && aux.rowi+row <= sheet->maxrow && 05435 aux.col0+column >= 0 && aux.coli+column <= sheet->maxcol){ 05436 05437 aux=sheet->drag_range; 05438 sheet->drag_range=sheet->range; 05439 05440 if(row<0) sheet->drag_range.row0=sheet->range.row0+row; 05441 if(row>0) sheet->drag_range.rowi=sheet->range.rowi+row; 05442 if(column<0) sheet->drag_range.col0=sheet->range.col0+column; 05443 if(column>0) sheet->drag_range.coli=sheet->range.coli+column; 05444 05445 if(aux.row0 != sheet->drag_range.row0 || 05446 aux.rowi != sheet->drag_range.rowi || 05447 aux.col0 != sheet->drag_range.col0 || 05448 aux.coli != sheet->drag_range.coli){ 05449 draw_xor_rectangle (sheet, aux); 05450 draw_xor_rectangle (sheet, sheet->drag_range); 05451 } 05452 } 05453 return TRUE; 05454 } 05455 05456 05457 05458 gtk_sheet_get_pixel_info (sheet, x, y, &row, &column); 05459 05460 if(sheet->state==GTK_SHEET_NORMAL && row==sheet->active_cell.row && 05461 column==sheet->active_cell.col) return TRUE; 05462 05463 if(GTK_SHEET_IN_SELECTION(sheet) && mods&GDK_BUTTON1_MASK) 05464 gtk_sheet_extend_selection(sheet, row, column); 05465 05466 return TRUE; 05467 } 05468 05469 static gint 05470 gtk_sheet_move_query(GtkSheet *sheet, gint row, gint column) 05471 { 05472 gint row_move, column_move; 05473 gfloat row_align, col_align; 05474 guint height, width; 05475 gint new_row = row; 05476 gint new_col = column; 05477 05478 row_move=FALSE; 05479 column_move=FALSE; 05480 row_align=-1.; 05481 col_align=-1.; 05482 05483 height = sheet->sheet_window_height; 05484 width = sheet->sheet_window_width; 05485 05486 if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) { 05487 row_align = 1.; 05488 new_row = MIN(sheet->maxrow, row + 1); 05489 row_move = TRUE; 05490 if(MAX_VISIBLE_ROW(sheet) == sheet->maxrow && 05491 ROW_TOP_YPIXEL(sheet, sheet->maxrow) + 05492 sheet->row[sheet->maxrow].height < height){ 05493 row_move = FALSE; 05494 row_align = -1.; 05495 } 05496 } 05497 if(row<MIN_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) { 05498 row_align= 0.; 05499 row_move = TRUE; 05500 } 05501 if(column>=MAX_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) { 05502 col_align = 1.; 05503 new_col = MIN(sheet->maxcol, column + 1); 05504 column_move = TRUE; 05505 if(MAX_VISIBLE_COLUMN(sheet) == sheet->maxcol && 05506 COLUMN_LEFT_XPIXEL(sheet, sheet->maxcol) + 05507 sheet->column[sheet->maxcol].width < width){ 05508 column_move = FALSE; 05509 col_align = -1.; 05510 } 05511 } 05512 if(column<MIN_VISIBLE_COLUMN(sheet) && sheet->state!=GTK_SHEET_ROW_SELECTED) { 05513 col_align = 0.; 05514 column_move = TRUE; 05515 } 05516 05517 if(row_move || column_move){ 05518 gtk_sheet_moveto(sheet, new_row, new_col, row_align, col_align); 05519 } 05520 05521 return(row_move || column_move); 05522 } 05523 05524 static void 05525 gtk_sheet_extend_selection(GtkSheet *sheet, gint row, gint column) 05526 { 05527 GtkSheetRange range; 05528 gint state; 05529 gint r,c; 05530 05531 if(row == sheet->selection_cell.row && column == sheet->selection_cell.col) 05532 return; 05533 05534 if(sheet->selection_mode == GTK_SELECTION_SINGLE) return; 05535 05536 gtk_sheet_move_query(sheet, row, column); 05537 gtk_widget_grab_focus(GTK_WIDGET(sheet)); 05538 05539 if(GTK_SHEET_IN_DRAG(sheet)) return; 05540 05541 state=sheet->state; 05542 05543 switch(sheet->state){ 05544 case GTK_SHEET_ROW_SELECTED: 05545 column = sheet->maxcol; 05546 break; 05547 case GTK_SHEET_COLUMN_SELECTED: 05548 row = sheet->maxrow; 05549 break; 05550 case GTK_SHEET_NORMAL: 05551 sheet->state=GTK_SHEET_RANGE_SELECTED; 05552 r=sheet->active_cell.row; 05553 c=sheet->active_cell.col; 05554 sheet->range.col0=c; 05555 sheet->range.row0=r; 05556 sheet->range.coli=c; 05557 sheet->range.rowi=r; 05558 gdk_draw_pixmap(sheet->sheet_window, 05559 GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL], 05560 sheet->pixmap, 05561 COLUMN_LEFT_XPIXEL(sheet,c)-1, 05562 ROW_TOP_YPIXEL(sheet,r)-1, 05563 COLUMN_LEFT_XPIXEL(sheet,c)-1, 05564 ROW_TOP_YPIXEL(sheet,r)-1, 05565 sheet->column[c].width+4, 05566 sheet->row[r].height+4); 05567 gtk_sheet_range_draw_selection(sheet, sheet->range); 05568 case GTK_SHEET_RANGE_SELECTED: 05569 sheet->state=GTK_SHEET_RANGE_SELECTED; 05570 } 05571 05572 sheet->selection_cell.row = row; 05573 sheet->selection_cell.col = column; 05574 05575 range.col0=MIN(column,sheet->active_cell.col); 05576 range.coli=MAX(column,sheet->active_cell.col); 05577 range.row0=MIN(row,sheet->active_cell.row); 05578 range.rowi=MAX(row,sheet->active_cell.row); 05579 05580 if(range.row0 != sheet->range.row0 || range.rowi != sheet->range.rowi || 05581 range.col0 != sheet->range.col0 || range.coli != sheet->range.coli || 05582 state==GTK_SHEET_NORMAL) 05583 gtk_sheet_real_select_range(sheet, &range); 05584 05585 } 05586 05587 /* Removed by SDB while cleaning up key press behavior */ 05588 #if 0 05589 static gint 05590 gtk_sheet_entry_key_press(GtkWidget *widget, 05591 GdkEventKey *key) 05592 { 05593 gboolean focus; 05594 #ifdef DEBUG 05595 printf("Entered gtk_sheet_entry_key_press. . . . . \n"); 05596 #endif 05597 05598 gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", key, &focus); 05599 return focus; 05600 } 05601 #endif 05602 05603 static gint 05604 gtk_sheet_key_press(GtkWidget *widget, 05605 GdkEventKey *key) 05606 { 05607 GtkSheet *sheet; 05608 gint row, col; 05609 gint state; 05610 gboolean extend_selection = FALSE; 05611 #if 0 05612 gboolean force_move = FALSE; 05613 #endif 05614 gboolean in_selection = FALSE; 05615 gboolean veto = TRUE; 05616 gint scroll = 1; 05617 05618 sheet = GTK_SHEET(widget); 05619 05620 #ifdef DEBUG 05621 printf("\n\nJust entered gtk_sheet_key_press. . . . \n"); 05622 #endif 05623 05624 05625 if(key->state & GDK_CONTROL_MASK || key->keyval==GDK_Control_L || 05626 key->keyval==GDK_Control_R) return FALSE; 05627 05628 /* 05629 { 05630 if(key->keyval=='c' || key->keyval == 'C' && sheet->state != GTK_STATE_NORMAL) 05631 gtk_sheet_clip_range(sheet, sheet->range); 05632 if(key->keyval=='x' || key->keyval == 'X') 05633 gtk_sheet_unclip_range(sheet); 05634 return FALSE; 05635 } 05636 */ 05637 05638 /* extend_selection is set when shift, ctrl, etc is pressed & held down */ 05639 extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval==GDK_Shift_L 05640 || key->keyval==GDK_Shift_R; 05641 05642 #ifdef DEBUG 05643 printf(". . . . extend_selection = %d\n", extend_selection); 05644 #endif 05645 05646 state=sheet->state; 05647 in_selection = GTK_SHEET_IN_SELECTION(sheet); 05648 GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); 05649 05650 #ifdef DEBUG 05651 printf("We are about to enter the switch statement. . .\n"); 05652 #endif 05653 05654 switch(key->keyval){ 05655 case GDK_Return: case GDK_KP_Enter: 05656 if(sheet->state == GTK_SHEET_NORMAL && 05657 !GTK_SHEET_IN_SELECTION(sheet)) 05658 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtk_sheet_get_entry(sheet)), 05659 "key_press_event"); 05660 row = sheet->active_cell.row; 05661 col = sheet->active_cell.col; 05662 if(sheet->state == GTK_SHEET_COLUMN_SELECTED) 05663 row = MIN_VISIBLE_ROW(sheet)-1; 05664 if(sheet->state == GTK_SHEET_ROW_SELECTED) 05665 col = MIN_VISIBLE_COLUMN(sheet); 05666 if(row < sheet->maxrow){ 05667 row = row + scroll; 05668 while(!sheet->row[row].is_visible && row<sheet->maxrow) row++; 05669 } 05670 gtk_sheet_click_cell(sheet, row, col, &veto); 05671 extend_selection = FALSE; 05672 break; 05673 05674 case GDK_ISO_Left_Tab: 05675 case GDK_Left: /* Left arrow */ 05676 #ifdef DEBUG 05677 printf("In gtk_sheet_key_press, received GDK_Left.\n"); 05678 #endif 05679 row = sheet->active_cell.row; 05680 col = sheet->active_cell.col; 05681 if(sheet->state == GTK_SHEET_ROW_SELECTED) 05682 col = MIN_VISIBLE_COLUMN(sheet)-1; 05683 if(sheet->state == GTK_SHEET_COLUMN_SELECTED) 05684 row = MIN_VISIBLE_ROW(sheet); 05685 if(col > 0){ 05686 col = col - scroll; 05687 while(!sheet->column[col].is_visible && col>0) col--; 05688 col=MAX(0, col); 05689 } 05690 gtk_sheet_click_cell(sheet, row, col, &veto); 05691 extend_selection = FALSE; 05692 break; 05693 05694 case GDK_Tab: 05695 case GDK_Right: /* Right arrow */ 05696 #ifdef DEBUG 05697 printf("In gtk_sheet_key_press, received GDK_Right.\n"); 05698 #endif 05699 row = sheet->active_cell.row; 05700 col = sheet->active_cell.col; 05701 if(sheet->state == GTK_SHEET_ROW_SELECTED) 05702 col = MIN_VISIBLE_COLUMN(sheet)-1; 05703 if(sheet->state == GTK_SHEET_COLUMN_SELECTED) 05704 row = MIN_VISIBLE_ROW(sheet); 05705 if(col < sheet->maxcol){ 05706 col = col + scroll; 05707 while(!sheet->column[col].is_visible && col<sheet->maxcol) col++; 05708 } 05709 gtk_sheet_click_cell(sheet, row, col, &veto); 05710 extend_selection = FALSE; 05711 break; 05712 05713 /* case GDK_BackSpace: 05714 if(sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0){ 05715 if(sheet->active_cell.col > 0){ 05716 col = sheet->active_cell.col - scroll; 05717 row = sheet->active_cell.row; 05718 while(!sheet->column[col].is_visible && col > 0) col--; 05719 } 05720 } 05721 gtk_sheet_click_cell(sheet, row, col, &veto); 05722 extend_selection = FALSE; 05723 break; 05724 */ 05725 05726 case GDK_Page_Up: 05727 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1; 05728 case GDK_Up: /* arrow key up */ 05729 if(extend_selection){ 05730 if(state==GTK_STATE_NORMAL){ 05731 row=sheet->active_cell.row; 05732 col=sheet->active_cell.col; 05733 gtk_sheet_click_cell(sheet, row, col, &veto); 05734 if(!veto) break; 05735 } 05736 if(sheet->selection_cell.row > 0){ 05737 row = sheet->selection_cell.row - scroll; 05738 while(!sheet->row[row].is_visible && row > 0) row--; 05739 row = MAX(0, row); 05740 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col); 05741 } 05742 return TRUE; 05743 } 05744 col = sheet->active_cell.col; 05745 row = sheet->active_cell.row; 05746 if(state==GTK_SHEET_COLUMN_SELECTED) 05747 row = MIN_VISIBLE_ROW(sheet); 05748 if(state==GTK_SHEET_ROW_SELECTED) 05749 col = MIN_VISIBLE_COLUMN(sheet); 05750 row = row - scroll; 05751 while(!sheet->row[row].is_visible && row > 0) row--; 05752 row = MAX(0,row); 05753 gtk_sheet_click_cell(sheet, row, col, &veto); 05754 extend_selection = FALSE; 05755 break; 05756 05757 case GDK_Page_Down: 05758 scroll=MAX_VISIBLE_ROW(sheet)-MIN_VISIBLE_ROW(sheet)+1; 05759 case GDK_Down: /* arrow key down */ 05760 if(extend_selection){ 05761 if(state==GTK_STATE_NORMAL){ 05762 row=sheet->active_cell.row; 05763 col=sheet->active_cell.col; 05764 gtk_sheet_click_cell(sheet, row, col, &veto); 05765 if(!veto) break; 05766 } 05767 if(sheet->selection_cell.row < sheet->maxrow){ 05768 row = sheet->selection_cell.row + scroll; 05769 while(!sheet->row[row].is_visible && row < sheet->maxrow) row++; 05770 row = MIN(sheet->maxrow, row); 05771 gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col); 05772 } 05773 return TRUE; 05774 } 05775 col = sheet->active_cell.col; 05776 row = sheet->active_cell.row; 05777 if(sheet->active_cell.row < sheet->maxrow){ 05778 if(state==GTK_SHEET_COLUMN_SELECTED) 05779 row = MIN_VISIBLE_ROW(sheet)-1; 05780 if(state==GTK_SHEET_ROW_SELECTED) 05781 col = MIN_VISIBLE_COLUMN(sheet); 05782 row = row + scroll; 05783 while(!sheet->row[row].is_visible && row < sheet->maxrow) row++; 05784 row = MIN(sheet->maxrow, row); 05785 } 05786 gtk_sheet_click_cell(sheet, row, col, &veto); 05787 extend_selection = FALSE; 05788 break; 05789 05790 #if 0 05791 case GDK_Right: 05792 if(extend_selection){ 05793 if(state==GTK_STATE_NORMAL){ 05794 row=sheet->active_cell.row; 05795 col=sheet->active_cell.col; 05796 gtk_sheet_click_cell(sheet, row, col, &veto); 05797 if(!veto) break; 05798 } 05799 if(sheet->selection_cell.col < sheet->maxcol){ 05800 col = sheet->selection_cell.col + 1; 05801 while(!sheet->column[col].is_visible && col < sheet->maxcol) col++; 05802 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col); 05803 } 05804 return TRUE; 05805 } 05806 col = sheet->active_cell.col; 05807 row = sheet->active_cell.row; 05808 if(sheet->active_cell.col < sheet->maxcol){ 05809 col ++; 05810 if(state==GTK_SHEET_ROW_SELECTED) 05811 col = MIN_VISIBLE_COLUMN(sheet)-1; 05812 if(state==GTK_SHEET_COLUMN_SELECTED) 05813 row = MIN_VISIBLE_ROW(sheet); 05814 while(!sheet->column[col].is_visible && col < sheet->maxcol) col++; 05815 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0 05816 || force_move) { 05817 gtk_sheet_click_cell(sheet, row, col, &veto); 05818 } 05819 else 05820 return FALSE; 05821 } 05822 extend_selection = FALSE; 05823 break; 05824 05825 05826 case GDK_Left: 05827 if(extend_selection){ 05828 if(state==GTK_STATE_NORMAL){ 05829 row=sheet->active_cell.row; 05830 col=sheet->active_cell.col; 05831 gtk_sheet_click_cell(sheet, row, col, &veto); 05832 if(!veto) break; 05833 } 05834 if(sheet->selection_cell.col > 0){ 05835 col = sheet->selection_cell.col - 1; 05836 while(!sheet->column[col].is_visible && col > 0) col--; 05837 gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col); 05838 } 05839 return TRUE; 05840 } 05841 col = sheet->active_cell.col - 1; 05842 row = sheet->active_cell.row; 05843 if(state==GTK_SHEET_ROW_SELECTED) 05844 col = MIN_VISIBLE_COLUMN(sheet)-1; 05845 if(state==GTK_SHEET_COLUMN_SELECTED) 05846 row = MIN_VISIBLE_ROW(sheet); 05847 while(!sheet->column[col].is_visible && col > 0) col--; 05848 col = MAX(0, col); 05849 05850 if(strlen(gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)))) == 0 05851 || force_move){ 05852 gtk_sheet_click_cell(sheet, row, col, &veto); 05853 } 05854 else 05855 return FALSE; 05856 extend_selection = FALSE; 05857 break; 05858 #endif 05859 05860 05861 case GDK_Home: 05862 row=0; 05863 while(!sheet->row[row].is_visible && row < sheet->maxrow) row++; 05864 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto); 05865 extend_selection = FALSE; 05866 break; 05867 05868 case GDK_End: 05869 row=sheet->maxrow; 05870 while(!sheet->row[row].is_visible && row > 0) row--; 05871 gtk_sheet_click_cell(sheet, row, sheet->active_cell.col, &veto); 05872 extend_selection = FALSE; 05873 break; 05874 05875 default: 05876 #ifdef DEBUG 05877 printf("In gtk_sheet_key_press, after switch, found default case.\n"); 05878 printf(" User probably typed letter key or DEL.\n"); 05879 #endif 05880 if(in_selection) { 05881 GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION); 05882 if(extend_selection) return TRUE; 05883 } 05884 if(state == GTK_SHEET_ROW_SELECTED) 05885 sheet->active_cell.col=MIN_VISIBLE_COLUMN(sheet); 05886 if(state == GTK_SHEET_COLUMN_SELECTED) 05887 sheet->active_cell.row=MIN_VISIBLE_ROW(sheet); 05888 return FALSE; 05889 } /* switch */ 05890 05891 if(extend_selection) return TRUE; 05892 05893 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, 05894 sheet->active_cell.col); 05895 05896 return TRUE; 05897 } 05898 05899 static void 05900 gtk_sheet_size_request (GtkWidget * widget, 05901 GtkRequisition * requisition) 05902 { 05903 GtkSheet *sheet; 05904 GList *children; 05905 GtkSheetChild *child; 05906 GtkRequisition child_requisition; 05907 05908 g_return_if_fail (widget != NULL); 05909 g_return_if_fail (GTK_IS_SHEET (widget)); 05910 g_return_if_fail (requisition != NULL); 05911 05912 sheet = GTK_SHEET (widget); 05913 05914 requisition->width = 3*DEFAULT_COLUMN_WIDTH; 05915 requisition->height = 3*DEFAULT_ROW_HEIGHT(widget); 05916 05917 /* compute the size of the column title area */ 05918 if(sheet->column_titles_visible) 05919 requisition->height += sheet->column_title_area.height; 05920 05921 /* compute the size of the row title area */ 05922 if(sheet->row_titles_visible) 05923 requisition->width += sheet->row_title_area.width; 05924 05925 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1); 05926 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1); 05927 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1); 05928 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width); 05929 05930 if(!sheet->column_titles_visible) 05931 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1); 05932 05933 if(!sheet->row_titles_visible) 05934 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1); 05935 05936 children = sheet->children; 05937 while (children) 05938 { 05939 child = children->data; 05940 children = g_list_next(children); 05941 05942 gtk_widget_size_request(child->widget, &child_requisition); 05943 } 05944 } 05945 05946 05947 static void 05948 gtk_sheet_size_allocate (GtkWidget * widget, 05949 GtkAllocation * allocation) 05950 { 05951 GtkSheet *sheet; 05952 GtkAllocation sheet_allocation; 05953 gint border_width; 05954 05955 g_return_if_fail (widget != NULL); 05956 g_return_if_fail (GTK_IS_SHEET (widget)); 05957 g_return_if_fail (allocation != NULL); 05958 05959 sheet = GTK_SHEET (widget); 05960 widget->allocation = *allocation; 05961 border_width = GTK_CONTAINER(widget)->border_width; 05962 05963 if (GTK_WIDGET_REALIZED (widget)) 05964 gdk_window_move_resize (widget->window, 05965 allocation->x + border_width, 05966 allocation->y + border_width, 05967 allocation->width - 2*border_width, 05968 allocation->height - 2*border_width); 05969 05970 /* use internal allocation structure for all the math 05971 * because it's easier than always subtracting the container 05972 * border width */ 05973 sheet->internal_allocation.x = 0; 05974 sheet->internal_allocation.y = 0; 05975 sheet->internal_allocation.width = allocation->width - 2*border_width; 05976 sheet->internal_allocation.height = allocation->height - 2*border_width; 05977 05978 sheet_allocation.x = 0; 05979 sheet_allocation.y = 0; 05980 sheet_allocation.width = allocation->width - 2*border_width; 05981 sheet_allocation.height = allocation->height - 2*border_width; 05982 05983 sheet->sheet_window_width = sheet_allocation.width; 05984 sheet->sheet_window_height = sheet_allocation.height; 05985 05986 if (GTK_WIDGET_REALIZED (widget)) 05987 gdk_window_move_resize (sheet->sheet_window, 05988 sheet_allocation.x, 05989 sheet_allocation.y, 05990 sheet_allocation.width, 05991 sheet_allocation.height); 05992 05993 /* position the window which holds the column title buttons */ 05994 sheet->column_title_area.x = 0; 05995 sheet->column_title_area.y = 0; 05996 if(sheet->row_titles_visible) 05997 sheet->column_title_area.x = sheet->row_title_area.width; 05998 sheet->column_title_area.width = sheet_allocation.width - 05999 sheet->column_title_area.x; 06000 if(GTK_WIDGET_REALIZED(widget) && sheet->column_titles_visible) 06001 gdk_window_move_resize (sheet->column_title_window, 06002 sheet->column_title_area.x, 06003 sheet->column_title_area.y, 06004 sheet->column_title_area.width, 06005 sheet->column_title_area.height); 06006 06007 sheet->sheet_window_width = sheet_allocation.width; 06008 sheet->sheet_window_height = sheet_allocation.height; 06009 06010 /* column button allocation */ 06011 size_allocate_column_title_buttons (sheet); 06012 06013 /* position the window which holds the row title buttons */ 06014 sheet->row_title_area.x = 0; 06015 sheet->row_title_area.y = 0; 06016 if(sheet->column_titles_visible) 06017 sheet->row_title_area.y = sheet->column_title_area.height; 06018 sheet->row_title_area.height = sheet_allocation.height - 06019 sheet->row_title_area.y; 06020 06021 if(GTK_WIDGET_REALIZED(widget) && sheet->row_titles_visible) 06022 gdk_window_move_resize (sheet->row_title_window, 06023 sheet->row_title_area.x, 06024 sheet->row_title_area.y, 06025 sheet->row_title_area.width, 06026 sheet->row_title_area.height); 06027 06028 06029 /* row button allocation */ 06030 size_allocate_row_title_buttons (sheet); 06031 06032 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1); 06033 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1); 06034 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1); 06035 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width); 06036 06037 if(!sheet->column_titles_visible) 06038 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1); 06039 06040 if(!sheet->row_titles_visible) 06041 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1); 06042 06043 size_allocate_column_title_buttons(sheet); 06044 size_allocate_row_title_buttons(sheet); 06045 06046 /* re-scale backing pixmap */ 06047 gtk_sheet_make_backing_pixmap(sheet, 0, 0); 06048 gtk_sheet_position_children(sheet); 06049 06050 /* set the scrollbars adjustments */ 06051 adjust_scrollbars (sheet); 06052 } 06053 06054 static void 06055 size_allocate_column_title_buttons (GtkSheet * sheet) 06056 { 06057 gint i; 06058 gint x,width; 06059 06060 if (!sheet->column_titles_visible) return; 06061 if (!GTK_WIDGET_REALIZED (sheet)) 06062 return; 06063 06064 width = sheet->sheet_window_width; 06065 x = 0; 06066 06067 if(sheet->row_titles_visible) 06068 { 06069 width -= sheet->row_title_area.width; 06070 x = sheet->row_title_area.width; 06071 } 06072 06073 if(sheet->column_title_area.width != width || sheet->column_title_area.x != x) 06074 { 06075 sheet->column_title_area.width = width; 06076 sheet->column_title_area.x = x; 06077 gdk_window_move_resize (sheet->column_title_window, 06078 sheet->column_title_area.x, 06079 sheet->column_title_area.y, 06080 sheet->column_title_area.width, 06081 sheet->column_title_area.height); 06082 } 06083 06084 06085 if(MAX_VISIBLE_COLUMN(sheet) == sheet->maxcol) 06086 gdk_window_clear_area (sheet->column_title_window, 06087 0,0, 06088 sheet->column_title_area.width, 06089 sheet->column_title_area.height); 06090 06091 if(!GTK_WIDGET_DRAWABLE(sheet)) return; 06092 06093 for (i = MIN_VISIBLE_COLUMN(sheet); i <= MAX_VISIBLE_COLUMN(sheet); i++) 06094 gtk_sheet_button_draw(sheet,-1,i); 06095 } 06096 06097 static void 06098 size_allocate_row_title_buttons (GtkSheet * sheet) 06099 { 06100 gint i; 06101 gint y, height; 06102 06103 if (!sheet->row_titles_visible) return; 06104 if (!GTK_WIDGET_REALIZED (sheet)) 06105 return; 06106 06107 height = sheet->sheet_window_height; 06108 y = 0; 06109 06110 if(sheet->column_titles_visible) 06111 { 06112 height -= sheet->column_title_area.height; 06113 y = sheet->column_title_area.height; 06114 } 06115 06116 if(sheet->row_title_area.height != height || sheet->row_title_area.y != y){ 06117 sheet->row_title_area.y = y; 06118 sheet->row_title_area.height = height; 06119 gdk_window_move_resize (sheet->row_title_window, 06120 sheet->row_title_area.x, 06121 sheet->row_title_area.y, 06122 sheet->row_title_area.width, 06123 sheet->row_title_area.height); 06124 } 06125 if(MAX_VISIBLE_ROW(sheet) == sheet->maxrow) 06126 gdk_window_clear_area (sheet->row_title_window, 06127 0,0, 06128 sheet->row_title_area.width, 06129 sheet->row_title_area.height); 06130 06131 if(!GTK_WIDGET_DRAWABLE(sheet)) return; 06132 06133 for(i = MIN_VISIBLE_ROW(sheet); i <= MAX_VISIBLE_ROW(sheet); i++) 06134 gtk_sheet_button_draw(sheet,i,-1); 06135 } 06136 06137 static void 06138 gtk_sheet_recalc_top_ypixels(GtkSheet *sheet, gint row) 06139 { 06140 gint i, cy; 06141 06142 cy = sheet->column_title_area.height; 06143 if(!sheet->column_titles_visible) cy = 0; 06144 for(i=0; i<=sheet->maxrow; i++){ 06145 sheet->row[i].top_ypixel=cy; 06146 if(sheet->row[i].is_visible) cy+=sheet->row[i].height; 06147 } 06148 } 06149 06150 static void 06151 gtk_sheet_recalc_left_xpixels(GtkSheet *sheet, gint column) 06152 { 06153 gint i, cx; 06154 06155 cx = sheet->row_title_area.width; 06156 if(!sheet->row_titles_visible) cx = 0; 06157 for(i=0; i<=sheet->maxcol; i++){ 06158 sheet->column[i].left_xpixel=cx; 06159 if(sheet->column[i].is_visible) cx+=sheet->column[i].width; 06160 } 06161 06162 } 06163 06164 06165 06166 static void 06167 gtk_sheet_size_allocate_entry(GtkSheet *sheet) 06168 { 06169 GtkAllocation shentry_allocation; 06170 GtkSheetCellAttr attributes; 06171 GtkEntry *sheet_entry; 06172 GtkStyle *style = NULL, *previous_style = NULL; 06173 gint row, col; 06174 gint size, max_size, text_size, column_width; 06175 const gchar *text; 06176 06177 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return; 06178 if(!GTK_WIDGET_MAPPED(GTK_WIDGET(sheet))) return; 06179 06180 sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet)); 06181 06182 gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes); 06183 06184 if(GTK_WIDGET_REALIZED(sheet->sheet_entry)){ 06185 06186 if(!GTK_WIDGET(sheet_entry)->style) 06187 gtk_widget_ensure_style(GTK_WIDGET(sheet_entry)); 06188 06189 previous_style = GTK_WIDGET(sheet_entry)->style; 06190 06191 style = gtk_style_copy(previous_style); 06192 style->bg[GTK_STATE_NORMAL] = attributes.background; 06193 style->fg[GTK_STATE_NORMAL] = attributes.foreground; 06194 style->text[GTK_STATE_NORMAL] = attributes.foreground; 06195 style->bg[GTK_STATE_ACTIVE] = attributes.background; 06196 style->fg[GTK_STATE_ACTIVE] = attributes.foreground; 06197 style->text[GTK_STATE_ACTIVE] = attributes.foreground; 06198 06199 pango_font_description_free(style->font_desc); 06200 style->font_desc = pango_font_description_copy(attributes.font_desc); 06201 06202 GTK_WIDGET(sheet_entry)->style = style; 06203 gtk_widget_size_request(sheet->sheet_entry, NULL); 06204 GTK_WIDGET(sheet_entry)->style = previous_style; 06205 06206 if(style != previous_style){ 06207 style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL]; 06208 style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL]; 06209 style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE]; 06210 style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE]; 06211 gtk_widget_set_style(GTK_WIDGET(sheet_entry), style); 06212 } 06213 } 06214 06215 max_size = 0; 06216 06217 text_size = 0; 06218 text = gtk_entry_get_text(GTK_ENTRY(sheet_entry)); 06219 if(text && strlen(text) > 0){ 06220 text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text); 06221 } 06222 06223 column_width=sheet->column[sheet->active_cell.col].width; 06224 06225 size=MIN(text_size, max_size); 06226 size=MAX(size,column_width-2*CELLOFFSET); 06227 06228 row=sheet->active_cell.row; 06229 col=sheet->active_cell.col; 06230 06231 shentry_allocation.x = COLUMN_LEFT_XPIXEL(sheet,sheet->active_cell.col); 06232 shentry_allocation.y = ROW_TOP_YPIXEL(sheet,sheet->active_cell.row); 06233 shentry_allocation.width = column_width; 06234 shentry_allocation.height = sheet->row[sheet->active_cell.row].height; 06235 06236 shentry_allocation.x += 2; 06237 shentry_allocation.y += 2; 06238 shentry_allocation.width -= MIN(shentry_allocation.width, 3); 06239 shentry_allocation.height -= MIN(shentry_allocation.height, 3); 06240 06241 gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation); 06242 06243 if(previous_style == style) gtk_style_unref(previous_style); 06244 } 06245 06246 06247 static void 06248 create_sheet_entry(GtkSheet *sheet) 06249 { 06250 GtkWidget *widget; 06251 GtkWidget *parent; 06252 GtkWidget *entry; 06253 GtkStyle *style; 06254 gint found_entry = FALSE; 06255 06256 widget = GTK_WIDGET(sheet); 06257 06258 style = gtk_style_copy(GTK_WIDGET(sheet)->style); 06259 06260 if(sheet->sheet_entry){ 06261 /* avoids warnings */ 06262 gtk_widget_ref(sheet->sheet_entry); 06263 gtk_widget_unparent(sheet->sheet_entry); 06264 gtk_widget_destroy(sheet->sheet_entry); 06265 } 06266 06267 if(sheet->entry_type){ 06268 06269 if(!gtk_type_is_a (sheet->entry_type, GTK_TYPE_ENTRY)){ 06270 06271 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type)); 06272 06273 sheet->sheet_entry = parent; 06274 06275 entry = gtk_sheet_get_entry (sheet); 06276 if(GTK_IS_ENTRY(entry)) found_entry = TRUE; 06277 06278 } else { 06279 06280 parent = GTK_WIDGET(gtk_type_new(sheet->entry_type)); 06281 entry = parent; 06282 found_entry = TRUE; 06283 06284 } 06285 06286 if(!found_entry){ 06287 06288 g_warning ("Entry type must be GtkEntry subclass, using default"); 06289 entry = gtk_entry_new (); 06290 sheet->sheet_entry = entry; 06291 06292 } else { 06293 06294 sheet->sheet_entry = parent; 06295 06296 } 06297 06298 06299 } else { 06300 06301 entry = gtk_entry_new (); 06302 sheet->sheet_entry = entry; 06303 06304 } 06305 06306 gtk_widget_size_request(sheet->sheet_entry, NULL); 06307 06308 if(GTK_WIDGET_REALIZED(sheet)) 06309 { 06310 gtk_widget_set_parent_window (sheet->sheet_entry, sheet->sheet_window); 06311 gtk_widget_set_parent(sheet->sheet_entry, GTK_WIDGET(sheet)); 06312 gtk_widget_realize(sheet->sheet_entry); 06313 } 06314 06315 /* #if 0 */ 06316 /* SDB says: I need to work out the event passing system */ 06317 gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event", 06318 (GtkSignalFunc) gtk_sheet_key_press, 06319 GTK_OBJECT(sheet)); 06320 /* gtk_signal_connect_object(GTK_OBJECT(entry),"key_press_event", 06321 (GtkSignalFunc) gtk_sheet_entry_key_press, 06322 GTK_OBJECT(sheet)); 06323 */ 06324 /* #endif */ 06325 06326 gtk_widget_show (sheet->sheet_entry); 06327 } 06328 06329 06330 GtkWidget * 06331 gtk_sheet_get_entry(GtkSheet *sheet) 06332 { 06333 GtkWidget *parent; 06334 GtkWidget *entry = NULL; 06335 GtkTableChild *table_child; 06336 GtkBoxChild *box_child; 06337 GList *children = NULL; 06338 06339 g_return_val_if_fail (sheet != NULL, NULL); 06340 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL); 06341 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL); 06342 06343 if(GTK_IS_ENTRY(sheet->sheet_entry)) return (sheet->sheet_entry); 06344 06345 parent = GTK_WIDGET(sheet->sheet_entry); 06346 06347 if(GTK_IS_TABLE(parent)) children = GTK_TABLE(parent)->children; 06348 if(GTK_IS_BOX(parent)) children = GTK_BOX(parent)->children; 06349 06350 if(!children) return NULL; 06351 06352 while(children){ 06353 if(GTK_IS_TABLE(parent)) { 06354 table_child = children->data; 06355 entry = table_child->widget; 06356 } 06357 if(GTK_IS_BOX(parent)){ 06358 box_child = children->data; 06359 entry = box_child->widget; 06360 } 06361 06362 if(GTK_IS_ENTRY(entry)) 06363 break; 06364 children = g_list_next(children); 06365 } 06366 06367 06368 if(!GTK_IS_ENTRY(entry)) return NULL; 06369 06370 return (entry); 06371 06372 } 06373 06374 GtkWidget * 06375 gtk_sheet_get_entry_widget(GtkSheet *sheet) 06376 { 06377 g_return_val_if_fail (sheet != NULL, NULL); 06378 g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL); 06379 g_return_val_if_fail (sheet->sheet_entry != NULL, NULL); 06380 06381 return (sheet->sheet_entry); 06382 } 06383 06384 /* BUTTONS */ 06385 static void 06386 row_button_set (GtkSheet *sheet, gint row) 06387 { 06388 if(sheet->row[row].button.state == GTK_STATE_ACTIVE) return; 06389 06390 sheet->row[row].button.state = GTK_STATE_ACTIVE; 06391 gtk_sheet_button_draw(sheet, row, -1); 06392 06393 } 06394 06395 static void 06396 column_button_set (GtkSheet *sheet, gint column) 06397 { 06398 if(sheet->column[column].button.state == GTK_STATE_ACTIVE) return; 06399 06400 sheet->column[column].button.state = GTK_STATE_ACTIVE; 06401 gtk_sheet_button_draw(sheet, -1, column); 06402 06403 } 06404 06405 static void 06406 row_button_release (GtkSheet *sheet, gint row) 06407 { 06408 if(sheet->row[row].button.state == GTK_STATE_NORMAL) return; 06409 06410 sheet->row[row].button.state = GTK_STATE_NORMAL; 06411 gtk_sheet_button_draw(sheet, row, -1); 06412 } 06413 06414 static void 06415 column_button_release (GtkSheet *sheet, gint column) 06416 { 06417 if(sheet->column[column].button.state == GTK_STATE_NORMAL) return; 06418 06419 sheet->column[column].button.state = GTK_STATE_NORMAL; 06420 gtk_sheet_button_draw(sheet, -1, column); 06421 } 06422 06423 static void 06424 gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column) 06425 { 06426 GdkWindow *window = NULL; 06427 GtkShadowType shadow_type; 06428 guint width = 0, height = 0; 06429 gint x = 0, y = 0; 06430 gint index = 0; 06431 gint text_width = 0, text_height = 0; 06432 GtkSheetButton *button = NULL; 06433 GtkSheetChild *child = NULL; 06434 GdkRectangle allocation; 06435 gboolean is_sensitive = FALSE; 06436 gint state = 0; 06437 gint len = 0; 06438 gchar *line = 0; 06439 gchar *words = 0; 06440 gchar label[10]; 06441 06442 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return; 06443 06444 if(row >= 0 && !sheet->row[row].is_visible) return; 06445 if(column >= 0 && !sheet->column[column].is_visible) return; 06446 if(row >= 0 && !sheet->row_titles_visible) return; 06447 if(column >= 0 && !sheet->column_titles_visible) return; 06448 if(column>=0 && column <MIN_VISIBLE_COLUMN(sheet)) return; 06449 if(column>=0 && column >MAX_VISIBLE_COLUMN(sheet)) return; 06450 if(row>=0 && row <MIN_VISIBLE_ROW(sheet)) return; 06451 if(row>=0 && row >MAX_VISIBLE_ROW(sheet)) return; 06452 if( (row == -1) && (column == -1) ) return; 06453 06454 if(row==-1){ 06455 window=sheet->column_title_window; 06456 button=&sheet->column[column].button; 06457 index=column; 06458 x = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING; 06459 if(sheet->row_titles_visible) x -= sheet->row_title_area.width; 06460 y = 0; 06461 width = sheet->column[column].width; 06462 height = sheet->column_title_area.height; 06463 is_sensitive=sheet->column[column].is_sensitive; 06464 } 06465 else if(column==-1){ 06466 window=sheet->row_title_window; 06467 button=&sheet->row[row].button; 06468 index=row; 06469 x = 0; 06470 y = ROW_TOP_YPIXEL(sheet, row)+CELL_SPACING; 06471 if(sheet->column_titles_visible) y-=sheet->column_title_area.height; 06472 width = sheet->row_title_area.width; 06473 height = sheet->row[row].height; 06474 is_sensitive=sheet->row[row].is_sensitive; 06475 } 06476 06477 allocation.x = x; 06478 allocation.y = y; 06479 allocation.width = width; 06480 allocation.height = height; 06481 06482 gdk_window_clear_area (window, 06483 x, y, 06484 width, height); 06485 06486 gtk_paint_box (sheet->button->style, window, 06487 GTK_STATE_NORMAL, GTK_SHADOW_OUT, 06488 &allocation, GTK_WIDGET(sheet), 06489 "buttondefault", x, y, width, height); 06490 06491 state = button->state; 06492 if(!is_sensitive) state=GTK_STATE_INSENSITIVE; 06493 06494 if (state == GTK_STATE_ACTIVE) 06495 shadow_type = GTK_SHADOW_IN; 06496 else 06497 shadow_type = GTK_SHADOW_OUT; 06498 06499 if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE) 06500 gtk_paint_box (sheet->button->style, window, 06501 button->state, shadow_type, 06502 &allocation, GTK_WIDGET(sheet), 06503 "button", x, y, width, height); 06504 06505 if(button->label_visible){ 06506 06507 text_height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))-2*CELLOFFSET; 06508 06509 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state], 06510 &allocation); 06511 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation); 06512 06513 y += DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))/2 + sheet->button->style->ythickness + DEFAULT_FONT_DESCENT(GTK_WIDGET(sheet)); 06514 06515 if(button->label && strlen(button->label)>0){ 06516 06517 words=button->label; 06518 line = g_new(gchar, 1); 06519 line[0]='\0'; 06520 06521 while(words && *words != '\0'){ 06522 if(*words != '\n'){ 06523 len=strlen(line); 06524 line=g_realloc(line, len+2); 06525 line[len]=*words; 06526 line[len+1]='\0'; 06527 } 06528 if(*words == '\n' || *(words+1) == '\0'){ 06529 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, line); 06530 06531 switch(button->justification){ 06532 case GTK_JUSTIFY_LEFT: 06533 gtk_paint_string (GTK_WIDGET(sheet)->style, window, state, 06534 &allocation, GTK_WIDGET(sheet), "label", 06535 x + CELLOFFSET, y, 06536 line); 06537 break; 06538 case GTK_JUSTIFY_RIGHT: 06539 gtk_paint_string (GTK_WIDGET(sheet)->style, window, state, 06540 &allocation, GTK_WIDGET(sheet), "label", 06541 x + width - text_width - CELLOFFSET, y, 06542 line); 06543 break; 06544 case GTK_JUSTIFY_CENTER: 06545 default: 06546 gtk_paint_string (GTK_WIDGET(sheet)->style, window, state, 06547 &allocation, GTK_WIDGET(sheet), "label", 06548 x + (width - text_width) /2, y, 06549 line); 06550 } 06551 06552 y += text_height + 2; 06553 06554 g_free(line); 06555 line = g_new(gchar, 1); 06556 line[0]='\0'; 06557 } 06558 words++; 06559 } 06560 g_free(line); 06561 }else{ 06562 sprintf(label,"%d",index); 06563 text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, label); 06564 06565 switch(button->justification){ 06566 case GTK_JUSTIFY_LEFT: 06567 gtk_paint_string (GTK_WIDGET(sheet)->style, window, state, 06568 &allocation, GTK_WIDGET(sheet), "label", 06569 x + CELLOFFSET, y, 06570 label); 06571 break; 06572 case GTK_JUSTIFY_RIGHT: 06573 gtk_paint_string (GTK_WIDGET(sheet)->style, window, state, 06574 &allocation, GTK_WIDGET(sheet), "label", 06575 x + width - text_width - CELLOFFSET, y, 06576 label); 06577 break; 06578 case GTK_JUSTIFY_CENTER: 06579 default: 06580 gtk_paint_string (GTK_WIDGET(sheet)->style, window, state, 06581 &allocation, GTK_WIDGET(sheet), "label", 06582 x + (width - text_width) /2, y, 06583 label); 06584 } 06585 06586 } 06587 06588 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state], 06589 NULL); 06590 gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, NULL); 06591 06592 } 06593 06594 if((child = button->child) && (child->widget)){ 06595 child->x = allocation.x; 06596 child->y = allocation.y; 06597 06598 child->x += (width - child->widget->requisition.width) / 2; 06599 child->y += (height - child->widget->requisition.height) / 2; 06600 allocation.x = child->x; 06601 allocation.y = child->y; 06602 allocation.width = child->widget->requisition.width; 06603 allocation.height = child->widget->requisition.height; 06604 06605 x = child->x; 06606 y = child->y; 06607 06608 gtk_widget_set_state(child->widget, button->state); 06609 06610 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && 06611 GTK_WIDGET_MAPPED(child->widget)) 06612 { 06613 gtk_widget_size_allocate(child->widget, 06614 &allocation); 06615 gtk_widget_queue_draw(child->widget); 06616 } 06617 } 06618 06619 } 06620 06621 06622 /* SCROLLBARS 06623 * 06624 * functions: 06625 * adjust_scrollbars 06626 * vadjustment_changed 06627 * hadjustment_changed 06628 * vadjustment_value_changed 06629 * hadjustment_value_changed */ 06630 06631 static void 06632 adjust_scrollbars (GtkSheet * sheet) 06633 { 06634 06635 if(sheet->vadjustment){ 06636 sheet->vadjustment->page_size = sheet->sheet_window_height; 06637 sheet->vadjustment->page_increment = sheet->sheet_window_height / 2; 06638 sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)); 06639 sheet->vadjustment->lower = 0; 06640 sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80; 06641 /* 06642 if (sheet->sheet_window_height - sheet->voffset > SHEET_HEIGHT (sheet)) 06643 { 06644 sheet->vadjustment->value = MAX(0, SHEET_HEIGHT (sheet) - 06645 sheet->sheet_window_height); 06646 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 06647 "value_changed"); 06648 } 06649 */ 06650 gtk_signal_emit_by_name (GTK_OBJECT(sheet->vadjustment), "changed"); 06651 06652 } 06653 06654 if(sheet->hadjustment){ 06655 sheet->hadjustment->page_size = sheet->sheet_window_width; 06656 sheet->hadjustment->page_increment = sheet->sheet_window_width / 2; 06657 sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH; 06658 sheet->hadjustment->lower = 0; 06659 sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80; 06660 /* 06661 if (sheet->sheet_window_width - sheet->hoffset > SHEET_WIDTH (sheet)) 06662 { 06663 sheet->hadjustment->value = MAX(0, SHEET_WIDTH (sheet) - 06664 sheet->sheet_window_width); 06665 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), 06666 "value_changed"); 06667 } 06668 */ 06669 gtk_signal_emit_by_name (GTK_OBJECT(sheet->hadjustment), "changed"); 06670 06671 } 06672 /* 06673 if(GTK_WIDGET_REALIZED(sheet)) 06674 { 06675 if(sheet->row_titles_visible){ 06676 size_allocate_row_title_buttons(sheet); 06677 gdk_window_show(sheet->row_title_window); 06678 } 06679 06680 if(sheet->column_titles_visible){ 06681 size_allocate_column_title_buttons(sheet); 06682 gdk_window_show(sheet->column_title_window); 06683 } 06684 06685 gtk_sheet_range_draw(sheet, NULL); 06686 } 06687 */ 06688 } 06689 06690 06691 static void 06692 vadjustment_changed (GtkAdjustment * adjustment, 06693 gpointer data) 06694 { 06695 GtkSheet *sheet; 06696 06697 g_return_if_fail (adjustment != NULL); 06698 g_return_if_fail (data != NULL); 06699 06700 sheet = GTK_SHEET (data); 06701 06702 } 06703 06704 static void 06705 hadjustment_changed (GtkAdjustment * adjustment, 06706 gpointer data) 06707 { 06708 GtkSheet *sheet; 06709 06710 g_return_if_fail (adjustment != NULL); 06711 g_return_if_fail (data != NULL); 06712 06713 sheet = GTK_SHEET (data); 06714 06715 } 06716 06717 06718 static void 06719 vadjustment_value_changed (GtkAdjustment * adjustment, 06720 gpointer data) 06721 { 06722 GtkSheet *sheet; 06723 gint diff, value, old_value; 06724 gint i; 06725 gint row, new_row; 06726 gint y=0; 06727 06728 g_return_if_fail (adjustment != NULL); 06729 g_return_if_fail (data != NULL); 06730 g_return_if_fail (GTK_IS_SHEET (data)); 06731 06732 sheet = GTK_SHEET (data); 06733 06734 if(GTK_SHEET_IS_FROZEN(sheet)) return; 06735 06736 row=ROW_FROM_YPIXEL(sheet,sheet->column_title_area.height + CELL_SPACING); 06737 if(!sheet->column_titles_visible) 06738 row=ROW_FROM_YPIXEL(sheet,CELL_SPACING); 06739 06740 old_value = -sheet->voffset; 06741 06742 for(i=0; i<= sheet->maxrow; i++){ 06743 if(sheet->row[i].is_visible) y+=sheet->row[i].height; 06744 if(y > adjustment->value) break; 06745 } 06746 y-=sheet->row[i].height; 06747 new_row=i; 06748 06749 if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. && 06750 sheet->row[i].height > sheet->vadjustment->step_increment){ 06751 /* This avoids embarrassing twitching */ 06752 if(row == new_row && row != sheet->maxrow && 06753 adjustment->value - sheet->old_vadjustment >= 06754 sheet->vadjustment->step_increment && 06755 new_row + 1 != MIN_VISIBLE_ROW(sheet)){ 06756 new_row+=1; 06757 y=y+sheet->row[row].height; 06758 } 06759 } 06760 06761 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */ 06762 if(sheet->old_vadjustment >= 0. && row == new_row){ 06763 sheet->old_vadjustment = sheet->vadjustment->value; 06764 return; 06765 } 06766 06767 sheet->old_vadjustment = sheet->vadjustment->value; 06768 adjustment->value=y; 06769 06770 06771 if(new_row == 0){ 06772 sheet->vadjustment->step_increment= 06773 sheet->row[0].height; 06774 }else{ 06775 sheet->vadjustment->step_increment= 06776 MIN(sheet->row[new_row].height, sheet->row[new_row-1].height); 06777 } 06778 06779 sheet->vadjustment->value=adjustment->value; 06780 06781 value = adjustment->value; 06782 06783 if (value >= -sheet->voffset) 06784 { 06785 /* scroll down */ 06786 diff = value + sheet->voffset; 06787 } 06788 else 06789 { 06790 /* scroll up */ 06791 diff = -sheet->voffset - value; 06792 } 06793 06794 sheet->voffset = -value; 06795 06796 sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1); 06797 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1); 06798 if(!sheet->column_titles_visible) 06799 sheet->view.row0=ROW_FROM_YPIXEL(sheet, 1); 06800 06801 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) && 06802 sheet->state == GTK_SHEET_NORMAL && 06803 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 && 06804 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row, 06805 sheet->active_cell.col)) 06806 { 06807 const gchar *text; 06808 06809 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet))); 06810 06811 if(!text || strlen(text)==0) 06812 gtk_sheet_cell_clear(sheet, 06813 sheet->active_cell.row, 06814 sheet->active_cell.col); 06815 gtk_widget_unmap(sheet->sheet_entry); 06816 } 06817 06818 gtk_sheet_position_children(sheet); 06819 06820 gtk_sheet_range_draw(sheet, NULL); 06821 size_allocate_row_title_buttons(sheet); 06822 size_allocate_global_button(sheet); 06823 } 06824 06825 static void 06826 hadjustment_value_changed (GtkAdjustment * adjustment, 06827 gpointer data) 06828 { 06829 GtkSheet *sheet; 06830 gint i, diff, value, old_value; 06831 gint column, new_column; 06832 gint x=0; 06833 06834 g_return_if_fail (adjustment != NULL); 06835 g_return_if_fail (data != NULL); 06836 g_return_if_fail (GTK_IS_SHEET (data)); 06837 06838 sheet = GTK_SHEET (data); 06839 06840 if(GTK_SHEET_IS_FROZEN(sheet)) return; 06841 06842 column=COLUMN_FROM_XPIXEL(sheet,sheet->row_title_area.width + CELL_SPACING); 06843 if(!sheet->row_titles_visible) 06844 column=COLUMN_FROM_XPIXEL(sheet, CELL_SPACING); 06845 06846 old_value = -sheet->hoffset; 06847 06848 for(i=0; i<= sheet->maxcol; i++){ 06849 if(sheet->column[i].is_visible) x+=sheet->column[i].width; 06850 if(x > adjustment->value) break; 06851 } 06852 x-=sheet->column[i].width; 06853 new_column=i; 06854 06855 if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 && 06856 sheet->column[i].width > sheet->hadjustment->step_increment){ 06857 /* This avoids embarrassing twitching */ 06858 if(column == new_column && column != sheet->maxcol && 06859 adjustment->value - sheet->old_hadjustment >= 06860 sheet->hadjustment->step_increment && 06861 new_column + 1 != MIN_VISIBLE_COLUMN(sheet)){ 06862 new_column+=1; 06863 x=x+sheet->column[column].width; 06864 } 06865 } 06866 06867 /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */ 06868 if(sheet->old_hadjustment >= 0. && new_column == column){ 06869 sheet->old_hadjustment = sheet->hadjustment->value; 06870 return; 06871 } 06872 06873 sheet->old_hadjustment = sheet->hadjustment->value; 06874 adjustment->value=x; 06875 06876 if(new_column == 0){ 06877 sheet->hadjustment->step_increment= 06878 sheet->column[0].width; 06879 }else{ 06880 sheet->hadjustment->step_increment= 06881 MIN(sheet->column[new_column].width, sheet->column[new_column-1].width); 06882 } 06883 06884 06885 sheet->hadjustment->value=adjustment->value; 06886 06887 value = adjustment->value; 06888 06889 if (value >= -sheet->hoffset) 06890 { 06891 /* scroll right */ 06892 diff = value + sheet->hoffset; 06893 } 06894 else 06895 { 06896 /* scroll left */ 06897 diff = -sheet->hoffset - value; 06898 } 06899 06900 sheet->hoffset = -value; 06901 06902 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1); 06903 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width); 06904 if(!sheet->row_titles_visible) 06905 sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, 1); 06906 06907 if(GTK_WIDGET_REALIZED(sheet->sheet_entry) && 06908 sheet->state == GTK_SHEET_NORMAL && 06909 sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 && 06910 !gtk_sheet_cell_isvisible(sheet, sheet->active_cell.row, 06911 sheet->active_cell.col)) 06912 { 06913 const gchar *text; 06914 06915 text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet))); 06916 if(!text || strlen(text)==0) 06917 gtk_sheet_cell_clear(sheet, 06918 sheet->active_cell.row, 06919 sheet->active_cell.col); 06920 06921 gtk_widget_unmap(sheet->sheet_entry); 06922 } 06923 06924 gtk_sheet_position_children(sheet); 06925 06926 gtk_sheet_range_draw(sheet, NULL); 06927 size_allocate_column_title_buttons(sheet); 06928 } 06929 06930 06931 /* COLUMN RESIZING */ 06932 static void 06933 draw_xor_vline (GtkSheet * sheet) 06934 { 06935 GtkWidget *widget; 06936 06937 g_return_if_fail (sheet != NULL); 06938 06939 widget = GTK_WIDGET (sheet); 06940 06941 gdk_draw_line (widget->window, sheet->xor_gc, 06942 sheet->x_drag, 06943 sheet->column_title_area.height, 06944 sheet->x_drag, 06945 sheet->sheet_window_height + 1); 06946 } 06947 06948 /* ROW RESIZING */ 06949 static void 06950 draw_xor_hline (GtkSheet * sheet) 06951 { 06952 GtkWidget *widget; 06953 06954 g_return_if_fail (sheet != NULL); 06955 06956 widget = GTK_WIDGET (sheet); 06957 06958 gdk_draw_line (widget->window, sheet->xor_gc, 06959 sheet->row_title_area.width, 06960 sheet->y_drag, 06961 06962 sheet->sheet_window_width + 1, 06963 sheet->y_drag); 06964 } 06965 06966 /* SELECTED RANGE */ 06967 static void 06968 draw_xor_rectangle(GtkSheet *sheet, GtkSheetRange range) 06969 { 06970 gint i; 06971 GdkRectangle clip_area, area; 06972 GdkGCValues values; 06973 06974 area.x=COLUMN_LEFT_XPIXEL(sheet, range.col0); 06975 area.y=ROW_TOP_YPIXEL(sheet, range.row0); 06976 area.width=COLUMN_LEFT_XPIXEL(sheet, range.coli)-area.x+ 06977 sheet->column[range.coli].width; 06978 area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+ 06979 sheet->row[range.rowi].height; 06980 06981 clip_area.x=sheet->row_title_area.width; 06982 clip_area.y=sheet->column_title_area.height; 06983 clip_area.width=sheet->sheet_window_width; 06984 clip_area.height=sheet->sheet_window_height; 06985 06986 if(!sheet->row_titles_visible) clip_area.x = 0; 06987 if(!sheet->column_titles_visible) clip_area.y = 0; 06988 06989 if(area.x<0) { 06990 area.width=area.width+area.x; 06991 area.x=0; 06992 } 06993 if(area.width>clip_area.width) area.width=clip_area.width+10; 06994 if(area.y<0) { 06995 area.height=area.height+area.y; 06996 area.y=0; 06997 } 06998 if(area.height>clip_area.height) area.height=clip_area.height+10; 06999 07000 clip_area.x--; 07001 clip_area.y--; 07002 clip_area.width+=3; 07003 clip_area.height+=3; 07004 07005 gdk_gc_get_values(sheet->xor_gc, &values); 07006 07007 gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area); 07008 07009 for(i=-1;i<=1;i++) 07010 gdk_draw_rectangle(sheet->sheet_window, 07011 sheet->xor_gc, 07012 FALSE, 07013 area.x+i, area.y+i, 07014 area.width-2*i, area.height-2*i); 07015 07016 07017 gdk_gc_set_clip_rectangle(sheet->xor_gc, NULL); 07018 07019 gdk_gc_set_foreground(sheet->xor_gc, &values.foreground); 07020 07021 } 07022 07023 07024 /* this function returns the new width of the column being resized given 07025 * the column and x position of the cursor; the x cursor position is passed 07026 * in as a pointer and automaticaly corrected if it's beyond min/max limits */ 07027 static guint 07028 new_column_width (GtkSheet * sheet, 07029 gint column, 07030 gint * x) 07031 { 07032 gint cx, width; 07033 GtkRequisition requisition; 07034 07035 cx = *x; 07036 07037 requisition.width = sheet->column[column].requisition; 07038 07039 /* you can't shrink a column to less than its minimum width */ 07040 if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + requisition.width) 07041 { 07042 *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + requisition.width; 07043 } 07044 07045 /* don't grow past the end of the window */ 07046 /* 07047 if (cx > sheet->sheet_window_width) 07048 { 07049 *x = cx = sheet->sheet_window_width; 07050 } 07051 */ 07052 /* calculate new column width making sure it doesn't end up 07053 * less than the minimum width */ 07054 width = cx - COLUMN_LEFT_XPIXEL (sheet, column); 07055 if (width < requisition.width) 07056 width = requisition.width; 07057 07058 sheet->column[column].width = width; 07059 gtk_sheet_recalc_left_xpixels(sheet, column+1); 07060 sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width); 07061 size_allocate_column_title_buttons (sheet); 07062 07063 return width; 07064 } 07065 07066 /* this function returns the new height of the row being resized given 07067 * the row and y position of the cursor; the y cursor position is passed 07068 * in as a pointer and automaticaly corrected if it's beyond min/max limits */ 07069 static guint 07070 new_row_height (GtkSheet * sheet, 07071 gint row, 07072 gint * y) 07073 { 07074 GtkRequisition requisition; 07075 gint cy, height; 07076 07077 cy = *y; 07078 07079 requisition.height = sheet->row[row].requisition; 07080 07081 /* you can't shrink a row to less than its minimum height */ 07082 if (cy < ROW_TOP_YPIXEL (sheet, row) + requisition.height) 07083 07084 { 07085 *y = cy = ROW_TOP_YPIXEL (sheet, row) + requisition.height; 07086 } 07087 07088 /* don't grow past the end of the window */ 07089 /* 07090 if (cy > sheet->sheet_window_height) 07091 { 07092 *y = cy = sheet->sheet_window_height; 07093 } 07094 */ 07095 /* calculate new row height making sure it doesn't end up 07096 * less than the minimum height */ 07097 height = (cy - ROW_TOP_YPIXEL (sheet, row)); 07098 if (height < requisition.height) 07099 height = requisition.height; 07100 07101 sheet->row[row].height = height; 07102 gtk_sheet_recalc_top_ypixels(sheet, row); 07103 sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1); 07104 size_allocate_row_title_buttons (sheet); 07105 07106 return height; 07107 } 07108 07109 void 07110 gtk_sheet_set_column_width (GtkSheet * sheet, 07111 gint column, 07112 guint width) 07113 { 07114 guint min_width; 07115 07116 g_return_if_fail (sheet != NULL); 07117 g_return_if_fail (GTK_IS_SHEET (sheet)); 07118 07119 if (column < 0 || column > sheet->maxcol) 07120 return; 07121 07122 gtk_sheet_column_size_request(sheet, column, &min_width); 07123 if(width < min_width) return; 07124 07125 sheet->column[column].width = width; 07126 07127 gtk_sheet_recalc_left_xpixels(sheet, column+1); 07128 07129 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){ 07130 size_allocate_column_title_buttons (sheet); 07131 adjust_scrollbars (sheet); 07132 gtk_sheet_size_allocate_entry(sheet); 07133 gtk_sheet_range_draw (sheet, NULL); 07134 } else 07135 07136 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, column); 07137 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_COL_WIDTH], column, width); 07138 07139 } 07140 07141 void 07142 gtk_sheet_set_row_height (GtkSheet * sheet, 07143 gint row, 07144 guint height) 07145 { 07146 guint min_height; 07147 07148 g_return_if_fail (sheet != NULL); 07149 g_return_if_fail (GTK_IS_SHEET (sheet)); 07150 07151 if (row < 0 || row > sheet->maxrow) 07152 return; 07153 07154 gtk_sheet_row_size_request(sheet, row, &min_height); 07155 if(height < min_height) return; 07156 07157 sheet->row[row].height = height; 07158 07159 gtk_sheet_recalc_top_ypixels(sheet, row+1); 07160 07161 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && !GTK_SHEET_IS_FROZEN(sheet)){ 07162 size_allocate_row_title_buttons (sheet); 07163 adjust_scrollbars (sheet); 07164 gtk_sheet_size_allocate_entry(sheet); 07165 gtk_sheet_range_draw (sheet, NULL); 07166 } 07167 07168 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], row, -1); 07169 gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[NEW_ROW_HEIGHT], row, height); 07170 07171 } 07172 07173 07174 void 07175 gtk_sheet_add_column(GtkSheet *sheet, guint ncols) 07176 { 07177 07178 g_return_if_fail (sheet != NULL); 07179 g_return_if_fail (GTK_IS_SHEET (sheet)); 07180 07181 AddColumn(sheet, ncols); 07182 07183 if(!GTK_WIDGET_REALIZED(sheet)) return; 07184 07185 adjust_scrollbars(sheet); 07186 07187 if(sheet->state==GTK_SHEET_ROW_SELECTED) sheet->range.coli+=ncols; 07188 07189 sheet->old_hadjustment = -1.; 07190 if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->hadjustment) 07191 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 07192 "value_changed"); 07193 } 07194 07195 void 07196 gtk_sheet_add_row(GtkSheet *sheet, guint nrows) 07197 { 07198 07199 g_return_if_fail (sheet != NULL); 07200 g_return_if_fail (GTK_IS_SHEET (sheet)); 07201 07202 AddRow(sheet, nrows); 07203 07204 if(!GTK_WIDGET_REALIZED(sheet)) return; 07205 07206 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) sheet->range.rowi+=nrows; 07207 07208 adjust_scrollbars(sheet); 07209 07210 sheet->old_vadjustment = -1.; 07211 if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->vadjustment) 07212 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 07213 "value_changed"); 07214 } 07215 07216 void 07217 gtk_sheet_insert_rows(GtkSheet *sheet, guint row, guint nrows) 07218 { 07219 GList *children; 07220 GtkSheetChild *child; 07221 07222 g_return_if_fail (sheet != NULL); 07223 g_return_if_fail (GTK_IS_SHEET (sheet)); 07224 07225 if(GTK_WIDGET_REALIZED(sheet)) 07226 gtk_sheet_real_unselect_range(sheet, NULL); 07227 07228 InsertRow(sheet, row, nrows); 07229 07230 children = sheet->children; 07231 while(children) 07232 { 07233 child = (GtkSheetChild *)children->data; 07234 07235 if(child->attached_to_cell) 07236 if(child->row >= row) child->row += nrows; 07237 07238 children = g_list_next(children); 07239 } 07240 07241 if(!GTK_WIDGET_REALIZED(sheet)) return; 07242 07243 if(sheet->state==GTK_SHEET_COLUMN_SELECTED) sheet->range.rowi+=nrows; 07244 adjust_scrollbars(sheet); 07245 07246 sheet->old_vadjustment = -1.; 07247 if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->vadjustment) 07248 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 07249 "value_changed"); 07250 07251 } 07252 07253 void 07254 gtk_sheet_insert_columns(GtkSheet *sheet, guint col, guint ncols) 07255 { 07256 GList *children; 07257 GtkSheetChild *child; 07258 07259 g_return_if_fail (sheet != NULL); 07260 g_return_if_fail (GTK_IS_SHEET (sheet)); 07261 07262 if(GTK_WIDGET_REALIZED(sheet)) 07263 gtk_sheet_real_unselect_range(sheet, NULL); 07264 07265 InsertColumn(sheet, col, ncols); 07266 07267 children = sheet->children; 07268 while(children) 07269 { 07270 child = (GtkSheetChild *)children->data; 07271 07272 if(child->attached_to_cell) 07273 if(child->col >= col) child->col += ncols; 07274 07275 children = g_list_next(children); 07276 } 07277 07278 if(!GTK_WIDGET_REALIZED(sheet)) return; 07279 07280 if(sheet->state==GTK_SHEET_ROW_SELECTED) sheet->range.coli+=ncols; 07281 adjust_scrollbars(sheet); 07282 07283 sheet->old_hadjustment = -1.; 07284 if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->hadjustment) 07285 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 07286 "value_changed"); 07287 07288 } 07289 07290 void 07291 gtk_sheet_delete_rows(GtkSheet *sheet, guint row, guint nrows) 07292 { 07293 GList *children; 07294 GtkSheetChild *child; 07295 gint irow, icol; 07296 gboolean veto; 07297 07298 g_return_if_fail (sheet != NULL); 07299 g_return_if_fail (GTK_IS_SHEET (sheet)); 07300 07301 nrows = MIN(nrows, sheet->maxrow-row+1); 07302 07303 if(GTK_WIDGET_REALIZED(sheet)) 07304 gtk_sheet_real_unselect_range(sheet, NULL); 07305 07306 DeleteRow(sheet, row, nrows); 07307 07308 children = sheet->children; 07309 while(children) 07310 { 07311 child = (GtkSheetChild *)children->data; 07312 07313 if(child->attached_to_cell && 07314 child->row >= row && child->row < row+nrows){ 07315 gtk_container_remove(GTK_CONTAINER(sheet), child->widget); 07316 children = sheet->children; 07317 } else 07318 children = g_list_next(children); 07319 } 07320 07321 children = sheet->children; 07322 while(children) 07323 { 07324 child = (GtkSheetChild *)children->data; 07325 07326 if(child->attached_to_cell && child->row > row) child->row -= nrows; 07327 children = g_list_next(children); 07328 } 07329 07330 if(!GTK_WIDGET_REALIZED(sheet)) return; 07331 07332 irow = sheet->active_cell.row; 07333 icol = sheet->active_cell.col; 07334 07335 sheet->active_cell.row = -1; 07336 sheet->active_cell.col = -1; 07337 07338 /* if(sheet->state == GTK_SHEET_ROW_SELECTED) 07339 */ 07340 07341 irow = MIN(irow, sheet->maxrow); 07342 irow = MAX(irow, 0); 07343 gtk_sheet_click_cell(sheet, irow, icol, &veto); 07344 07345 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, 07346 sheet->active_cell.col); 07347 07348 adjust_scrollbars(sheet); 07349 07350 sheet->old_vadjustment = -1.; 07351 if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->vadjustment) 07352 gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 07353 "value_changed"); 07354 07355 } 07356 07357 void 07358 gtk_sheet_delete_columns(GtkSheet *sheet, guint col, guint ncols) 07359 { 07360 GList *children; 07361 GtkSheetChild *child; 07362 gint irow, icol; 07363 gboolean veto; 07364 07365 g_return_if_fail (sheet != NULL); 07366 g_return_if_fail (GTK_IS_SHEET (sheet)); 07367 07368 ncols = MIN(ncols, sheet->maxcol-col+1); 07369 07370 if(GTK_WIDGET_REALIZED(sheet)) 07371 gtk_sheet_real_unselect_range(sheet, NULL); 07372 07373 DeleteColumn(sheet, col, ncols); 07374 07375 children = sheet->children; 07376 while(children) 07377 { 07378 child = (GtkSheetChild *)children->data; 07379 07380 if(child->attached_to_cell && 07381 child->col >= col && child->col < col+ncols){ 07382 gtk_container_remove(GTK_CONTAINER(sheet), child->widget); 07383 children = sheet->children; 07384 } else 07385 children = g_list_next(children); 07386 } 07387 07388 children = sheet->children; 07389 while(children) 07390 { 07391 child = (GtkSheetChild *)children->data; 07392 07393 if(child->attached_to_cell && child->col > col) child->col -= ncols; 07394 children = g_list_next(children); 07395 } 07396 07397 if(!GTK_WIDGET_REALIZED(sheet)) return; 07398 07399 irow = sheet->active_cell.row; 07400 icol = sheet->active_cell.col; 07401 07402 sheet->active_cell.row = -1; 07403 sheet->active_cell.col = -1; 07404 07405 /* if(sheet->state == GTK_SHEET_COLUMN_SELECTED) 07406 */ 07407 07408 icol = MIN(icol, sheet->maxcol); 07409 icol = MAX(icol, 0); 07410 gtk_sheet_click_cell(sheet, irow, icol, &veto); 07411 07412 gtk_sheet_activate_cell(sheet, sheet->active_cell.row, 07413 sheet->active_cell.col); 07414 07415 adjust_scrollbars(sheet); 07416 07417 sheet->old_hadjustment = -1.; 07418 if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->hadjustment) 07419 gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 07420 "value_changed"); 07421 07422 } 07423 07424 void 07425 gtk_sheet_range_set_background(GtkSheet *sheet, const GtkSheetRange *urange, const GdkColor *color) 07426 { 07427 gint i, j; 07428 GtkSheetCellAttr attributes; 07429 GtkSheetRange range; 07430 07431 g_return_if_fail (sheet != NULL); 07432 g_return_if_fail (GTK_IS_SHEET (sheet)); 07433 07434 if(!urange) 07435 range = sheet->range; 07436 else 07437 range = *urange; 07438 07439 for (i=range.row0; i<=range.rowi; i++) 07440 for (j=range.col0; j<=range.coli; j++){ 07441 gtk_sheet_get_attributes(sheet, i, j, &attributes); 07442 if(color != NULL) 07443 attributes.background = *color; 07444 else 07445 attributes.background = sheet->bg_color; 07446 07447 gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 07448 } 07449 07450 range.row0--; 07451 range.col0--; 07452 range.rowi++; 07453 range.coli++; 07454 07455 if(!GTK_SHEET_IS_FROZEN(sheet)) 07456 gtk_sheet_range_draw(sheet, &range); 07457 07458 } 07459 07460 void 07461 gtk_sheet_range_set_foreground(GtkSheet *sheet, const GtkSheetRange *urange, const GdkColor *color) 07462 { 07463 gint i, j; 07464 GtkSheetCellAttr attributes; 07465 GtkSheetRange range; 07466 07467 g_return_if_fail (sheet != NULL); 07468 g_return_if_fail (GTK_IS_SHEET (sheet)); 07469 07470 if(!urange) 07471 range = sheet->range; 07472 else 07473 range = *urange; 07474 07475 for (i=range.row0; i<=range.rowi; i++) 07476 for (j=range.col0; j<=range.coli; j++){ 07477 gtk_sheet_get_attributes(sheet, i, j, &attributes); 07478 07479 if(color != NULL) 07480 attributes.foreground = *color; 07481 else 07482 gdk_color_black(gdk_colormap_get_system(), &attributes.foreground); 07483 07484 gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 07485 } 07486 07487 if(!GTK_SHEET_IS_FROZEN(sheet)) 07488 gtk_sheet_range_draw(sheet, &range); 07489 07490 } 07491 07492 void 07493 gtk_sheet_range_set_justification(GtkSheet *sheet, const GtkSheetRange *urange, 07494 GtkJustification just) 07495 { 07496 gint i, j; 07497 GtkSheetCellAttr attributes; 07498 GtkSheetRange range; 07499 07500 g_return_if_fail (sheet != NULL); 07501 g_return_if_fail (GTK_IS_SHEET (sheet)); 07502 07503 if(!urange) 07504 range = sheet->range; 07505 else 07506 range = *urange; 07507 07508 for (i=range.row0; i<=range.rowi; i++) 07509 for (j=range.col0; j<=range.coli; j++){ 07510 gtk_sheet_get_attributes(sheet, i, j, &attributes); 07511 attributes.justification = just; 07512 gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 07513 } 07514 07515 range.col0 = sheet->view.col0; 07516 range.coli = sheet->view.coli; 07517 07518 if(!GTK_SHEET_IS_FROZEN(sheet)) 07519 gtk_sheet_range_draw(sheet, &range); 07520 07521 } 07522 07523 void 07524 gtk_sheet_column_set_justification(GtkSheet *sheet, gint col, 07525 GtkJustification justification) 07526 { 07527 g_return_if_fail (sheet != NULL); 07528 g_return_if_fail (GTK_IS_SHEET (sheet)); 07529 07530 if(col > sheet->maxcol) return; 07531 07532 sheet->column[col].justification = justification; 07533 07534 if(GTK_WIDGET_REALIZED(sheet) && !GTK_SHEET_IS_FROZEN(sheet) && 07535 col >= MIN_VISIBLE_COLUMN(sheet) && col <= MAX_VISIBLE_COLUMN(sheet)) 07536 gtk_sheet_range_draw(sheet, NULL); 07537 07538 } 07539 07540 void 07541 gtk_sheet_range_set_editable(GtkSheet *sheet, const GtkSheetRange *urange, gboolean editable) 07542 { 07543 gint i, j; 07544 GtkSheetCellAttr attributes; 07545 GtkSheetRange range; 07546 07547 g_return_if_fail (sheet != NULL); 07548 g_return_if_fail (GTK_IS_SHEET (sheet)); 07549 07550 if(!urange) 07551 range = sheet->range; 07552 else 07553 range = *urange; 07554 07555 for (i=range.row0; i<=range.rowi; i++) 07556 for (j=range.col0; j<=range.coli; j++){ 07557 gtk_sheet_get_attributes(sheet, i, j, &attributes); 07558 attributes.is_editable = editable; 07559 gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 07560 } 07561 07562 if(!GTK_SHEET_IS_FROZEN(sheet)) 07563 gtk_sheet_range_draw(sheet, &range); 07564 07565 } 07566 07567 void 07568 gtk_sheet_range_set_visible(GtkSheet *sheet, const GtkSheetRange *urange, gboolean visible) 07569 { 07570 gint i, j; 07571 GtkSheetCellAttr attributes; 07572 GtkSheetRange range; 07573 07574 g_return_if_fail (sheet != NULL); 07575 g_return_if_fail (GTK_IS_SHEET (sheet)); 07576 07577 if(!urange) 07578 range = sheet->range; 07579 else 07580 range = *urange; 07581 07582 for (i=range.row0; i<=range.rowi; i++) 07583 for (j=range.col0; j<=range.coli; j++){ 07584 gtk_sheet_get_attributes(sheet, i, j, &attributes); 07585 attributes.is_visible=visible; 07586 gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 07587 } 07588 07589 if(!GTK_SHEET_IS_FROZEN(sheet)) 07590 gtk_sheet_range_draw(sheet, &range); 07591 07592 } 07593 07594 void 07595 gtk_sheet_range_set_border(GtkSheet *sheet, const GtkSheetRange *urange, gint mask, 07596 guint width, gint line_style) 07597 { 07598 gint i, j; 07599 GtkSheetCellAttr attributes; 07600 GtkSheetRange range; 07601 07602 g_return_if_fail (sheet != NULL); 07603 g_return_if_fail (GTK_IS_SHEET (sheet)); 07604 07605 if(!urange) 07606 range = sheet->range; 07607 else 07608 range = *urange; 07609 07610 for (i=range.row0; i<=range.rowi; i++) 07611 for (j=range.col0; j<=range.coli; j++){ 07612 gtk_sheet_get_attributes(sheet, i, j, &attributes); 07613 attributes.border.mask = mask; 07614 attributes.border.width = width; 07615 attributes.border.line_style=line_style; 07616 attributes.border.cap_style=GDK_CAP_NOT_LAST; 07617 attributes.border.join_style=GDK_JOIN_MITER; 07618 gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 07619 } 07620 07621 range.row0--; 07622 range.col0--; 07623 range.rowi++; 07624 range.coli++; 07625 07626 if(!GTK_SHEET_IS_FROZEN(sheet)) 07627 gtk_sheet_range_draw(sheet, &range); 07628 07629 } 07630 07631 void 07632 gtk_sheet_range_set_border_color(GtkSheet *sheet, const GtkSheetRange *urange, const GdkColor *color) 07633 { 07634 gint i, j; 07635 GtkSheetCellAttr attributes; 07636 GtkSheetRange range; 07637 07638 g_return_if_fail (sheet != NULL); 07639 g_return_if_fail (GTK_IS_SHEET (sheet)); 07640 07641 if(!urange) 07642 range = sheet->range; 07643 else 07644 range = *urange; 07645 07646 for (i=range.row0; i<=range.rowi; i++) 07647 for (j=range.col0; j<=range.coli; j++){ 07648 gtk_sheet_get_attributes(sheet, i, j, &attributes); 07649 attributes.border.color = *color; 07650 gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 07651 } 07652 07653 if(!GTK_SHEET_IS_FROZEN(sheet)) 07654 gtk_sheet_range_draw(sheet, &range); 07655 07656 } 07657 07658 void 07659 gtk_sheet_range_set_font(GtkSheet *sheet, const GtkSheetRange *urange, PangoFontDescription *font) 07660 { 07661 gint i, j; 07662 gint font_height; 07663 GtkSheetCellAttr attributes; 07664 GtkSheetRange range; 07665 PangoContext *context; 07666 PangoFontMetrics *metrics; 07667 07668 g_return_if_fail (sheet != NULL); 07669 g_return_if_fail (GTK_IS_SHEET (sheet)); 07670 07671 if(!urange) 07672 range = sheet->range; 07673 else 07674 range = *urange; 07675 07676 gtk_sheet_freeze(sheet); 07677 07678 context = gtk_widget_get_pango_context(GTK_WIDGET(sheet)); 07679 metrics = pango_context_get_metrics(context, 07680 font, 07681 pango_context_get_language(context)); 07682 font_height = pango_font_metrics_get_descent(metrics) + 07683 pango_font_metrics_get_ascent(metrics); 07684 font_height = PANGO_PIXELS(font_height) + 2*CELLOFFSET; 07685 07686 for (i=range.row0; i<=range.rowi; i++) 07687 for (j=range.col0; j<=range.coli; j++){ 07688 gtk_sheet_get_attributes(sheet, i, j, &attributes); 07689 attributes.font_desc = font; 07690 if(font_height > sheet->row[i].height){ 07691 sheet->row[i].height = font_height; 07692 gtk_sheet_recalc_top_ypixels(sheet, i); 07693 } 07694 07695 gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 07696 } 07697 07698 gtk_sheet_thaw(sheet); 07699 pango_font_metrics_unref(metrics); 07700 } 07701 07702 static void 07703 gtk_sheet_set_cell_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr attributes) 07704 { 07705 GtkSheetCell **cell; 07706 07707 if(row > sheet->maxrow || col >sheet->maxcol) return; 07708 07709 CheckBounds(sheet, row, col); 07710 07711 cell = &sheet->data[row][col]; 07712 07713 if(*cell==NULL){ 07714 (*cell) = gtk_sheet_cell_new(); 07715 (*cell)->row = row; 07716 (*cell)->col = col; 07717 } 07718 07719 if((*cell)->attributes == NULL) 07720 (*cell)->attributes = g_new(GtkSheetCellAttr, 1); 07721 07722 *((*cell)->attributes) = attributes; 07723 } 07724 07725 gboolean 07726 gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr *attributes) 07727 { 07728 GtkSheetCell **cell = NULL; 07729 07730 g_return_val_if_fail (sheet != NULL, FALSE); 07731 g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE); 07732 07733 if(row < 0 || col < 0) return FALSE; 07734 07735 if(row > sheet->maxallocrow || col > sheet->maxalloccol){ 07736 init_attributes(sheet, col, attributes); 07737 return FALSE; 07738 } 07739 07740 if(row <= sheet->maxallocrow && col <= sheet->maxalloccol){ 07741 if(sheet->data[row] && sheet->data[row][col]) 07742 cell = &sheet->data[row][col]; 07743 if(cell == NULL || *cell == NULL){ 07744 init_attributes(sheet, col, attributes); 07745 return FALSE; 07746 } else 07747 if((*cell)->attributes == NULL){ 07748 init_attributes(sheet, col, attributes); 07749 return FALSE; 07750 }else{ 07751 *attributes = *(sheet->data[row][col]->attributes); 07752 if(sheet->column[col].justification != GTK_JUSTIFY_FILL) 07753 attributes->justification = sheet->column[col].justification; 07754 } 07755 } 07756 07757 return TRUE; 07758 } 07759 07760 static void 07761 init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes) 07762 { 07763 /* DEFAULT VALUES */ 07764 attributes->foreground = GTK_WIDGET(sheet)->style->black; 07765 attributes->background = sheet->bg_color; 07766 if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){ 07767 GdkColormap *colormap; 07768 colormap=gdk_colormap_get_system(); 07769 gdk_color_black(colormap, &attributes->foreground); 07770 attributes->background = sheet->bg_color; 07771 } 07772 attributes->justification = sheet->column[col].justification; 07773 attributes->border.width = 0; 07774 attributes->border.line_style = GDK_LINE_SOLID; 07775 attributes->border.cap_style = GDK_CAP_NOT_LAST; 07776 attributes->border.join_style = GDK_JOIN_MITER; 07777 attributes->border.mask = 0; 07778 attributes->border.color = GTK_WIDGET(sheet)->style->black; 07779 attributes->is_editable = TRUE; 07780 attributes->is_visible = TRUE; 07781 attributes->font = GTK_WIDGET(sheet)->style->private_font; 07782 attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc; 07783 07784 } 07785 07786 /********************************************************************** 07787 * Memory allocation routines: 07788 * AddRow & AddColumn allocate memory for GtkSheetColumn & GtkSheetRow structs. 07789 * InsertRow 07790 * InsertColumn 07791 * DeleteRow 07792 * DeleteColumn 07793 * GrowSheet allocates memory for the sheet cells contents using an array of 07794 * pointers. Alternative to this could be a linked list or a hash table. 07795 * CheckBounds checks whether the given cell is currently allocated or not. 07796 * If not, it calls to GrowSheet. 07797 **********************************************************************/ 07798 07799 static gint 07800 AddColumn(GtkSheet *tbl, gint ncols) 07801 { 07802 gint i; 07803 07804 if(ncols == -1 && tbl->maxcol == 0) 07805 { 07806 ncols = 1; 07807 } 07808 else 07809 { 07810 tbl->maxcol += ncols; 07811 tbl->column = (GtkSheetColumn *)g_realloc(tbl->column,(tbl->maxcol+1)* 07812 sizeof(GtkSheetColumn)); 07813 } 07814 07815 for(i=tbl->maxcol-ncols+1; i<= tbl->maxcol; i++){ 07816 tbl->column[i].width=DEFAULT_COLUMN_WIDTH; 07817 tbl->column[i].button.label=NULL; 07818 tbl->column[i].button.child=NULL; 07819 tbl->column[i].button.state=GTK_STATE_NORMAL; 07820 tbl->column[i].button.justification=GTK_JUSTIFY_CENTER; 07821 tbl->column[i].button.label_visible = TRUE; 07822 tbl->column[i].name=NULL; 07823 tbl->column[i].is_visible=TRUE; 07824 tbl->column[i].is_sensitive=TRUE; 07825 tbl->column[i].left_text_column=i; 07826 tbl->column[i].right_text_column=i; 07827 tbl->column[i].justification=GTK_JUSTIFY_FILL; 07828 tbl->column[i].requisition=DEFAULT_COLUMN_WIDTH; 07829 if(i>0) 07830 { 07831 tbl->column[i].left_text_column=tbl->column[i-1].left_text_column; 07832 tbl->column[i].left_xpixel=tbl->column[i-1].left_xpixel + 07833 tbl->column[i-1].width; 07834 } 07835 else 07836 { 07837 tbl->column[i].left_xpixel=tbl->row_title_area.width; 07838 if(!tbl->row_titles_visible) 07839 tbl->column[i].left_xpixel=0; 07840 } 07841 } 07842 return TRUE; 07843 } 07844 07845 static gint 07846 AddRow(GtkSheet *tbl, gint nrows) 07847 { 07848 gint i; 07849 07850 if(nrows == -1 && tbl->maxrow == 0) 07851 { 07852 nrows = 1; 07853 } 07854 else 07855 { 07856 tbl->maxrow += nrows; 07857 tbl->row = (GtkSheetRow *)g_realloc(tbl->row,(tbl->maxrow+1)* 07858 sizeof(GtkSheetRow)); 07859 } 07860 07861 for(i=tbl->maxrow-nrows+1; i<= tbl->maxrow; i++){ 07862 tbl->row[i].requisition=tbl->row[i].height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(tbl)); 07863 tbl->row[i].button.label=NULL; 07864 tbl->row[i].button.child=NULL; 07865 tbl->row[i].button.state=GTK_STATE_NORMAL; 07866 tbl->row[i].button.justification=GTK_JUSTIFY_CENTER; 07867 tbl->row[i].button.label_visible = TRUE; 07868 tbl->row[i].name=NULL; 07869 tbl->row[i].is_visible=TRUE; 07870 tbl->row[i].is_sensitive=TRUE; 07871 if(i>0) 07872 tbl->row[i].top_ypixel=tbl->row[i-1].top_ypixel+tbl->row[i-1].height; 07873 else 07874 { 07875 tbl->row[i].top_ypixel=tbl->column_title_area.height; 07876 if(!tbl->column_titles_visible) 07877 tbl->row[i].top_ypixel=0; 07878 } 07879 } 07880 return TRUE; 07881 } 07882 07883 static gint 07884 InsertRow(GtkSheet *tbl, gint row, gint nrows) 07885 { 07886 GtkSheetCell **pp; 07887 gint i,j; 07888 GtkSheetCell **auxdata; 07889 GtkSheetRow auxrow; 07890 07891 AddRow(tbl,nrows); 07892 07893 for(i=tbl->maxrow; i>=row+nrows; i--){ 07894 auxrow = tbl->row[i]; 07895 tbl->row[i]=tbl->row[i-nrows]; 07896 tbl->row[i].is_visible=tbl->row[i-nrows].is_visible; 07897 tbl->row[i].is_sensitive=tbl->row[i-nrows].is_sensitive; 07898 if(auxrow.is_visible) 07899 tbl->row[i].top_ypixel+=nrows*DEFAULT_ROW_HEIGHT(GTK_WIDGET(tbl)); 07900 tbl->row[i-nrows]=auxrow; 07901 } 07902 07903 if(row <= tbl->maxallocrow){ 07904 07905 GrowSheet(tbl,nrows,0); 07906 07907 for(i=tbl->maxallocrow; i>=row+nrows; i--){ 07908 auxdata = tbl->data[i]; 07909 tbl->data[i]=tbl->data[i-nrows]; 07910 07911 pp= tbl->data[i]; 07912 for(j=0; j<=tbl->maxalloccol; j++,pp++){ 07913 if(*pp!=(GtkSheetCell *)NULL) 07914 (*pp)->row=i; 07915 07916 } 07917 tbl->data[i-nrows]=auxdata; 07918 } 07919 } 07920 gtk_sheet_recalc_top_ypixels(tbl, 0); 07921 return TRUE; 07922 } 07923 07924 static gint 07925 InsertColumn(GtkSheet *tbl, gint col, gint ncols) 07926 { 07927 gint i,j; 07928 GtkSheetColumn auxcol; 07929 07930 AddColumn(tbl,ncols); 07931 07932 for(i=tbl->maxcol; i>=col+ncols; i--){ 07933 auxcol = tbl->column[i]; 07934 tbl->column[i]=tbl->column[i-ncols]; 07935 tbl->column[i].is_visible=tbl->column[i-ncols].is_visible; 07936 tbl->column[i].is_sensitive=tbl->column[i-ncols].is_sensitive; 07937 tbl->column[i].left_text_column=tbl->column[i-ncols].left_text_column; 07938 tbl->column[i].right_text_column=tbl->column[i-ncols].right_text_column; 07939 tbl->column[i].justification=tbl->column[i-ncols].justification; 07940 if(auxcol.is_visible) tbl->column[i].left_xpixel+=ncols*DEFAULT_COLUMN_WIDTH; 07941 tbl->column[i-ncols]=auxcol; 07942 } 07943 07944 if(col <= tbl->maxalloccol){ 07945 07946 GrowSheet(tbl,0,ncols); 07947 07948 for(i=0; i<=tbl->maxallocrow; i++){ 07949 for(j=tbl->maxalloccol; j>=col+ncols; j--){ 07950 gtk_sheet_real_cell_clear(tbl, i, j, TRUE); 07951 tbl->data[i][j]=tbl->data[i][j-ncols]; 07952 if(tbl->data[i][j]) tbl->data[i][j]->col=j; 07953 tbl->data[i][j-ncols]=NULL; 07954 } 07955 } 07956 } 07957 gtk_sheet_recalc_left_xpixels(tbl, 0); 07958 return TRUE; 07959 } 07960 07961 static gint 07962 DeleteRow(GtkSheet *tbl, gint row, gint nrows) 07963 { 07964 GtkSheetCell **auxdata = NULL; 07965 gint i,j; 07966 07967 if(nrows <= 0 || row > tbl->maxrow) return TRUE; 07968 07969 nrows=MIN(nrows,tbl->maxrow-row+1); 07970 07971 for(i=row; i<row+nrows; i++){ 07972 if(tbl->row[i].name){ 07973 g_free(tbl->row[i].name); 07974 tbl->row[i].name = NULL; 07975 } 07976 if(tbl->row[i].button.label){ 07977 g_free(tbl->row[i].button.label); 07978 tbl->row[i].button.label = NULL; 07979 } 07980 } 07981 07982 for(i=row; i<=tbl->maxrow-nrows; i++){ 07983 if(i+nrows <= tbl->maxrow){ 07984 tbl->row[i]=tbl->row[i+nrows]; 07985 } 07986 } 07987 07988 if(row <= tbl->maxallocrow){ 07989 07990 for(i=row; i<=tbl->maxrow-nrows; i++){ 07991 if(i<=tbl->maxallocrow){ 07992 auxdata=tbl->data[i]; 07993 for(j=0; j<=tbl->maxalloccol; j++){ 07994 gtk_sheet_real_cell_clear(tbl, i, j, TRUE); 07995 } 07996 } 07997 if(i+nrows<=tbl->maxallocrow){ 07998 tbl->data[i]=tbl->data[i+nrows]; 07999 tbl->data[i+nrows]=auxdata; 08000 for(j=0; j<=tbl->maxalloccol; j++){ 08001 if(tbl->data[i][j]) tbl->data[i][j]->row=i; 08002 } 08003 } 08004 } 08005 08006 for(i=tbl->maxrow-nrows+1; i<=tbl->maxallocrow; i++){ 08007 if(i > 0 && tbl->data[i]){ 08008 g_free(tbl->data[i]); 08009 tbl->data[i] = NULL; 08010 } 08011 } 08012 08013 tbl->maxallocrow-=MIN(nrows,tbl->maxallocrow-row+1); 08014 tbl->maxallocrow = MIN(tbl->maxallocrow, tbl->maxrow); 08015 08016 } 08017 08018 tbl->maxrow-=nrows; 08019 gtk_sheet_recalc_top_ypixels(tbl, 0); 08020 return TRUE; 08021 } 08022 08023 static gint 08024 DeleteColumn(GtkSheet *tbl, gint column, gint ncols) 08025 { 08026 gint i,j; 08027 GtkSheetColumn auxcol; 08028 08029 ncols = MIN(ncols,tbl->maxcol-column+1); 08030 08031 if(ncols <= 0 || column > tbl->maxcol) return TRUE; 08032 08033 for(i=column; i<column+ncols; i++){ 08034 auxcol=tbl->column[i]; 08035 if(tbl->column[i].name){ 08036 g_free(tbl->column[i].name); 08037 tbl->column[i].name = NULL; 08038 } 08039 if(tbl->column[i].button.label){ 08040 g_free(tbl->column[i].button.label); 08041 tbl->column[i].button.label = NULL; 08042 } 08043 } 08044 08045 for(i=column; i<=tbl->maxcol-ncols; i++){ 08046 if(i+ncols <= tbl->maxcol){ 08047 tbl->column[i]=tbl->column[i+ncols]; 08048 } 08049 } 08050 08051 if(column <= tbl->maxalloccol){ 08052 08053 for(i=column; i<=tbl->maxcol-ncols; i++){ 08054 if(i<=tbl->maxalloccol){ 08055 for(j=0; j<=tbl->maxallocrow; j++){ 08056 gtk_sheet_real_cell_clear(tbl, j, i, TRUE); 08057 if(i+ncols <= tbl->maxalloccol){ 08058 tbl->data[j][i] = tbl->data[j][i+ncols]; 08059 tbl->data[j][i+ncols] = NULL; 08060 if(tbl->data[j][i]) tbl->data[j][i]->col=i; 08061 } 08062 } 08063 } 08064 08065 } 08066 08067 tbl->maxalloccol-=MIN(ncols,tbl->maxalloccol-column+1); 08068 tbl->maxalloccol = MIN(tbl->maxalloccol, tbl->maxcol); 08069 } 08070 tbl->maxcol-=ncols; 08071 gtk_sheet_recalc_left_xpixels(tbl, 0); 08072 return TRUE; 08073 } 08074 08075 static gint 08076 GrowSheet(GtkSheet *tbl, gint newrows, gint newcols) 08077 { 08078 gint i,j; 08079 gint inirow, inicol; 08080 08081 inirow = tbl->maxallocrow + 1; 08082 inicol = tbl->maxalloccol + 1; 08083 08084 tbl->maxalloccol = tbl->maxalloccol + newcols; 08085 tbl->maxallocrow = tbl->maxallocrow + newrows; 08086 08087 if(newrows>0){ 08088 tbl->data = (GtkSheetCell***) 08089 g_realloc(tbl->data,(tbl->maxallocrow+1)*sizeof(GtkSheetCell **)+sizeof(double)); 08090 08091 for(i=inirow; i <= tbl->maxallocrow; i++){ 08092 tbl->data[i] = (GtkSheetCell **) \ 08093 g_malloc((tbl->maxcol+1)*sizeof(GtkSheetCell *)+sizeof(double)); 08094 for(j=0; j<inicol; j++) { 08095 tbl->data[i][j] = NULL; 08096 } 08097 } 08098 08099 } 08100 08101 if(newcols>0){ 08102 for(i=0; i <= tbl->maxallocrow; i++) { 08103 tbl->data[i] = (GtkSheetCell **) \ 08104 g_realloc(tbl->data[i],(tbl->maxalloccol+1)*sizeof(GtkSheetCell *)+sizeof(double)); 08105 for(j=inicol; j <= tbl->maxalloccol; j++) { 08106 tbl->data[i][j] = NULL; 08107 } 08108 } 08109 } 08110 08111 return(0); 08112 } 08113 08114 static gint 08115 CheckBounds(GtkSheet *tbl, gint row, gint col) 08116 { 08117 gint newrows=0,newcols=0; 08118 08119 if(col>tbl->maxalloccol) newcols=col-tbl->maxalloccol; 08120 if(row>tbl->maxallocrow) newrows=row-tbl->maxallocrow; 08121 if(newrows>0 || newcols>0) GrowSheet(tbl, newrows, newcols); 08122 return(0); 08123 } 08124 08125 /******************************************************************** 08126 * Container Functions: 08127 * gtk_sheet_add 08128 * gtk_sheet_put 08129 * gtk_sheet_attach 08130 * gtk_sheet_remove 08131 * gtk_sheet_move_child 08132 * gtk_sheet_position_child 08133 * gtk_sheet_position_children 08134 * gtk_sheet_realize_child 08135 * gtk_sheet_get_child_at 08136 ********************************************************************/ 08137 08138 GtkSheetChild * 08139 gtk_sheet_put(GtkSheet *sheet, GtkWidget *child, gint x, gint y) 08140 { 08141 GtkRequisition child_requisition; 08142 GtkSheetChild *child_info; 08143 08144 g_return_val_if_fail(sheet != NULL, NULL); 08145 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL); 08146 g_return_val_if_fail(child != NULL, NULL); 08147 g_return_val_if_fail(child->parent == NULL, NULL); 08148 08149 child_info = g_new (GtkSheetChild, 1); 08150 child_info->widget = child; 08151 child_info->x = x; 08152 child_info->y = y; 08153 child_info->attached_to_cell = FALSE; 08154 child_info->floating = TRUE; 08155 child_info->xpadding = child_info->ypadding = 0; 08156 child_info->xexpand = child_info->yexpand = FALSE; 08157 child_info->xshrink = child_info->yshrink = FALSE; 08158 child_info->xfill = child_info->yfill = FALSE; 08159 08160 sheet->children = g_list_append(sheet->children, child_info); 08161 08162 gtk_widget_set_parent (child, GTK_WIDGET(sheet)); 08163 08164 gtk_widget_size_request(child, &child_requisition); 08165 08166 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet))) 08167 { 08168 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && 08169 (!GTK_WIDGET_REALIZED(child) || GTK_WIDGET_NO_WINDOW(child))) 08170 gtk_sheet_realize_child(sheet, child_info); 08171 08172 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) && 08173 !GTK_WIDGET_MAPPED(child)) 08174 gtk_widget_map(child); 08175 } 08176 08177 gtk_sheet_position_child(sheet, child_info); 08178 08179 /* This will avoid drawing on the titles */ 08180 08181 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) 08182 { 08183 if(sheet->row_titles_visible) 08184 gdk_window_show(sheet->row_title_window); 08185 if(sheet->column_titles_visible) 08186 gdk_window_show(sheet->column_title_window); 08187 } 08188 08189 return (child_info); 08190 } 08191 08192 void 08193 gtk_sheet_attach_floating (GtkSheet *sheet, 08194 GtkWidget *widget, 08195 gint row, gint col) 08196 { 08197 GdkRectangle area; 08198 GtkSheetChild *child; 08199 08200 if(row < 0 || col < 0){ 08201 gtk_sheet_button_attach(sheet, widget, row, col); 08202 return; 08203 } 08204 08205 gtk_sheet_get_cell_area(sheet, row, col, &area); 08206 child = gtk_sheet_put(sheet, widget, area.x, area.y); 08207 child->attached_to_cell = TRUE; 08208 child->row = row; 08209 child->col = col; 08210 } 08211 08212 void 08213 gtk_sheet_attach_default (GtkSheet *sheet, 08214 GtkWidget *widget, 08215 gint row, gint col) 08216 { 08217 if(row < 0 || col < 0){ 08218 gtk_sheet_button_attach(sheet, widget, row, col); 08219 return; 08220 } 08221 08222 gtk_sheet_attach(sheet, widget, row, col, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 0, 0); 08223 } 08224 08225 void 08226 gtk_sheet_attach (GtkSheet *sheet, 08227 GtkWidget *widget, 08228 gint row, gint col, 08229 gint xoptions, 08230 gint yoptions, 08231 gint xpadding, 08232 gint ypadding) 08233 { 08234 GdkRectangle area; 08235 GtkSheetChild *child = NULL; 08236 08237 if(row < 0 || col < 0){ 08238 gtk_sheet_button_attach(sheet, widget, row, col); 08239 return; 08240 } 08241 08242 child = g_new0(GtkSheetChild, 1); 08243 child->attached_to_cell = TRUE; 08244 child->floating = FALSE; 08245 child->widget = widget; 08246 child->row = row; 08247 child->col = col; 08248 child->xpadding = xpadding; 08249 child->ypadding = ypadding; 08250 child->xexpand = (xoptions & GTK_EXPAND) != 0; 08251 child->yexpand = (yoptions & GTK_EXPAND) != 0; 08252 child->xshrink = (xoptions & GTK_SHRINK) != 0; 08253 child->yshrink = (yoptions & GTK_SHRINK) != 0; 08254 child->xfill = (xoptions & GTK_FILL) != 0; 08255 child->yfill = (yoptions & GTK_FILL) != 0; 08256 08257 sheet->children = g_list_append(sheet->children, child); 08258 08259 gtk_sheet_get_cell_area(sheet, row, col, &area); 08260 08261 child->x = area.x + child->xpadding; 08262 child->y = area.y + child->ypadding; 08263 08264 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet))) 08265 { 08266 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && 08267 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget))) 08268 gtk_sheet_realize_child(sheet, child); 08269 08270 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) && 08271 !GTK_WIDGET_MAPPED(widget)) 08272 gtk_widget_map(widget); 08273 } 08274 08275 gtk_sheet_position_child(sheet, child); 08276 08277 /* This will avoid drawing on the titles */ 08278 08279 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) 08280 { 08281 if(GTK_SHEET_ROW_TITLES_VISIBLE(sheet)) 08282 gdk_window_show(sheet->row_title_window); 08283 if(GTK_SHEET_COL_TITLES_VISIBLE(sheet)) 08284 gdk_window_show(sheet->column_title_window); 08285 } 08286 08287 } 08288 08289 void 08290 gtk_sheet_button_attach (GtkSheet *sheet, 08291 GtkWidget *widget, 08292 gint row, gint col) 08293 { 08294 GtkSheetButton *button; 08295 GtkSheetChild *child; 08296 GtkRequisition button_requisition; 08297 08298 if(row >= 0 && col >= 0) return; 08299 if(row < 0 && col < 0) return; 08300 08301 child = g_new (GtkSheetChild, 1); 08302 child->widget = widget; 08303 child->x = 0; 08304 child->y = 0; 08305 child->attached_to_cell = TRUE; 08306 child->floating = FALSE; 08307 child->row = row; 08308 child->col = col; 08309 child->xpadding = child->ypadding = 0; 08310 child->xshrink = child->yshrink = FALSE; 08311 child->xfill = child->yfill = FALSE; 08312 08313 if(row == -1){ 08314 button = &sheet->column[col].button; 08315 button->child = child; 08316 } 08317 else 08318 { 08319 button = &sheet->row[row].button; 08320 button->child = child; 08321 } 08322 08323 sheet->children = g_list_append(sheet->children, child); 08324 08325 gtk_sheet_button_size_request(sheet, button, &button_requisition); 08326 08327 if(row == -1){ 08328 if(button_requisition.height > sheet->column_title_area.height) 08329 sheet->column_title_area.height = button_requisition.height; 08330 if(button_requisition.width > sheet->column[col].width) 08331 sheet->column[col].width = button_requisition.width; 08332 } 08333 08334 if(col == -1){ 08335 if(button_requisition.width > sheet->row_title_area.width) 08336 sheet->row_title_area.width = button_requisition.width; 08337 if(button_requisition.height > sheet->row[row].height) 08338 sheet->row[row].height = button_requisition.height; 08339 } 08340 08341 if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet))) 08342 { 08343 if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)) && 08344 (!GTK_WIDGET_REALIZED(widget) || GTK_WIDGET_NO_WINDOW(widget))) 08345 gtk_sheet_realize_child(sheet, child); 08346 08347 if(GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)) && 08348 !GTK_WIDGET_MAPPED(widget)) 08349 gtk_widget_map(widget); 08350 } 08351 08352 if(row == -1) size_allocate_column_title_buttons(sheet); 08353 if(col == -1) size_allocate_row_title_buttons(sheet); 08354 08355 } 08356 08357 static void 08358 label_size_request(GtkSheet *sheet, gchar *label, GtkRequisition *req) 08359 { 08360 gchar *words; 08361 gchar word[1000]; 08362 gint n = 0; 08363 gint row_height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)) - 2*CELLOFFSET + 2; 08364 08365 req->height = 0; 08366 req->width = 0; 08367 words=label; 08368 08369 while(words && *words != '\0'){ 08370 if(*words == '\n' || *(words+1) == '\0'){ 08371 req->height += row_height; 08372 08373 word[n] = '\0'; 08374 req->width = MAX(req->width, STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, word)); 08375 n = 0; 08376 } else { 08377 word[n++] = *words; 08378 } 08379 words++; 08380 } 08381 08382 if(n > 0) req->height -= 2; 08383 } 08384 08385 static void 08386 gtk_sheet_button_size_request (GtkSheet *sheet, 08387 GtkSheetButton *button, 08388 GtkRequisition *button_requisition) 08389 { 08390 GtkRequisition requisition; 08391 GtkRequisition label_requisition; 08392 08393 if(gtk_sheet_autoresize(sheet) && button->label && strlen(button->label) > 0){ 08394 label_size_request(sheet, button->label, &label_requisition); 08395 label_requisition.width += 2*CELLOFFSET; 08396 label_requisition.height += 2*CELLOFFSET; 08397 } else { 08398 label_requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)); 08399 label_requisition.width = COLUMN_MIN_WIDTH; 08400 } 08401 08402 if(button->child) 08403 { 08404 gtk_widget_size_request(button->child->widget, &requisition); 08405 requisition.width += 2*button->child->xpadding; 08406 requisition.height += 2*button->child->ypadding; 08407 requisition.width += 2*sheet->button->style->xthickness; 08408 requisition.height += 2*sheet->button->style->ythickness; 08409 } 08410 else 08411 { 08412 requisition.height = DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet)); 08413 requisition.width = COLUMN_MIN_WIDTH; 08414 } 08415 08416 *button_requisition = requisition; 08417 button_requisition->width = MAX(requisition.width, label_requisition.width); 08418 button_requisition->height = MAX(requisition.height, label_requisition.height); 08419 08420 } 08421 08422 static void 08423 gtk_sheet_row_size_request (GtkSheet *sheet, 08424 gint row, 08425 guint *requisition) 08426 { 08427 GtkRequisition button_requisition; 08428 GList *children; 08429 08430 gtk_sheet_button_size_request(sheet, &sheet->row[row].button, &button_requisition); 08431 08432 *requisition = button_requisition.height; 08433 08434 children = sheet->children; 08435 while(children){ 08436 GtkSheetChild *child = (GtkSheetChild *)children->data; 08437 GtkRequisition child_requisition; 08438 08439 if(child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink){ 08440 gtk_widget_get_child_requisition(child->widget, &child_requisition); 08441 08442 if(child_requisition.height + 2 * child->ypadding > *requisition) 08443 *requisition = child_requisition.height + 2 * child->ypadding; 08444 } 08445 children = g_list_next(children); 08446 } 08447 08448 sheet->row[row].requisition = *requisition; 08449 } 08450 08451 static void 08452 gtk_sheet_column_size_request (GtkSheet *sheet, 08453 gint col, 08454 guint *requisition) 08455 { 08456 GtkRequisition button_requisition; 08457 GList *children; 08458 08459 gtk_sheet_button_size_request(sheet, &sheet->column[col].button, &button_requisition); 08460 08461 *requisition = button_requisition.width; 08462 08463 children = sheet->children; 08464 while(children){ 08465 GtkSheetChild *child = (GtkSheetChild *)children->data; 08466 GtkRequisition child_requisition; 08467 08468 if(child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink){ 08469 gtk_widget_get_child_requisition(child->widget, &child_requisition); 08470 08471 if(child_requisition.width + 2 * child->xpadding > *requisition) 08472 *requisition = child_requisition.width + 2 * child->xpadding; 08473 } 08474 children = g_list_next(children); 08475 } 08476 08477 sheet->column[col].requisition = *requisition; 08478 } 08479 08480 void 08481 gtk_sheet_move_child(GtkSheet *sheet, GtkWidget *widget, gint x, gint y) 08482 { 08483 GtkSheetChild *child; 08484 GList *children; 08485 08486 g_return_if_fail(sheet != NULL); 08487 g_return_if_fail(GTK_IS_SHEET(sheet)); 08488 08489 children = sheet->children; 08490 while(children) 08491 { 08492 child = children->data; 08493 08494 if(child->widget == widget){ 08495 child->x = x; 08496 child->y = y; 08497 child->row = ROW_FROM_YPIXEL(sheet, y); 08498 child->col = COLUMN_FROM_XPIXEL(sheet, x); 08499 gtk_sheet_position_child(sheet, child); 08500 return; 08501 } 08502 08503 children = g_list_next(children); 08504 } 08505 08506 g_warning("Widget must be a GtkSheet child"); 08507 08508 } 08509 08510 static void 08511 gtk_sheet_position_child(GtkSheet *sheet, GtkSheetChild *child) 08512 { 08513 GtkRequisition child_requisition; 08514 GtkAllocation child_allocation; 08515 gint xoffset = 0; 08516 gint yoffset = 0; 08517 gint x = 0, y = 0; 08518 GdkRectangle area; 08519 08520 gtk_widget_get_child_requisition(child->widget, &child_requisition); 08521 08522 if(sheet->column_titles_visible) 08523 yoffset = sheet->column_title_area.height; 08524 08525 if(sheet->row_titles_visible) 08526 xoffset = sheet->row_title_area.width; 08527 08528 if(child->attached_to_cell){ 08529 /* 08530 child->x = COLUMN_LEFT_XPIXEL(sheet, child->col); 08531 child->y = ROW_TOP_YPIXEL(sheet, child->row); 08532 08533 if(sheet->row_titles_visible) 08534 child->x-=sheet->row_title_area.width; 08535 if(sheet->column_titles_visible) 08536 child->y-=sheet->column_title_area.height; 08537 08538 width = sheet->column[child->col].width; 08539 height = sheet->row[child->row].height; 08540 */ 08541 08542 gtk_sheet_get_cell_area(sheet, child->row, child->col, &area); 08543 child->x = area.x + child->xpadding; 08544 child->y = area.y + child->ypadding; 08545 08546 if(!child->floating){ 08547 if(child_requisition.width + 2*child->xpadding <= sheet->column[child->col].width){ 08548 if(child->xfill){ 08549 child_requisition.width = child_allocation.width = sheet->column[child->col].width - 2*child->xpadding; 08550 } else { 08551 if(child->xexpand){ 08552 child->x = area.x + sheet->column[child->col].width / 2 - 08553 child_requisition.width / 2; 08554 } 08555 child_allocation.width = child_requisition.width; 08556 } 08557 } else { 08558 if(!child->xshrink){ 08559 gtk_sheet_set_column_width(sheet, child->col, child_requisition.width + 2 * child->xpadding); 08560 } 08561 child_allocation.width = sheet->column[child->col].width - 2*child->xpadding; 08562 } 08563 08564 if(child_requisition.height + 2*child->ypadding <= sheet->row[child->row].height){ 08565 if(child->yfill){ 08566 child_requisition.height = child_allocation.height = sheet->row[child->row].height - 2*child->ypadding; 08567 } else { 08568 if(child->yexpand){ 08569 child->y = area.y + sheet->row[child->row].height / 2 - 08570 child_requisition.height / 2; 08571 } 08572 child_allocation.height = child_requisition.height; 08573 } 08574 } else { 08575 if(!child->yshrink){ 08576 gtk_sheet_set_row_height(sheet, child->row, child_requisition.height + 2 * child->ypadding); 08577 } 08578 child_allocation.height = sheet->row[child->row].height - 2*child->ypadding; 08579 } 08580 } else { 08581 child_allocation.width = child_requisition.width; 08582 child_allocation.height = child_requisition.height; 08583 } 08584 08585 x = child_allocation.x = child->x + xoffset; 08586 y = child_allocation.y = child->y + yoffset; 08587 } 08588 else 08589 { 08590 x = child_allocation.x = child->x + sheet->hoffset + xoffset; 08591 x = child_allocation.x = child->x + xoffset; 08592 y = child_allocation.y = child->y + sheet->voffset + yoffset; 08593 y = child_allocation.y = child->y + yoffset; 08594 child_allocation.width = child_requisition.width; 08595 child_allocation.height = child_requisition.height; 08596 } 08597 08598 gtk_widget_size_allocate(child->widget, &child_allocation); 08599 gtk_widget_queue_draw(child->widget); 08600 } 08601 08602 static void 08603 gtk_sheet_forall (GtkContainer *container, 08604 gboolean include_internals, 08605 GtkCallback callback, 08606 gpointer callback_data) 08607 { 08608 GtkSheet *sheet; 08609 GtkSheetChild *child; 08610 GList *children; 08611 08612 g_return_if_fail (GTK_IS_SHEET (container)); 08613 g_return_if_fail (callback != NULL); 08614 08615 sheet = GTK_SHEET (container); 08616 08617 children = sheet->children; 08618 while (children) 08619 { 08620 child = children->data; 08621 children = g_list_next(children); 08622 08623 (* callback) (child->widget, callback_data); 08624 } 08625 if(sheet->button) 08626 (* callback) (sheet->button, callback_data); 08627 if(sheet->sheet_entry) 08628 (* callback) (sheet->sheet_entry, callback_data); 08629 } 08630 08631 08632 static void 08633 gtk_sheet_position_children(GtkSheet *sheet) 08634 { 08635 GList *children; 08636 GtkSheetChild *child; 08637 08638 children = sheet->children; 08639 08640 while(children) 08641 { 08642 child = (GtkSheetChild *)children->data; 08643 08644 if(child->col !=-1 && child->row != -1) 08645 gtk_sheet_position_child(sheet, child); 08646 08647 if(child->row == -1){ 08648 if(child->col < MIN_VISIBLE_COLUMN(sheet) || 08649 child->col > MAX_VISIBLE_COLUMN(sheet)) 08650 gtk_sheet_child_hide(child); 08651 else 08652 gtk_sheet_child_show(child); 08653 } 08654 if(child->col == -1){ 08655 if(child->row < MIN_VISIBLE_ROW(sheet) || 08656 child->row > MAX_VISIBLE_ROW(sheet)) 08657 gtk_sheet_child_hide(child); 08658 else 08659 gtk_sheet_child_show(child); 08660 } 08661 08662 children = g_list_next(children); 08663 } 08664 08665 } 08666 08667 static void 08668 gtk_sheet_remove (GtkContainer *container, GtkWidget *widget) 08669 { 08670 GtkSheet *sheet; 08671 GList *children; 08672 GtkSheetChild *child = 0; 08673 08674 g_return_if_fail(container != NULL); 08675 g_return_if_fail(GTK_IS_SHEET(container)); 08676 08677 sheet = GTK_SHEET(container); 08678 08679 children = sheet->children; 08680 08681 while(children) 08682 { 08683 child = (GtkSheetChild *)children->data; 08684 08685 if(child->widget == widget) break; 08686 08687 children = g_list_next(children); 08688 } 08689 08690 if (children) 08691 { 08692 if(child->row == -1) 08693 sheet->row[child->col].button.child = NULL; 08694 08695 if(child->col == -1) 08696 sheet->column[child->row].button.child = NULL; 08697 08698 gtk_widget_unparent (widget); 08699 child->widget = NULL; 08700 08701 sheet->children = g_list_remove_link (sheet->children, children); 08702 g_list_free_1 (children); 08703 g_free(child); 08704 } 08705 08706 } 08707 08708 static void 08709 gtk_sheet_realize_child(GtkSheet *sheet, GtkSheetChild *child) 08710 { 08711 GtkWidget *widget; 08712 08713 widget = GTK_WIDGET(sheet); 08714 08715 if(GTK_WIDGET_REALIZED(widget)){ 08716 if(child->row == -1) 08717 gtk_widget_set_parent_window(child->widget, sheet->column_title_window); 08718 else if(child->col == -1) 08719 gtk_widget_set_parent_window(child->widget, sheet->row_title_window); 08720 else 08721 gtk_widget_set_parent_window(child->widget, sheet->sheet_window); 08722 } 08723 08724 gtk_widget_set_parent(child->widget, widget); 08725 } 08726 08727 08728 08729 GtkSheetChild * 08730 gtk_sheet_get_child_at(GtkSheet *sheet, gint row, gint col) 08731 { 08732 GList *children; 08733 GtkSheetChild *child = 0; 08734 08735 g_return_val_if_fail(sheet != NULL, NULL); 08736 g_return_val_if_fail(GTK_IS_SHEET(sheet), NULL); 08737 08738 children = sheet->children; 08739 08740 while(children) 08741 { 08742 child = (GtkSheetChild *)children->data; 08743 08744 if(child->attached_to_cell) 08745 if(child->row == row && child->col == col) break; 08746 08747 children = g_list_next(children); 08748 } 08749 08750 if(children) return child; 08751 08752 return NULL; 08753 } 08754 08755 static void 08756 gtk_sheet_child_hide(GtkSheetChild *child) 08757 { 08758 g_return_if_fail(child != NULL); 08759 gtk_widget_hide(child->widget); 08760 } 08761 08762 static void 08763 gtk_sheet_child_show(GtkSheetChild *child) 08764 { 08765 g_return_if_fail(child != NULL); 08766 08767 gtk_widget_show(child->widget); 08768 }