Project

General

Profile

Revision 962

Added beginning GUI code, does not compile.

View differences:

branches/simulator/projects/simulator/simulator/gui/gtk_gui.h
1
/**
2
 * @file gtk_gui.c
3
 * @author Brian Coltin
4
 *
5
 * A header file for functions to create and utilize
6
 * a GUI based on GTK.
7
 **/
8

  
9
/**
10
 * Run the GTK GUI. This function is blocking and
11
 * does not return until the GUI closes.
12
 *
13
 * @param argc argc as passed to main
14
 * @param argv argv as passed to main
15
 *
16
 * @return nonzero on failure, or 0 on window closure
17
 **/
18
int run_gtk_gui(int argc, char* argv);
19

  
branches/simulator/projects/simulator/simulator/gui/gtk_environment_view.c
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
static void gtk_environment_view_render_begin(GtkEnvironmentView* view);
36
static void gtk_environment_view_render_abort(GtkEnvironmentView* view);
37

  
38
static void gtk_environment_view_get_pixel(GtkEnvironmentView* view,
39
		double x,double y, unsigned char* pixel);
40

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

  
56
		environment_view_type = gtk_type_unique(GTK_TYPE_WIDGET,
57
			&environment_view_info);
58
	}
59

  
60
	return environment_view_type;
61
}
62

  
63
static void gtk_environment_view_class_init(GtkEnvironmentViewClass* environmentClass)
64
{
65
	GtkObjectClass* object_class;
66
	GtkWidgetClass* widget_class;
67

  
68
	object_class = (GtkObjectClass*)environmentClass;
69
	widget_class = (GtkWidgetClass*)environmentClass;
70

  
71
	parent_class = gtk_type_class(gtk_widget_get_type());
72

  
73
	object_class->destroy = gtk_environment_view_destroy;
74

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

  
84
GtkWidget* gtk_environment_view_new(void)
85
{
86
	GtkEnvironmentView* view;
87
	view = gtk_type_new(gtk_environment_view_get_type());
88

  
89
	return GTK_WIDGET(view);
90
}
91

  
92
static void gtk_environment_view_init(GtkEnvironmentView* view)
93
{
94
	view->buf = NULL;
95
	view->topLeftX = -2.0;
96
	view->topLeftY = -1.3;
97
	view->scale = 2.0 / 800.0;
98
	view->width = -1;
99
	view->height = -1;
100

  
101
	view->mouseDown = 0;
102
}
103

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

  
110
	view = GTK_ENVIRONMENT_VIEW(object);
111
	gtk_environment_view_render_abort(view);
112
	
113
	if (view->buf != NULL)
114
	{
115
		free(view->buf);
116
		view->buf = NULL;
117
		view->width = -1;
118
		view->height = -1;
119
	}
120

  
121
	if (GTK_OBJECT_CLASS(parent_class)->destroy)
122
		(* GTK_OBJECT_CLASS(parent_class)->destroy) (object);
123
}
124

  
125
static void gtk_environment_view_realize(GtkWidget* widget)
126
{
127
	GtkEnvironmentView* view;
128
	GdkWindowAttr attributes;
129
	gint attributes_mask;
130

  
131
	g_return_if_fail( widget != NULL);
132
	g_return_if_fail( GTK_IS_ENVIRONMENT_VIEW(widget));
133

  
134
	GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
135
	view = GTK_ENVIRONMENT_VIEW(widget);
136

  
137
	attributes.x = widget->allocation.x;
138
	attributes.y = widget->allocation.y;
139
	attributes.width = widget->allocation.width;
140
	attributes.height = widget->allocation.height;
141
	attributes.wclass = GDK_INPUT_OUTPUT;
142
	attributes.window_type = GDK_WINDOW_CHILD;
143
	attributes.event_mask = gtk_widget_get_events(widget) |
144
		GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
145
		GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
146
		GDK_POINTER_MOTION_HINT_MASK;
147
	attributes.visual = gtk_widget_get_visual(widget);
148
	attributes.colormap = gtk_widget_get_colormap(widget);
149

  
150
	attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
151
	widget->window = gdk_window_new(widget->parent->window, &attributes,
152
			attributes_mask);
153
	gdk_window_set_user_data(widget->window, widget);
154
	widget->style = gtk_style_attach(widget->style, widget->window);
155
	gtk_style_set_background(widget->style, widget->window,
156
			GTK_STATE_NORMAL);
157
}
158

  
159
static void gtk_environment_view_size_request(GtkWidget* widget, 
160
		GtkRequisition* req)
