sheet-control-gui.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