diff options
-rw-r--r-- | src/Gui/RenderArea.cpp | 128 | ||||
-rw-r--r-- | src/Gui/RenderArea.h | 31 | ||||
-rw-r--r-- | zoomedit.glade | 22 |
3 files changed, 158 insertions, 23 deletions
diff --git a/src/Gui/RenderArea.cpp b/src/Gui/RenderArea.cpp index c19c0a5..ec37f67 100644 --- a/src/Gui/RenderArea.cpp +++ b/src/Gui/RenderArea.cpp @@ -1,6 +1,8 @@ #include "RenderArea.h" #include <iostream> #include <cstdlib> +#include <cmath> +#include <gtkmm/toolbutton.h> #include <GL/gl.h> namespace ZoomEdit { @@ -9,7 +11,7 @@ namespace Gui { GdkGLConfig *RenderArea::glconfig = NULL; RenderArea::RenderArea(BaseObjectType *cobject, const Glib::RefPtr<Gnome::Glade::Xml> &xml) -: Gtk::DrawingArea(cobject) { +: Gtk::DrawingArea(cobject), zoomLevel(0), scale(100), x(0), y(0) { if(!glconfig) { glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(GDK_GL_MODE_RGB | GDK_GL_MODE_DOUBLE)); if(!glconfig) glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB); // Hmm, can't find double buffered config @@ -20,19 +22,24 @@ RenderArea::RenderArea(BaseObjectType *cobject, const Glib::RefPtr<Gnome::Glade: } signal_realize().connect(sigc::mem_fun(this, &RenderArea::onRealize)); + signal_configure_event().connect(sigc::mem_fun(this, &RenderArea::onConfigureEvent)); + signal_expose_event().connect(sigc::mem_fun(this, &RenderArea::onExposeEvent)); + signal_scroll_event().connect(sigc::mem_fun(this, &RenderArea::onScrollEvent)); + + Gtk::ToolButton *button; + xml->get_widget("ToolButtonZoomIn", button); + if(button) + button->signal_clicked().connect(sigc::bind(sigc::mem_fun(this, &RenderArea::zoom), 2, 0.5f, 0.5f)); + + xml->get_widget("ToolButtonZoomOut", button); + if(button) + button->signal_clicked().connect(sigc::bind(sigc::mem_fun(this, &RenderArea::zoom), -2, 0.5f, 0.5f)); gtk_widget_set_gl_capability(GTK_WIDGET(cobject), glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE); } -RenderArea::~RenderArea() { -} - void RenderArea::onRealize() { - GtkWidget *widget = GTK_WIDGET(gobj()); - GdkGLContext *context = gtk_widget_get_gl_context(widget); - GdkGLDrawable *drawable = gtk_widget_get_gl_drawable(widget); - - if(!gdk_gl_drawable_gl_begin(drawable, context)) + if(!gdkGLBegin()) return; glClearColor(0, 0, 0, 0); @@ -46,7 +53,108 @@ void RenderArea::onRealize() { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - gdk_gl_drawable_gl_end(drawable); + gdkGLEnd(); +} + +bool RenderArea::onConfigureEvent(GdkEventConfigure *event) { + updateViewport(); + return true; +} + +bool RenderArea::onExposeEvent(GdkEventExpose *event) { + if(!gdkGLBegin()) + return false; + + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + glScalef(scale, scale, 1); + glTranslatef(-x, -y, 0); + + + drawGrid(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + + gdkSwapBuffers(); + gdkGLEnd(); + + return true; +} + +bool RenderArea::onScrollEvent(GdkEventScroll *event) { + switch(event->direction) { + case GDK_SCROLL_UP: + zoom(1, event->x/get_width(), event->y/get_height()); + return true; + case GDK_SCROLL_DOWN: + zoom(-1, event->x/get_width(), event->y/get_height()); + return true; + default: + return false; + } +} + +void RenderArea::zoom(int zoom, float x, float y) { + zoomLevel = std::max(std::min(zoomLevel + zoom, 50), -100); + scale = 100*std::pow(1.1f, zoomLevel); + + queue_draw(); +} + +void RenderArea::updateViewport() { + if(!gdkGLBegin()) + return; + + glViewport(0, 0, get_width(), get_height()); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + if(get_width() != 0 && get_height() != 0) + glScalef(2.0f/get_width(), -2.0f/get_height(), 1); + + gdkGLEnd(); + + queue_draw(); +} + +void RenderArea::drawGrid() { + float depth = std::log10(scale)-0.75f; + float depth2 = std::floor(depth); + float step = std::pow(0.1f, depth2); + float f; + int i; + float x1 = x-get_width()/(2*scale), y1 = y-get_height()/(2*scale); + float x2 = x+get_width()/(2*scale), y2 = y+get_height()/(2*scale); + + + glLineWidth(1.0f); + + glBegin(GL_LINES); + + for(i = 0; 0.4f*(depth-depth2+i-1) < 0.5f; i++) { + f = std::min(0.4f*(depth-depth2+i), 0.5f); + glColor3f(f, f, f); + + for(f = x1 - std::fmod(x1, step) - step; f <= x2; f+=step) { + glVertex2f(f, y1); + glVertex2f(f, y2); + } + + for(f = y1 - std::fmod(y1, step) - step; f <= y2; f+=step) { + glVertex2f(x1, f); + glVertex2f(x2, f); + } + + step *= 10; + } + + glEnd(); } } diff --git a/src/Gui/RenderArea.h b/src/Gui/RenderArea.h index 6695e09..d0b4ad3 100644 --- a/src/Gui/RenderArea.h +++ b/src/Gui/RenderArea.h @@ -11,12 +11,39 @@ namespace Gui { class RenderArea : public Gtk::DrawingArea { public: RenderArea(BaseObjectType *cobject, const Glib::RefPtr<Gnome::Glade::Xml> &xml); - virtual ~RenderArea(); - + private: static GdkGLConfig *glconfig; + float x, y; + + int zoomLevel; + float scale; + void onRealize(); + bool onConfigureEvent(GdkEventConfigure *event); + bool onExposeEvent(GdkEventExpose *event); + bool onScrollEvent(GdkEventScroll *event); + + void zoom(int zoom, float x = 0.5f, float y = 0.5f); + + void updateViewport(); + + void drawGrid(); + + bool gdkGLBegin() { + GtkWidget *widget = GTK_WIDGET(gobj()); + + return gdk_gl_drawable_gl_begin(gtk_widget_get_gl_drawable(widget), gtk_widget_get_gl_context(widget)); + } + + void gdkSwapBuffers() { + gdk_gl_drawable_swap_buffers(gtk_widget_get_gl_drawable(GTK_WIDGET(gobj()))); + } + + void gdkGLEnd() { + gdk_gl_drawable_gl_end(gtk_widget_get_gl_drawable(GTK_WIDGET(gobj()))); + } }; } diff --git a/zoomedit.glade b/zoomedit.glade index 6921eed..8efd02b 100644 --- a/zoomedit.glade +++ b/zoomedit.glade @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> -<!--Generated with glade3 3.4.3 on Sun Apr 6 23:07:46 2008 --> +<!--Generated with glade3 3.4.0 on Tue Apr 8 21:03:00 2008 --> <glade-interface> <widget class="GtkWindow" id="WindowMain"> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> @@ -170,7 +170,7 @@ <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> - <widget class="GtkToolButton" id="toolbutton1"> + <widget class="GtkToolButton" id="ToolButtonZoomIn"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="stock_id">gtk-zoom-in</property> @@ -180,7 +180,7 @@ </packing> </child> <child> - <widget class="GtkToolButton" id="toolbutton2"> + <widget class="GtkToolButton" id="ToolButtonZoomOut"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="stock_id">gtk-zoom-out</property> @@ -210,16 +210,10 @@ <placeholder/> </child> <child> - <widget class="GtkHScrollbar" id="Hscrollbar"> + <widget class="GtkDrawingArea" id="RenderArea"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="adjustment">0 0 100 1 10 10</property> </widget> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> </child> <child> <widget class="GtkVScrollbar" id="Vscrollbar"> @@ -234,10 +228,16 @@ </packing> </child> <child> - <widget class="GtkDrawingArea" id="RenderArea"> + <widget class="GtkHScrollbar" id="Hscrollbar"> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="adjustment">0 0 100 1 10 10</property> </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> </child> </widget> <packing> |