sheet-view.c 25.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"
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"
Jody Goldberg's avatar
Jody Goldberg committed
25
#include "cellspan.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
26 27 28 29 30 31 32 33

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

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

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

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

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

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

	/* Find the range of columns that require a redraw */
Arturo Espinosa's avatar
Arturo Espinosa committed
80 81
	for (col = first_col; col <= last_col; col++)
		for (row = first_row; row <= last_row; row++){
82 83 84 85 86
			Cell *cell;

			cell = sheet_cell_get (sheet, col, row);

			if (cell){
Jody Goldberg's avatar
Jody Goldberg committed
87 88 89 90 91 92 93 94
				int col1 = cell->col->pos, col2 = col1;
				CellSpanInfo const * span =
					row_span_get (cell->row, col1);

				if (span != NULL) {
					col1 = span->left;
					col2 = span->right;
				}
95 96 97 98
				min_col = MIN (col1, min_col);
				max_col = MAX (col2, max_col);
			}
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
99

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

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

109 110
	x += canvas->layout.xoffset - canvas->zoom_xofs;
	y += canvas->layout.yoffset - canvas->zoom_yofs;
Jody Goldberg's avatar
Jody Goldberg committed
111 112 113 114 115 116 117 118

#if 0
	fprintf (stderr, "%s%d:", col_name(min_col), first_row+1);
	fprintf (stderr, "%s%d\n", col_name(max_col), last_row+1);
#endif

	/* redraw a border of 1 pixel around the region to handle thick borders
	 * NOTE the 2nd coordinates are excluded so add 1 extra (+1border +1include) */
119
	gnome_canvas_request_redraw (GNOME_CANVAS (gsheet),
Jody Goldberg's avatar
Jody Goldberg committed
120 121
				     x-1, y-1,
				     x+w+1+1, y+h+1+1);
Arturo Espinosa's avatar
Arturo Espinosa committed
122 123 124
}

void
Jody Goldberg's avatar
Jody Goldberg committed
125 126 127
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
128
{
Jody Goldberg's avatar
Jody Goldberg committed
129
	GnumericSheet *gsheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
130 131 132
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));

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

Jody Goldberg's avatar
Jody Goldberg committed
135
	if (col) {
136
		int left = 0, right = INT_MAX-1;
Jody Goldberg's avatar
Jody Goldberg committed
137 138 139 140 141 142 143
		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) {
144
				left = gsheet->col_offset.first +
145
				    sheet_col_get_distance_pixels (sheet_view->sheet,
146
							    gsheet->col.first, r->start.col);
Jody Goldberg's avatar
Jody Goldberg committed
147
				right = left +
148
				    sheet_col_get_distance_pixels (sheet_view->sheet,
Jody Goldberg's avatar
Jody Goldberg committed
149 150 151
							    r->start.col, r->end.col+1);
			}
		}
152
		/* Request excludes the far coordinate.  Add 1 to include them */
Jody Goldberg's avatar
Jody Goldberg committed
153 154
		gnome_canvas_request_redraw (
			GNOME_CANVAS (sheet_view->col_canvas),
155
			left, 0, right+1, INT_MAX);
Jody Goldberg's avatar
Jody Goldberg committed
156
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
157

Jody Goldberg's avatar
Jody Goldberg committed
158
	if (row) {
159
		int top = 0, bottom = INT_MAX-1;
Jody Goldberg's avatar
Jody Goldberg committed
160 161 162 163 164 165 166
		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) {
167
				top = gsheet->row_offset.first +
168
				    sheet_row_get_distance_pixels (sheet_view->sheet,
169
							    gsheet->row.first, r->start.row);
Jody Goldberg's avatar
Jody Goldberg committed
170
				bottom = top +
171
				    sheet_row_get_distance_pixels (sheet_view->sheet,
Jody Goldberg's avatar
Jody Goldberg committed
172 173 174
							    r->start.row, r->end.row+1);
			}
		}
175
		/* Request excludes the far coordinate.  Add 1 to include them */
Jody Goldberg's avatar
Jody Goldberg committed
176 177
		gnome_canvas_request_redraw (
			GNOME_CANVAS (sheet_view->row_canvas),
178
			0, top, INT_MAX, bottom+1);
Jody Goldberg's avatar
Jody Goldberg committed
179
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
180 181 182 183 184
}

