Better cut cursors and better chosen hot spots.
[gliv.git] / src / zoom_frame.c
blob0e220c0a437000af74dbb5942f842f3e8d885c1b
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <guichaz@yahoo.fr>
21 /************************************
22 * The zoom frame with funky colors *
23 ************************************/
25 #include <gtk/gtkgl.h>
27 #include "gliv.h"
28 #include "zoom_frame.h"
29 #include "options.h"
30 #include "rendering.h"
31 #include "matrix.h"
33 extern rt_struct *rt;
34 extern GtkWidget *gl_widget;
36 /* Dimensions of the zoom frame. */
37 static gint zoom_frame_x, zoom_frame_y;
38 static gint zoom_frame_width, zoom_frame_height;
40 static gboolean zoom_frame_cleared = FALSE;
42 #define TARGET_SIZE 10
44 /* This the box with the cross and the circle in it. */
45 static void draw_zoom_box(GdkDrawable * d, GdkGC * gc,
46 gint x, gint y, gint w, gint h, gboolean clear)
48 static gint target = 0;
50 gdk_draw_rectangle(d, gc, FALSE, x, y, w, h);
52 if (w > TARGET_SIZE * 2 && h > TARGET_SIZE * 2) {
53 gint x_middle = x + w / 2;
54 gint y_middle = y + h / 2;
56 /* If we are clearing, we must reuse the same parameters. */
57 if (clear == FALSE) {
58 target += 320;
59 if (target == 180 * 64)
60 target = 0;
63 gdk_draw_line(d, gc, x_middle, y_middle - TARGET_SIZE / 3,
64 x_middle, y_middle + TARGET_SIZE / 3);
66 gdk_draw_line(d, gc, x_middle - TARGET_SIZE / 3, y_middle,
67 x_middle + TARGET_SIZE / 3, y_middle);
69 gdk_draw_arc(d, gc, FALSE,
70 x_middle - TARGET_SIZE, y_middle - TARGET_SIZE,
71 TARGET_SIZE * 2, TARGET_SIZE * 2, target, 90 * 64);
73 gdk_draw_arc(d, gc, FALSE,
74 x_middle - TARGET_SIZE, y_middle - TARGET_SIZE,
75 TARGET_SIZE * 2, TARGET_SIZE * 2,
76 target + 180 * 64, 90 * 64);
80 void draw_zoom_frame(gboolean draw)
83 * We keep the coordinates of the previous
84 * frame to erase it with a XOR.
86 static gint x = 0;
87 static gint y = 0;
88 static gint width = 0;
89 static gint height = 0;
90 static GdkGC *gc = NULL;
91 GdkDrawable *d;
93 d = gl_widget->window;
94 if (gc == NULL) {
95 /* First time. */
96 gc = gdk_gc_new(d);
97 gdk_gc_set_foreground(gc, &(gl_widget->style->white));
98 gdk_gc_set_function(gc, GDK_XOR);
101 if (draw)
102 /* Erase the previous frame. */
103 draw_zoom_box(d, gc, x, y, width, height, TRUE);
105 /* Update saved coordinates. */
106 x = zoom_frame_x;
107 y = zoom_frame_y;
108 width = zoom_frame_width;
109 height = zoom_frame_height;
111 if (draw) {
112 /* Draw the new frame. */
113 draw_zoom_box(d, gc, x, y, width, height, FALSE);
115 zoom_frame_cleared = FALSE;
117 gdk_gl_drawable_wait_gdk(gtk_widget_get_gl_drawable(gl_widget));
121 void set_zoom_frame(gint x, gint y, gint width, gint height)
123 if (width < 0) {
124 zoom_frame_x = x + width;
125 zoom_frame_width = -width;
126 } else {
127 zoom_frame_x = x;
128 zoom_frame_width = width;
131 if (height < 0) {
132 zoom_frame_y = y + height;
133 zoom_frame_height = -height;
134 } else {
135 zoom_frame_y = y;
136 zoom_frame_height = height;
140 void clear_zoom_frame(void)
142 if (zoom_frame_cleared == FALSE) {
143 set_zoom_frame(-1, -1, 0, 0);
144 draw_zoom_frame(FALSE);
145 zoom_frame_cleared = TRUE;
149 void zoom_frame(void)
151 gfloat x, y, zoom;
153 if (zoom_frame_width == 0 || zoom_frame_height == 0) {
154 /* To avoid division by zero. */
155 set_zoom_frame(-1, -1, 0, 0);
156 draw_zoom_frame(TRUE);
157 return;
160 zoom = MIN((gfloat) rt->wid_size->width / zoom_frame_width,
161 (gfloat) rt->wid_size->height / zoom_frame_height);
163 x = zoom_frame_x + zoom_frame_width / 2.0;
164 y = zoom_frame_y + zoom_frame_height / 2.0;
166 /* zoom. */
167 matrix_zoom(zoom, x, y);
169 /* center. */
170 matrix_move(rt->wid_size->width / 2.0 - x, rt->wid_size->height / 2.0 - y);
172 refresh(REFRESH_IMAGE | REFRESH_STATUS | APPEND_HISTORY);