sheet-view.c 25.2 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"
17
#include "cell.h"
Michael Meeks's avatar
Michael Meeks committed
18
#include "selection.h"
Michael Meeks's avatar
Michael Meeks committed
19
#include "sheet-object.h"
20
#include "item-cursor.h"
21
#include "gnumeric-util.h"
22
#include "utils.h"
23
#include "selection.h"
24
#include "application.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
25 26 27 28 29 30 31 32

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

Arturo Espinosa's avatar
Arturo Espinosa committed
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
	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;
49
	GnomeCanvas *canvas;
Arturo Espinosa's avatar
Arturo Espinosa committed
50
	Sheet *sheet = sheet_view->sheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
51
	int first_col, first_row, last_col, last_row;
52
	int col, row, min_col, max_col;
Arturo Espinosa's avatar
Arturo Espinosa committed
53
	int x, y, w, h;
54

Arturo Espinosa's avatar
Arturo Espinosa committed
55 56 57 58 59
	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));
60
	canvas = GNOME_CANVAS (gsheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
61

62 63 64 65
	if ((end_col < gsheet->col.first) ||
	    (end_row < gsheet->row.first) ||
	    (start_col > gsheet->col.last_visible) ||
	    (start_row > gsheet->row.last_visible))
66
		return;
67

68
	/* The region on which we care to redraw */
69 70 71 72
	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);
73 74

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

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

93
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
94

95
	/* Only draw those regions that are visible */
96 97
	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
98

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

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

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

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

Jody Goldberg's avatar
Jody Goldberg committed
122 123 124 125 126 127 128 129 130
	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) {
131
				left = gsheet->col_offset.first +
132
				    sheet_col_get_distance_pixels (sheet_view->sheet,
133
							    gsheet->col.first, r->start.col);
Jody Goldberg's avatar
Jody Goldberg committed
134
				right = left +
135
				    sheet_col_get_distance_pixels (sheet_view->sheet,
Jody Goldberg's avatar
Jody Goldberg committed
136 137 138
							    r->start.col, r->end.col+1);
			}
		}
139
		/* Request excludes the far coordinate.  Add 1 to include them */
Jody Goldberg's avatar
Jody Goldberg committed
140 141
		gnome_canvas_request_redraw (
			GNOME_CANVAS (sheet_view->col_canvas),
142
			left, 0, right+1, INT_MAX);
Jody Goldberg's avatar
Jody Goldberg committed
143
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
144

Jody Goldberg's avatar
Jody Goldberg committed
145 146 147 148 149 150 151 152 153
	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) {
154
				top = gsheet->row_offset.first +
155
				    sheet_row_get_distance_pixels (sheet_view->sheet,
156
							    gsheet->row.first, r->start.row);
Jody Goldberg's avatar
Jody Goldberg committed
157
				bottom = top +
158
				    sheet_row_get_distance_pixels (sheet_view->sheet,
Jody Goldberg's avatar
Jody Goldberg committed
159 160 161
							    r->start.row, r->end.row+1);
			}
		}
162
		/* Request excludes the far coordinate.  Add 1 to include them */
Jody Goldberg's avatar
Jody Goldberg committed
163 164
		gnome_canvas_request_redraw (
			GNOME_CANVAS (sheet_view->row_canvas),
165
			0, top, INT_MAX, bottom+1);
Jody Goldberg's avatar
Jody Goldberg committed
166
	}
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
	GList *l;
	GnumericSheet *gsheet;
174 175
	ItemBar *col_item, *row_item;
	int h, w;
176

Arturo Espinosa's avatar
Arturo Espinosa committed
177 178
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));
179

180
	gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
181 182
	col_item = ITEM_BAR (sheet_view->col_item);
	row_item = ITEM_BAR (sheet_view->row_item);
183

184
	/* Set pixels_per_unit before the font.  The item bars look here for the number */
185
	gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (gsheet), factor);
186

187
	/* resize the header fonts */
188 189 190 191 192 193 194
	item_bar_fonts_init (col_item);
	item_bar_fonts_init (row_item);

	/*
	 * Use the size of the bold header font to size the free dimensions
	 * No need to zoom, the size of the font takes that into consideration.
	 */
195

196 197 198 199 200 201
	/* 2 pixels above and below */
	h = 2 + 2 + style_font_get_height (col_item->bold_font);
	/* 5 pixels left and right plus the width of the widest string I can think of */
	w = 5 + 5 + gdk_string_width (style_font_gdk_font (col_item->bold_font), "88888");

	gtk_widget_set_usize (GTK_WIDGET (sheet_view->col_canvas), -1, h);
202
	gnome_canvas_set_scroll_region (GNOME_CANVAS (sheet_view->col_canvas), 0, 0,
203
					1000000*factor, h);
204