void
sheet_view_set_zoom_factor (SheetView *sheet_view, double factor)
{
185 186
	GList *l;
	GnumericSheet *gsheet;
187 188
	ItemBar *col_item, *row_item;
	int h, w;
189

Arturo Espinosa's avatar
Arturo Espinosa committed
190 191
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));
192

193
	gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
194 195
	col_item = ITEM_BAR (sheet_view->col_item);
	row_item = ITEM_BAR (sheet_view->row_item);
196

197
	/* Set pixels_per_unit before the font.  The item bars look here for the number */
198
	gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (gsheet), factor);
199

200
	/* resize the header fonts */
201 202 203 204 205 206 207
	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.
	 */
208

209 210 211 212 213 214
	/* 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);
215
	gnome_canvas_set_scroll_region (GNOME_CANVAS (sheet_view->col_canvas), 0, 0,
216
					1000000*factor, h);
217

218
	gtk_widget_set_usize (GTK_WIDGET (sheet_view->row_canvas), w, -1);
219
	gnome_canvas_set_scroll_region (GNOME_CANVAS (sheet_view->row_canvas), 0, 0,
220
					w, 1200000*factor);
221

222 223
	/* Recalibrate the starting offsets */
	gsheet->col_offset.first =
224
	    sheet_col_get_distance_pixels (sheet_view->sheet, 0, gsheet->col.first);
225
	gsheet->row_offset.first =
226
	    sheet_row_get_distance_pixels (sheet_view->sheet, 0, gsheet->row.first);
227 228 229

	/* Ensure that the current cell remains visible when we zoom */
	gnumeric_sheet_make_cell_visible (gsheet,
230 231 232
					  sheet_view->sheet->cursor.edit_pos.col,
					  sheet_view->sheet->cursor.edit_pos.row,
					  TRUE);
233 234 235 236 237 238 239

	/* 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
240 241 242 243 244 245 246 247 248 249 250
}

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)
{
251 252 253 254 255 256 257 258 259 260
	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
261 262 263 264 265

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

266
	*itemp = item;
Arturo Espinosa's avatar
Arturo Espinosa committed
267
	gtk_widget_show (canvas);
268

269
	return GNOME_CANVAS(canvas);
Arturo Espinosa's avatar
Arturo Espinosa committed
270 271
}

Jody Goldberg's avatar
Jody Goldberg committed
272 273 274
/* Manages the scrollbar dimensions and paging parameters. */
void
sheet_view_scrollbar_config (SheetView const *sheet_view)
Arturo Espinosa's avatar
Arturo Espinosa committed
275 276 277 278
{
	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
279
	Sheet         *sheet = sheet_view->sheet;
280 281
	int const last_col = gsheet->col.last_full;
	int const last_row = gsheet->row.last_full;
Arturo Espinosa's avatar
Arturo Espinosa committed
282

Jody Goldberg's avatar
Jody Goldberg committed
283
	va->upper = MAX (MAX (last_row,
284
			      sheet_view->sheet->rows.max_used),
285 286
			 MAX (sheet->cursor.move_corner.row,
			      sheet->cursor.base_corner.row));
287
	va->page_size = last_row - gsheet->row.first;
288
	va->value = gsheet->row.first;
Jody Goldberg's avatar
Jody Goldberg committed
289 290
	va->step_increment = va->page_increment =
	    va->page_size / 2;
291

Jody Goldberg's avatar
Jody Goldberg committed
292
	ha->upper = MAX (MAX (last_col,
293
			      sheet_view->sheet->cols.max_used),
294 295
			 MAX (sheet->cursor.move_corner.col,
			      sheet->cursor.base_corner.col));
296
	ha->page_size = last_col - gsheet->col.first;
297
	ha->value = gsheet->col.first;
Jody Goldberg's avatar
Jody Goldberg committed
298 299
	ha->step_increment = ha->page_increment =
	    ha->page_size / 2;
Arturo Espinosa's avatar
Arturo Espinosa committed
300 301 302 303 304

	gtk_adjustment_changed (va);
	gtk_adjustment_changed (ha);
}

