Statistics
| Revision:

root / branches / simulator / projects / simulator / simulator / gui / gtk_environment_view.c @ 975

History | View | Annotate | Download (9.11 KB)

1
#include <math.h>
2
#include <stdlib.h>
3
#include <stdio.h>
4
#include <sys/time.h>
5
#include <string.h>
6

    
7
#include <gtk/gtkmain.h>
8
#include <gtk/gtksignal.h>
9

    
10
#include "gtk_environment_view.h"
11

    
12
#define ENVIRONMENT_VIEW_MIN_WIDTH                100
13
#define ENVIRONMENT_VIEW_MIN_HEIGHT                50
14

    
15
static GtkWidgetClass* parent_class = NULL;
16

    
17
static void gtk_environment_view_class_init(GtkEnvironmentViewClass* environmentClass);
18
static void gtk_environment_view_init(GtkEnvironmentView* view);
19
static void gtk_environment_view_destroy(GtkObject* object);
20

    
21
static void gtk_environment_view_size_request(GtkWidget* widget,
22
                GtkRequisition* req);
23
static void gtk_environment_view_realize(GtkWidget* widget);
24
static void gtk_environment_view_size_allocate(GtkWidget* widget, GtkAllocation* a);
25
static gboolean gtk_environment_view_expose(GtkWidget* widget,
26
                GdkEventExpose* event);
27

    
28
static gboolean gtk_environment_view_mouse_down(GtkWidget* widget,
29
                                GdkEventButton* event);
30
static gboolean gtk_environment_view_mouse_release(GtkWidget* widget,
31
                                GdkEventButton* event);
32
static gboolean gtk_environment_view_mouse_move(GtkWidget* widget,
33
                                GdkEventMotion* event);
34

    
35
GtkType gtk_environment_view_get_type(void)
36
{
37
        static GtkType environment_view_type = 0;
38
        if (!environment_view_type)
39
        {
40
                static const GtkTypeInfo environment_view_info =
41
                {
42
                        "GtkEnvironmentView",
43
                        sizeof(GtkEnvironmentView),
44
                        sizeof(GtkEnvironmentViewClass),
45
                        (GtkClassInitFunc)gtk_environment_view_class_init,
46
                        (GtkObjectInitFunc)gtk_environment_view_init,
47
                        NULL, NULL, (GtkClassInitFunc)NULL
48
                };
49

    
50
                environment_view_type = gtk_type_unique(GTK_TYPE_WIDGET,
51
                        &environment_view_info);
52
        }
53

    
54
        return environment_view_type;
55
}
56

    
57
static void gtk_environment_view_class_init(GtkEnvironmentViewClass* environmentClass)
58
{
59
        GtkObjectClass* object_class;
60
        GtkWidgetClass* widget_class;
61

    
62
        object_class = (GtkObjectClass*)environmentClass;
63
        widget_class = (GtkWidgetClass*)environmentClass;
64

    
65
        parent_class = gtk_type_class(gtk_widget_get_type());
66

    
67
        object_class->destroy = gtk_environment_view_destroy;
68

    
69
        widget_class->realize = gtk_environment_view_realize;
70
        widget_class->expose_event = gtk_environment_view_expose;
71
        widget_class->size_request = gtk_environment_view_size_request;
72
        widget_class->size_allocate = gtk_environment_view_size_allocate;
73
        widget_class->button_press_event = gtk_environment_view_mouse_down;
74
        widget_class->button_release_event = gtk_environment_view_mouse_release;
75
        widget_class->motion_notify_event = gtk_environment_view_mouse_move;
76
}
77

    
78
GtkWidget* gtk_environment_view_new(void)
79
{
80
        GtkEnvironmentView* view;
81
        view = gtk_type_new(gtk_environment_view_get_type());
82

    
83
        return GTK_WIDGET(view);
84
}
85

    
86
static void gtk_environment_view_init(GtkEnvironmentView* view)
87
{
88
        view->topLeftX = -2.0;
89
        view->topLeftY = -1.3;
90
        view->scale = 2.0 / 800.0;
91
        view->width = -1;
92
        view->height = -1;
93

    
94
        GTK_WIDGET_SET_FLAGS(&(view->widget), GTK_DOUBLE_BUFFERED);
95

    
96
        view->mouseDown = 0;
97
}
98

    
99
static void gtk_environment_view_destroy(GtkObject* object)
100
{
101
        GtkEnvironmentView* view;
102
        g_return_if_fail(object != NULL);
103
        g_return_if_fail(GTK_IS_ENVIRONMENT_VIEW(object));
104

    
105
        view = GTK_ENVIRONMENT_VIEW(object);
106

    
107
        if (GTK_OBJECT_CLASS(parent_class)->destroy)
108
                (* GTK_OBJECT_CLASS(parent_class)->destroy) (object);
109
}
110

    
111
static void gtk_environment_view_realize(GtkWidget* widget)
112
{
113
        GtkEnvironmentView* view;
114
        GdkWindowAttr attributes;
115
        gint attributes_mask;
116

    
117
        g_return_if_fail( widget != NULL);
118
        g_return_if_fail( GTK_IS_ENVIRONMENT_VIEW(widget));
119

    
120
        GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
121
        view = GTK_ENVIRONMENT_VIEW(widget);
122

    
123
        attributes.x = widget->allocation.x;
124
        attributes.y = widget->allocation.y;
125
        attributes.width = widget->allocation.width;
126
        attributes.height = widget->allocation.height;
127
        attributes.wclass = GDK_INPUT_OUTPUT;
128
        attributes.window_type = GDK_WINDOW_CHILD;
129
        attributes.event_mask = gtk_widget_get_events(widget) |
130
                GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
131
                GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
132
                GDK_POINTER_MOTION_HINT_MASK;
133
        attributes.visual = gtk_widget_get_visual(widget);
134
        attributes.colormap = gtk_widget_get_colormap(widget);
135

    
136
        attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
137
        widget->window = gdk_window_new(widget->parent->window, &attributes,
138
                        attributes_mask);
139
        gdk_window_set_user_data(widget->window, widget);
140
        widget->style = gtk_style_attach(widget->style, widget->window);
141
        gtk_style_set_background(widget->style, widget->window,
142
                        GTK_STATE_NORMAL);
143
}
144

    
145
static void gtk_environment_view_size_request(GtkWidget* widget, 
146
                GtkRequisition* req)
