Beispiel #1
0
/**
 * position within the sheet in pixel coordinates
 *
 * coordinates are clamped to grid if grid is enabled
 * see snap_to_grid
 * zero point : top left corner of the window (not widget!)
 *
 * @param x horizontal, left to right
 * @param y vertical, top to bottom
 * @returns wether the position could be detected properly
 *
 * @attention never call in event handlers!
 */
gboolean sheet_get_pointer_pixel (Sheet *sheet, gdouble *x, gdouble *y)
{
	GtkAdjustment *hadj = NULL, *vadj = NULL;
	gdouble x1, y1;
	gint _x, _y;
	GdkDeviceManager *device_manager;
	GdkDevice *device_pointer;
	GdkRectangle allocation;
	GdkDisplay *display;
	GdkWindow *window;

	// deprecated gtk_widget_get_pointer (GTK_WIDGET (sheet), &_x, &_y);
	// replaced by a code copied from evince

	if (G_UNLIKELY (!sheet || !gtk_widget_get_realized (GTK_WIDGET (sheet)))) {
		NG_DEBUG ("Widget is not realized.");
		return FALSE;
	}

	display = gtk_widget_get_display (GTK_WIDGET (sheet));
	device_manager = gdk_display_get_device_manager (display);
	// gdk_device_manager_get_client_pointer
	// shall not be used within events
	device_pointer = gdk_device_manager_get_client_pointer (device_manager);
	window = gtk_widget_get_window (GTK_WIDGET (sheet));

	if (!window) {
		NG_DEBUG ("Window is not realized.");
		return FALSE;
	}
	// even though above is all defined the below will always return NUL for
	// unknown reason and _x and _y are populated as expected
	gdk_window_get_device_position (window, device_pointer, &_x, &_y, NULL);
#if 0
	if (!window) { //fails always
		NG_DEBUG ("Window does not seem to be realized yet?");
		return FALSE;
	}
#else
	NG_DEBUG ("\n%p %p %p %p %i %i\n\n", display, device_manager, device_pointer, window, _x, _y);
#endif

	gtk_widget_get_allocation (GTK_WIDGET (sheet), &allocation);

	_x -= allocation.x;
	_y -= allocation.y;

	x1 = (gdouble)_x;
	y1 = (gdouble)_y;

	if (!sheet_get_adjustments (sheet, &hadj, &vadj))
		return FALSE;

	x1 += gtk_adjustment_get_value (hadj);
	y1 += gtk_adjustment_get_value (vadj);

	*x = x1;
	*y = y1;
	return TRUE;
}
Beispiel #2
0
/*
 * position within the sheet in pixel coordinates
 * coordinates are clamped to grid if grid is enabled
 * see snap_to_grid
 * zero point : top left corner of the window (not widget!)
 * x : horizontal, left to right
 * y : vertical, top to bottom
 * returns wether the position could be detected properly
 */
gboolean
sheet_get_pointer_pixel (Sheet *sheet, gdouble *x, gdouble *y)
{
	GtkAdjustment *hadj, *vadj;
	gdouble x1, y1;
	gint _x, _y;
	GdkDeviceManager *device_manager;
	GdkDevice *device_pointer;
	GdkRectangle allocation;


	// deprecated gtk_widget_get_pointer (GTK_WIDGET (sheet), &_x, &_y);
	// replaced by a code copied from evince

	if (G_UNLIKELY (!sheet || !gtk_widget_get_realized (GTK_WIDGET (sheet)))) {
		NG_DEBUG ("widget not realized");
		return FALSE;
	}

	device_manager = gdk_display_get_device_manager (
			gtk_widget_get_display (GTK_WIDGET (sheet)));
	device_pointer = gdk_device_manager_get_client_pointer (device_manager);
	//FIXME add another check based on the following functions return val
	//FIXME gtkdoc says this shall not be used in event handlers
	gdk_window_get_device_position (gtk_widget_get_window (GTK_WIDGET (sheet)),
					device_pointer,
					&_x, &_y, NULL);

	if (!gtk_widget_get_has_window (GTK_WIDGET (sheet))) {
		NG_DEBUG ("some weird gtk window shit failed");
		return FALSE;
	}
	
	gtk_widget_get_allocation (GTK_WIDGET (sheet), &allocation);

	_x -= allocation.x;
	_y -= allocation.y;

	x1 = (gdouble) _x;
	y1 = (gdouble) _y;

	if (!sheet_get_adjustments (sheet, &hadj, &vadj))
	      return FALSE;

	x1 += gtk_adjustment_get_value (hadj);
	y1 += gtk_adjustment_get_value (vadj);

	*x = x1;
	*y = y1;
	return TRUE;
}
Beispiel #3
0
/*
 * scroll to <dx,dy> in pixels relative to the current coords
 * note that pixels are _not_ affected by zoom
 */
