diff options
Diffstat (limited to 'Drawer.cpp')
-rw-r--r-- | Drawer.cpp | 218 |
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); +} |