205
	gtk_widget_set_usize (GTK_WIDGET (sheet_view->row_canvas), w, -1);
206
	gnome_canvas_set_scroll_region (GNOME_CANVAS (sheet_view->row_canvas), 0, 0,
207
					w, 1200000*factor);
208

209 210
	/* Recalibrate the starting offsets */
	gsheet->col_offset.first =
211
	    sheet_col_get_distance_pixels (sheet_view->sheet, 0, gsheet->col.first);
212
	gsheet->row_offset.first =
213
	    sheet_row_get_distance_pixels (sheet_view->sheet, 0, gsheet->row.first);
214 215 216

	/* Ensure that the current cell remains visible when we zoom */
	gnumeric_sheet_make_cell_visible (gsheet,
217 218 219
					  sheet_view->sheet->cursor.edit_pos.col,
					  sheet_view->sheet->cursor.edit_pos.row,
					  TRUE);
220 221 222 223 224 225 226

	/* 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
227 228 229 230 231 232 233 234 235 236 237
}

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)
{
238 239 240 241 242 243 244 245 246 247
	GtkWidget *canvas =
	    gnome_canvas_new ();
	GnomeCanvasGroup *group =
	    GNOME_CANVAS_GROUP (GNOME_CANVAS (canvas)->root);
	GnomeCanvasItem *item =
	    gnome_canvas_item_new (group,
				   item_bar_get_type (),
				   "ItemBar::SheetView", sheet_view,
				   "ItemBar::Orientation", o,
				   NULL);
Arturo Espinosa's avatar
Arturo Espinosa committed
248 249 250 251 252

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

253
	*itemp = item;
Arturo Espinosa's avatar
Arturo Espinosa committed
254
	gtk_widget_show (canvas);
255

256
	return GNOME_CANVAS(canvas);
Arturo Espinosa's avatar
Arturo Espinosa committed
257 258
}

Jody Goldberg's avatar
Jody Goldberg committed
259 260 261
/* Manages the scrollbar dimensions and paging parameters. */
void
sheet_view_scrollbar_config (SheetView const *sheet_view)
Arturo Espinosa's avatar
Arturo Espinosa committed
262 263 264 265
{
	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
266
	Sheet         *sheet = sheet_view->sheet;
267 268
	int const last_col = gsheet->col.last_full;
	int const last_row = gsheet->row.last_full;
Arturo Espinosa's avatar
Arturo Espinosa committed
269

Jody Goldberg's avatar
Jody Goldberg committed
270
	va->upper = MAX (MAX (last_row,
271
			      sheet_view->sheet->rows.max_used),
272 273
			 MAX (sheet->cursor.move_corner.row,
			      sheet->cursor.base_corner.row));
274
	va->page_size = last_row - gsheet->row.first;
275
	va->value = gsheet->row.first;
Jody Goldberg's avatar
Jody Goldberg committed
276 277
	va->step_increment = va->page_increment =
	    va->page_size / 2;
278

Jody Goldberg's avatar
Jody Goldberg committed
279
	ha->upper = MAX (MAX (last_col,
280
			      sheet_view->sheet->cols.max_used),
281 282
			 MAX (sheet->cursor.move_corner.col,
			      sheet->cursor.base_corner.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 300
sheet_view_col_selection_changed (ItemBar *item_bar, int col, int modifiers, SheetView *sheet_view)
{
Arturo Espinosa's avatar
Arturo Espinosa committed
301
	Sheet *sheet = sheet_view->sheet;
302 303
	GnumericSheet *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);

304
	/* Ensure that the col exists, ignore result */
305 306
	sheet_col_fetch (sheet, col);

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 313 314

			start_col = MIN (ss->user.start.col, col);
			end_col = MAX (ss->user.end.col, col);

315
			sheet_selection_set (sheet,
316
					     start_col, gsheet->row.first,
317 318 319 320
					     start_col, 0,
					     end_col, SHEET_MAX_ROWS-1);
			return;
		}
321

322 323
		if (!(modifiers & GDK_CONTROL_MASK))
			sheet_selection_reset_only (sheet);
324

325 326 327 328
		sheet_selection_add_range (sheet,
					   col, gsheet->row.first,
					   col, 0,
					   col, SHEET_MAX_ROWS-1);
Arturo Espinosa's avatar
Arturo Espinosa committed
329
	} else
330
		sheet_selection_extend_to (sheet, col, SHEET_MAX_ROWS - 1);
Arturo Espinosa's avatar
Arturo Espinosa committed
331 332 333 334 335 336
}

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

	type = sheet_col_selection_type (sheet, col);

341 342 343 344 345 346
 	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;
347

348
 			if (sheet_col_selection_type (sheet, ci->pos) == ITEM_BAR_FULL_SELECTION)
349
 				sheet_col_set_size_pixels (sheet, ci->pos, width, TRUE);