161
{
162
	if (req->width < ENVIRONMENT_VIEW_MIN_WIDTH)
163
		req->width = ENVIRONMENT_VIEW_MIN_WIDTH;
164
	if (req->height < ENVIRONMENT_VIEW_MIN_HEIGHT)
165
		req->height = ENVIRONMENT_VIEW_MIN_HEIGHT;
166
}
167

  
168
static void gtk_environment_view_size_allocate(GtkWidget* widget, GtkAllocation* a)
169
{
170
	GtkEnvironmentView* view;
171

  
172
	g_return_if_fail(widget != NULL);
173
	g_return_if_fail(GTK_IS_ENVIRONMENT_VIEW(widget));
174
	g_return_if_fail(a != NULL);
175

  
176
	view = GTK_ENVIRONMENT_VIEW(widget);
177
	gtk_environment_view_render_abort(view);
178
	widget->allocation = *a;
179

  
180
	// resize buffer
181
	if (view->buf != NULL)
182
	{
183
		free(view->buf);
184
		view->buf = NULL;
185
		view->width = -1;
186
		view->height = -1;
187
	}
188
	view->buf = (guchar*)malloc(a->width * a->height * 3 * sizeof(guchar));
189
	memset(view->buf, 0, a->width * a->height * 3 * sizeof(guchar));
190
	view->width = a->width;
191
	view->height = a->height;
192

  
193
	if (GTK_WIDGET_REALIZED(widget))
194
	{
195
		gdk_window_move_resize(widget->window, a->x, a->y, a->width, a->height);
196
		gtk_environment_view_render_begin(view);
197
	}
198
}
199

  
200
static gboolean gtk_environment_view_expose(GtkWidget* widget,
201
		GdkEventExpose* event)
202
{
203
	GtkEnvironmentView* view;
204

  
205
	if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
206
		return FALSE;
207
	if (event->count > 0)
208
		return FALSE;
209
	
210
	view = GTK_ENVIRONMENT_VIEW(widget);
211
	
212
	gdk_draw_rgb_image(widget->window, widget->style->fg_gc[
213
			GTK_WIDGET_STATE(widget)], event->area.x, 
214
			event->area.y, event->area.width, 
215
			event->area.height, GDK_RGB_DITHER_NONE, 
216
			view->buf + 3 * (event->area.y * view->width + event->area.x),
217
			3 * view->width);
218
	
219
	return FALSE;
220
}
221

  
222
static gboolean gtk_environment_view_mouse_down(GtkWidget* widget,
223
				GdkEventButton* event)
224
{
225
	GtkEnvironmentView* view;
226

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

  
230
	view = GTK_ENVIRONMENT_VIEW(widget);
231

  
232
	if (event->button != 1)
233
		return FALSE;
234

  
235
	view->mouseDownX = event->x;
236
	view->mouseDownY = event->y;
237
	view->mouseX = event->x;
238
	view->mouseY = event->y;
239
	view->mouseDown = 1;
240

  
241
	return FALSE;
242
}
243

  
244
static gboolean gtk_environment_view_mouse_release(GtkWidget* widget,
245
				GdkEventButton* event)
246
{
247
	GtkEnvironmentView* view;
248
	double x1, x2, y1, y2;
249
	int w, h;
250

  
251
	if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
252
		return FALSE;
253

  
254
	view = GTK_ENVIRONMENT_VIEW(widget);
255

  
256
	if (event->button != 1 && event->button != 3)
257
		return FALSE;
258
	
259
	if (event->button == 1)
260
		view->mouseDown = 0;
261
	view->mouseX = event->x;
262
	view->mouseY = event->y;
263
	w = abs(view->mouseX - view->mouseDownX);
264
	h = abs(view->mouseY - view->mouseDownY);
265
	
266
	gtk_environment_view_render_abort(view);
267
	
268
	// if the box is big, zoom to the box
269
	if (event->button == 1 && (w >= 10 || h >= 10))
270
	{
271
		// we need to make sure the box is to scale
272
		// scale to height
273
		if (fabs((double)w / h) <= fabs((double)view->width / view->height))
274
		{
275
			w = (int)((double)view->width / view->height * h);
276
			if (view->mouseX < view->mouseDownX)
277
				view->mouseX = view->mouseDownX - w;
278
			else
279
				view->mouseX = view->mouseDownX + w;
280
		}
281
		// scale to width
282
		else
283
		{
284
			h = (int)((double)view->height / view->width * w);
285
			if (view->mouseY < view->mouseDownY)
286
				view->mouseY = view->mouseDownY - h;
287
			else
288
				view->mouseY = view->mouseDownY + h;
289
		}
290
	
291
		x1 = view->mouseX * view->scale + view->topLeftX;
292
		y1 = view->mouseY * view->scale + view->topLeftY;
293
		x2 = view->mouseDownX * view->scale + view->topLeftX;
294
		y2 = view->mouseDownY * view->scale + view->topLeftY;
295
		if (x2 < x1)
296
			x1 = x2;
297
		if (y2 < y1)
298
			y1 = y2;
299

  
300
		view->scale = (w * view->scale) / view->width;
301
		view->topLeftX = x1;
302
		view->topLeftY = y1;
303
	}
304
	else
305
	{
306
		x1 = view->mouseX * view->scale + view->topLeftX;
307
		y1 = view->mouseY * view->scale + view->topLeftY;
308

  
309
		// zoom in on left click, out on right click
310
		if (event->button == 1)
311
			view->scale /= 2.0;
312
		else
313
			view->scale *= 2.0;
314
		view->topLeftX = x1 - view->width / 2 * view->scale;
315
		view->topLeftY = y1 - view->height / 2 * view->scale;
316
	}
317

  
318
	gtk_environment_view_render_begin(view);
319

  
320
	return FALSE;
321
}
322

  
323
static gboolean gtk_environment_view_mouse_move(GtkWidget* widget,
324
				GdkEventMotion* event)
