sheet-view.c 26.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 "parse-util.h"
23
#include "selection.h"
24
#include "application.h"
Jody Goldberg's avatar
Jody Goldberg committed
25
#include "cellspan.h"
Jody Goldberg's avatar
Jody Goldberg committed
26
#include "cmd-edit.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
27 28 29 30 31 32 33 34

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

Arturo Espinosa's avatar
Arturo Espinosa committed
36 37 38 39 40 41 42 43 44 45 46
	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);
}

Jody Goldberg's avatar
Jody Goldberg committed
47
/*
48
 * Redraw selected range, do not honour spans
Jody Goldberg's avatar
Jody Goldberg committed
49
 */
Arturo Espinosa's avatar
Arturo Espinosa committed
50
void
Jody Goldberg's avatar
Jody Goldberg committed
51 52 53
sheet_view_redraw_cell_region (SheetView *sheet_view,
			       int start_col, int start_row,
			       int end_col, int end_row)
Arturo Espinosa's avatar
Arturo Espinosa committed
54 55
{
	GnumericSheet *gsheet;
56
	GnomeCanvas *canvas;
Arturo Espinosa's avatar
Arturo Espinosa committed
57 58
	Sheet *sheet = sheet_view->sheet;
	int x, y, w, h;
59

Arturo Espinosa's avatar
Arturo Espinosa committed
60 61 62 63 64
	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));
65
	canvas = GNOME_CANVAS (gsheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
66

67 68 69 70
	if ((end_col < gsheet->col.first) ||
	    (end_row < gsheet->row.first) ||
	    (start_col > gsheet->col.last_visible) ||
	    (start_row > gsheet->row.last_visible))
71
		return;
72

73
	/* Only draw those regions that are visible */
74 75 76 77
	start_col = MAX (gsheet->col.first, start_col);
	start_row = MAX (gsheet->row.first, start_row);
	end_col =  MIN (gsheet->col.last_visible, end_col);
	end_row =  MIN (gsheet->row.last_visible, end_row);
Arturo Espinosa's avatar
Arturo Espinosa committed
78

79 80 81 82
	x = sheet_col_get_distance_pixels (sheet, gsheet->col.first, start_col);
	y = sheet_row_get_distance_pixels (sheet, gsheet->row.first, start_row);
	w = sheet_col_get_distance_pixels (sheet, start_col, end_col+1);
	h = sheet_row_get_distance_pixels (sheet, start_row, end_row+1);
Arturo Espinosa's avatar
Arturo Espinosa committed
83

84 85
	x += canvas->layout.xoffset - canvas->zoom_xofs;
	y += canvas->layout.yoffset - canvas->zoom_yofs;
Jody Goldberg's avatar
Jody Goldberg committed
86 87 88 89 90 91 92 93

#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) */
94
	gnome_canvas_request_redraw (GNOME_CANVAS (gsheet),
Jody Goldberg's avatar
Jody Goldberg committed
95 96
				     x-1, y-1,
				     x+w+1+1, y+h+1+1);
Arturo Espinosa's avatar
Arturo Espinosa committed
97 98 99
}

void
Jody Goldberg's avatar
Jody Goldberg committed
100 101 102
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
103
{
Jody Goldberg's avatar
Jody Goldberg committed
104
	GnumericSheet *gsheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
105 106 107
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));

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

Jody Goldberg's avatar
Jody Goldberg committed
110
	if (col) {
111
		int left = 0, right = INT_MAX-1;
Jody Goldberg's avatar
Jody Goldberg committed
112 113 114 115 116 117 118
		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) {
119
				left = gsheet->col_offset.first +
120
				    sheet_col_get_distance_pixels (sheet_view->sheet,
121
							    gsheet->col.first, r->start.col);
Jody Goldberg's avatar
Jody Goldberg committed
122
				right = left +
123
				    sheet_col_get_distance_pixels (sheet_view->sheet,
Jody Goldberg's avatar
Jody Goldberg committed
124 125 126
							    r->start.col, r->end.col+1);
			}
		}
127
		/* Request excludes the far coordinate.  Add 1 to include them */
Jody Goldberg's avatar
Jody Goldberg committed
128 129
		gnome_canvas_request_redraw (
			GNOME_CANVAS (sheet_view->col_canvas),
130
			left, 0, right+1, INT_MAX);
Jody Goldberg's avatar
Jody Goldberg committed
131
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
132

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