void
sheet_scroll_pixel (const Sheet *sheet, int delta_x, int delta_y)
{
	GtkAdjustment *hadj, *vadj;
	GtkAllocation allocation;
	gfloat vnew, hnew;
	gfloat hmax, vmax;
	gfloat x1, y1;
	const SheetPriv *priv = sheet->priv;

	if (sheet_get_adjustments (sheet, &hadj, &vadj)) {
		x1 = gtk_adjustment_get_value (hadj);
		y1 = gtk_adjustment_get_value (vadj);
	} else {
		x1 = y1 = 0.f;
	}

	gtk_widget_get_allocation (GTK_WIDGET (sheet), &allocation);

	if (priv->width > allocation.width)
		hmax = (gfloat) (priv->width - allocation.width);
	else
		hmax = 0.f;

	if (priv->height > allocation.height)
		vmax = (gfloat) (priv->height -  allocation.height);
	else
		vmax = 0.f;

	hnew = CLAMP (x1 + (gfloat) delta_x, 0.f, hmax);
	vnew = CLAMP (y1 + (gfloat) delta_y, 0.f, vmax);

	if (hnew != x1) {
		gtk_adjustment_set_value (hadj, hnew);
		g_signal_emit_by_name (G_OBJECT (hadj), "value_changed");
	}
	if (vnew != y1) {
		gtk_adjustment_set_value (vadj, vnew);
		g_signal_emit_by_name (G_OBJECT (vadj), "value_changed");
	}
}
Beispiel #4
0
/*
 * change the zoom by factor <rate>
 * zoom origin when zooming in is the cursor
 * zoom origin when zooming out is the center of the current viewport
 * sane <rate> values are in range of [0.5 .. 2]
 */
void
sheet_change_zoom (Sheet *sheet, gdouble rate)
{
	g_return_if_fail (sheet);
	g_return_if_fail (IS_SHEET (sheet));
//////////////////////////////////////////////7

	gdouble x, y;
	gdouble rx, ry;
	gdouble px, py;
	gdouble dx, dy;
	gdouble cx, cy;
	gdouble dcx, dcy;
	GtkAdjustment *hadj, *vadj;
	GooCanvas *canvas;

	canvas = GOO_CANVAS (sheet);

	// if we scroll out, just scroll to the center
	if (rate < 1.) {
		goo_canvas_set_scale (canvas, rate * goo_canvas_get_scale (canvas));
		return;
	}

	// top left corner in pixels
	if (sheet_get_adjustments (sheet, &hadj, &vadj)) {
		x = gtk_adjustment_get_value (hadj);
		y = gtk_adjustment_get_value (vadj);
	} else {
		x = y = 0.;
	}

	// get pointer position in pixels
	sheet_get_pointer_pixel (sheet, &px, &py);

	// get the page size in pixels
	dx = gtk_adjustment_get_page_size (hadj);
	dy = gtk_adjustment_get_page_size (vadj);
	// calculate the center of the widget in pixels
	cx = x + dx/2;
	cy = y + dy/2;
	
	// calculate the delta between the center and the pointer in pixels
	// this is required as the center is the zoom target
	dcx = px - cx;
	dcy = py - cy;

	// increase the top left position in pixels by our calculated delta
	x += dcx;
	y += dcy;

	//convert to canvas coords
	goo_canvas_convert_from_pixels (canvas, &x, &y);

	//the center of the canvas is now our cursor position
	goo_canvas_scroll_to (canvas, x, y);

	//calculate a correction term
	//for the case that we can not scroll the pane far enough to
	//compensate the whole off-due-to-wrong-center-error
	rx = gtk_adjustment_get_value (hadj);
	ry = gtk_adjustment_get_value (vadj);
	goo_canvas_convert_from_pixels (canvas, &rx, &ry);
	//the correction term in goo coordinates, to be subtracted from the backscroll distance
	rx -= x;
	ry -= y;

	// no the center is our cursor position and we can safely call scale
	goo_canvas_set_scale (canvas, rate * goo_canvas_get_scale (canvas));

	// top left corner in pixels after scaling
	if (sheet_get_adjustments (sheet, &hadj, &vadj)) {
		x = gtk_adjustment_get_value (hadj);
		y = gtk_adjustment_get_value (vadj);
	} else {
		x = y = 0.;
	}
	// not sure if the below part is required, could be zer0
	NG_DEBUG ("rx %lf\n", rx);
	NG_DEBUG ("ry %lf\n", ry);
	NG_DEBUG ("dcx %lf\n", dcx);
	NG_DEBUG ("dcy %lf\n", dcy);
	NG_DEBUG ("\n\n");
	// gtk_adjustment_get_page_size is constant
	x -= (dcx) / sheet->priv->zoom;
	y -= (dcy) / sheet->priv->zoom;
	goo_canvas_convert_from_pixels (canvas, &x, &y);

	goo_canvas_scroll_to (canvas, x-rx, y-ry);

	gtk_widget_queue_draw (GTK_WIDGET (canvas));
}
Beispiel #5
0
/**
 * change the zoom by factor
 *
 * zoom origin when zooming in is the cursor
 * zoom origin when zooming out is the center of the current viewport
 *
 * @param sheet
 * @param factor values should be in the range of [0.5 .. 2]
 */
