Commit 4629294c authored by Colomban Wendling's avatar Colomban Wendling
Browse files

Implement zoom in OVCCGtkBoard.

parent 660ac22c
......@@ -43,6 +43,8 @@ struct _OVCCGtkBoardPrivate
GdkGC *gc;
OVCCPosition cursor_pos;
gdouble zoom;
};
enum
......@@ -50,7 +52,8 @@ enum
PROP_0,
PROP_BOARD,
PROP_CURSOR_POSITION,
PROP_MARGIN
PROP_MARGIN,
PROP_ZOOM
};
enum
......@@ -77,6 +80,8 @@ static gboolean ovccgtk_board_expose (GtkWidget *self,
GdkEventExpose *event);
static gboolean ovccgtk_board_button_release (GtkWidget *widget,
GdkEventButton *event);
static gboolean ovccgtk_board_scroll (GtkWidget *widget,
GdkEventScroll *event);
static gboolean ovccgtk_board_key_press (GtkWidget *widget,
GdkEventKey *event);
static void ovccgtk_board_set_scroll_adjustments (OVCCGtkBoard *board,
......@@ -98,6 +103,7 @@ static void ovccgtk_board_class_init (OVCCGtkBoardClass *klass)
widget_class->size_request = ovccgtk_board_size_request;
widget_class->expose_event = ovccgtk_board_expose;
widget_class->button_release_event = ovccgtk_board_button_release;
widget_class->scroll_event = ovccgtk_board_scroll;
widget_class->key_press_event = ovccgtk_board_key_press;
klass->add_tile = NULL;
klass->set_scroll_adjustments = ovccgtk_board_set_scroll_adjustments;
......@@ -140,6 +146,18 @@ static void ovccgtk_board_class_init (OVCCGtkBoardClass *klass)
G_PARAM_READWRITE
)
);
g_object_class_install_property (
object_class, PROP_ZOOM,
g_param_spec_double (
"zoom",
"Zoom",
"The zoom factor",
0.0,
8.0 /* arbitrary maximum zoom (800%) */,
1.0,
G_PARAM_READWRITE
)
);
/**
* OVCCGtkBoard::add-tile:
......@@ -183,6 +201,7 @@ static void ovccgtk_board_init (OVCCGtkBoard *self)
self->priv->gc = NULL;
self->priv->cursor_pos.x = 0;
self->priv->cursor_pos.y = 0;
self->priv->zoom = 1.0;
}
static void
......@@ -227,6 +246,9 @@ ovccgtk_board_set_property (GObject *object,
case PROP_MARGIN:
ovccgtk_board_set_margin (board, g_value_get_int (value));
break;
case PROP_ZOOM:
ovccgtk_board_set_zoom (board, g_value_get_double (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......@@ -253,6 +275,9 @@ ovccgtk_board_get_property (GObject *object,
case PROP_MARGIN:
g_value_set_int (value, ovccgtk_board_get_margin (board));
break;
case PROP_ZOOM:
g_value_set_double (value, ovccgtk_board_get_zoom (board));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......@@ -298,8 +323,8 @@ ovccgtk_board_size_request (GtkWidget *widget,
ovcc_board_get_bounds (self->priv->board, NULL, NULL, NULL, NULL,
&requisition->width, &requisition->height);
g_debug ("req (board size): [%u,%u]", requisition->width, requisition->height);
requisition->width *= TILE_SIZE + 1;
requisition->height *= TILE_SIZE + 1;
requisition->width *= ((gint)(TILE_SIZE * self->priv->zoom)) + 1;
requisition->height *= ((gint)(TILE_SIZE * self->priv->zoom)) + 1;
/* add margins */
requisition->width += 2 * self->priv->margin;
requisition->height += 2 * self->priv->margin;
......@@ -318,19 +343,21 @@ draw_tile_cb (OVCCBoard *board,
gint dest_x,
dest_y;
gint rotation;
pix = tile_get_pixbuf (tile);
ovccgtk_board_board_to_widget_coords (self, pos->x, pos->y, &dest_x, &dest_y);
gdk_draw_pixbuf (window, self->priv->gc, pix, 0, 0, dest_x, dest_y,
TILE_SIZE, TILE_SIZE, GDK_RGB_DITHER_NORMAL, 0, 0);
g_object_unref (pix);
if (pos->x == 0 && pos->y == 0) {
gdk_draw_arc (window, self->priv->gc,
FALSE,
dest_x + TILE_SIZE / 4,
dest_y + TILE_SIZE / 4,
(TILE_SIZE / 2), (TILE_SIZE / 2),
0, 64 * 360);
gint size = (gint)(TILE_SIZE * self->priv->zoom);
if (size > 0) {
ovccgtk_board_board_to_widget_coords (self, pos->x, pos->y, &dest_x, &dest_y);
pix = tile_get_pixbuf (tile, size);
gdk_draw_pixbuf (window, self->priv->gc, pix, 0, 0, dest_x, dest_y,
size, size, GDK_RGB_DITHER_NORMAL, 0, 0);
g_object_unref (pix);
if (pos->x == 0 && pos->y == 0) {
gdk_draw_arc (window, self->priv->gc,
FALSE,
dest_x + size / 4, dest_y + size / 4,
size / 2, size / 2,
0, 64 * 360);
}
}
return TRUE;
......@@ -341,13 +368,13 @@ paint_cursor (OVCCGtkBoard *self)
{
GtkWidget *widget = GTK_WIDGET (self);
gint dest_x, dest_y;
gint size = (gint)(TILE_SIZE * self->priv->zoom);
ovccgtk_board_board_to_widget_coords (self, self->priv->cursor_pos.x,
self->priv->cursor_pos.y,
&dest_x, &dest_y);
gdk_draw_rectangle (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
FALSE,
dest_x - 1, dest_y - 1, TILE_SIZE + 1, TILE_SIZE + 1);
FALSE, dest_x - 1, dest_y - 1, size + 1, size + 1);
}
static gboolean
......@@ -394,6 +421,33 @@ ovccgtk_board_button_release (GtkWidget *widget,
return stop;
}
static gboolean
ovccgtk_board_scroll (GtkWidget *widget,
GdkEventScroll *event)
{
gboolean stop = FALSE;
OVCCGtkBoard *self = (OVCCGtkBoard *)widget;
guint mods = event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK);
if (mods == GDK_CONTROL_MASK) {
stop = TRUE;
switch (event->direction) {
case GDK_SCROLL_DOWN:
ovccgtk_board_set_zoom (self, self->priv->zoom / 2.0);
break;
case GDK_SCROLL_UP:
ovccgtk_board_set_zoom (self, self->priv->zoom * 2.0);
break;
default:
stop = FALSE;
}
}
return stop;
}
static gboolean
ovccgtk_board_key_press (GtkWidget *widget,
GdkEventKey *event)
......@@ -475,7 +529,7 @@ ovccgtk_board_widget_to_board_coords (OVCCGtkBoard *self,
GtkWidget *widget = GTK_WIDGET (self);
gint margin_left, margin_right;
gint base_x, base_y;
const gdouble coeff = (gdouble)(TILE_SIZE + 1);
const gdouble coeff = floor (TILE_SIZE * self->priv->zoom) + 1;
ovcc_board_get_bounds (self->priv->board,
&base_x, &base_y, NULL, NULL, NULL, NULL);
......@@ -510,7 +564,7 @@ ovccgtk_board_board_to_widget_coords (OVCCGtkBoard *self,
GtkWidget *widget = GTK_WIDGET (self);
gint margin_left, margin_right;
gint base_x, base_y;
const gdouble coeff = (gdouble)(TILE_SIZE + 1);
const gdouble coeff = floor (TILE_SIZE * self->priv->zoom) + 1;
ovcc_board_get_bounds (self->priv->board,
&base_x, &base_y, NULL, NULL, NULL, NULL);
......@@ -636,3 +690,23 @@ ovccgtk_board_get_cursor (const OVCCGtkBoard *self)
return &self->priv->cursor_pos;
}
gdouble
ovccgtk_board_get_zoom (const OVCCGtkBoard *self)
{
g_return_val_if_fail (OVCCGTK_IS_BOARD (self), 1.0);
return self->priv->zoom;
}
void
ovccgtk_board_set_zoom (const OVCCGtkBoard *self,
gdouble zoom)
{
g_return_if_fail (OVCCGTK_IS_BOARD (self));
g_return_if_fail (zoom < 8.0);
self->priv->zoom = zoom;
g_object_notify (G_OBJECT (self), "zoom");
gtk_widget_queue_resize (GTK_WIDGET (self));
}
......@@ -80,6 +80,9 @@ gint ovccgtk_board_get_margin (OVCCGtkBoard *self);
gboolean ovccgtk_board_move_cursor (OVCCGtkBoard *self,
const OVCCPosition *pos);
const OVCCPosition *ovccgtk_board_get_cursor (const OVCCGtkBoard *self);
gdouble ovccgtk_board_get_zoom (const OVCCGtkBoard *self);
void ovccgtk_board_set_zoom (const OVCCGtkBoard *self,
gdouble zoom);
G_END_DECLS
......
......@@ -209,7 +209,7 @@ update_tile_image (App *app)
if (tile) {
GdkPixbuf *pix;
pix = tile_get_pixbuf (tile);
pix = tile_get_pixbuf (tile, -1);
gtk_image_set_from_pixbuf (GTK_IMAGE (app->current_tile_image), pix);
g_object_unref (pix);
g_object_unref (tile);
......
......@@ -145,17 +145,14 @@ load_tile (OVCCTileID id)
}
static GdkPixbuf *
tile_get_procedural (const OVCCTile *tile)
tile_get_procedural (const OVCCTile *tile,
gint size)
{
GdkColormap *colormap;
GdkPixbuf *pixbuf;
GdkPixmap *pixmap;
OVCCTileSide *side;
GdkPoint points[3] = {
{0,0},
{0,0},
{TILE_SIZE / 2,TILE_SIZE / 2}
};
GdkPoint points[3];
GdkGC *gc;
GdkColor city = { 0, 52428, 0, 0 };
GdkColor field = { 0, 29555, 53970, 5654 };
......@@ -165,13 +162,11 @@ tile_get_procedural (const OVCCTile *tile)
gint i = 0;
colormap = gdk_colormap_get_system ();
pixmap = gdk_pixmap_new (NULL, TILE_SIZE, TILE_SIZE,
pixmap = gdk_pixmap_new (NULL, size, size,
gdk_colormap_get_visual (colormap)->depth);
gc = gdk_gc_new (GDK_DRAWABLE (pixmap));
/*gdk_gc_set_line_attributes (gc, 3, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);*/
#define SIZE TILE_SIZE
for (i = 0; i < OVCC_TILE_SIDE_NUM; i++) {
side = ovcc_tile_get_side (tile, i);
switch (i) {
......@@ -179,33 +174,33 @@ tile_get_procedural (const OVCCTile *tile)
points[0].x = 0;
points[0].y = 0;
points[1].x = 0;
points[1].y = SIZE;
points[2].x = SIZE / 2;
points[2].y = SIZE / 2;
points[1].y = size;
points[2].x = size / 2;
points[2].y = size / 2;
break;
case OVCC_TILE_SIDE_POS_TOP:
points[0].x = 0;
points[0].y = 0;
points[1].x = SIZE;
points[1].x = size;
points[1].y = 0;
points[2].x = SIZE / 2;
points[2].y = SIZE / 2;
points[2].x = size / 2;
points[2].y = size / 2;
break;
case OVCC_TILE_SIDE_POS_RIGHT:
points[0].x = SIZE;
points[0].x = size;
points[0].y = 0;
points[1].x = SIZE;
points[1].y = SIZE;
points[2].x = SIZE / 2;
points[2].y = SIZE / 2;
points[1].x = size;
points[1].y = size;
points[2].x = size / 2;
points[2].y = size / 2;
break;
case OVCC_TILE_SIDE_POS_BOTTOM:
points[0].x = 0;
points[0].y = SIZE;
points[1].x = SIZE;
points[1].y = SIZE;
points[2].x = SIZE / 2;
points[2].y = SIZE / 2;
points[0].y = size;
points[1].x = size;
points[1].y = size;
points[2].x = size / 2;
points[2].y = size / 2;
break;
}
switch (ovcc_tile_side_get_content_type (side)) {
......@@ -220,11 +215,11 @@ tile_get_procedural (const OVCCTile *tile)
if (ovcc_tile_get_center_type (tile) == OVCC_TILE_CONTENT_TYPE_MONASTERY) {
gdk_gc_set_rgb_fg_color (gc, &monastery);
gdk_draw_arc (GDK_DRAWABLE (pixmap), gc, TRUE,
SIZE / 3, SIZE / 3, SIZE / 3, SIZE / 3, 0, 64 * 360);
size / 3, size / 3, size / 3, size / 3, 0, 64 * 360);
}
pixbuf = gdk_pixbuf_get_from_drawable (NULL, GDK_DRAWABLE (pixmap), colormap,
0, 0, 0, 0, TILE_SIZE, TILE_SIZE);
0, 0, 0, 0, size, size);
g_object_unref (pixmap);
return pixbuf;
......@@ -234,6 +229,7 @@ tile_get_procedural (const OVCCTile *tile)
/**
* tile_get_pixbuf_by_id:
* @id: An #OVCCTileID
* @size: the size of the tile to get. If <= 0, get the default size.
*
* Gets a graphical representation of a tile from its ID.
* See tile_get_pixbuf() too.
......@@ -242,7 +238,8 @@ tile_get_procedural (const OVCCTile *tile)
* pixbuf when no longer needed.
*/
GdkPixbuf *
tile_get_pixbuf_by_id (OVCCTileID id)
tile_get_pixbuf_by_id (OVCCTileID id,
gint size)
{
GdkPixbuf *pixbuf;
......@@ -251,13 +248,20 @@ tile_get_pixbuf_by_id (OVCCTileID id)
if (! pixbuf) {
pixbuf = load_tile (id);
}
if (size > 0 && gdk_pixbuf_get_width (pixbuf) != size) {
/* TODO: cache other sizes? */
pixbuf = gdk_pixbuf_scale_simple (pixbuf, size, size, GDK_INTERP_BILINEAR);
} else {
g_object_ref (pixbuf);
}
return g_object_ref (pixbuf);
return pixbuf;
}
/**
* tile_get_pixbuf:
* @tile: An #OVCCTile
* @size: see tile_get_pixbuf_by_id()
*
* Gets a graphical representation of a tile.
* It gets the image, as tile_get_pixbuf_by_id() does, but rotates it if needed
......@@ -267,15 +271,16 @@ tile_get_pixbuf_by_id (OVCCTileID id)
* when no longer needed.
*/
GdkPixbuf *
tile_get_pixbuf (OVCCTile *tile)
tile_get_pixbuf (OVCCTile *tile,
gint size)
{
GdkPixbuf *pix;
gint rotation = ovcc_tile_get_rotation (tile);
#if 0
pix = tile_get_procedural (tile);
pix = tile_get_procedural (tile, size > 0 ? size : TILE_SIZE);
#else
pix = tile_get_pixbuf_by_id (ovcc_tile_get_id (tile));
pix = tile_get_pixbuf_by_id (ovcc_tile_get_id (tile), size);
if (rotation > 0) {
GdkPixbuf *new;
......@@ -291,5 +296,5 @@ tile_get_pixbuf (OVCCTile *tile)
gboolean
tile_exists (OVCCTileID id)
{
return tile_get_pixbuf_by_id (id) != NULL;
return tile_get_pixbuf_by_id (id, -1) != NULL;
}
......@@ -29,8 +29,10 @@ G_BEGIN_DECLS
#define TILE_SIZE 64
GdkPixbuf *tile_get_pixbuf_by_id (OVCCTileID id);
GdkPixbuf *tile_get_pixbuf (OVCCTile *tile);
GdkPixbuf *tile_get_pixbuf_by_id (OVCCTileID id,
gint size);
GdkPixbuf *tile_get_pixbuf (OVCCTile *tile,
gint size);
gboolean tile_exists (OVCCTileID id);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment