Statistics
| Revision:

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

History | View | Annotate | Download (9.23 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
#define ENVIRONMENT_VIEW_MIN_WIDTH                100
14
#define ENVIRONMENT_VIEW_MIN_HEIGHT                50
15

    
16
static GtkWidgetClass* parent_class = NULL;
17

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

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

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

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

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

    
55
        return environment_view_type;
56
}
57

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

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

    
66
        parent_class = gtk_type_class(gtk_widget_get_type());
67

    
68
        object_class->destroy = gtk_environment_view_destroy;
69

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

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

    
84
        return GTK_WIDGET(view);
85
}
86

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

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

    
97
        view->mouseDown = 0;
98
}
99

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

    
106
        view = GTK_ENVIRONMENT_VIEW(object);
107

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
190
//        gdk_draw_arc(widget->window, 
191
//                widget->style->fg_gc[GTK_WIDGET_STATE(widget)], FALSE, 0, 0,
192
//                100, 100, 0, 360*64);
193
        draw_robot(widget->window, 
194
                widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 10, 10, 370);
195

    
196
        return FALSE;
197
}
198

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

    
204
        if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
205
                return FALSE;
206

    
207
        view = GTK_ENVIRONMENT_VIEW(widget);
208

    
209
        if (event->button != 1)
210
                return FALSE;
211

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

    
218
        return FALSE;
219
}
220

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

    
228
        if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
229
                return FALSE;
230

    
231
        view = GTK_ENVIRONMENT_VIEW(widget);
232

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

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

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

    
293
        return FALSE;
294
}
295

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

    
301
        if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
302
                return FALSE;
303

    
304
        view = GTK_ENVIRONMENT_VIEW(widget);
305

    
306
        view->mouseX = event->x;
307
        view->mouseY = event->y;
308

    
309
        if (!view->mouseDown)
310
                return FALSE;
311

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

    
334
        gtk_widget_queue_draw_area(widget, 0, 0, view->width, view->height);
335

    
336
        return FALSE;
337
}
338

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