Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (9.38 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
#include "draw_funcs.h"
12

    
13
#include "robot.h"
14

    
15
#define ENVIRONMENT_VIEW_MIN_WIDTH                100
16
#define ENVIRONMENT_VIEW_MIN_HEIGHT                50
17

    
18
static GtkWidgetClass* parent_class = NULL;
19

    
20
static void gtk_environment_view_class_init(GtkEnvironmentViewClass* environmentClass);
21
static void gtk_environment_view_init(GtkEnvironmentView* view);
22
static void gtk_environment_view_destroy(GtkObject* object);
23

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

    
31
static gboolean gtk_environment_view_mouse_down(GtkWidget* widget,
32
                                GdkEventButton* event);
33
static gboolean gtk_environment_view_mouse_release(GtkWidget* widget,
34
                                GdkEventButton* event);
35
static gboolean gtk_environment_view_mouse_move(GtkWidget* widget,
36
                                GdkEventMotion* event);
37

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

    
53
                environment_view_type = gtk_type_unique(GTK_TYPE_WIDGET,
54
                        &environment_view_info);
55
        }
56

    
57
        return environment_view_type;
58
}
59

    
60
static void gtk_environment_view_class_init(GtkEnvironmentViewClass* environmentClass)
61
{
62
        GtkObjectClass* object_class;
63
        GtkWidgetClass* widget_class;
64

    
65
        object_class = (GtkObjectClass*)environmentClass;
66
        widget_class = (GtkWidgetClass*)environmentClass;
67

    
68
        parent_class = gtk_type_class(gtk_widget_get_type());
69

    
70
        object_class->destroy = gtk_environment_view_destroy;
71

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

    
81
GtkWidget* gtk_environment_view_new(void)
82
{
83
        GtkEnvironmentView* view;
84
        view = gtk_type_new(gtk_environment_view_get_type());
85

    
86
        return GTK_WIDGET(view);
87
}
88

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

    
97
        GTK_WIDGET_SET_FLAGS(&(view->widget), GTK_DOUBLE_BUFFERED);
98

    
99
        view->mouseDown = 0;
100
}
101

    
102
static void gtk_environment_view_destroy(GtkObject* object)
103
{
104
        GtkEnvironmentView* view;
105
        g_return_if_fail(object != NULL);
106
        g_return_if_fail(GTK_IS_ENVIRONMENT_VIEW(object));
107

    
108
        view = GTK_ENVIRONMENT_VIEW(object);
109

    
110
        if (GTK_OBJECT_CLASS(parent_class)->destroy)
111
                (* GTK_OBJECT_CLASS(parent_class)->destroy) (object);
112
}
113

    
114
static void gtk_environment_view_realize(GtkWidget* widget)
115
{
116
        GtkEnvironmentView* view;
117
        GdkWindowAttr attributes;
118
        gint attributes_mask;
119

    
120
        g_return_if_fail( widget != NULL);
121
        g_return_if_fail( GTK_IS_ENVIRONMENT_VIEW(widget));
122

    
123
        GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
124
        view = GTK_ENVIRONMENT_VIEW(widget);
125

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

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

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

    
157
static void gtk_environment_view_size_allocate(GtkWidget* widget, GtkAllocation* a)
158
{
159
        GtkEnvironmentView* view;
160

    
161
        g_return_if_fail(widget != NULL);
162
        g_return_if_fail(GTK_IS_ENVIRONMENT_VIEW(widget));
163
        g_return_if_fail(a != NULL);
164

    
165
        view = GTK_ENVIRONMENT_VIEW(widget);
166
        widget->allocation = *a;
167

    
168
        view->width = a->width;
169
        view->height = a->height;
170

    
171
        if (GTK_WIDGET_REALIZED(widget))
172
        {
173
                gdk_window_move_resize(widget->window, a->x, a->y, a->width, a->height);
174
        }
175
}
176

    
177
static gboolean gtk_environment_view_expose(GtkWidget* widget,
178
                GdkEventExpose* event)
179
{
180
        GtkEnvironmentView* view;
181

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

    
192
//        gdk_draw_arc(widget->window, 
193
//                widget->style->fg_gc[GTK_WIDGET_STATE(widget)], FALSE, 0, 0,
194
//                100, 100, 0, 360*64);
195
        
196
        robot_iterator_reset();
197
        Robot* r;
198
        while ((r = robot_iterator_next()) != NULL)
199
                draw_robot(widget->window, 
200
                        widget->style->fg_gc[GTK_WIDGET_STATE(widget)], r->pose.x, r->pose.y, r->pose.theta);
201

    
202
        return FALSE;
203
}
204

    
205
static gboolean gtk_environment_view_mouse_down(GtkWidget* widget,
206
                                GdkEventButton* event)
207
{
208
        GtkEnvironmentView* view;
209

    
210
        if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
211
                return FALSE;
212

    
213
        view = GTK_ENVIRONMENT_VIEW(widget);
214

    
215
        if (event->button != 1)
216
                return FALSE;
217

    
218
        view->mouseDownX = event->x;
219
        view->mouseDownY = event->y;
220
        view->mouseX = event->x;
221
        view->mouseY = event->y;
222
        view->mouseDown = 1;
223

    
224
        return FALSE;
225
}
226

    
227
static gboolean gtk_environment_view_mouse_release(GtkWidget* widget,
228
                                GdkEventButton* event)
229
{
230
        GtkEnvironmentView* view;
231
        double x1, x2, y1, y2;
232
        int w, h;
233

    
234
        if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
235
                return FALSE;
236

    
237
        view = GTK_ENVIRONMENT_VIEW(widget);
238

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

    
281
                view->scale = (w * view->scale) / view->width;
282
                view->topLeftX = x1;
283
                view->topLeftY = y1;
284
        }
285
        else
286
        {
287
                x1 = view->mouseX * view->scale + view->topLeftX;
288
                y1 = view->mouseY * view->scale + view->topLeftY;
289

    
290
                // zoom in on left click, out on right click
291
                if (event->button == 1)
292
                        view->scale /= 2.0;
293
                else
294
                        view->scale *= 2.0;
295
                view->topLeftX = x1 - view->width / 2 * view->scale;
296
                view->topLeftY = y1 - view->height / 2 * view->scale;
297
        }
298

    
299
        return FALSE;
300
}
301

    
302
static gboolean gtk_environment_view_mouse_move(GtkWidget* widget,
303
                                GdkEventMotion* event)
