item-bar.c 22.1 KB
Newer Older
1 2 3 4 5 6 7
/*
 * Implements the resizable guides for columns and rows
 * in the Gnumeric Spreadsheet.
 *
 * Author:
 *     Miguel de Icaza (miguel@kernel.org)
 */
8 9 10 11
#include <config.h>

#include <gnome.h>
#include "gnumeric.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
12
#include "gnumeric-sheet.h"
13 14
#include "item-bar.h"
#include "item-debug.h"
15
#include "parse-util.h"
16
#include "gnumeric-util.h"
Jody Goldberg's avatar
Jody Goldberg committed
17
#include "selection.h"
18
#include "workbook-cmd-format.h"
19
#include "application.h"
20
#include "style.h"
21

Arturo Espinosa's avatar
Arturo Espinosa committed
22
/* Marshal forward declarations */
Arturo Espinosa's avatar
Arturo Espinosa committed
23 24 25 26
static void   item_bar_marshal      (GtkObject *,
				     GtkSignalFunc,
				     gpointer,
				     GtkArg *);
Morten Welinder's avatar
Morten Welinder committed
27

Arturo Espinosa's avatar
Arturo Espinosa committed
28 29 30 31
/* The signal signatures */
typedef void (*ItemBarSignal1) (GtkObject *, gint arg1, gpointer data);
typedef void (*ItemBarSignal2) (GtkObject *, gint arg1, gint arg2, gpointer data);

32 33
/* The signals we emit */
enum {
Arturo Espinosa's avatar
Arturo Espinosa committed
34 35 36
	SELECTION_CHANGED,
	SIZE_CHANGED,
	LAST_SIGNAL
37
};
Arturo Espinosa's avatar
Arturo Espinosa committed
38
static guint item_bar_signals [LAST_SIGNAL] = { 0 };
39 40 41 42 43 44

static GnomeCanvasItem *item_bar_parent_class;

/* The arguments we take */
enum {
	ARG_0,
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
45
	ARG_SHEET_VIEW,
46 47 48 49
	ARG_ORIENTATION,
	ARG_FIRST_ELEMENT
};

50 51 52 53 54 55 56 57 58 59 60 61 62 63
static void
item_bar_fonts_unref (ItemBar *item_bar)
{
	if (item_bar->normal_font != NULL) {
		style_font_unref (item_bar->normal_font);
		item_bar->normal_font = NULL;
	}

	if (item_bar->bold_font != NULL) {
		style_font_unref (item_bar->bold_font);
		item_bar->bold_font = NULL;
	}
}

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
static void
item_bar_destroy (GtkObject *object)
{
	ItemBar *bar;

	bar = ITEM_BAR (object);

	item_bar_fonts_unref (bar);

	if (bar->tip)
		gtk_object_unref (GTK_OBJECT (bar->tip));

	if (GTK_OBJECT_CLASS (item_bar_parent_class)->destroy)
		(*GTK_OBJECT_CLASS (item_bar_parent_class)->destroy)(object);
}

80 81 82 83
/*
 * Scale the item-bar heading fonts by the pixels_per_unit of
 * th associated sheet.
 */
84
void
85
item_bar_fonts_init (ItemBar *item_bar)
86
{
87 88
	double const zoom_factor =
		item_bar->sheet_view->sheet->last_zoom_factor_used;
89 90
	double const res    = MIN(application_display_dpi_get (FALSE), 
				  application_display_dpi_get (TRUE)) / 72.;
91
	StyleFont * const normal_font =
92
		style_font_new_simple (DEFAULT_FONT, DEFAULT_SIZE,
93
				       res*zoom_factor, FALSE, FALSE);
94
	StyleFont * const bold_font =
95
		style_font_new_simple (DEFAULT_FONT, DEFAULT_SIZE,
96
				       res*zoom_factor, TRUE, FALSE);
97 98 99 100 101 102 103

	/* Now that we have the new fonts unref the old ones */
	item_bar_fonts_unref (item_bar);

	/* And finish up by assigning the new fonts. */
	item_bar->normal_font = normal_font;
	item_bar->bold_font = bold_font;
104 105
}

106 107 108 109 110 111
static void
item_bar_realize (GnomeCanvasItem *item)
{
	ItemBar *item_bar;
	GdkWindow *window;
	GdkGC *gc;
112
	GdkColor c;
Arturo Espinosa's avatar
Arturo Espinosa committed
113 114 115 116

	if (GNOME_CANVAS_ITEM_CLASS (item_bar_parent_class)->realize)
		(*GNOME_CANVAS_ITEM_CLASS (item_bar_parent_class)->realize)(item);

117 118
	item_bar = ITEM_BAR (item);
	window = GTK_WIDGET (item->canvas)->window;
Morten Welinder's avatar
Morten Welinder committed
119

120 121
	/* Configure our gc */
	item_bar->gc = gc = gdk_gc_new (window);
122 123
	gnome_canvas_get_color (item->canvas, "black", &c);
	gdk_gc_set_foreground (item_bar->gc, &c);
124 125 126 127 128 129

	item_bar->normal_cursor = gdk_cursor_new (GDK_ARROW);
	if (item_bar->orientation == GTK_ORIENTATION_VERTICAL)
		item_bar->change_cursor = gdk_cursor_new (GDK_SB_V_DOUBLE_ARROW);
	else
		item_bar->change_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
130

131
	item_bar_fonts_init (item_bar);
132 133 134 135 136 137
}

