summaryrefslogtreecommitdiffstats
path: root/Drawer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Drawer.cpp')
-rw-r--r--Drawer.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/Drawer.cpp b/Drawer.cpp
new file mode 100644
index 0000000..48bc730
--- /dev/null
+++ b/Drawer.cpp
@@ -0,0 +1,218 @@
+#include "Drawer.h"
+#include "Window.h"
+#include "draw.h"
+#include "edit.h"
+#include <GL/gl.h>
+#include <math.h>
+
+
+void Drawer::realize(GtkWidget *widget, Drawer *drawer) {
+ GdkGLContext *context = gtk_widget_get_gl_context(widget);
+ GdkGLDrawable *drawable = gtk_widget_get_gl_drawable(widget);
+
+ if(!gdk_gl_drawable_gl_begin(drawable, context))
+ return;
+
+ glClearColor(0, 0, 0, 1);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ glEnable(GL_LINE_SMOOTH);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ gdk_gl_drawable_gl_end(drawable);
+}
+
+gboolean Drawer::eventHandler(GtkWidget *widget, GdkEvent *event, Drawer *drawer) {
+ switch(event->type) {
+ case GDK_CONFIGURE:
+ drawer->updateViewport();
+ drawer->updateScrollbars();
+ return TRUE;
+
+ case GDK_EXPOSE:
+ drawTopView(widget, &event->expose, NULL);
+ return TRUE;
+
+ case GDK_MOTION_NOTIFY:
+ drawer->updateHoveredPoint(event->motion.x, event->motion.y);
+ return TRUE;
+
+ case GDK_ENTER_NOTIFY:
+ drawer->updateHoveredPoint(event->crossing.x, event->crossing.y);
+ return TRUE;
+
+ case GDK_LEAVE_NOTIFY:
+ setHoveredVertex(NULL);
+ drawer->window->update();
+ return TRUE;
+
+ case GDK_BUTTON_PRESS:
+ switch(event->button.button) {
+ case 1:
+ if(!getHoveredVertex())
+ break;
+
+ switch(drawer->window->getEditManager().getMode()) {
+ case EditManager::VIEW:
+ setActiveRoom(getHoveredRoom());
+ break;
+
+ case EditManager::ADD:
+ if(isVertexOk(getHoveredVertex()))
+ drawer->window->getEditManager().addVertex(*getHoveredVertex());
+ }
+
+ drawer->window->update();
+ break;
+
+ default:
+ return FALSE;
+ }
+ return TRUE;
+
+ case GDK_SCROLL:
+ switch(event->scroll.direction) {
+ case GDK_SCROLL_UP:
+ drawer->zoom(1, event->scroll.x/widget->allocation.width, event->scroll.y/widget->allocation.height);
+ break;
+ case GDK_SCROLL_DOWN:
+ drawer->zoom(-1, event->scroll.x/widget->allocation.width, event->scroll.y/widget->allocation.height);
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+void Drawer::valueChanged(GtkAdjustment *adjustment, Drawer *drawer) {
+ drawer->updateScrolling();
+}
+
+
+void Drawer::updateViewport() {
+ GdkGLContext *context = gtk_widget_get_gl_context(drawingArea);
+ GdkGLDrawable *drawable = gtk_widget_get_gl_drawable(drawingArea);
+
+ if(!gdk_gl_drawable_gl_begin(drawable, context))
+ return;
+
+ glViewport(0, 0, getWidth(), getHeight());
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ if(getWidth() != 0 && getHeight() != 0) {
+ glTranslatef(-1, 1, 0);
+ glScalef(2.0f/getWidth(), -2.0f/getHeight(), 1);
+ }
+
+ gdk_gl_drawable_gl_end(drawable);
+}
+
+void Drawer::updateScrolling() {
+ if(getImageWidth() < getWidth())
+ setXTranslate((getImageWidth()-getWidth())/2);
+ else
+ setXTranslate(gtk_adjustment_get_value(hAdjustment));
+
+ if(getImageHeight() < getHeight())
+ setYTranslate((getImageHeight()-getHeight())/2);
+ else
+ setYTranslate(gtk_adjustment_get_value(vAdjustment));
+
+ update();
+}
+
+void Drawer::updateScrollbars(float x, float y) {
+ const gdouble imageWidth = getImageWidth(), imageHeight = getImageHeight();
+ const gdouble width = getWidth(), height = getHeight();
+ gdouble upper, pageSize, value;
+
+ gdk_window_freeze_updates(drawingArea->window);
+
+ g_object_get(G_OBJECT(hAdjustment), "upper", &upper, "page_size", &pageSize, NULL);
+ g_object_set(G_OBJECT(hAdjustment), "upper", imageWidth, "page_size", width, NULL);
+ gtk_adjustment_changed(hAdjustment);
+
+ if((pageSize > upper && width < imageWidth) || upper == 0)
+ value = (imageWidth-width)/2;
+ else
+ value = (gtk_adjustment_get_value(hAdjustment)+pageSize*x)/upper*imageWidth-width*x;
+ gtk_adjustment_set_value(hAdjustment, MAX(MIN(value, imageWidth-width), 0));
+
+ g_object_get(G_OBJECT(vAdjustment), "upper", &upper, "page_size", &pageSize, NULL);
+ g_object_set(G_OBJECT(vAdjustment), "upper", imageHeight, "page_size", height, NULL);
+ gtk_adjustment_changed(vAdjustment);
+
+ if((pageSize > upper && height < imageHeight) || upper == 0)
+ value = (imageHeight-height)/2;
+ else
+ value = (gtk_adjustment_get_value(vAdjustment)+pageSize*y)/upper*imageHeight-height*y;
+ gtk_adjustment_set_value(vAdjustment, MAX(MIN(value, imageHeight-height), 0));
+
+ gdk_window_thaw_updates(drawingArea->window);
+
+ updateScrolling();
+}
+
+void Drawer::updateHoveredPoint(float x, float y) {
+ Vertex v(x, y);
+ viewToImage(&v);
+ setHoveredVertex(&v);
+
+ window->update();
+}
+
+Drawer::Drawer(Window *window, GdkGLConfig *glconfig) {
+ this->window = window;
+ zoomExp = 0;
+
+ drawer = gtk_table_new(2, 2, FALSE);
+ g_object_ref_sink(G_OBJECT(drawer));
+
+ drawingArea = gtk_drawing_area_new();
+ gtk_widget_set_gl_capability(drawingArea, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
+ g_signal_connect(G_OBJECT(drawingArea), "realize", G_CALLBACK(realize), this);
+ g_signal_connect(G_OBJECT(drawingArea), "configure-event", G_CALLBACK(eventHandler), this);
+ g_signal_connect(G_OBJECT(drawingArea), "expose-event", G_CALLBACK(eventHandler), this);
+ g_signal_connect(G_OBJECT(drawingArea), "button-press-event", G_CALLBACK(eventHandler), this);
+ //g_signal_connect(G_OBJECT(drawingArea), "button-release-event", G_CALLBACK(eventHandler), this);
+ g_signal_connect(G_OBJECT(drawingArea), "enter-notify-event", G_CALLBACK(eventHandler), this);
+ g_signal_connect(G_OBJECT(drawingArea), "leave-notify-event", G_CALLBACK(eventHandler), this);
+ g_signal_connect(G_OBJECT(drawingArea), "motion-notify-event", G_CALLBACK(eventHandler), this);
+ g_signal_connect(G_OBJECT(drawingArea), "scroll-event", G_CALLBACK(eventHandler), this);
+ gtk_widget_add_events(drawingArea, GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
+ gtk_table_attach(GTK_TABLE(drawer), drawingArea, 0, 1, 0, 1, (GtkAttachOptions)(GTK_FILL|GTK_EXPAND|GTK_SHRINK), (GtkAttachOptions)(GTK_FILL|GTK_EXPAND|GTK_SHRINK), 0, 0);
+
+ hAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100));
+ GtkWidget *hScroll = gtk_hscrollbar_new(hAdjustment);
+ g_signal_connect(G_OBJECT(hScroll), "value-changed", G_CALLBACK(valueChanged), this);
+ gtk_table_attach(GTK_TABLE(drawer), hScroll, 0, 1, 1, 2, (GtkAttachOptions)(GTK_FILL|GTK_EXPAND|GTK_SHRINK), (GtkAttachOptions)0, 0, 0);
+
+ vAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100));
+ GtkWidget *vScroll = gtk_vscrollbar_new(vAdjustment);
+ g_signal_connect(G_OBJECT(vScroll), "value-changed", G_CALLBACK(valueChanged), this);
+ gtk_table_attach(GTK_TABLE(drawer), vScroll, 1, 2, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)(GTK_FILL|GTK_EXPAND|GTK_SHRINK), 0, 0);
+
+ gtk_widget_show_all(drawer);
+}
+
+Drawer::~Drawer() {
+ g_object_unref(G_OBJECT(drawer));
+}
+
+void Drawer::zoom(int zoom, float x, float y) {
+ zoomExp = MAX(MIN(zoomExp + zoom, 50), -100);
+
+ setScale(100*powf(1.1f, zoomExp));
+
+ updateScrollbars(x, y);
+}