325
{
326
	GtkEnvironmentView* view;
327

  
328
	if (widget == NULL || !GTK_IS_ENVIRONMENT_VIEW(widget) || event == NULL)
329
		return FALSE;
330

  
331
	view = GTK_ENVIRONMENT_VIEW(widget);
332

  
333
	view->mouseX = event->x;
334
	view->mouseY = event->y;
335

  
336
	if (!view->mouseDown)
337
		return FALSE;
338

  
339
	// we need to make sure the new view is to scale
340
	int w = abs(view->mouseX - view->mouseDownX);
341
	int h = abs(view->mouseY - view->mouseDownY);
342
	// scale to height
343
	if (fabs((double)w / h) <= fabs((double)view->width / view->height))
344
	{
345
		w = (int)((double)view->width / view->height * h);
346
		if (view->mouseX < view->mouseDownX)
347
			view->mouseX = view->mouseDownX - w;
348
		else
349
			view->mouseX = view->mouseDownX + w;
350
	}
351
	// scale to width
352
	else
353
	{
354
		h = (int)((double)view->height / view->width * w);
355
		if (view->mouseY < view->mouseDownY)
356
			view->mouseY = view->mouseDownY - h;
357
		else
358
			view->mouseY = view->mouseDownY + h;
359
	}
360

  
361
	gtk_widget_queue_draw_area(widget, 0, 0, view->width, view->height);
362

  
363
	return FALSE;
364
}
365

  
366
static void* gtk_environment_view_do_work(void* arg)
367
{
368
	GtkEnvironmentView* view = (GtkEnvironmentView*)arg;
369
	GtkWidget* widget = GTK_WIDGET(view);
370
	int row, col;
371
	while ((row = gtk_environment_view_acquire_row(view)) >= 0 && view->working)
372
	{
373
		int pos = 3 * row * view->width;
374
		double y = row * view->scale + view->topLeftY;
375
		double x = view->topLeftX;
376
		for (col = 0; col < view->width && view->working; col++)
377
		{
378
			gtk_environment_view_get_pixel(view, x, y, &view->buf[pos]);
379
			pos += 3;
380
			x += view->scale;
381
		}
382
		gdk_threads_enter();
383
		gtk_widget_queue_draw_area(widget, 0, row, view->width, 1);
384
		gdk_threads_leave();
385
	}
386
	view->num_active_threads--;
387
	// print out time in milliseconds
388
	if (view->num_active_threads == 0)
389
	{
390
		struct timeval t;
391
		gettimeofday(&t, NULL);
392
		unsigned int diff = (t.tv_sec - view->starttime.tv_sec) * 1000 +
393
							(t.tv_usec - view->starttime.tv_usec) / 1000;
394
		printf("Generated in %d milliseconds.\n", diff);
395
	}
396

  
397
	return NULL;
398
}
399

  
400
// spawn worker threads
401
static void gtk_environment_view_render_begin(GtkEnvironmentView* view)
402
{
403
	int i;
404
	view->working = 1;
405
	view->cur_row = 0;
406
	view->num_active_threads = NUM_THREADS;
407
	gettimeofday(&view->starttime, NULL);
408
	for (i = 0; i < NUM_THREADS; i++)
409
		view->worker_threads[i] = g_thread_create(
410
				gtk_environment_view_do_work, view, TRUE, NULL);
411
}
412

  
413
static void gtk_environment_view_render_abort(GtkEnvironmentView* view)
414
{
415
	int i;
416
	if (view->working)
417
	{
418
		view->working = 0;
419
		gdk_threads_leave();
420
		for (i = 0; i < NUM_THREADS; i++)
421
			g_thread_join(view->worker_threads[i]);
422
		gdk_threads_enter();
423
	}
424
}
425

  
branches/simulator/projects/simulator/simulator/gui/gtk_environment_view.h
1
#ifndef __ENVIRONMENT_VIEW_H__
2
#define __ENVIRONMENT_VIEW_H__
3

  
4
#include <gdk/gdk.h>
5
#include <gtk/gtkwidget.h>
6

  
7
#include <pthread.h>
8
#include <time.h>
9

  
10
#define GTK_ENVIRONMENT_VIEW(obj)		GTK_CHECK_CAST(obj, \
11
									gtk_environment_view_get_type(), GtkEnvironmentView)
