sheet-view.c 24.5 KB
Newer Older
Arturo Espinosa's avatar
Arturo Espinosa committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * sheet-view.c: Implements a view of the Sheet.
 *
 * Author:
 *    Miguel de Icaza (miguel@kernel.org)
 *
 */
#include <config.h>

#include <gnome.h>
#include <gdk/gdkkeysyms.h>
#include <gdk/gdkx.h>
#include <string.h>
#include "gnumeric.h"
#include "gnumeric-sheet.h"
Michael Meeks's avatar
Michael Meeks committed
16
#include "selection.h"
Michael Meeks's avatar
Michael Meeks committed
17
#include "sheet-object.h"
18
#include "item-cursor.h"
19
#include "gnumeric-util.h"
20
#include "utils.h"
21
#include "selection.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
22

23 24 25
/* Sizes for column/row headers */

#define COLUMN_HEADER_HEIGHT 20
26
#define ROW_HEADER_WIDTH 50
27

Arturo Espinosa's avatar
Arturo Espinosa committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
static GtkTableClass *sheet_view_parent_class;

void
sheet_view_redraw_all (SheetView *sheet_view)
{
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));
	
	gnome_canvas_request_redraw (
		GNOME_CANVAS (sheet_view->sheet_view),
		0, 0, INT_MAX, INT_MAX);
	gnome_canvas_request_redraw (
		GNOME_CANVAS (sheet_view->col_canvas),
		0, 0, INT_MAX, INT_MAX);
	gnome_canvas_request_redraw (
		GNOME_CANVAS (sheet_view->row_canvas),
		0, 0, INT_MAX, INT_MAX);
}

void
sheet_view_redraw_cell_region (SheetView *sheet_view, int start_col, int start_row, int end_col, int end_row)
{
	GnumericSheet *gsheet;
51
	GnomeCanvas *canvas;
Arturo Espinosa's avatar
Arturo Espinosa committed
52
	Sheet *sheet = sheet_view->sheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
53
	int first_col, first_row, last_col, last_row;
54
	int col, row, min_col, max_col;
Arturo Espinosa's avatar
Arturo Espinosa committed
55 56 57 58 59 60 61
	int x, y, w, h;
	
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));

	gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
	g_return_if_fail (GNUMERIC_IS_SHEET (gsheet));
62
	canvas = GNOME_CANVAS (gsheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
63

64 65 66 67
	if ((end_col < gsheet->col.first) ||
	    (end_row < gsheet->row.first) ||
	    (start_col > gsheet->col.last_visible) ||
	    (start_row > gsheet->row.last_visible))
68 69 70
		return;
	
	/* The region on which we care to redraw */
71 72 73 74
	first_col = MAX (gsheet->col.first, start_col);
	first_row = MAX (gsheet->row.first, start_row);
	last_col =  MIN (gsheet->col.last_visible, end_col);
	last_row =  MIN (gsheet->row.last_visible, end_row);
75 76

	/* Initial values for min/max column computation */
Arturo Espinosa's avatar
Arturo Espinosa committed
77 78
	min_col = first_col;
	max_col = last_col;
79 80

	/* Find the range of columns that require a redraw */
Arturo Espinosa's avatar
Arturo Espinosa committed
81 82
	for (col = first_col; col <= last_col; col++)
		for (row = first_row; row <= last_row; row++){
83 84 85 86 87 88 89 90 91 92 93 94 95
			Cell *cell;
			int  col1, col2;

			cell = sheet_cell_get (sheet, col, row);

			if (cell){
				cell_get_span (cell, &col1, &col2);

				min_col = MIN (col1, min_col);
				max_col = MAX (col2, max_col);
			}
			
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
96

97
	/* Only draw those regions that are visible */
98 99
	min_col = MAX (MIN (first_col, min_col), gsheet->col.first);
	max_col = MIN (MAX (last_col, max_col), gsheet->col.last_visible);
Arturo Espinosa's avatar
Arturo Espinosa committed
100

101 102
	x = sheet_col_get_distance (sheet, gsheet->col.first, min_col);
	y = sheet_row_get_distance (sheet, gsheet->row.first, first_row);
103
	w = sheet_col_get_distance (sheet, min_col, max_col+1);
Arturo Espinosa's avatar
Arturo Espinosa committed
104
	h = sheet_row_get_distance (sheet, first_row, last_row+1);
Arturo Espinosa's avatar
Arturo Espinosa committed
105

106 107
	x += canvas->layout.xoffset - canvas->zoom_xofs;
	y += canvas->layout.yoffset - canvas->zoom_yofs;
108 109 110
	gnome_canvas_request_redraw (GNOME_CANVAS (gsheet),
				     x, y,
				     x+w, y+h);
Arturo Espinosa's avatar
Arturo Espinosa committed
111 112 113
}

void
Jody Goldberg's avatar
Jody Goldberg committed
114 115 116
sheet_view_redraw_headers (SheetView *sheet_view,
			   gboolean const col, gboolean const row,
			   Range const * r /* optional == NULL */)
Arturo Espinosa's avatar
Arturo Espinosa committed
117
{
Jody Goldberg's avatar
Jody Goldberg committed
118
	GnumericSheet *gsheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
119 120 121
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));