Jody Goldberg's avatar
Jody Goldberg committed
305 306 307 308 309 310
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
311
static void
312 313
sheet_view_col_selection_changed (ItemBar *item_bar, int col, int modifiers, SheetView *sheet_view)
{
Arturo Espinosa's avatar
Arturo Espinosa committed
314
	Sheet *sheet = sheet_view->sheet;
315 316
	GnumericSheet *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);

317
	/* Ensure that the col exists, ignore result */
318 319
	sheet_col_fetch (sheet, col);

320 321 322 323
	if (modifiers){
		if ((modifiers & GDK_SHIFT_MASK) && sheet->selections){
			SheetSelection *ss = sheet->selections->data;
			int start_col, end_col;
324 325 326 327

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

328
			sheet_selection_set (sheet,
329
					     start_col, gsheet->row.first,
330 331 332 333
					     start_col, 0,
					     end_col, SHEET_MAX_ROWS-1);
			return;
		}
334

335 336
		if (!(modifiers & GDK_CONTROL_MASK))
			sheet_selection_reset_only (sheet);
337

338 339 340 341
		sheet_selection_add_range (sheet,
					   col, gsheet->row.first,
					   col, 0,
					   col, SHEET_MAX_ROWS-1);
Arturo Espinosa's avatar
Arturo Espinosa committed
342
	} else
343
		sheet_selection_extend_to (sheet, col, SHEET_MAX_ROWS - 1);
Arturo Espinosa's avatar
Arturo Espinosa committed
344 345 346 347 348 349
}

static void
sheet_view_col_size_changed (ItemBar *item_bar, int col, int width, SheetView *sheet_view)
{
	Sheet *sheet = sheet_view->sheet;
350 351 352 353
	ItemBarSelectionType type;

	type = sheet_col_selection_type (sheet, col);

354 355 356 357 358 359
 	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;
360

Jody Goldberg's avatar
Jody Goldberg committed
361 362 363 364 365
 			if (sheet_col_selection_type (sheet, ci->pos) == ITEM_BAR_FULL_SELECTION) {
 				sheet_col_set_size_pixels (sheet, i, width, TRUE);
				/* FIXME should be done later */
				sheet_recompute_spans_for_col (sheet, i);
			}
366
 		}
Jody Goldberg's avatar
Jody Goldberg committed
367
	} else {
368
 		sheet_col_set_size_pixels (sheet, col, width, TRUE);
Jody Goldberg's avatar
Jody Goldberg committed
369 370 371
		/* FIXME should be done later */
		sheet_recompute_spans_for_col (sheet, col);
	}
372

Jody Goldberg's avatar
Jody Goldberg committed
373
	sheet_update (sheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
374 375 376
}

static void
377
sheet_view_row_selection_changed (ItemBar *item_bar, int row, int modifiers, SheetView *sheet_view)
Arturo Espinosa's avatar
Arturo Espinosa committed
378 379
{
	Sheet *sheet = sheet_view->sheet;
380
	GnumericSheet *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
381

382 383
	/* Ensure that the row exists, ignore result */
	sheet_row_fetch (sheet, row);
384

385 386 387 388
	if (modifiers){
		if ((modifiers & GDK_SHIFT_MASK) && sheet->selections){
			SheetSelection *ss = sheet->selections->data;
			int start_row, end_row;
389 390 391 392

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

393
			sheet_selection_set (sheet,
394
					     gsheet->col.first, start_row,
395 396 397 398
					     0, start_row,
					     SHEET_MAX_COLS-1, end_row);
			return;
		}
399

400 401
		if (!(modifiers & GDK_CONTROL_MASK))
 			sheet_selection_reset_only (sheet);
402 403 404 405 406

		sheet_selection_add_range (sheet,
					   gsheet->col.first, row,
					   0, row,
					   SHEET_MAX_COLS-1, row);
Arturo Espinosa's avatar
Arturo Espinosa committed
407
	} else
408
		sheet_selection_extend_to (sheet, SHEET_MAX_COLS-1, row);
Arturo Espinosa's avatar
Arturo Espinosa committed
409 410 411 412 413 414
}

static void
sheet_view_row_size_changed (ItemBar *item_bar, int row, int height, SheetView *sheet_view)
{
	Sheet *sheet = sheet_view->sheet;
415 416 417 418
	ItemBarSelectionType type;

	type = sheet_row_selection_type (sheet, row);

419 420 421 422 423 424
	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;
425

426
			if (sheet_row_selection_type (sheet, ri->pos) == ITEM_BAR_FULL_SELECTION)
427
					sheet_row_set_size_pixels (sheet, ri->pos, height, TRUE);
428
		}