static void
item_bar_unrealize (GnomeCanvasItem *item)
{
	ItemBar *item_bar = ITEM_BAR (item);
138

139 140 141
	gdk_gc_unref (item_bar->gc);
	gdk_cursor_destroy (item_bar->change_cursor);
	gdk_cursor_destroy (item_bar->normal_cursor);
142
	item_bar_fonts_unref (item_bar);
Arturo Espinosa's avatar
Arturo Espinosa committed
143 144 145

	if (GNOME_CANVAS_ITEM_CLASS (item_bar_parent_class)->unrealize)
		(*GNOME_CANVAS_ITEM_CLASS (item_bar_parent_class)->unrealize)(item);
146 147 148
}

static void
149
item_bar_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
150
{
Arturo Espinosa's avatar
Arturo Espinosa committed
151 152
	if (GNOME_CANVAS_ITEM_CLASS (item_bar_parent_class)->update)
		(*GNOME_CANVAS_ITEM_CLASS (item_bar_parent_class)->update)(item, affine, clip_path, flags);
153

154 155 156 157 158 159 160
	item->x1 = 0;
	item->y1 = 0;
	item->x2 = INT_MAX;
	item->y2 = INT_MAX;
	gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
}

Morten Welinder's avatar
Morten Welinder committed
161
static const char *
162 163
get_row_name (int n)
{
Arturo Espinosa's avatar
Arturo Espinosa committed
164
	static char x [4 * sizeof (int)];
165

Morten Welinder's avatar
Morten Welinder committed
166
	g_assert (n >= 0 && n < SHEET_MAX_ROWS);
167 168

	sprintf (x, "%d", n + 1);
169 170 171 172
	return x;
}

static void
173 174
bar_draw_cell (ItemBar const * const item_bar,
	       GdkDrawable *drawable, ItemBarSelectionType const type,
175
	       char const * const str, GdkRectangle * rect)
176 177
{
	GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (item_bar)->canvas);
178
	GdkFont *font;
179 180 181
	GdkGC *gc;
	int len, texth, shadow;

182 183 184 185 186
	switch (type){
	default:
	case ITEM_BAR_NO_SELECTION:
		shadow = GTK_SHADOW_OUT;
		gc = canvas->style->bg_gc [GTK_STATE_ACTIVE];
187
		font = style_font_gdk_font (item_bar->normal_font);
188
		break;
189

190
	case ITEM_BAR_PARTIAL_SELECTION:
191
		shadow = GTK_SHADOW_OUT;
Jody Goldberg's avatar
Jody Goldberg committed
192
		gc = canvas->style->dark_gc [GTK_STATE_PRELIGHT];
193
		font = style_font_gdk_font (item_bar->bold_font);
194
		break;
195

196 197 198
	case ITEM_BAR_FULL_SELECTION:
		shadow = GTK_SHADOW_IN;
		gc = canvas->style->dark_gc [GTK_STATE_NORMAL];
199
		font = style_font_gdk_font (item_bar->bold_font);
200
		break;
201
	}
202

203 204 205
	len = gdk_string_width (font, str);
	texth = font->ascent + font->descent;

206 207
	gdk_gc_set_clip_rectangle (gc, rect);
	gdk_draw_rectangle (drawable, gc, TRUE, rect->x + 1, rect->y + 1, rect->width-2, rect->height-2);
Morten Welinder's avatar
Morten Welinder committed
208
	gtk_draw_shadow (canvas->style, drawable, GTK_STATE_NORMAL, shadow,
209
			 rect->x, rect->y, rect->width, rect->height);
210
	gdk_draw_string (drawable, font, item_bar->gc,
211
			 rect->x + (rect->width - len) / 2,
212
			 rect->y + (rect->height - texth) / 2 + font->ascent + 1,
213 214 215 216 217 218
			 str);
}

static void
item_bar_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height)
{
219 220
	ItemBar const * const item_bar = ITEM_BAR (item);
	Sheet   const * const sheet = item_bar->sheet_view->sheet;
Jody Goldberg's avatar
Jody Goldberg committed
221
	GnumericSheet const * const gsheet = GNUMERIC_SHEET (item_bar->sheet_view->sheet_view);
222
	GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (item)->canvas);
223
	int pixels;
224
	GdkRectangle rect;