Jody Goldberg's avatar
Jody Goldberg committed
122
	gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
Arturo Espinosa's avatar
Arturo Espinosa committed
123

Jody Goldberg's avatar
Jody Goldberg committed
124 125 126 127 128 129 130 131 132
	if (col) {
		int left = 0, right = INT_MAX;
		if (r != NULL) {
			int const size = r->end.col - r->start.col;
/* A rough heuristic guess of the number of when the
 * trade off point of redrawing all vs calculating the
 * redraw size is crossed */
#define COL_HEURISTIC	20
			if (-COL_HEURISTIC < size && size < COL_HEURISTIC) {
133
				left = gsheet->col_offset.first +
Jody Goldberg's avatar
Jody Goldberg committed
134
				    sheet_col_get_distance (sheet_view->sheet,
135
							    gsheet->col.first, r->start.col);
Jody Goldberg's avatar
Jody Goldberg committed
136 137 138 139 140 141 142 143 144
				right = left +
				    sheet_col_get_distance (sheet_view->sheet,
							    r->start.col, r->end.col+1);
			}
		}
		gnome_canvas_request_redraw (
			GNOME_CANVAS (sheet_view->col_canvas),
			left, 0, right, INT_MAX);
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
145

Jody Goldberg's avatar
Jody Goldberg committed
146 147 148 149 150 151 152 153 154
	if (row) {
		int top = 0, bottom = INT_MAX;
		if (r != NULL) {
			int const size = r->end.row - r->start.row;
/* A rough heuristic guess of the number of when the
 * trade off point of redrawing all vs calculating the
 * redraw size is crossed */
#define ROW_HEURISTIC	50
			if (-ROW_HEURISTIC < size && size < ROW_HEURISTIC) {
155
				top = gsheet->row_offset.first +
Jody Goldberg's avatar
Jody Goldberg committed
156
				    sheet_row_get_distance (sheet_view->sheet,
157
							    gsheet->row.first, r->start.row);
Jody Goldberg's avatar
Jody Goldberg committed
158 159 160 161 162 163 164 165 166
				bottom = top +
				    sheet_row_get_distance (sheet_view->sheet,
							    r->start.row, r->end.row+1);
			}
		}
		gnome_canvas_request_redraw (
			GNOME_CANVAS (sheet_view->row_canvas),
			0, top, INT_MAX, bottom);
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
167 168 169 170 171
}

void
sheet_view_set_zoom_factor (SheetView *sheet_view, double factor)
{
172 173 174
	GList *l;
	GnumericSheet *gsheet;

Arturo Espinosa's avatar
Arturo Espinosa committed
175 176 177
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));
	
178 179
	gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);

180
	/* Set pixels_per_unit before the font.  The item bars look here for the number */
181
	gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (gsheet), factor);
Arturo Espinosa's avatar
Arturo Espinosa committed
182
	
183 184 185 186
	/* resize the header fonts */
	item_bar_fonts_init (ITEM_BAR (sheet_view->col_item));
	item_bar_fonts_init (ITEM_BAR (sheet_view->row_item));

187 188 189 190 191 192 193 194 195 196
	gtk_widget_set_usize (GTK_WIDGET (sheet_view->col_canvas),
			      -1, COLUMN_HEADER_HEIGHT * factor);
	gnome_canvas_set_scroll_region (GNOME_CANVAS (sheet_view->col_canvas), 0, 0,
					1000000*factor, COLUMN_HEADER_HEIGHT*factor);

	gtk_widget_set_usize (GTK_WIDGET (sheet_view->row_canvas),
			      ROW_HEADER_WIDTH * factor, -1);
	gnome_canvas_set_scroll_region (GNOME_CANVAS (sheet_view->row_canvas), 0, 0,
					ROW_HEADER_WIDTH*factor, 1200000*factor);

197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
	/* Recalibrate the starting offsets */
	gsheet->col_offset.first =
	    sheet_col_get_distance (sheet_view->sheet, 0, gsheet->col.first);
	gsheet->row_offset.first =
	    sheet_row_get_distance (sheet_view->sheet, 0, gsheet->row.first);

	/* Ensure that the current cell remains visible when we zoom */
	gnumeric_sheet_make_cell_visible (gsheet,
					  sheet_view->sheet->cursor_col,
					  sheet_view->sheet->cursor_row, TRUE);

	/* Repsition the cursor */
	item_cursor_reposition (gsheet->item_cursor);

	/* Adjust the animated cursors */
	for (l = sheet_view->anted_cursors; l; l = l->next)
		item_cursor_reposition (ITEM_CURSOR (l->data));