void
Jody Goldberg's avatar
Jody Goldberg committed
158
sheet_view_update_cursor_pos (SheetView *sheet_view)
Arturo Espinosa's avatar
Arturo Espinosa committed
159
{
160 161
	GList *l;
	GnumericSheet *gsheet;
Jody Goldberg's avatar
Jody Goldberg committed
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179

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

	gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);

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

	/* Reposition the animated cursors */
	for (l = sheet_view->anted_cursors; l; l = l->next)
		item_cursor_reposition (ITEM_CURSOR (l->data));
}

void
sheet_view_set_zoom_factor (SheetView *sheet_view, double factor)
{
	GnumericSheet *gsheet;
180 181
	ItemBar *col_item, *row_item;
	int h, w;
182

Arturo Espinosa's avatar
Arturo Espinosa committed
183 184
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));
185

186
	gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
187 188
	col_item = ITEM_BAR (sheet_view->col_item);
	row_item = ITEM_BAR (sheet_view->row_item);
189

190
	/* Set pixels_per_unit before the font.  The item bars look here for the number */
191
	gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (gsheet), factor);
192

193
	/* resize the header fonts */
194 195 196 197 198 199 200
	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.
	 */
201

202 203 204 205 206 207
	/* 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);
208
	gnome_canvas_set_scroll_region (GNOME_CANVAS (sheet_view->col_canvas), 0, 0,
209
					1000000*factor, h);
210

211
	gtk_widget_set_usize (GTK_WIDGET (sheet_view->row_canvas), w, -1);
212
	gnome_canvas_set_scroll_region (GNOME_CANVAS (sheet_view->row_canvas), 0, 0,
213
					w, 1200000*factor);
214

215 216
	/* Recalibrate the starting offsets */
	gsheet->col_offset.first =
217
	    sheet_col_get_distance_pixels (sheet_view->sheet, 0, gsheet->col.first);
218
	gsheet->row_offset.first =
219
	    sheet_row_get_distance_pixels (sheet_view->sheet, 0, gsheet->row.first);
220

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

Jody Goldberg's avatar
Jody Goldberg committed
229
	sheet_view_update_cursor_pos (sheet_view);
Arturo Espinosa's avatar
Arturo Espinosa committed
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)
{
241 242 243 244 245 246 247 248 249 250
	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
251 252 253 254 255

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

256
	*itemp = item;
Arturo Espinosa's avatar
Arturo Espinosa committed
257
	gtk_widget_show (canvas);
258

259
	return GNOME_CANVAS(canvas);
Arturo Espinosa's avatar
Arturo Espinosa committed
260 261
}

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

Jody Goldberg's avatar
Jody Goldberg committed
273
	va->upper = MAX (MAX (last_row,
274
			      sheet_view->sheet->rows.max_used),
275 276
			 MAX (sheet->cursor.move_corner.row,
			      sheet->cursor.base_corner.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;
281

Jody Goldberg's avatar
Jody Goldberg committed
282
	ha->upper = MAX (MAX (last_col,
283
			      sheet_view->sheet->cols.max_used),
284 285
			 MAX (sheet->cursor.move_corner.col,
			      sheet->cursor.base_corner.col));
286
	ha->page_size = last_col - gsheet->col.first;
287
	ha->value = gsheet->col.first;
Jody Goldberg's avatar
Jody Goldberg committed
288 289
	ha->step_increment = ha->page_increment =
	    ha->page_size / 2;
Arturo Espinosa's avatar
Arturo Espinosa committed
290 291 292 293 294

	gtk_adjustment_changed (va);
	gtk_adjustment_changed (ha);
}

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
/*
 * sheet_view_make_edit_pos_visible
 * @sheet_view  Sheet view
 *
 * Make the cell at the edit position visible.
 *
 * To be called from the "size_allocate" signal handler when the geometry of a
 * new sheet view has been configured. 
 */
static void
sheet_view_make_edit_pos_visible (SheetView const *sheet_view)
{
	GnumericSheet *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);

	gnumeric_sheet_make_cell_visible
		(gsheet,
		 sheet_view->sheet->cursor.edit_pos.col,
		 sheet_view->sheet->cursor.edit_pos.row,
		 TRUE);

}