225 226

	if (item_bar->orientation == GTK_ORIENTATION_VERTICAL) {
227 228 229 230 231 232 233 234 235 236 237
		/* Include a 1 pixel buffer.
		 * To avoid overlaping the cells the shared pixel belongs to the cell above.
		 * This has the nice property that the bottom dark line of the
		 * shadow aligns with the grid lines.
		 * Unfortunately it also implies a 1 pixel empty space at the
		 * top of the bar.  Which we are forced to fill in with
		 * something.  For now I draw a black line there to be
		 * compatible with the default colour used on the bottom of the
		 * cell shadows.
		 */
		int total = 1 + gsheet->row_offset.first - y;
238
		int element = gsheet->row.first;
239

240 241 242 243 244 245 246 247 248 249
		rect.x = -x;
		rect.width = canvas->allocation.width;

		/* FIXME : How to avoid hard coding this color ?
		 * We need the color that will be drawn as the bottom bevel
		 * for the button shadow
		 */
		gdk_draw_line (drawable, canvas->style->black_gc,
			       rect.x, total-1,
			       rect.x + rect.width, total-1);
250
		do {
251
			ColRowInfo const *cri;
Jody Goldberg's avatar
Jody Goldberg committed
252
			if (element >= SHEET_MAX_ROWS)
253
				return;
Jody Goldberg's avatar
Jody Goldberg committed
254

255 256 257 258
			cri = sheet_row_get_info (sheet, element);
			pixels = (item_bar->resize_pos != element)
			    ? cri->size_pixels
			    : item_bar->resize_width;
Morten Welinder's avatar
Morten Welinder committed
259

260
			if (cri->visible) {
261 262 263
				total += pixels;
				if (total >= 0) {
					char const * const str = get_row_name (element);
264 265
					rect.y = total - pixels;
					rect.height = pixels;
266 267
					bar_draw_cell (item_bar, drawable,
						       sheet_row_selection_type (sheet, element),
268
						       str, &rect);
269
				}
270
			}
271 272 273
			++element;
		} while (total < height);
	} else {
274 275
		/* See comment above for explaination of the extra 1 pixel */
		int total = 1 + gsheet->col_offset.first - x;
276
		int element = gsheet->col.first;
277 278 279 280 281 282 283 284 285 286 287

		rect.y = -y;
		rect.height = canvas->allocation.height;

		/* FIXME : How to avoid hard coding this color ?
		 * We need the color that will be drawn as the right bevel
		 * for the button shadow
		 */
		gdk_draw_line (drawable, canvas->style->black_gc,
			       total-1, rect.y,
			       total-1, rect.y + rect.height);
288 289

		do {
290
			ColRowInfo const *cri;
Jody Goldberg's avatar
Jody Goldberg committed
291
			if (element >= SHEET_MAX_COLS)
292
				return;
Jody Goldberg's avatar
Jody Goldberg committed
293

294 295 296 297
			cri = sheet_col_get_info (sheet, element);
			pixels = (item_bar->resize_pos != element)
			    ? cri->size_pixels
			    : item_bar->resize_width;
298

299
			if (cri->visible) {
300
				total += pixels;
301 302 303
				if (total >= 0) {
					rect.x = total - pixels;
					rect.width = pixels;
304 305
					bar_draw_cell (item_bar, drawable,
						       sheet_col_selection_type (sheet, element),
306 307
						       col_name (element), &rect);
				}
308
			}
Morten Welinder's avatar
Morten Welinder committed
309

310 311 312
			++element;
		} while (total < width);
	}
313 314 315 316
}

static double
item_bar_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
317
		GnomeCanvasItem **actual_item)
318 319 320 321 322 323 324 325 326 327 328
{
	*actual_item = item;
	return 0.0;
}

static void
item_bar_translate (GnomeCanvasItem *item, double dx, double dy)
{
	printf ("item_bar_translate %g, %g\n", dx, dy);
}

Arturo Espinosa's avatar
Arturo Espinosa committed
329 330
static ColRowInfo *
is_pointer_on_division (ItemBar *item_bar, int pos, int *the_total, int *the_element)
331
{
332
	ColRowInfo *cri;
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
333
	Sheet *sheet;
334
	int i, total;
Morten Welinder's avatar
Morten Welinder committed
335

336
	total = 0;
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
337
	sheet = item_bar->sheet_view->sheet;
Morten Welinder's avatar
Morten Welinder committed
338

339
	for (i = item_bar->first_element; total < pos; i++){
340 341 342
		if (item_bar->orientation == GTK_ORIENTATION_VERTICAL){
			if (i >= SHEET_MAX_ROWS)
				return NULL;
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
343
			cri = sheet_row_get_info (sheet, i);
344 345 346
		} else {
			if (i >= SHEET_MAX_COLS)
				return NULL;
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
347
			cri = sheet_col_get_info (sheet, i);
348
		}
349

350 351
		if (cri->visible) {
			total += cri->size_pixels;
352 353 354 355 356
			if ((total - 4 < pos) && (pos < total + 4)) {
				if (the_total)
					*the_total = total;
				if (the_element)
					*the_element = i;
Arturo Espinosa's avatar
Arturo Espinosa committed
357

358 359
				return cri;
			}
Arturo Espinosa's avatar
Arturo Espinosa committed
360
		}
361

362
		if (total > pos) {
363 364 365 366
			if (the_element)
				*the_element = i;
			return NULL;
		}
367
	}
Arturo Espinosa's avatar
Arturo Espinosa committed
368
	return NULL;
369 370 371 372 373 374 375
}