429
	} else
430
		sheet_row_set_size_pixels (sheet, row, height, TRUE);
Jody Goldberg's avatar
Jody Goldberg committed
431 432

	sheet_update (sheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
433 434 435 436 437 438
}

static void
button_select_all (GtkWidget *the_button, SheetView *sheet_view)
{
	sheet_select_all (sheet_view->sheet);
439
	sheet_redraw_all (sheet_view->sheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
440 441 442 443 444
}

static void
vertical_scroll_change (GtkAdjustment *adj, SheetView *sheet_view)
{
445 446 447 448 449
	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
450 451 452 453 454
}

static void
horizontal_scroll_change (GtkAdjustment *adj, SheetView *sheet_view)
{
455 456 457 458
	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
459 460 461 462 463 464 465
	}
}

static int
horizontal_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet_view)
{
	if (event->type == GDK_BUTTON_PRESS){
466 467 468
		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
469
		gtk_widget_show_all (gtk_widget_get_toplevel (sheet_view->tip));
470 471 472 473
	}
	else if (event->type == GDK_BUTTON_RELEASE)
	{
		GnumericSheet  *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
474
		int col;
475

476 477 478 479 480 481
		/* 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
482

483 484
		col = GTK_ADJUSTMENT (sheet_view->ha)->value;

485
		gnumeric_sheet_set_left_col (gsheet, col);
486
		/* NOTE : Excel does not move the cursor, just scrolls the sheet. */
Arturo Espinosa's avatar
Arturo Espinosa committed
487
	}
488

Arturo Espinosa's avatar
Arturo Espinosa committed
489 490 491 492 493 494 495
	return FALSE;
}

static int
vertical_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet_view)
{
	if (event->type == GDK_BUTTON_PRESS){
496 497 498
		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
499
		gtk_widget_show_all (gtk_widget_get_toplevel (sheet_view->tip));
500 501 502 503
	}
	else if (event->type == GDK_BUTTON_RELEASE)
	{
		GnumericSheet  *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
504
		int row;
505

506 507 508 509 510 511
		/* 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
512

513
		row = GTK_ADJUSTMENT (sheet_view->va)->value;
514

515
		gnumeric_sheet_set_top_row (gsheet, row);
516
		/* NOTE : Excel does not move the cursor, just scrolls the sheet. */
Arturo Espinosa's avatar
Arturo Espinosa committed
517 518 519 520 521
	}

	return FALSE;
}

522 523 524 525
static void
sheet_view_init (SheetView *sheet_view)
{
	GtkTable *table = GTK_TABLE (sheet_view);
526

527 528 529 530
	table->homogeneous = FALSE;
	gtk_table_resize (table, 4, 4);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
531 532 533
static void
sheet_view_construct (SheetView *sheet_view)
{
534
	GnomeCanvasGroup *root_group;
Arturo Espinosa's avatar
Arturo Espinosa committed
535 536
	GtkTable  *table = GTK_TABLE (sheet_view);
	Sheet *sheet = sheet_view->sheet;
537

Arturo Espinosa's avatar
Arturo Espinosa committed
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
	/* 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);
554

Arturo Espinosa's avatar
Arturo Espinosa committed
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
	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
572

Arturo Espinosa's avatar
Arturo Espinosa committed
573 574 575 576
	gtk_signal_connect_after (
		GTK_OBJECT (sheet_view), "size_allocate",
		GTK_SIGNAL_FUNC (sheet_view_size_allocate), sheet_view);

577 578 579
	/* Create the object group inside the GnumericSheet */
	root_group = GNOME_CANVAS_GROUP (
		GNOME_CANVAS (sheet_view->sheet_view)->root);
580 581 582 583 584 585 586
	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));
587

Arturo Espinosa's avatar
Arturo Espinosa committed
588 589 590 591 592 593 594 595
	/* 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);

596 597 598 599 600 601 602 603 604 605
	/*
	 * 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));
606

Arturo Espinosa's avatar
Arturo Espinosa committed
607
	/* The select-all button */