Arturo Espinosa's avatar
Arturo Espinosa committed
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
}

static void
canvas_bar_realized (GtkWidget *widget, gpointer data)
{
	gdk_window_set_back_pixmap (GTK_LAYOUT (widget)->bin_window, NULL, FALSE);
}

static GnomeCanvas *
new_canvas_bar (SheetView *sheet_view, GtkOrientation o, GnomeCanvasItem **itemp)
{
	GnomeCanvasGroup *group;
	GnomeCanvasItem *item;
	GtkWidget *canvas;
	int w, h;
	
	canvas = gnome_canvas_new ();

	gtk_signal_connect (GTK_OBJECT (canvas), "realize",
			    (GtkSignalFunc) canvas_bar_realized,
			    NULL);

	/* FIXME: need to set the correct scrolling regions.  This will do for now */

	if (o == GTK_ORIENTATION_VERTICAL){
239
		w = ROW_HEADER_WIDTH;
240
		h = -1;
241
		gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0, 0, w, 1200000);
Arturo Espinosa's avatar
Arturo Espinosa committed
242
	} else {
243
		w = -1;
244
		h = COLUMN_HEADER_HEIGHT;
Arturo Espinosa's avatar
Arturo Espinosa committed
245 246
		gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0, 0, 1000000, h);
	}
247
	gtk_widget_set_usize (canvas, w, h);
Arturo Espinosa's avatar
Arturo Espinosa committed
248 249 250 251 252 253 254 255 256 257 258 259 260
	group = GNOME_CANVAS_GROUP (GNOME_CANVAS (canvas)->root);
	item = gnome_canvas_item_new (group,
				      item_bar_get_type (),
				      "ItemBar::SheetView", sheet_view,
				      "ItemBar::Orientation", o,
				      NULL);

	*itemp = GNOME_CANVAS_ITEM (item);
	gtk_widget_show (canvas);
	
	return GNOME_CANVAS (canvas);
}

Jody Goldberg's avatar
Jody Goldberg committed
261 262 263
/* Manages the scrollbar dimensions and paging parameters. */
void
sheet_view_scrollbar_config (SheetView const *sheet_view)
Arturo Espinosa's avatar
Arturo Espinosa committed
264 265 266 267
{
	GtkAdjustment *va = GTK_ADJUSTMENT (sheet_view->va);
	GtkAdjustment *ha = GTK_ADJUSTMENT (sheet_view->ha);
	GnumericSheet *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
Jody Goldberg's avatar
Jody Goldberg committed
268
	Sheet         *sheet = sheet_view->sheet;
269 270
	int const last_col = gsheet->col.last_full;
	int const last_row = gsheet->row.last_full;
Arturo Espinosa's avatar
Arturo Espinosa committed
271

Jody Goldberg's avatar
Jody Goldberg committed
272
	va->upper = MAX (MAX (last_row,
273
			      sheet_view->sheet->rows.max_used),
Jody Goldberg's avatar
Jody Goldberg committed
274
			 sheet->cursor_row);
275
	va->page_size = last_row - gsheet->row.first;
276
	va->value = gsheet->row.first;
Jody Goldberg's avatar
Jody Goldberg committed
277 278
	va->step_increment = va->page_increment =
	    va->page_size / 2;
Arturo Espinosa's avatar
Arturo Espinosa committed
279
	
Jody Goldberg's avatar
Jody Goldberg committed
280
	ha->upper = MAX (MAX (last_col,
281
			      sheet_view->sheet->cols.max_used),
Jody Goldberg's avatar
Jody Goldberg committed
282
			 sheet->cursor_col);
283
	ha->page_size = last_col - gsheet->col.first;
284
	ha->value = gsheet->col.first;
Jody Goldberg's avatar
Jody Goldberg committed
285 286
	ha->step_increment = ha->page_increment =
	    ha->page_size / 2;
Arturo Espinosa's avatar
Arturo Espinosa committed
287 288 289 290 291

	gtk_adjustment_changed (va);
	gtk_adjustment_changed (ha);
}