147
{
148
        if (req->width < ENVIRONMENT_VIEW_MIN_WIDTH)
149
                req->width = ENVIRONMENT_VIEW_MIN_WIDTH;
150
        if (req->height < ENVIRONMENT_VIEW_MIN_HEIGHT)
151
                req->height = ENVIRONMENT_VIEW_MIN_HEIGHT;
152
}
153

    
154
static void gtk_environment_view_size_allocate(GtkWidget* widget, GtkAllocation* a)
155
{
156
        GtkEnvironmentView* view;
157

    
158
        g_return_if_fail(widget != NULL);
159
        g_return_if_fail(GTK_IS_ENVIRONMENT_VIEW(widget));
160
        g_return_if_fail(a != NULL);
161

    
162
        view = GTK_ENVIRONMENT_VIEW(widget);
163
        widget->allocation = *a;
164

    
165
        view->width = a->width;
166
        view->height = a->height;
167

    
168
        if (GTK_WIDGET_REALIZED(widget))
169
        {
170
                gdk_window_move_resize(widget->window, a->x, a->y, a->width, a->height);
171
        }
172
}
173

    
174
static gboolean gtk_environment_view_expose(GtkWidget* widget,
175
                GdkEventExpose* event)
176
{
177
        GtkEnvironmentView* view;
178

    
179
        if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
180
                return FALSE;
181
        if (event->count > 0)
182
                return FALSE;
183
        
184
        view = GTK_ENVIRONMENT_VIEW(widget);
185
        
186
        gdk_draw_rectangle(widget->window, widget->style->fg_gc[
187
                        GTK_WIDGET_STATE(widget)], 0, 100, 100, 100, 100);
188

    
189
        gdk_draw_arc(widget->window, 
190
                widget->style->fg_gc[GTK_WIDGET_STATE(widget)], FALSE, 0, 0,
191
                100, 100, 0, 360*64);
192

    
193

    
194
        return FALSE;
195
}
196

    
197
static gboolean gtk_environment_view_mouse_down(GtkWidget* widget,
198
                                GdkEventButton* event)
199
{
200
        GtkEnvironmentView* view;
201

    
202
        if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
203
                return FALSE;
204

    
205
        view = GTK_ENVIRONMENT_VIEW(widget);
206

    
207
        if (event->button != 1)
208
                return FALSE;
209

    
210
        view->mouseDownX = event->x;
211
        view->mouseDownY = event->y;
212
        view->mouseX = event->x;
213
        view->mouseY = event->y;
214
        view->mouseDown = 1;
215

    
216
        return FALSE;
217
}
218

    
219
static gboolean gtk_environment_view_mouse_release(GtkWidget* widget,
220
                                GdkEventButton* event)