static void
set_cursor (ItemBar *item_bar, int pos)
{
	GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (item_bar)->canvas);

376 377 378
	/* We might be invoked before we are realized */
	if (!canvas->window)
		return;
Morten Welinder's avatar
Morten Welinder committed
379

Arturo Espinosa's avatar
Arturo Espinosa committed
380
	if (is_pointer_on_division (item_bar, pos, NULL, NULL))
Arturo Espinosa's avatar
Arturo Espinosa committed
381
		gdk_window_set_cursor (canvas->window, item_bar->change_cursor);
382
	else
Arturo Espinosa's avatar
Arturo Espinosa committed
383
		gdk_window_set_cursor (canvas->window, item_bar->normal_cursor);
384 385
}

Jody Goldberg's avatar
Jody Goldberg committed
386 387
static void
item_bar_start_resize (ItemBar *bar)
388
{
Jody Goldberg's avatar
Jody Goldberg committed
389
	Sheet const * const sheet = bar->sheet_view->sheet;
390 391 392 393 394 395 396 397 398
#if 0
	/*
	 * handle the zoom from the item-grid canvas, the resolution scaling is
	 * handled elsewhere
	 */
	double const res  = application_display_dpi_get (bar->orientation ==
							 GTK_ORIENTATION_VERTICAL);
#endif
	double const zoom = sheet->last_zoom_factor_used; /* * res / 72.; */
Jody Goldberg's avatar
Jody Goldberg committed
399 400 401 402 403
	GnumericSheet const * const gsheet = GNUMERIC_SHEET (bar->sheet_view->sheet_view);
	GnomeCanvas const * const canvas = GNOME_CANVAS (gsheet);
	GnomeCanvasGroup * const group = GNOME_CANVAS_GROUP (canvas->root);
	GnomeCanvasPoints * const points =
	    bar->resize_points = gnome_canvas_points_new (2);
404
	GnomeCanvasItem * item =
Jody Goldberg's avatar
Jody Goldberg committed
405 406 407 408 409 410 411
	    gnome_canvas_item_new ( group,
				    gnome_canvas_line_get_type (),
				    "fill_color", "black",
				    "width_pixels", 1,
				    NULL);
	bar->resize_guide = GTK_OBJECT (item);

412 413
	/* NOTE : Set the position of the stationary line here.
	 * Set the guide line later based on the motion coordinates.
Jody Goldberg's avatar
Jody Goldberg committed
414 415
	 */
	if (bar->orientation == GTK_ORIENTATION_VERTICAL) {
416
		double const y =
417
		    sheet_row_get_distance_pixels (sheet, 0, bar->resize_pos) / zoom;
Jody Goldberg's avatar
Jody Goldberg committed
418
		points->coords [0] =
419
		    sheet_col_get_distance_pixels (sheet, 0, gsheet->col.first) / zoom;
420
		points->coords [1] = y;
Jody Goldberg's avatar
Jody Goldberg committed
421
		points->coords [2] =
422
		    sheet_col_get_distance_pixels (sheet, 0, gsheet->col.last_visible+1) / zoom;
423
		points->coords [3] = y;
424
	} else {
425
		double const x =
426
		    sheet_col_get_distance_pixels (sheet, 0, bar->resize_pos) / zoom;
427
		points->coords [0] = x;
Jody Goldberg's avatar
Jody Goldberg committed
428
		points->coords [1] =
429
		    sheet_row_get_distance_pixels (sheet, 0, gsheet->row.first) / zoom;
430
		points->coords [2] = x;
Jody Goldberg's avatar
Jody Goldberg committed
431
		points->coords [3] =
432
		    sheet_row_get_distance_pixels (sheet, 0, gsheet->row.last_visible+1) / zoom;
433
	}
434 435 436 437 438 439 440 441

	item = gnome_canvas_item_new ( group,
				       gnome_canvas_line_get_type (),
				       "points", points,
				       "fill_color", "black",
				       "width_pixels", 1,
				       NULL);
	bar->resize_start = GTK_OBJECT (item);
Arturo Espinosa's avatar
Arturo Espinosa committed
442 443
}