Jody Goldberg's avatar
Jody Goldberg committed
292 293 294 295 296 297
static void
sheet_view_size_allocate (GtkWidget *widget, GtkAllocation *alloc, SheetView *sheet_view)
{
	sheet_view_scrollbar_config (sheet_view);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
298
static void
299
sheet_view_col_selection_changed (ItemBar *item_bar, int column, int modifiers, SheetView *sheet_view)
Arturo Espinosa's avatar
Arturo Espinosa committed
300 301 302
{	
	Sheet *sheet = sheet_view->sheet;
	
303 304
	/* Ensure that col row exists, ignore result */
	sheet_col_fetch (sheet, column);
305
	
306 307 308 309 310
	if (modifiers){
		if ((modifiers & GDK_SHIFT_MASK) && sheet->selections){
			SheetSelection *ss = sheet->selections->data;
			int start_col, end_col;
			
311 312
			start_col = MIN (ss->base.col, column);
			end_col = MAX (ss->base.col, column);
313 314 315 316 317 318
			
			sheet_selection_set (sheet,
					     start_col, 0,
					     end_col, SHEET_MAX_ROWS-1);
			return;
		}
319 320

		sheet_cursor_move (sheet, column, sheet->cursor_row, FALSE, FALSE);
321 322
		if (!(modifiers & GDK_CONTROL_MASK))
			sheet_selection_reset_only (sheet);
323

Arturo Espinosa's avatar
Arturo Espinosa committed
324 325 326 327 328
		sheet_selection_append_range (sheet,
					      column, 0,
					      column, 0,
					      column, SHEET_MAX_ROWS-1);
	} else
329
		sheet_selection_extend_to (sheet, column, SHEET_MAX_ROWS - 1);
Arturo Espinosa's avatar
Arturo Espinosa committed
330 331 332 333 334 335
}

static void
sheet_view_col_size_changed (ItemBar *item_bar, int col, int width, SheetView *sheet_view)
{
	Sheet *sheet = sheet_view->sheet;
336 337 338 339
	ItemBarSelectionType type;

	type = sheet_col_selection_type (sheet, col);

340 341 342 343 344 345
 	if (type == ITEM_BAR_FULL_SELECTION) {
		int i = sheet->cols.max_used;
		for (;i >= 0 ; --i) {
 			ColRowInfo *ci = sheet_col_get (sheet, i);
			if (ci == NULL)
				continue;
346 347 348 349
 
 			if (sheet_col_selection_type (sheet, ci->pos) == ITEM_BAR_FULL_SELECTION)
 				sheet_col_set_width (sheet, ci->pos, width);
 		}
350
	} else
351
 		sheet_col_set_width (sheet, col, width);
352
	
Arturo Espinosa's avatar
Arturo Espinosa committed
353 354 355 356
	gnumeric_sheet_compute_visible_ranges (GNUMERIC_SHEET (sheet_view->sheet_view));
}

static void
357
sheet_view_row_selection_changed (ItemBar *item_bar, int row, int modifiers, SheetView *sheet_view)
Arturo Espinosa's avatar
Arturo Espinosa committed
358 359
{
	Sheet *sheet = sheet_view->sheet;
360

361 362
	/* Ensure that the row exists, ignore result */
	sheet_row_fetch (sheet, row);
363
	
364 365 366 367 368
	if (modifiers){
		if ((modifiers & GDK_SHIFT_MASK) && sheet->selections){
			SheetSelection *ss = sheet->selections->data;
			int start_row, end_row;
			
369 370
			start_row = MIN (ss->base.row, row);
			end_row = MAX (ss->base.row, row);
371 372 373 374 375 376
			
			sheet_selection_set (sheet,
					     0, start_row,
					     SHEET_MAX_COLS-1, end_row);
			return;
		}
377 378

		sheet_cursor_move (sheet, sheet->cursor_col, row, FALSE, FALSE);
379 380
		if (!(modifiers & GDK_CONTROL_MASK))
 			sheet_selection_reset_only (sheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
381 382 383 384 385 386
	
		sheet_selection_append_range (sheet,
					      0, row,
					      0, row,
					      SHEET_MAX_COLS-1, row);
	} else
387
		sheet_selection_extend_to (sheet, SHEET_MAX_COLS-1, row);
Arturo Espinosa's avatar
Arturo Espinosa committed
388 389 390 391 392 393
}

static void
sheet_view_row_size_changed (ItemBar *item_bar, int row, int height, SheetView *sheet_view)
{
	Sheet *sheet = sheet_view->sheet;
394 395 396 397
	ItemBarSelectionType type;

	type = sheet_row_selection_type (sheet, row);

398 399 400 401 402 403
	if (type == ITEM_BAR_FULL_SELECTION) {
		int i;
		for (i = sheet->rows.max_used; i >= 0 ; --i) {
 			ColRowInfo *ri = sheet_row_get (sheet, i);
			if (ri == NULL)
				continue;
404
			
405
			if (sheet_row_selection_type (sheet, ri->pos) == ITEM_BAR_FULL_SELECTION)
406 407
					sheet_row_set_height (sheet, ri->pos, height, TRUE);
		}
408
	} else
409
		sheet_row_set_height (sheet, row, height, TRUE);
Arturo Espinosa's avatar
Arturo Espinosa committed
410 411 412 413 414 415 416 417 418 419 420
}

static void
button_select_all (GtkWidget *the_button, SheetView *sheet_view)
{
	sheet_select_all (sheet_view->sheet);
}

static void
vertical_scroll_change (GtkAdjustment *adj, SheetView *sheet_view)
{
421 422 423 424 425
	if (sheet_view->tip) {
		char buffer [20 + sizeof (long) * 4];
		snprintf (buffer, sizeof (buffer), _("Row: %d"), (int) adj->value + 1);
		gtk_label_set_text (GTK_LABEL (sheet_view->tip), buffer);
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
426 427 428 429 430
}

static void
horizontal_scroll_change (GtkAdjustment *adj, SheetView *sheet_view)
{
431 432 433 434
	if (sheet_view->tip) {
		char buffer [20 + sizeof (long) * 4];
		snprintf (buffer, sizeof (buffer), _("Column: %s"), col_name (adj->value));
		gtk_label_set_text (GTK_LABEL (sheet_view->tip), buffer);
Arturo Espinosa's avatar
Arturo Espinosa committed
435 436 437 438 439 440 441
	}
}

static int
horizontal_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet_view)
{
	if (event->type == GDK_BUTTON_PRESS){
442 443 444
		sheet_view->tip = gnumeric_create_tooltip ();
		horizontal_scroll_change (GTK_ADJUSTMENT (sheet_view->ha), sheet_view);
		gnumeric_position_tooltip (sheet_view->tip, 1);
Arturo Espinosa's avatar
Arturo Espinosa committed
445
		gtk_widget_show_all (gtk_widget_get_toplevel (sheet_view->tip));
446 447 448 449
	}
	else if (event->type == GDK_BUTTON_RELEASE)
	{
		GnumericSheet  *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
450
		int col;
Arturo Espinosa's avatar
Arturo Espinosa committed
451
		
452 453 454 455 456 457
		/* A button release can be generated without a press by people
		 * with mouse wheels */
		if (sheet_view->tip) {
			gtk_widget_destroy (gtk_widget_get_toplevel (sheet_view->tip));
			sheet_view->tip = NULL;
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
458

459 460
		col = GTK_ADJUSTMENT (sheet_view->ha)->value;

461
		gnumeric_sheet_set_left_col (gsheet, col);
462
		/* NOTE : Excel does not move the cursor, just scrolls the sheet. */
Arturo Espinosa's avatar
Arturo Espinosa committed
463 464 465 466 467 468 469 470 471
	}
	
	return FALSE;
}

static int
vertical_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet_view)
{
	if (event->type == GDK_BUTTON_PRESS){
472 473 474
		sheet_view->tip = gnumeric_create_tooltip ();
		vertical_scroll_change (GTK_ADJUSTMENT (sheet_view->va), sheet_view);
		gnumeric_position_tooltip (sheet_view->tip, 0);
Arturo Espinosa's avatar
Arturo Espinosa committed
475
		gtk_widget_show_all (gtk_widget_get_toplevel (sheet_view->tip));
476 477 478 479
	}
	else if (event->type == GDK_BUTTON_RELEASE)
	{
		GnumericSheet  *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
480
		int row;
Arturo Espinosa's avatar
Arturo Espinosa committed
481
		
482 483 484 485 486 487
		/* A button release can be generated without a press by people
		 * with mouse wheels */
		if (sheet_view->tip) {
			gtk_widget_destroy (gtk_widget_get_toplevel (sheet_view->tip));
			sheet_view->tip = NULL;
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
488

489 490 491
		row = GTK_ADJUSTMENT (sheet_view->va)->value;
		
		gnumeric_sheet_set_top_row (gsheet, row);
492
		/* NOTE : Excel does not move the cursor, just scrolls the sheet. */
Arturo Espinosa's avatar
Arturo Espinosa committed
493 494 495 496 497
	}

	return FALSE;
}

498 499 500 501 502 503 504 505 506
static void
sheet_view_init (SheetView *sheet_view)
{
	GtkTable *table = GTK_TABLE (sheet_view);
	
	table->homogeneous = FALSE;
	gtk_table_resize (table, 4, 4);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
507 508 509
static void
sheet_view_construct (SheetView *sheet_view)
{
510
	GnomeCanvasGroup *root_group;
Arturo Espinosa's avatar
Arturo Espinosa committed
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
	GtkTable  *table = GTK_TABLE (sheet_view);
	Sheet *sheet = sheet_view->sheet;
	
	/* Column canvas */
	sheet_view->col_canvas = new_canvas_bar (sheet_view, GTK_ORIENTATION_HORIZONTAL, &sheet_view->col_item);
	gtk_table_attach (table, GTK_WIDGET (sheet_view->col_canvas),
			  1, 2, 0, 1,
			  GTK_EXPAND | GTK_FILL | GTK_SHRINK,
			  GTK_FILL,
			  0, 0);
	gtk_signal_connect (GTK_OBJECT (sheet_view->col_item), "selection_changed",
			    GTK_SIGNAL_FUNC (sheet_view_col_selection_changed),
			    sheet_view);
	gtk_signal_connect (GTK_OBJECT (sheet_view->col_item), "size_changed",
			    GTK_SIGNAL_FUNC (sheet_view_col_size_changed),
			    sheet_view);

	/* Row canvas */
	sheet_view->row_canvas = new_canvas_bar (sheet_view, GTK_ORIENTATION_VERTICAL, &sheet_view->row_item);
	
	gtk_table_attach (table, GTK_WIDGET (sheet_view->row_canvas),
			  0, 1, 1, 2,
			  GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK,
			  0, 0);
	gtk_signal_connect (GTK_OBJECT (sheet_view->row_item), "selection_changed",
			    GTK_SIGNAL_FUNC (sheet_view_row_selection_changed),
			    sheet_view);
	gtk_signal_connect (GTK_OBJECT (sheet_view->row_item), "size_changed",
			    GTK_SIGNAL_FUNC (sheet_view_row_size_changed),
			    sheet_view);


	/* Create the gnumeric sheet canvas */
	sheet_view->sheet_view = gnumeric_sheet_new (
		sheet_view,
		ITEM_BAR (sheet_view->col_item),
		ITEM_BAR (sheet_view->row_item));
Michael Meeks's avatar
Michael Meeks committed
548

Arturo Espinosa's avatar
Arturo Espinosa committed
549 550 551 552
	gtk_signal_connect_after (
		GTK_OBJECT (sheet_view), "size_allocate",
		GTK_SIGNAL_FUNC (sheet_view_size_allocate), sheet_view);

553 554 555
	/* Create the object group inside the GnumericSheet */
	root_group = GNOME_CANVAS_GROUP (
		GNOME_CANVAS (sheet_view->sheet_view)->root);
556 557 558 559 560 561 562
	sheet_view->object_group = GNOME_CANVAS_GROUP (
		gnome_canvas_item_new (
			root_group,
			gnome_canvas_group_get_type (),
			"x", 0.0,
			"y", 0.0,
			NULL));
563
		
Arturo Espinosa's avatar
Arturo Espinosa committed
564 565 566 567 568 569 570 571
	/* Attach the GnumericSheet */
	gtk_table_attach (table, sheet_view->sheet_view,
			  1, 2, 1, 2,
			  GTK_EXPAND | GTK_FILL | GTK_SHRINK,
			  GTK_EXPAND | GTK_FILL | GTK_SHRINK,
			  0, 0);
	gtk_widget_show (sheet_view->sheet_view);

572 573 574 575 576 577 578 579 580 581 582
	/*
	 * The selection group
	 */
	sheet_view->selection_group = GNOME_CANVAS_GROUP (
		gnome_canvas_item_new (
			root_group,
			gnome_canvas_group_get_type (),
			"x", 0.0,
			"y", 0.0,
			NULL));
	
Arturo Espinosa's avatar
Arturo Espinosa committed
583
	/* The select-all button */
Jody Goldberg's avatar
Jody Goldberg committed
584 585 586 587
	sheet_view->select_all = gtk_button_new ();
	GTK_WIDGET_UNSET_FLAGS (sheet_view->select_all, GTK_CAN_FOCUS);
	gtk_table_attach (table, sheet_view->select_all, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
	gtk_signal_connect (GTK_OBJECT (sheet_view->select_all), "clicked",
Arturo Espinosa's avatar
Arturo Espinosa committed
588 589 590
			    GTK_SIGNAL_FUNC (button_select_all), sheet_view);
	
	/* Scroll bars and their adjustments */
591 592
	sheet_view->va = gtk_adjustment_new (0.0, 0.0, sheet->rows.max_used, 1.0, 1.0, 1.0);
	sheet_view->ha = gtk_adjustment_new (0.0, 0.0, sheet->cols.max_used, 1.0, 1.0, 1.0);
Arturo Espinosa's avatar
Arturo Espinosa committed
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
	sheet_view->hs = gtk_hscrollbar_new (GTK_ADJUSTMENT (sheet_view->ha));
	sheet_view->vs = gtk_vscrollbar_new (GTK_ADJUSTMENT (sheet_view->va));

	gtk_signal_connect (GTK_OBJECT (sheet_view->ha), "value_changed",
			    GTK_SIGNAL_FUNC (horizontal_scroll_change), sheet_view);
	gtk_signal_connect (GTK_OBJECT (sheet_view->va), "value_changed",
			    GTK_SIGNAL_FUNC (vertical_scroll_change), sheet_view);
	gtk_signal_connect (GTK_OBJECT (sheet_view->hs), "event",
			    GTK_SIGNAL_FUNC (horizontal_scroll_event), sheet_view);
	gtk_signal_connect (GTK_OBJECT (sheet_view->vs), "event",
			    GTK_SIGNAL_FUNC (vertical_scroll_event), sheet_view);
	
	/* Attach the horizontal scroll */
	gtk_table_attach (table, sheet_view->hs,
			  1, 2, 2, 3,
			  GTK_EXPAND | GTK_FILL | GTK_SHRINK,
			  GTK_FILL,
			  0, 0);

	/* Attach the vertical scroll */
	gtk_table_attach (table, sheet_view->vs,
			  2, 3, 1, 2,
			  GTK_FILL,
			  GTK_EXPAND | GTK_FILL | GTK_SHRINK,
			  0, 0);
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
}

void
sheet_view_set_header_visibility (SheetView *sheet_view,
				  gboolean col_headers_visible,
				  gboolean row_headers_visible)
{
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));

	if (col_headers_visible){
		if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (sheet_view->col_canvas)))
			gtk_widget_show (GTK_WIDGET (sheet_view->col_canvas));
	} else {
		if (GTK_WIDGET_VISIBLE (GTK_WIDGET (sheet_view->col_canvas)))
			gtk_widget_hide (GTK_WIDGET (sheet_view->col_canvas));
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
635
	
636 637 638 639 640 641 642
	if (row_headers_visible){
		if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (sheet_view->row_canvas)))
			gtk_widget_show (GTK_WIDGET (sheet_view->row_canvas));
	} else {
		if (GTK_WIDGET_VISIBLE (GTK_WIDGET (sheet_view->row_canvas)))
			gtk_widget_hide (GTK_WIDGET (sheet_view->row_canvas));
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
643 644 645 646 647 648 649 650 651
}

GtkWidget *
sheet_view_new (Sheet *sheet)
{
	SheetView *sheet_view;

	sheet_view = gtk_type_new (sheet_view_get_type ());
	sheet_view->sheet = sheet;
652
	sheet_view->tip = NULL;
653

Arturo Espinosa's avatar
Arturo Espinosa committed
654 655 656 657 658 659 660 661 662 663 664 665
	sheet_view_construct (sheet_view);
	
	return GTK_WIDGET (sheet_view);
}

static void
sheet_view_destroy (GtkObject *object)
{
	SheetView *sheet_view = SHEET_VIEW (object);

	/* Add shutdown code here */
	if (sheet_view->tip)
666
		gtk_object_unref (GTK_OBJECT (sheet_view->tip));
Arturo Espinosa's avatar
Arturo Espinosa committed
667 668 669 670 671 672
	
	if (GTK_OBJECT_CLASS (sheet_view_parent_class)->destroy)
		(*GTK_OBJECT_CLASS (sheet_view_parent_class)->destroy)(object);
}

static void
Jody Goldberg's avatar
Jody Goldberg committed
673
sheet_view_class_init (SheetViewClass *Class)
Arturo Espinosa's avatar
Arturo Espinosa committed
674 675 676
{
	GtkObjectClass *object_class;

Jody Goldberg's avatar
Jody Goldberg committed
677
	object_class = (GtkObjectClass *) Class;
Arturo Espinosa's avatar
Arturo Espinosa committed
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706

	sheet_view_parent_class = gtk_type_class (gtk_table_get_type ());
	
	object_class->destroy = sheet_view_destroy;
}

GtkType
sheet_view_get_type (void)
{
	static GtkType sheet_view_type = 0;

	if (!sheet_view_type){
		GtkTypeInfo sheet_view_info = {
			"SheetView",
			sizeof (SheetView),
			sizeof (SheetViewClass),
			(GtkClassInitFunc) sheet_view_class_init,
			(GtkObjectInitFunc) sheet_view_init,
			NULL, /* reserved 1 */
			NULL, /* reserved 2 */
			(GtkClassInitFunc) NULL
		};

		sheet_view_type = gtk_type_unique (gtk_table_get_type (), &sheet_view_info);
	}

	return sheet_view_type;
}
		     
Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
void
sheet_view_hide_cursor (SheetView *sheet_view)
{
	GnumericSheet *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);

	item_cursor_set_visibility (gsheet->item_cursor, FALSE);
}

