sheet-view.c 24.9 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"
16
#include "workbook.h"
Michael Meeks's avatar
Michael Meeks committed
17
#include "selection.h"
Michael Meeks's avatar
Michael Meeks committed
18
#include "sheet-object.h"
19
#include "item-cursor.h"
20
#include "gnumeric-util.h"
21
#include "utils.h"
22
#include "selection.h"
23
#include "application.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
24

25 26 27
/* Sizes for column/row headers */

#define COLUMN_HEADER_HEIGHT 20
28
#define ROW_HEADER_WIDTH 50
29

Arturo Espinosa's avatar
Arturo Espinosa committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
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;
53
	GnomeCanvas *canvas;
Arturo Espinosa's avatar
Arturo Espinosa committed
54
	Sheet *sheet = sheet_view->sheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
55
	int first_col, first_row, last_col, last_row;
56
	int col, row, min_col, max_col;
Arturo Espinosa's avatar
Arturo Espinosa committed
57 58 59 60 61 62 63
	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));
64
	canvas = GNOME_CANVAS (gsheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
65

66 67 68 69
	if ((end_col < gsheet->col.first) ||
	    (end_row < gsheet->row.first) ||
	    (start_col > gsheet->col.last_visible) ||
	    (start_row > gsheet->row.last_visible))
70 71 72
		return;
	
	/* The region on which we care to redraw */
73 74 75 76
	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);
77 78

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

	/* Find the range of columns that require a redraw */
Arturo Espinosa's avatar
Arturo Espinosa committed
83 84
	for (col = first_col; col <= last_col; col++)
		for (row = first_row; row <= last_row; row++){
85 86 87 88 89 90 91 92 93 94 95 96 97
			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
98

99
	/* Only draw those regions that are visible */
100 101
	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
102

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

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

void
Jody Goldberg's avatar
Jody Goldberg committed
116 117 118
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
119
{
Jody Goldberg's avatar
Jody Goldberg committed
120
	GnumericSheet *gsheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
121 122 123
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));

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

Jody Goldberg's avatar
Jody Goldberg committed
126 127 128 129 130 131 132 133 134
	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) {
135
				left = gsheet->col_offset.first +
Jody Goldberg's avatar
Jody Goldberg committed
136
				    sheet_col_get_distance (sheet_view->sheet,
137
							    gsheet->col.first, r->start.col);
Jody Goldberg's avatar
Jody Goldberg committed
138 139 140 141 142 143 144 145 146
				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
147

Jody Goldberg's avatar
Jody Goldberg committed
148 149 150 151 152 153 154 155 156
	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) {
157
				top = gsheet->row_offset.first +
Jody Goldberg's avatar
Jody Goldberg committed
158
				    sheet_row_get_distance (sheet_view->sheet,
159
							    gsheet->row.first, r->start.row);
Jody Goldberg's avatar
Jody Goldberg committed
160 161 162 163 164 165 166 167 168
				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
169 170 171 172 173
}

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

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

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

189 190 191 192 193 194 195 196 197 198
	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);

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
	/* 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
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
}

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){
241
		w = ROW_HEADER_WIDTH;
242
		h = -1;
243
		gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0, 0, w, 1200000);
Arturo Espinosa's avatar
Arturo Espinosa committed
244
	} else {
245
		w = -1;
246
		h = COLUMN_HEADER_HEIGHT;
Arturo Espinosa's avatar
Arturo Espinosa committed
247 248
		gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0, 0, 1000000, h);
	}
249
	gtk_widget_set_usize (canvas, w, h);
Arturo Espinosa's avatar
Arturo Espinosa committed
250 251 252 253 254 255 256 257 258 259 260 261 262
	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
263 264 265
/* Manages the scrollbar dimensions and paging parameters. */
void
sheet_view_scrollbar_config (SheetView const *sheet_view)
Arturo Espinosa's avatar
Arturo Espinosa committed
266 267 268 269
{
	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
270
	Sheet         *sheet = sheet_view->sheet;
271 272
	int const last_col = gsheet->col.last_full;
	int const last_row = gsheet->row.last_full;
Arturo Espinosa's avatar
Arturo Espinosa committed
273

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

	gtk_adjustment_changed (va);
	gtk_adjustment_changed (ha);
}

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

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

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

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

	type = sheet_col_selection_type (sheet, col);

342 343 344 345 346 347
 	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;
348 349 350 351
 
 			if (sheet_col_selection_type (sheet, ci->pos) == ITEM_BAR_FULL_SELECTION)
 				sheet_col_set_width (sheet, ci->pos, width);
 		}
352
	} else
353
 		sheet_col_set_width (sheet, col, width);
354
	
Arturo Espinosa's avatar
Arturo Espinosa committed
355 356 357 358
	gnumeric_sheet_compute_visible_ranges (GNUMERIC_SHEET (sheet_view->sheet_view));
}

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

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

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

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

	type = sheet_row_selection_type (sheet, row);