Arturo Espinosa's avatar
Arturo Espinosa committed
444 445 446 447
static int
get_col_from_pos (ItemBar *item_bar, int pos)
{
	ColRowInfo *cri;
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
448
	Sheet *sheet;
449
	int i, total;
Morten Welinder's avatar
Morten Welinder committed
450

Arturo Espinosa's avatar
Arturo Espinosa committed
451
	total = 0;
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
452
	sheet = item_bar->sheet_view->sheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
453
	for (i = item_bar->first_element; total < pos; i++){
454 455 456
		if (item_bar->orientation == GTK_ORIENTATION_VERTICAL){
			if (i >= SHEET_MAX_ROWS)
				return i-1;
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
457
			cri = sheet_row_get_info (sheet, i);
458 459 460
		} else {
			if (i >= SHEET_MAX_COLS)
				return i-1;
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
461
			cri = sheet_col_get_info (sheet, i);
462
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
463

464 465
		if (cri->visible) {
			total += cri->size_pixels;
466 467 468
			if (total > pos)
				return i;
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
469 470 471 472
	}
	return i;
}

473
static void
474
colrow_tip_setlabel (ItemBar *item_bar, gboolean const is_vertical, int size_pixels)
475 476 477
{
	if (item_bar->tip) {
		char buffer [20 + sizeof (long) * 4];
478
		double const scale = 72. / application_display_dpi_get (is_vertical);
479
		if (is_vertical)
480 481
			snprintf (buffer, sizeof (buffer), _("Height: %.2f (%d pixels)"),
				  scale*size_pixels, size_pixels);
482
		else
483 484
			snprintf (buffer, sizeof (buffer), _("Width: %.2f (%d pixels)"),
				  scale*size_pixels, size_pixels);
485 486 487 488 489 490 491
		gtk_label_set_text (GTK_LABEL (item_bar->tip), buffer);
	}
}

static void
item_bar_end_resize (ItemBar *item_bar, int new_size)
{
492 493 494 495 496
	if (new_size > 0)
		gtk_signal_emit (GTK_OBJECT (item_bar),
				 item_bar_signals [SIZE_CHANGED],
				 item_bar->resize_pos,
				 new_size);
497

Jody Goldberg's avatar
Jody Goldberg committed
498 499 500 501
	if (item_bar->resize_points) {
		gnome_canvas_points_free (item_bar->resize_points);
		item_bar->resize_points = NULL;
	}
502
	if (item_bar->resize_guide) {
503 504
		gtk_object_destroy (item_bar->resize_start);
		item_bar->resize_start = NULL;
505 506 507 508 509 510 511
		gtk_object_destroy (item_bar->resize_guide);
		item_bar->resize_guide = NULL;
	}
	if (item_bar->tip) {
		gtk_widget_destroy (gtk_widget_get_toplevel (item_bar->tip));
		item_bar->tip = NULL;
	}
512

513 514 515
	item_bar->resize_pos = -1;
}

516
static gint
517
item_bar_event (GnomeCanvasItem *item, GdkEvent *e)
518
{
Arturo Espinosa's avatar
Arturo Espinosa committed
519
	ColRowInfo *cri;
Jody Goldberg's avatar
Jody Goldberg committed
520 521 522
	GnomeCanvas * const canvas = item->canvas;
	ItemBar * const item_bar = ITEM_BAR (item);
	Sheet   * const sheet = item_bar->sheet_view->sheet;
Arturo Espinosa's avatar
Arturo Espinosa committed
523 524
	const gboolean resizing = ITEM_BAR_RESIZING (item_bar);
	const gboolean is_vertical = (item_bar->orientation == GTK_ORIENTATION_VERTICAL);
525 526 527 528 529
#if 0
	/*
	 * handle the zoom from the item-grid canvas, the resolution scaling is
	 * handled elsewhere
	 */
530
	double const res  = application_display_dpi_get (is_vertical);
531 532
#endif
	double const zoom = sheet->last_zoom_factor_used; /* * res / 72.; */
Jody Goldberg's avatar
Jody Goldberg committed
533
	int pos, start, element;
534

Jody Goldberg's avatar
Jody Goldberg committed
535 536 537 538
	/* NOTE :
	 * No need to map coordinates since we do the zooming of the item bars manually
	 * there is no transform needed.
	 */
539
	switch (e->type){
540
	case GDK_ENTER_NOTIFY:
541
		if (is_vertical)
Jody Goldberg's avatar
Jody Goldberg committed
542
			pos = e->crossing.y;
543
		else
Jody Goldberg's avatar
Jody Goldberg committed
544
			pos = e->crossing.x;
545
		set_cursor (item_bar, pos);
546
		break;
Morten Welinder's avatar
Morten Welinder committed
547

548
	case GDK_MOTION_NOTIFY:
549
		if (is_vertical)
Jody Goldberg's avatar
Jody Goldberg committed
550
			pos = e->motion.y;
551
		else
Jody Goldberg's avatar
Jody Goldberg committed
552
			pos = e->motion.x;
Arturo Espinosa's avatar
Arturo Espinosa committed
553

554
		/* Do col/row resizing or incremental marking */
555
		if (resizing){
556
			GnomeCanvasItem *resize_guide;
Jody Goldberg's avatar
Jody Goldberg committed
557
			GnomeCanvasPoints *points;
Arturo Espinosa's avatar
Arturo Espinosa committed
558 559
			int npos;

Jody Goldberg's avatar
Jody Goldberg committed
560 561
			if (item_bar->resize_guide == NULL) {
				item_bar_start_resize (item_bar);
562 563 564 565 566 567 568
				gnome_canvas_item_grab (item,
							GDK_POINTER_MOTION_MASK |
							GDK_BUTTON_RELEASE_MASK,
							item_bar->change_cursor,
							e->button.time);
			}
			
Arturo Espinosa's avatar
Arturo Espinosa committed
569
			npos = pos - item_bar->resize_start_pos;
Arturo Espinosa's avatar
Arturo Espinosa committed
570 571
			if (npos <= 0)
				break;
572

Arturo Espinosa's avatar
Arturo Espinosa committed
573
			item_bar->resize_width = npos;
574

575
			colrow_tip_setlabel (item_bar, is_vertical, item_bar->resize_width);
576
			resize_guide = GNOME_CANVAS_ITEM (item_bar->resize_guide);
Jody Goldberg's avatar
Jody Goldberg committed
577
			points = item_bar->resize_points;
Morten Welinder's avatar
Morten Welinder committed
578

Jody Goldberg's avatar
Jody Goldberg committed
579 580 581 582
			if (is_vertical)
				points->coords [1] = points->coords [3] = pos / zoom;
			else
				points->coords [0] = points->coords [2] = pos / zoom;
Morten Welinder's avatar
Morten Welinder committed
583

584 585 586 587 588
			gnome_canvas_item_set (resize_guide, "points",  points, NULL);

			/* Redraw the ItemBar to show nice incremental progress */
			gnome_canvas_request_redraw (
				canvas, 0, 0, INT_MAX, INT_MAX);
Morten Welinder's avatar
Morten Welinder committed
589

590
		} else if (ITEM_BAR_IS_SELECTING (item_bar)) {
591
			element = get_col_from_pos (item_bar, pos);
Arturo Espinosa's avatar
Arturo Espinosa committed
592

593 594 595
			gtk_signal_emit (
				GTK_OBJECT (item),
				item_bar_signals [SELECTION_CHANGED],
596
				element, 0);
597

Arturo Espinosa's avatar
Arturo Espinosa committed
598
			set_cursor (item_bar, pos);
599
		} else
600
			set_cursor (item_bar, pos);
601
		break;
602 603

	case GDK_BUTTON_PRESS:
604 605 606 607
		/* Ignore scroll wheel events */
		if (e->button.button > 3)
			return FALSE;

608
		if (is_vertical)
Jody Goldberg's avatar
Jody Goldberg committed
609
			pos = e->button.y;
610
		else
Jody Goldberg's avatar
Jody Goldberg committed
611
			pos = e->button.x;
Arturo Espinosa's avatar
Arturo Espinosa committed
612

613
		cri = is_pointer_on_division (item_bar, pos, &start, &element);
614

615
		if (is_vertical) {
616 617 618 619 620 621
			if (element > SHEET_MAX_ROWS-1)
				break;
		} else {
			if (element > SHEET_MAX_COLS-1)
				break;
		}
Morten Welinder's avatar
Morten Welinder committed
622

623 624 625 626 627 628 629 630 631 632
		if (e->button.button == 3) {
			/* If the selection does not contain the current row/col
			 * then clear the selection and add it.
			 */
			if (!selection_contains_colrow (sheet, element, !is_vertical))
				gtk_signal_emit (GTK_OBJECT (item),
						 item_bar_signals [SELECTION_CHANGED],
						 element, e->button.state | GDK_BUTTON1_MASK);

			if (is_vertical)
633
				item_grid_popup_menu (sheet, e, 0, element, FALSE, TRUE);
634
			else
635
				item_grid_popup_menu (sheet, e, element, 0, TRUE, FALSE);
636
		} else if (cri){
637 638 639 640 641 642 643
			/*
			 * Record the important bits.
			 *
			 * By setting resize_pos to a non -1 value,
			 * we know that we are being resized (used in the
			 * other event handlers).
			 */
644
			item_bar->resize_pos = element;
645 646
			item_bar->resize_start_pos = start - cri->size_pixels;
			item_bar->resize_width = cri->size_pixels;
647 648 649 650 651 652 653

			if (item_bar->tip == NULL) {
				item_bar->tip = gnumeric_create_tooltip ();
				colrow_tip_setlabel (item_bar, is_vertical, item_bar->resize_width);
				gnumeric_position_tooltip (item_bar->tip, !is_vertical);
				gtk_widget_show_all (gtk_widget_get_toplevel (item_bar->tip));
			}
Arturo Espinosa's avatar
Arturo Espinosa committed
654
		} else {
655
			item_bar->start_selection = element;
656 657 658 659 660
			gnome_canvas_item_grab (item,
						GDK_POINTER_MOTION_MASK |
						GDK_BUTTON_RELEASE_MASK,
						item_bar->normal_cursor,
						e->button.time);
Arturo Espinosa's avatar
Arturo Espinosa committed
661 662
			gtk_signal_emit (GTK_OBJECT (item),
					 item_bar_signals [SELECTION_CHANGED],
663
					 element, e->button.state | GDK_BUTTON1_MASK);
Arturo Espinosa's avatar
Arturo Espinosa committed
664
		}
665
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
666

Jody Goldberg's avatar
Jody Goldberg committed
667 668
	case GDK_2BUTTON_PRESS:
	{
669
		Sheet *sheet;
670 671
		int new_size;
		
672 673 674 675
		/* Ignore scroll wheel events */
		if (e->button.button > 3)
			return FALSE;

676 677
		if (!resizing)
			break;
678

679 680
		if (e->button.button == 3)
			break;
681

682
		sheet = item_bar->sheet_view->sheet;
683
		if (is_vertical)
684
			new_size = sheet_row_size_fit_pixels (sheet, item_bar->resize_pos);
685
		else
686
			new_size = sheet_col_size_fit_pixels (sheet, item_bar->resize_pos);
687

Jody Goldberg's avatar
Jody Goldberg committed
688 689 690
		/* autosizing an empty col/row returns 0 */
		if (new_size > 0)
			item_bar_end_resize (item_bar, new_size);
691
		break;
Jody Goldberg's avatar
Jody Goldberg committed
692
	}
693
		
Arturo Espinosa's avatar
Arturo Espinosa committed
694
	case GDK_BUTTON_RELEASE:
695 696
	{
		gboolean needs_ungrab = FALSE;
697

698 699 700 701
		/* Ignore scroll wheel events */
		if (e->button.button > 3)
			return FALSE;

Jody Goldberg's avatar
typo  
Jody Goldberg committed
702
		if (item_bar->start_selection >= 0) {
703 704 705
			needs_ungrab = TRUE;
			item_bar->start_selection = -1;
		}
706
		if (item_bar->resize_pos >= 0) {
707
			needs_ungrab = (item_bar->resize_guide != NULL);
708 709
			item_bar_end_resize (item_bar, item_bar->resize_width);
		}
710 711
		if (needs_ungrab)
			gnome_canvas_item_ungrab (item, e->button.time);
Arturo Espinosa's avatar
Arturo Espinosa committed
712
		break;
713
	}
Morten Welinder's avatar
Morten Welinder committed
714

715 716 717 718 719 720 721 722 723 724 725 726 727
	default:
		return FALSE;
	}
	return TRUE;
}

/*
 * Instance initialization
 */
static void
item_bar_init (ItemBar *item_bar)
{
	GnomeCanvasItem *item = GNOME_CANVAS_ITEM (item_bar);
Morten Welinder's avatar
Morten Welinder committed
728

729 730 731 732
	item->x1 = 0;
	item->y1 = 0;
	item->x2 = 0;
	item->y2 = 0;
Morten Welinder's avatar
Morten Welinder committed
733

734 735
	item_bar->first_element = 0;
	item_bar->orientation = GTK_ORIENTATION_VERTICAL;
Arturo Espinosa's avatar
Arturo Espinosa committed
736
	item_bar->resize_pos = -1;
Arturo Espinosa's avatar
Arturo Espinosa committed
737
	item_bar->start_selection = -1;
738
	item_bar->tip = NULL;
739 740
	item_bar->normal_font = NULL;
	item_bar->bold_font = NULL;
Jody Goldberg's avatar
Jody Goldberg committed
741
	item_bar->resize_guide = NULL;
742
	item_bar->resize_start = NULL;
Jody Goldberg's avatar
Jody Goldberg committed
743
	item_bar->resize_points = NULL;
744 745 746 747 748 749 750 751
}

static void
item_bar_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
{
	GnomeCanvasItem *item;
	ItemBar *item_bar;
	int v;
Morten Welinder's avatar
Morten Welinder committed
752

753 754
	item = GNOME_CANVAS_ITEM (o);
	item_bar = ITEM_BAR (o);
Morten Welinder's avatar
Morten Welinder committed
755

756
	switch (arg_id){
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
757 758
	case ARG_SHEET_VIEW:
		item_bar->sheet_view = GTK_VALUE_POINTER (*arg);
759 760 761 762 763 764 765 766 767 768 769 770
		break;
	case ARG_ORIENTATION:
		item_bar->orientation = GTK_VALUE_INT (*arg);
		break;
	case ARG_FIRST_ELEMENT:
		v = GTK_VALUE_INT (*arg);
		if (item_bar->first_element != v){
			item_bar->first_element = v;
			g_warning ("ARG_FIRST_ELEMENT: do scroll\n");
		}
		break;
	}
771
	item_bar_update (item, NULL, NULL, 0);
772 773 774 775 776 777 778 779 780 781 782
}

/*
 * ItemBar class initialization
 */
static void
item_bar_class_init (ItemBarClass *item_bar_class)
{
	GtkObjectClass  *object_class;
	GnomeCanvasItemClass *item_class;

Arturo Espinosa's avatar
Arturo Espinosa committed
783
	item_bar_parent_class = gtk_type_class (gnome_canvas_item_get_type ());
Morten Welinder's avatar
Morten Welinder committed
784

785 786 787
	object_class = (GtkObjectClass *) item_bar_class;
	item_class = (GnomeCanvasItemClass *) item_bar_class;

Morten Welinder's avatar
Morten Welinder committed
788
	gtk_object_add_arg_type ("ItemBar::SheetView", GTK_TYPE_POINTER,
Arturo Espinosa's avatar
Today:  
Arturo Espinosa committed
789
				 GTK_ARG_WRITABLE, ARG_SHEET_VIEW);
Morten Welinder's avatar
Morten Welinder committed
790
	gtk_object_add_arg_type ("ItemBar::Orientation", GTK_TYPE_INT,
791
				 GTK_ARG_WRITABLE, ARG_ORIENTATION);
Arturo Espinosa's avatar
Arturo Espinosa committed
792 793 794 795 796 797

	item_bar_signals [SELECTION_CHANGED] =
		gtk_signal_new ("selection_changed",
				GTK_RUN_LAST,
				object_class->type,
				GTK_SIGNAL_OFFSET (ItemBarClass, selection_changed),
Arturo Espinosa's avatar
Arturo Espinosa committed
798
				item_bar_marshal,
Arturo Espinosa's avatar
Arturo Espinosa committed
799
				GTK_TYPE_NONE,
Arturo Espinosa's avatar
Arturo Espinosa committed
800 801
				2,
				GTK_TYPE_INT, GTK_TYPE_INT);
Arturo Espinosa's avatar
Arturo Espinosa committed
802 803 804 805 806
	item_bar_signals [SIZE_CHANGED] =
		gtk_signal_new ("size_changed",
				GTK_RUN_LAST,
				object_class->type,
				GTK_SIGNAL_OFFSET (ItemBarClass, size_changed),
Arturo Espinosa's avatar
Arturo Espinosa committed
807
				item_bar_marshal,
Arturo Espinosa's avatar
Arturo Espinosa committed
808 809 810 811 812 813 814 815
				GTK_TYPE_NONE,
				2,
				GTK_TYPE_INT,
				GTK_TYPE_INT);

	/* Register our signals */
	gtk_object_class_add_signals (object_class, item_bar_signals,
				      LAST_SIGNAL);
Morten Welinder's avatar
Morten Welinder committed
816

Arturo Espinosa's avatar
Arturo Espinosa committed
817
	/* Method overrides */
818
	object_class->destroy = item_bar_destroy;
819 820 821
	object_class->set_arg = item_bar_set_arg;

	/* GnomeCanvasItem method overrides */
822
	item_class->update      = item_bar_update;
823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
	item_class->realize     = item_bar_realize;
	item_class->unrealize   = item_bar_unrealize;
	item_class->draw        = item_bar_draw;
	item_class->point       = item_bar_point;
	item_class->translate   = item_bar_translate;
	item_class->event       = item_bar_event;
}

GtkType
item_bar_get_type (void)
{
	static GtkType item_bar_type = 0;

	if (!item_bar_type) {
		GtkTypeInfo item_bar_info = {
			"ItemBar",
			sizeof (ItemBar),
			sizeof (ItemBarClass),
			(GtkClassInitFunc) item_bar_class_init,
			(GtkObjectInitFunc) item_bar_init,
			NULL, /* reserved_1 */
			NULL, /* reserved_2 */
			(GtkClassInitFunc) NULL
		};

		item_bar_type = gtk_type_unique (gnome_canvas_item_get_type (), &item_bar_info);
	}

	return item_bar_type;
}
Arturo Espinosa's avatar
Arturo Espinosa committed
853 854 855 856 857 858


/*
 * Marshaling routines for our signals
 */
static void
Arturo Espinosa's avatar
Arturo Espinosa committed
859 860 861 862
item_bar_marshal (GtkObject     *object,
		  GtkSignalFunc func,
		  gpointer      func_data,
		  GtkArg        *args)
Arturo Espinosa's avatar
Arturo Espinosa committed
863 864
{
	ItemBarSignal2 rfunc;
Morten Welinder's avatar
Morten Welinder committed
865

Arturo Espinosa's avatar
Arturo Espinosa committed
866 867 868 869 870 871 872
	rfunc = (ItemBarSignal2) func;
	(*rfunc) (object,
		  GTK_VALUE_INT (args [0]),
		  GTK_VALUE_INT (args [1]),
		  func_data);
}