void
sheet_view_show_cursor (SheetView *sheet_view)
{
	GnumericSheet *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);

	item_cursor_set_visibility (gsheet->item_cursor, TRUE);
}
722 723 724

#define TRIANGLE_WIDTH 6

725 726
static GnomeCanvasPoints *
sheet_view_comment_get_points (SheetView *sheet_view, int col, int row)
727 728
{
	GnomeCanvasPoints *points;
729
	int x, y, i;
730 731 732 733 734 735 736 737 738 739 740 741 742

	points = gnome_canvas_points_new (3);

	x = sheet_col_get_distance (sheet_view->sheet, 0, col+1);
	y = 1+sheet_row_get_distance (sheet_view->sheet, 0, row);

	points->coords [0] = x - TRIANGLE_WIDTH;
	points->coords [1] = y;
	points->coords [2] = x;
	points->coords [3] = y;
	points->coords [4] = x;
	points->coords [5] = y + TRIANGLE_WIDTH;

743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
	for (i = 0; i < 3; i++){
		gnome_canvas_c2w (GNOME_CANVAS (sheet_view->sheet_view),
				  points->coords [i*2],
				  points->coords [i*2+1],
				  &(points->coords [i*2]),
				  &(points->coords [i*2+1]));
	}
	return points;
}