Jody Goldberg's avatar
Jody Goldberg committed
317 318 319
static void
sheet_view_size_allocate (GtkWidget *widget, GtkAllocation *alloc, SheetView *sheet_view)
{
320
	sheet_view_make_edit_pos_visible (sheet_view);
Jody Goldberg's avatar
Jody Goldberg committed
321 322 323
	sheet_view_scrollbar_config (sheet_view);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
324
static void
325 326
sheet_view_col_selection_changed (ItemBar *item_bar, int col, int modifiers, SheetView *sheet_view)
{
Arturo Espinosa's avatar
Arturo Espinosa committed
327
	Sheet *sheet = sheet_view->sheet;
328 329
	GnumericSheet *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);

330 331 332 333
	if (modifiers){
		if ((modifiers & GDK_SHIFT_MASK) && sheet->selections){
			SheetSelection *ss = sheet->selections->data;
			int start_col, end_col;
334 335 336 337

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

338
			sheet_selection_set (sheet,
339
					     start_col, gsheet->row.first,
340 341 342 343
					     start_col, 0,
					     end_col, SHEET_MAX_ROWS-1);
			return;
		}
344

345 346
		if (!(modifiers & GDK_CONTROL_MASK))
			sheet_selection_reset_only (sheet);
347

348 349 350 351
		sheet_selection_add_range (sheet,
					   col, gsheet->row.first,
					   col, 0,
					   col, SHEET_MAX_ROWS-1);
352
	} else {
353
		sheet_selection_extend_to (sheet, col, SHEET_MAX_ROWS - 1);
354 355
		gnumeric_sheet_make_cell_visible (gsheet, col, gsheet->row.first, FALSE);
	}
356 357 358

	/* The edit pos, and the selection may have changed */
	sheet_update (sheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
359 360
}

361 362 363 364 365 366 367 368 369 370 371 372
struct closure_colrow_resize {
	int size_pixels;
	gboolean is_cols;
};

static gboolean
cb_colrow_resize (Sheet *sheet, Range const *r, gpointer user_data)
{
	struct closure_colrow_resize const *info = user_data;
	int tmp;

	if (info->is_cols) {
373
		if (r->start.row == 0 && r->end.row >= SHEET_MAX_ROWS - 1)
374 375 376 377 378 379 380 381 382 383 384 385
			for (tmp = r->start.col; tmp <= r->end.col ; ++tmp) {
				sheet_col_set_size_pixels (sheet, tmp, info->size_pixels, TRUE);
				/* FIXME should be done later */
				sheet_recompute_spans_for_col (sheet, tmp);
			}
	} else if (r->start.col == 0 && r->end.col >= SHEET_MAX_COLS - 1)
		for (tmp = r->start.row; tmp <= r->end.row ; ++tmp)
			sheet_row_set_size_pixels (sheet, tmp, info->size_pixels, TRUE);

	return TRUE;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
386
static void
387 388
sheet_view_col_size_changed (ItemBar *item_bar, int col, int width,
			     SheetView *sheet_view)
Arturo Espinosa's avatar
Arturo Espinosa committed
389 390
{
	Sheet *sheet = sheet_view->sheet;
391
	ItemBarSelectionType const type = sheet_col_selection_type (sheet, col);
392

393 394 395 396
	/*
	 * If the column that changed size is completely selected (top to
	 * bottom) then resize all other columns which are fully selected too.
	 */
397
 	if (type == ITEM_BAR_FULL_SELECTION) {
398 399 400 401
		struct closure_colrow_resize	closure;
		closure.size_pixels = width;
		closure.is_cols = TRUE;
		selection_foreach_range (sheet, &cb_colrow_resize, &closure);
Jody Goldberg's avatar
Jody Goldberg committed
402
	} else {
403
 		sheet_col_set_size_pixels (sheet, col, width, TRUE);
Jody Goldberg's avatar
Jody Goldberg committed
404 405 406
		/* FIXME should be done later */
		sheet_recompute_spans_for_col (sheet, col);
	}
407

Jody Goldberg's avatar
Jody Goldberg committed
408
	sheet_update (sheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
409 410 411
}

static void
412
sheet_view_row_selection_changed (ItemBar *item_bar, int row, int modifiers, SheetView *sheet_view)
Arturo Espinosa's avatar
Arturo Espinosa committed
413 414
{
	Sheet *sheet = sheet_view->sheet;
415
	GnumericSheet *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
416 417 418 419 420

	if (modifiers){
		if ((modifiers & GDK_SHIFT_MASK) && sheet->selections){
			SheetSelection *ss = sheet->selections->data;
			int start_row, end_row;
421 422 423 424

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

425
			sheet_selection_set (sheet,
426
					     gsheet->col.first, start_row,
427 428 429 430
					     0, start_row,
					     SHEET_MAX_COLS-1, end_row);
			return;
		}
431

432 433
		if (!(modifiers & GDK_CONTROL_MASK))
 			sheet_selection_reset_only (sheet);
434 435 436 437 438

		sheet_selection_add_range (sheet,
					   gsheet->col.first, row,
					   0, row,
					   SHEET_MAX_COLS-1, row);
439
	} else {
440
		sheet_selection_extend_to (sheet, SHEET_MAX_COLS-1, row);
441 442
		gnumeric_sheet_make_cell_visible (gsheet, gsheet->col.first, row, FALSE);
	}
443 444
	/* The edit pos, and the selection may have changed */
	sheet_update (sheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
445 446 447 448 449 450
}

static void
sheet_view_row_size_changed (ItemBar *item_bar, int row, int height, SheetView *sheet_view)
{
	Sheet *sheet = sheet_view->sheet;
451
	ItemBarSelectionType const type = sheet_row_selection_type (sheet, row);
452

453 454 455 456 457 458 459 460 461
	/*
	 * If the row that changed size is completely selected (left to
	 * right) then resize all other rows which are fully selected too.
	 */
 	if (type == ITEM_BAR_FULL_SELECTION) {
		struct closure_colrow_resize	closure;
		closure.size_pixels = height;
		closure.is_cols = FALSE;
		selection_foreach_range (sheet, &cb_colrow_resize, &closure);
462
	} else
463
		sheet_row_set_size_pixels (sheet, row, height, TRUE);
Jody Goldberg's avatar
Jody Goldberg committed
464 465

	sheet_update (sheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
466 467 468 469 470
}

static void
button_select_all (GtkWidget *the_button, SheetView *sheet_view)
{
Jody Goldberg's avatar
Jody Goldberg committed
471
	cmd_select_all (sheet_view->sheet);
Arturo Espinosa's avatar
Arturo Espinosa committed
472 473 474 475 476
}

static void
vertical_scroll_change (GtkAdjustment *adj, SheetView *sheet_view)
{
477 478 479 480 481
	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
482 483 484 485 486
}

static void
horizontal_scroll_change (GtkAdjustment *adj, SheetView *sheet_view)
{
487 488 489 490
	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
491 492 493 494 495 496 497
	}
}

static int
horizontal_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet_view)
{
	if (event->type == GDK_BUTTON_PRESS){
498 499 500
		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
501
		gtk_widget_show_all (gtk_widget_get_toplevel (sheet_view->tip));
502 503

	} else if (event->type == GDK_BUTTON_RELEASE) {
504
		GnumericSheet  *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
505
		int col;
506

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

514 515
		col = GTK_ADJUSTMENT (sheet_view->ha)->value;

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

Arturo Espinosa's avatar
Arturo Espinosa committed
520 521 522 523 524 525 526
	return FALSE;
}

static int
vertical_scroll_event (GtkScrollbar *scroll, GdkEvent *event, SheetView *sheet_view)
{
	if (event->type == GDK_BUTTON_PRESS){
527 528 529
		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
530
		gtk_widget_show_all (gtk_widget_get_toplevel (sheet_view->tip));
531 532

	} else if (event->type == GDK_BUTTON_RELEASE) {
533
		GnumericSheet  *gsheet = GNUMERIC_SHEET (sheet_view->sheet_view);
534
		int row;
535

536 537 538 539 540 541
		/* 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
542

543
		row = GTK_ADJUSTMENT (sheet_view->va)->value;
544

545
		gnumeric_sheet_set_top_row (gsheet, row);
546
		/* NOTE : Excel does not move the cursor, just scrolls the sheet. */
Arturo Espinosa's avatar
Arturo Espinosa committed
547 548 549 550 551
	}

	return FALSE;
}

552 553 554 555
static void
sheet_view_init (SheetView *sheet_view)
{
	GtkTable *table = GTK_TABLE (sheet_view);
556

557 558 559 560
	table->homogeneous = FALSE;
	gtk_table_resize (table, 4, 4);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
561 562 563
static void
sheet_view_construct (SheetView *sheet_view)
{
564
	GnomeCanvasGroup *root_group;
Arturo Espinosa's avatar
Arturo Espinosa committed
565 566
	GtkTable  *table = GTK_TABLE (sheet_view);
	Sheet *sheet = sheet_view->sheet;
567

Arturo Espinosa's avatar
Arturo Espinosa committed
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
	/* 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);
584

Arturo Espinosa's avatar
Arturo Espinosa committed
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
	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
602

Arturo Espinosa's avatar
Arturo Espinosa committed
603 604 605 606
	gtk_signal_connect_after (
		GTK_OBJECT (sheet_view), "size_allocate",
		GTK_SIGNAL_FUNC (sheet_view_size_allocate), sheet_view);

607 608 609
	/* Create the object group inside the GnumericSheet */
	root_group = GNOME_CANVAS_GROUP (
		GNOME_CANVAS (sheet_view->sheet_view)->root);
610 611 612 613 614 615 616
	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));
617

Arturo Espinosa's avatar
Arturo Espinosa committed
618 619 620 621 622 623 624 625
	/* 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);

626 627 628 629 630 631 632 633 634 635
	/*
	 * 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));
636

Arturo Espinosa's avatar
Arturo Espinosa committed
637
	/* The select-all button */
638 639 640 641
	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
642
			    GTK_SIGNAL_FUNC (button_select_all), sheet_view);
643

Arturo Espinosa's avatar
Arturo Espinosa committed
644
	/* Scroll bars and their adjustments */
645 646
	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
647 648 649 650 651 652 653 654 655 656 657
	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);
658

Arturo Espinosa's avatar
Arturo Espinosa committed
659 660 661 662 663 664 665 666 667 668 669 670 671
	/* 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);
672
	sheet_view_set_zoom_factor (sheet_view, 1.);
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
}

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

691 692 693 694 695 696 697
	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
698 699 700 701 702 703 704 705 706
}

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

	sheet_view = gtk_type_new (sheet_view_get_type ());
	sheet_view->sheet = sheet;
707
	sheet_view->tip = NULL;
708

Arturo Espinosa's avatar
Arturo Espinosa committed
709
	sheet_view_construct (sheet_view);
710

Arturo Espinosa's avatar
Arturo Espinosa committed
711 712 713 714 715 716 717 718 719 720
	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)
721
		gtk_object_unref (GTK_OBJECT (sheet_view->tip));
722

Arturo Espinosa's avatar
Arturo Espinosa committed
723 724 725 726 727
	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
728
sheet_view_class_init (SheetViewClass *Class)
Arturo Espinosa's avatar
Arturo Espinosa committed
729 730 731
{
	GtkObjectClass *object_class;

Jody Goldberg's avatar
Jody Goldberg committed
732
	object_class = (GtkObjectClass *) Class;
Arturo Espinosa's avatar
Arturo Espinosa committed
733 734

	sheet_view_parent_class = gtk_type_class (gtk_table_get_type ());
735

Arturo Espinosa's avatar
Arturo Espinosa committed
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
	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;
}
761

Miguel de Icaza's avatar
New:  
Miguel de Icaza committed
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
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);
}
777 778 779

#define TRIANGLE_WIDTH 6

780 781
static GnomeCanvasPoints *
sheet_view_comment_get_points (SheetView *sheet_view, int col, int row)
782 783
{
	GnomeCanvasPoints *points;
784
	int x, y, i;
785 786 787

	points = gnome_canvas_points_new (3);

788 789
	x = sheet_col_get_distance_pixels (sheet_view->sheet, 0, col+1);
	y = 1+sheet_row_get_distance_pixels (sheet_view->sheet, 0, row);
790 791 792 793 794 795 796 797

	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;

798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
	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;
814

815 816 817 818 819 820
	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);

821 822 823 824 825 826 827 828
	i = gnome_canvas_item_new (
		group, gnome_canvas_polygon_get_type (),
		"points",     points,
		"fill_color", "red",
		NULL);

	return i;
}
829 830 831 832 833 834 835 836 837 838 839 840 841 842

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);
Morten Welinder's avatar
Morten Welinder committed
843
	gnome_canvas_points_free (points);
844 845
}

846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
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;
870

871 872
	g_return_if_fail (sheet_view != NULL);
	g_return_if_fail (IS_SHEET_VIEW (sheet_view));
873

874 875 876 877 878
	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;
879

880 881 882
	for (l = sheet_view->sheet->selections; l; l = l->next){
		SheetSelection *ss = l->data;
		ItemCursor *item_cursor;
883

884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
		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);
	}
}

899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
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)
916
		gtk_widget_show (sheet_view->select_all_btn);
917
	else
918
		gtk_widget_hide (sheet_view->select_all_btn);
919 920 921 922 923 924 925 926 927 928 929

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

931
StyleFont *
932
sheet_view_get_style_font (const Sheet *sheet, MStyle const * const mstyle)
933 934
{
	/* Scale the font size by the average scaling factor for the
935
	 * display.  72dpi is base size
936 937 938 939 940 941 942 943 944
	 */

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

945
#if 0
946 947
#ifdef ENABLE_BONOBO
void
948
sheet_view_insert_object (SheetView *sheet_view, BonoboObjectClient *object)
949
{
Michael Meeks's avatar
Michael Meeks committed
950
/*	GtkWidget *view;*/
951 952 953 954 955

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

957
	/* view = gnome_bonobo_object_new_view (object); */
958 959 960
	g_warning ("Stick this into the SheetView");
}
#endif
961
#endif