304
{
305
        GtkEnvironmentView* view;
306

    
307
        if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
308
                return FALSE;
309

    
310
        view = GTK_ENVIRONMENT_VIEW(widget);
311

    
312
        view->mouseX = event->x;
313
        view->mouseY = event->y;
314

    
315
        if (!view->mouseDown)
316
                return FALSE;
317

    
318
        // we need to make sure the new view is to scale
319
        int w = abs(view->mouseX - view->mouseDownX);
320
        int h = abs(view->mouseY - view->mouseDownY);
321
        // scale to height
322
        if (fabs((double)w / h) <= fabs((double)view->width / view->height))
323
        {
324
                w = (int)((double)view->width / view->height * h);
325
                if (view->mouseX < view->mouseDownX)
326
                        view->mouseX = view->mouseDownX - w;
327
                else
328
                        view->mouseX = view->mouseDownX + w;
329
        }
330
        // scale to width
331
        else
332
        {
333
                h = (int)((double)view->height / view->width * w);
334
                if (view->mouseY < view->mouseDownY)
335
                        view->mouseY = view->mouseDownY - h;
336
                else
337
                        view->mouseY = view->mouseDownY + h;
338
        }
339

    
340
        gtk_widget_queue_draw_area(widget, 0, 0, view->width, view->height);
341

    
342
        return FALSE;
343
}
344

    
345
void gtk_environment_view_refresh(GtkWidget* view)
346
{
347
        gdk_threads_enter();
348
        gtk_widget_queue_draw(view);
349
        gdk_threads_leave();
350
}
351