221
{
222
        GtkEnvironmentView* view;
223
        double x1, x2, y1, y2;
224
        int w, h;
225

    
226
        if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
227
                return FALSE;
228

    
229
        view = GTK_ENVIRONMENT_VIEW(widget);
230

    
231
        if (event->button != 1 && event->button != 3)
232
                return FALSE;
233
        
234
        if (event->button == 1)
235
                view->mouseDown = 0;
236
        view->mouseX = event->x;
237
        view->mouseY = event->y;
238
        w = abs(view->mouseX - view->mouseDownX);
239
        h = abs(view->mouseY - view->mouseDownY);
240
        
241
        // if the box is big, zoom to the box
242
        if (event->button == 1 && (w >= 10 || h >= 10))
243
        {
244
                // we need to make sure the box is to scale
245
                // scale to height
246
                if (fabs((double)w / h) <= fabs((double)view->width / view->height))
247
                {
248
                        w = (int)((double)view->width / view->height * h);
249
                        if (view->mouseX < view->mouseDownX)
250
                                view->mouseX = view->mouseDownX - w;
251
                        else
252
                                view->mouseX = view->mouseDownX + w;
253
                }
254
                // scale to width
255
                else
256
                {
257
                        h = (int)((double)view->height / view->width * w);
258
                        if (view->mouseY < view->mouseDownY)
259
                                view->mouseY = view->mouseDownY - h;
260
                        else
261
                                view->mouseY = view->mouseDownY + h;
262
                }
263
        
264
                x1 = view->mouseX * view->scale + view->topLeftX;
265
                y1 = view->mouseY * view->scale + view->topLeftY;
266
                x2 = view->mouseDownX * view->scale + view->topLeftX;
267
                y2 = view->mouseDownY * view->scale + view->topLeftY;
268
                if (x2 < x1)
269
                        x1 = x2;
270
                if (y2 < y1)
271
                        y1 = y2;
272

    
273
                view->scale = (w * view->scale) / view->width;
274
                view->topLeftX = x1;
275
                view->topLeftY = y1;
276
        }
277
        else
278
        {
279
                x1 = view->mouseX * view->scale + view->topLeftX;
280
                y1 = view->mouseY * view->scale + view->topLeftY;
281

    
282
                // zoom in on left click, out on right click
283
                if (event->button == 1)
284
                        view->scale /= 2.0;
285
                else
286
                        view->scale *= 2.0;
287
                view->topLeftX = x1 - view->width / 2 * view->scale;
288
                view->topLeftY = y1 - view->height / 2 * view->scale;
289
        }
290

    
291
        return FALSE;
292
}
293

    
294
static gboolean gtk_environment_view_mouse_move(GtkWidget* widget,
295
                                GdkEventMotion* event)
296
{
297
        GtkEnvironmentView* view;
298

    
299
        if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
300
                return FALSE;
301

    
302
        view = GTK_ENVIRONMENT_VIEW(widget);
303

    
304
        view->mouseX = event->x;
305
        view->mouseY = event->y;
306

    
307
        if (!view->mouseDown)
308
                return FALSE;
309

    
310
        // we need to make sure the new view is to scale
311
        int w = abs(view->mouseX - view->mouseDownX);
312
        int h = abs(view->mouseY - view->mouseDownY);
313
        // scale to height
314
        if (fabs((double)w / h) <= fabs((double)view->width / view->height))
315
        {
316
                w = (int)((double)view->width / view->height * h);
317
                if (view->mouseX < view->mouseDownX)
318
                        view->mouseX = view->mouseDownX - w;
319
                else
320
                        view->mouseX = view->mouseDownX + w;
321
        }
322
        // scale to width
323
        else
324
        {
325
                h = (int)((double)view->height / view->width * w);
326
                if (view->mouseY < view->mouseDownY)
327
                        view->mouseY = view->mouseDownY - h;
328
                else
329
                        view->mouseY = view->mouseDownY + h;
330
        }
331

    
332
        gtk_widget_queue_draw_area(widget, 0, 0, view->width, view->height);
333

    
334
        return FALSE;
335
}
336

    
337
        /*gdk_threads_enter();
338
        gtk_widget_queue_draw_area(widget, 0, row, view->width, 1);
339
        gdk_threads_leave();*/
340