350
 		}
351
	} else
352
 		sheet_col_set_size_pixels (sheet, col, width, TRUE);
353

Arturo Espinosa's avatar
Arturo Espinosa committed
354 355 356 357
	gnumeric_sheet_compute_visible_ranges (GNUMERIC_SHEET (sheet_view->sheet_view));
}

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

363 364
	/* Ensure that the row exists, ignore result */
	sheet_row_fetch (sheet, row);
365

366 367 368 369
	if (modifiers){
		if ((modifiers & GDK_SHIFT_MASK) && sheet->selections){
			SheetSelection *ss = sheet->selections->data;
			int start_row, end_row;
370 371 372 373

			start_row = MIN (ss->user.start.row, row);
			end_row = MAX (ss->user.end.row, row);

374
			sheet_selection_set (sheet,
375
					     gsheet->col.first, start_row,
376 377 378 379
					     0, start_row,
					     SHEET_MAX_COLS-1, end_row);
			return;
		}
380

381 382
		if (!(modifiers & GDK_CONTROL_MASK))
 			sheet_selection_reset_only (sheet);
383 384 385 386 387

		sheet_selection_add_range (sheet,
					   gsheet->col.first, row,
					   0, row,
					   SHEET_MAX_COLS-1, row);
Arturo Espinosa's avatar
Arturo Espinosa committed
388
	} 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
					sheet_row_set_size_pixels (sheet, ri->pos, height, TRUE);
409
		}
410
	} else
411
		sheet_row_set_size_pixels (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;
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

Arturo Espinosa's avatar
Arturo Espinosa committed
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;
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
		row = GTK_ADJUSTMENT (sheet_view->va)->value;
492

493
		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
static void
sheet_view_init (SheetView *sheet_view)
{
	GtkTable *table = GTK_TABLE (sheet_view);
504

505 506 507 508
	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
	GtkTable  *table = GTK_TABLE (sheet_view);
	Sheet *sheet = sheet_view->sheet;
515

Arturo Espinosa's avatar
Arturo Espinosa committed
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
	/* 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);
532

Arturo Espinosa's avatar
Arturo Espinosa committed
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
	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
	/*
	 * 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));
584

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
			    GTK_SIGNAL_FUNC (button_select_all), sheet_view);
591

Arturo Espinosa's avatar
Arturo Espinosa committed
592
	/* 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
	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);
606

Arturo Espinosa's avatar
Arturo Espinosa committed
607 608 609 610 611 612 613 614 615 616 617 618 619
	/* 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
	sheet_view_set_zoom_factor (sheet_view, 1.);
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
}

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

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

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

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

Arturo Espinosa's avatar
Arturo Espinosa committed
657
	sheet_view_construct (sheet_view);
658

Arturo Espinosa's avatar
Arturo Espinosa committed
659 660 661 662 663 664 665 666 667 668
	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)
669
		gtk_object_unref (GTK_OBJECT (sheet_view->tip));
670

Arturo Espinosa's avatar
Arturo Espinosa committed
671 672 673 674 675
	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
676
sheet_view_class_init (SheetViewClass *Class)
Arturo Espinosa's avatar
Arturo Espinosa committed
677 678 679
{
	GtkObjectClass *object_class;

Jody Goldberg's avatar
Jody Goldberg committed
680
	object_class = (GtkObjectClass *) Class;
Arturo Espinosa's avatar
Arturo Espinosa committed
681 682

	sheet_view_parent_class = gtk_type_class (gtk_table_get_type ());
683

Arturo Espinosa's avatar
Arturo Espinosa committed
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
	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;
}
709

Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724
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);
}
725 726 727

#define TRIANGLE_WIDTH 6

728 729
static GnomeCanvasPoints *
sheet_view_comment_get_points (SheetView *sheet_view, int col, int row)
730 731
{
	GnomeCanvasPoints *points;
732
	int x, y, i;
733 734 735

	points = gnome_canvas_points_new (3);

736 737
	x = sheet_col_get_distance_pixels (sheet_view->sheet, 0, col+1);
	y = 1+sheet_row_get_distance_pixels (sheet_view->sheet, 0, row);
738 739 740 741 742 743 744 745

	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;

746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
	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;
762

763 764 765 766 767 768
	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);

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

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

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

793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
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;
817

818 819
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));
820

821 822 823 824 825
	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;
826

827 828 829
	for (l = sheet_view->sheet->selections; l; l = l->next){
		SheetSelection *ss = l->data;
		ItemCursor *item_cursor;
830

831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
		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);
	}
}

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

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

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

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

	/*
	 * Commented out because the new_view api changed and it isn't
	 * used anyways.
	 */
903

904
	/* view = gnome_bonobo_object_new_view (object); */
905 906 907
	g_warning ("Stick this into the SheetView");
}
#endif
908
#endif