12
#define GTK_ENVIRONMENT_VIEW_CLASS(kclass)	GTK_CHECK_CLASS_CAST ( \
13
										kclass, gtk_environment_view_get_type(), \
14
										GtkEnvironmentViewClass)
15
#define GTK_IS_ENVIRONMENT_VIEW(obj)		GTK_CHECK_TYPE(obj, \
16
										gtk_environment_view_get_type())
17

  
18
#define NUM_THREADS		4
19

  
20
struct _GtkEnvironmentView
21
{
22
	GtkWidget widget;
23
	
24
	int width;
25
	int height;
26
	guchar* buf;
27
	double topLeftX;
28
	double topLeftY;
29
	double scale;
30

  
31
	int mouseDownX;
32
	int mouseDownY;
33
	int mouseX;
34
	int mouseY;
35
	int mouseDown;
36
};
37

  
38
struct _GtkEnvironmentViewClass
39
{
40
	GtkWidgetClass parent_class;
41
};
42

  
43
typedef struct _GtkEnvironmentView GtkEnvironmentView;
44
typedef struct _GtkEnvironmentViewClass GtkEnvironmentViewClass;
45

  
46
GtkWidget* gtk_environment_view_new(void);
47
GtkType gtk_environment_view_get_type(void);
48

  
49
#endif
50

  
branches/simulator/projects/simulator/simulator/gui/gtk_gui.c
1
#include <stdlib.h>
2
#include <gtk/gtk.h>
3
#include <glib.h>
4

  
5
#include "gtk_gui.h"
6

  
7
void destroy_callback(int arg)
8
{
9
	gtk_main_quit();
10
}
11

  
12
int gtk_gui_run(int argc, char* argv[])
13
{
14
	GtkWidget* window;
15
	GtkWidget* view;
16
	
17
	g_thread_init(NULL);
18
	gdk_threads_init();
19
	gdk_threads_enter();
20
	gtk_init(&argc, &argv);
21

  
22
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
23
	gtk_window_set_title(GTK_WINDOW(window), "Colony Simulator");
24
	gtk_window_maximize(GTK_WINDOW(window));
25
	//g_signal_connect(G_OBJECT(window), "delete_event",
26
	//		G_CALLBACK(delete_event), NULL);
27
	
28
	g_signal_connect(G_OBJECT(window), "destroy",
29
			G_CALLBACK(destroy_callback), NULL);
30
	
31
	gtk_container_set_border_width(GTK_CONTAINER(window), 0);
32

  
33
	view = gtk_environment_view_new();
34
	gtk_container_add(GTK_CONTAINER(window), view);
35
	gtk_widget_show(view);
36

  
37
	gtk_widget_show(window);
38

  
39
	gtk_main();
40
	gdk_threads_leave();
41

  
42
	return 0;
43
}
44

  
branches/simulator/projects/simulator/simulator/Makefile
1
SRCS := main.c gtk_fractal_view.c
2
OBJS := $(patsubst %.c, %.o, $(SRCS))
3
PROG := simulator
4

  
5
CFLAGS := -Wall
6
CFLAGS += `pkg-config --cflags gtk+-2.0 gthread-2.0`
7

  
8
LDFLAGS :=
9
LDFLAGS += `pkg-config --libs gtk+-2.0 gthread-2.0`
10

  
11
CC := gcc
12

  
13
all: $(OBJS)
14
	$(CC) $(CFLAGS) $(LDFLAGS) -o $(PROG) $(OBJS)
15

  
16
%.o: %.c %.h
17
	$(CC) $(CFLAGS) -c -o $@ $<
18

  
19
clean:
20
	rm *~ *.o $(PROG)
21

  

Also available in: Unified diff