GnomeCanvasItem *
sheet_view_comment_create_marker (SheetView *sheet_view, int col, int row)
{
	GnomeCanvasPoints *points;
	GnomeCanvasGroup *group;
	GnomeCanvasItem *i;
	
	g_return_val_if_fail (sheet_view != NULL, NULL);
	g_return_val_if_fail (IS_SHEET_VIEW (sheet_view), NULL);

	group = GNOME_CANVAS_GROUP (GNOME_CANVAS (sheet_view->sheet_view)->root);
	points = sheet_view_comment_get_points (sheet_view, col, row);

766 767 768 769 770 771 772 773
	i = gnome_canvas_item_new (
		group, gnome_canvas_polygon_get_type (),
		"points",     points,
		"fill_color", "red",
		NULL);

	return i;
}
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789

void
sheet_view_comment_relocate (SheetView *sheet_view, int col, int row, GnomeCanvasItem *o)
{
	GnomeCanvasPoints *points;

	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));
	g_return_if_fail (o != NULL);
	g_return_if_fail (GNOME_IS_CANVAS_ITEM (o));

	points = sheet_view_comment_get_points (sheet_view, col, row);

	gnome_canvas_item_set (o, "points", points, NULL);
}

790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
void
sheet_view_selection_unant (SheetView *sheet_view)
{
	GList *l;

	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));

	if (sheet_view->anted_cursors == NULL)
		return;

	for (l = sheet_view->anted_cursors; l; l = l->next)
		gtk_object_destroy (GTK_OBJECT (l->data));

	g_list_free (sheet_view->anted_cursors);
	sheet_view->anted_cursors = NULL;
}