400 401 402 403 404 405
	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;
406
			
407
			if (sheet_row_selection_type (sheet, ri->pos) == ITEM_BAR_FULL_SELECTION)
408 409
					sheet_row_set_height (sheet, ri->pos, height, TRUE);
		}
410
	} else
411
		sheet_row_set_height (sheet, row, height, TRUE);
Arturo Espinosa's avatar
Arturo Espinosa committed
412 413 414 415 416 417 418 419 420 421 422
}

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)
{
423 424 425 426 427
	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
428 429 430 431 432
}

static void
horizontal_scroll_change (GtkAdjustment *adj, SheetView *sheet_view)
{
433 434 435 436
	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
437 438 439 440 441 442 443
	}
}

static int
horizontal_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet_view)
{
	if (event->type == GDK_BUTTON_PRESS){
444 445 446
		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
447
		gtk_widget_show_all (gtk_widget_get_toplevel (sheet_view->tip));
448 449 450 451
	}
	else if (event->type == GDK_BUTTON_RELEASE)
	{
		GnumericSheet  *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
452
		int col;
Arturo Espinosa's avatar
Arturo Espinosa committed
453
		
454 455 456 457 458 459
		/* 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
460

461 462
		col = GTK_ADJUSTMENT (sheet_view->ha)->value;

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

static int
vertical_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet_view)
{
	if (event->type == GDK_BUTTON_PRESS){
474 475 476
		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
477
		gtk_widget_show_all (gtk_widget_get_toplevel (sheet_view->tip));
478 479 480 481
	}
	else if (event->type == GDK_BUTTON_RELEASE)
	{
		GnumericSheet  *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
482
		int row;
Arturo Espinosa's avatar
Arturo Espinosa committed
483
		
484 485 486 487 488 489
		/* 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
490

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

	return FALSE;
}

500 501 502 503 504 505 506 507 508
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
509 510 511
static void
sheet_view_construct (SheetView *sheet_view)
{
512
	GnomeCanvasGroup *root_group;
Arturo Espinosa's avatar
Arturo Espinosa committed
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 548 549
	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
550

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

555 556 557
	/* Create the object group inside the GnumericSheet */
	root_group = GNOME_CANVAS_GROUP (
		GNOME_CANVAS (sheet_view->sheet_view)->root);
558 559 560 561 562 563 564
	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));
565
		
Arturo Espinosa's avatar
Arturo Espinosa committed
566 567 568 569 570 571 572 573
	/* 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);

574 575 576 577 578 579 580 581 582 583 584
	/*
	 * 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
585
	/* The select-all button */
Jody Goldberg's avatar
Jody Goldberg committed
586 587 588 589
	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
590 591 592
			    GTK_SIGNAL_FUNC (button_select_all), sheet_view);
	
	/* Scroll bars and their adjustments */
593 594
	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
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
	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);
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
}

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
637
	
638 639 640 641 642 643 644
	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
645 646 647 648 649 650 651 652 653
}

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

	sheet_view = gtk_type_new (sheet_view_get_type ());
	sheet_view->sheet = sheet;
654
	sheet_view->tip = NULL;
655

Arturo Espinosa's avatar
Arturo Espinosa committed
656 657 658 659 660 661 662 663 664 665 666 667
	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)
668
		gtk_object_unref (GTK_OBJECT (sheet_view->tip));
Arturo Espinosa's avatar
Arturo Espinosa committed
669 670 671 672 673 674
	
	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
675
sheet_view_class_init (SheetViewClass *Class)
Arturo Espinosa's avatar
Arturo Espinosa committed
676 677 678
{
	GtkObjectClass *object_class;

Jody Goldberg's avatar
Jody Goldberg committed
679
	object_class = (GtkObjectClass *) Class;
Arturo Espinosa's avatar
Arturo Espinosa committed
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 707 708

	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
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
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);
}
724 725 726

#define TRIANGLE_WIDTH 6

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

	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;

745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767
	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);

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

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

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);
}

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 843 844
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);
	}
}

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 874 875
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);
}
876

877 878 879 880 881 882 883 884 885 886 887 888 889 890
StyleFont *
sheet_view_get_style_font (const Sheet *sheet, MStyle *mstyle)
{
	/* Scale the font size by the average scaling factor for the
	 * display.  72dpi is base size 
	 */

	double const zoom = sheet->last_zoom_factor_used;
	double const res  = MIN(application_display_dpi_get (FALSE),
				application_display_dpi_get (TRUE)) / 72.;

	return mstyle_get_font (mstyle, zoom * res);
}

891
#if 0
892 893
#ifdef ENABLE_BONOBO
void
894
sheet_view_insert_object (SheetView *sheet_view, BonoboObjectClient *object)
895
{
Michael Meeks's avatar
Michael Meeks committed
896
/*	GtkWidget *view;*/
897 898 899 900 901 902 903

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