void
sheet_change_zoom (Sheet *sheet, gdouble factor)
{
	g_return_if_fail (sheet);
	g_return_if_fail (IS_SHEET (sheet));

	Coords adju, r, pointer, delta, center, pagesize;
	GtkAdjustment *hadj = NULL, *vadj = NULL;
	GooCanvas *canvas;
	gboolean b = FALSE;

	canvas = GOO_CANVAS (sheet);

	// if we scroll out, just use the center as focus
	// mouse curser centered scroll out "feels" awkward
	if (factor < 1.) {
		goo_canvas_set_scale (canvas, factor * goo_canvas_get_scale (canvas));
		return;
	}

	// get pointer position in pixels
	// just skip the correction if we can not get the pointer
	if (!sheet_get_pointer_pixel (sheet, &pointer.x, &pointer.y)) {
		goo_canvas_set_scale (canvas, factor * goo_canvas_get_scale (canvas));
		g_warning ("Failed to get cursor position.");
		return;
	}

	// top left corner in pixels
	b = sheet_get_adjustments (sheet, &hadj, &vadj);
	if (b) {
		adju.x = gtk_adjustment_get_value (hadj);
		adju.y = gtk_adjustment_get_value (vadj);
		// get the page size in pixels
		pagesize.x = gtk_adjustment_get_page_size (hadj);
		pagesize.y = gtk_adjustment_get_page_size (vadj);
	} else {
		//FIXME untested codepath, check for variable space conversion
		//FIXME Pixel vs GooUnits
		gdouble left, right, top, bottom;
		goo_canvas_get_bounds (canvas, &left, &top, &right, &bottom);
		pagesize.x = bottom - top;
		pagesize.y = right - left;
		adju.x = adju.y = 0.;
	}

	// calculate the center of the widget in pixels
	center.x = adju.x + pagesize.x/2.;
	center.y = adju.y + pagesize.y/2.;

	// calculate the delta between the center and the pointer in pixels
	// this is required as the center is the zoom target
	delta.x = pointer.x - center.x;
	delta.y = pointer.y - center.y;

	// increase the top left position in pixels by our calculated delta
	adju.x += delta.x;
	adju.y += delta.y;

	//convert to canvas coords
	goo_canvas_convert_from_pixels (canvas, &adju.x, &adju.y);

	//the center of the canvas is now our cursor position
	goo_canvas_scroll_to (canvas, adju.x, adju.y);

	//calculate a correction term
	//for the case that we can not scroll the pane far enough to
	//compensate the whole off-due-to-wrong-center-error

	if (b) {
		r.x = gtk_adjustment_get_value (hadj);
		r.y = gtk_adjustment_get_value (vadj);
		goo_canvas_convert_from_pixels (canvas, &r.x, &r.y);
		//the correction term in goo coordinates, to be subtracted from the backscroll distance
		r.x -= adju.x;
		r.y -= adju.y;
	} else {
		r.x = r.y = 0.;
	}

	// no the center is our cursor position and we can safely call scale
	goo_canvas_set_scale (canvas, factor * goo_canvas_get_scale (canvas));

	// top left corner in pixels after scaling
	if (b) {
		adju.x = gtk_adjustment_get_value (hadj);
		adju.y = gtk_adjustment_get_value (vadj);
	} else {
		adju.x = adju.y = 0.;
	}

	// gtk_adjustment_get_page_size is constant before and after scale
	adju.x -= (delta.x) / sheet->priv->zoom;
	adju.y -= (delta.y) / sheet->priv->zoom;
	goo_canvas_convert_from_pixels (canvas, &adju.x, &adju.y);

	goo_canvas_scroll_to (canvas, adju.x-r.x, adju.y-r.y);

	gtk_widget_queue_draw (GTK_WIDGET (canvas));
}