608 609 610 611
	sheet_view->select_all_btn = gtk_button_new ();
	GTK_WIDGET_UNSET_FLAGS (sheet_view->select_all_btn, GTK_CAN_FOCUS);
	gtk_table_attach (table, sheet_view->select_all_btn, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
	gtk_signal_connect (GTK_OBJECT (sheet_view->select_all_btn), "clicked",
Arturo Espinosa's avatar
Arturo Espinosa committed
612
			    GTK_SIGNAL_FUNC (button_select_all), sheet_view);
613

Arturo Espinosa's avatar
Arturo Espinosa committed
614
	/* Scroll bars and their adjustments */
615 616
	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
617 618 619 620 621 622 623 624 625 626 627
	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);
628

Arturo Espinosa's avatar
Arturo Espinosa committed
629 630 631 632 633 634 635 636 637 638 639 640 641
	/* 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);
642
	sheet_view_set_zoom_factor (sheet_view, 1.);
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
}

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

661 662 663 664 665 666 667
	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
668 669 670 671 672 673 674 675 676
}

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

	sheet_view = gtk_type_new (sheet_view_get_type ());
	sheet_view->sheet = sheet;
677
	sheet_view->tip = NULL;
678

Arturo Espinosa's avatar
Arturo Espinosa committed
679
	sheet_view_construct (sheet_view);
680

Arturo Espinosa's avatar
Arturo Espinosa committed
681 682 683 684 685 686 687 688 689 690
	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)
691
		gtk_object_unref (GTK_OBJECT (sheet_view->tip));
692

Arturo Espinosa's avatar
Arturo Espinosa committed
693 694 695 696 697
	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
698
sheet_view_class_init (SheetViewClass *Class)
Arturo Espinosa's avatar
Arturo Espinosa committed
699 700 701
{
	GtkObjectClass *object_class;

Jody Goldberg's avatar
Jody Goldberg committed
702
	object_class = (GtkObjectClass *) Class;
Arturo Espinosa's avatar
Arturo Espinosa committed
703 704

	sheet_view_parent_class = gtk_type_class (gtk_table_get_type ());
705

Arturo Espinosa's avatar
Arturo Espinosa committed
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
	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;
}
731

Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
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);
}
747 748 749

#define TRIANGLE_WIDTH 6

750 751
static GnomeCanvasPoints *
sheet_view_comment_get_points (SheetView *sheet_view, int col, int row)
752 753
{
	GnomeCanvasPoints *points;
754
	int x, y, i;
755 756 757

	points = gnome_canvas_points_new (3);

758 759
	x = sheet_col_get_distance_pixels (sheet_view->sheet, 0, col+1);
	y = 1+sheet_row_get_distance_pixels (sheet_view->sheet, 0, row);
760 761 762 763 764 765 766 767

	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;

768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
	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;
784

785 786 787 788 789 790
	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);

791 792 793 794 795 796 797 798
	i = gnome_canvas_item_new (
		group, gnome_canvas_polygon_get_type (),
		"points",     points,
		"fill_color", "red",
		NULL);

	return i;
}
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814

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

815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
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;
839

840 841
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));
842

843 844 845 846 847
	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;
848

849 850 851
	for (l = sheet_view->sheet->selections; l; l = l->next){
		SheetSelection *ss = l->data;
		ItemCursor *item_cursor;
852

853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
		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);
	}
}

868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
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)
885
		gtk_widget_show (sheet_view->select_all_btn);
886
	else
887
		gtk_widget_hide (sheet_view->select_all_btn);
888 889 890 891 892 893 894 895 896 897 898

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

900 901 902 903
StyleFont *
sheet_view_get_style_font (const Sheet *sheet, MStyle *mstyle)
{
	/* Scale the font size by the average scaling factor for the
904
	 * display.  72dpi is base size
905 906 907 908 909 910 911 912 913
	 */

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

914
#if 0
915 916
#ifdef ENABLE_BONOBO
void
917
sheet_view_insert_object (SheetView *sheet_view, BonoboObjectClient *object)
918
{
Michael Meeks's avatar
Michael Meeks committed
919
/*	GtkWidget *view;*/
920 921 922 923 924

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

926
	/* view = gnome_bonobo_object_new_view (object); */
927 928 929
	g_warning ("Stick this into the SheetView");
}
#endif
930
#endif