void
sheet_view_selection_ant (SheetView *sheet_view)
{
	GnomeCanvasGroup *group;
	ItemGrid *grid;
	GList *l;
	
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));
	
	if (sheet_view->anted_cursors)
		sheet_view_selection_unant (sheet_view);

	group = sheet_view->selection_group;
	grid = GNUMERIC_SHEET (sheet_view->sheet_view)->item_grid;
	
	for (l = sheet_view->sheet->selections; l; l = l->next){
		SheetSelection *ss = l->data;
		ItemCursor *item_cursor;
		
		item_cursor = ITEM_CURSOR (gnome_canvas_item_new (
			group, item_cursor_get_type (),
			"Sheet", sheet_view->sheet,
			"Grid",  grid,
			"Style", ITEM_CURSOR_ANTED,
			NULL));
		item_cursor_set_bounds (
			item_cursor,
			ss->user.start.col, ss->user.start.row,
			ss->user.end.col, ss->user.end.row);

		sheet_view->anted_cursors = g_list_prepend (sheet_view->anted_cursors, item_cursor);
	}
}

843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
void
sheet_view_adjust_preferences (SheetView *sheet_view)
{
	Sheet *sheet = sheet_view->sheet;
	Workbook *wb = sheet->workbook;

	if (sheet->show_col_header)
		gtk_widget_show (GTK_WIDGET (sheet_view->col_canvas));
	else
		gtk_widget_hide (GTK_WIDGET (sheet_view->col_canvas));

	if (sheet->show_row_header)
		gtk_widget_show (GTK_WIDGET (sheet_view->row_canvas));
	else
		gtk_widget_hide (GTK_WIDGET (sheet_view->row_canvas));

	if (sheet->show_col_header && sheet->show_row_header)
		gtk_widget_show (sheet_view->select_all);
	else
		gtk_widget_hide (sheet_view->select_all);

	if (wb->show_horizontal_scrollbar)
		gtk_widget_show (sheet_view->hs);
	else
		gtk_widget_hide (sheet_view->hs);

	if (wb->show_vertical_scrollbar)
		gtk_widget_show (sheet_view->vs);
	else
		gtk_widget_hide (sheet_view->vs);
}
874

875
#if 0
876 877
#ifdef ENABLE_BONOBO
void
878
sheet_view_insert_object (SheetView *sheet_view, GnomeObjectClient *object)
879
{
Michael Meeks's avatar
Michael Meeks committed
880
/*	GtkWidget *view;*/
881 882 883 884 885 886 887

	/*
	 * Commented out because the new_view api changed and it isn't
	 * used anyways.
	 */
	   
	/* view = gnome_bonobo_object_new_view (object); */
888 889 890
	g_warning ("Stick this into the SheetView");
}
#endif
891
#endif