/* * RenderArea.cpp * * Copyright (C) 2008 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "RenderArea.h" #include #include #include #include #include namespace ZoomEdit { namespace Gui { GdkGLConfig *RenderArea::glconfig = 0; RenderArea::RenderArea(BaseObjectType *cobject, const Glib::RefPtr&) : Gtk::DrawingArea(cobject), view(0), inWindow(false) { 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 if(!glconfig) { std::cerr << "*** No appropriate OpenGL-capable visual found." << std::endl; std::exit(1); } } 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)); signal_button_press_event().connect(sigc::mem_fun(this, &RenderArea::onButtonPressEvent)); signal_enter_notify_event().connect(sigc::mem_fun(this, &RenderArea::onEnterNotifyEvent)); signal_leave_notify_event().connect(sigc::mem_fun(this, &RenderArea::onLeaveNotifyEvent)); signal_motion_notify_event().connect(sigc::mem_fun(this, &RenderArea::onMotionNotifyEvent)); gtk_widget_set_gl_capability(GTK_WIDGET(cobject), glconfig, 0, TRUE, GDK_GL_RGBA_TYPE); } void RenderArea::onRealize() { if(!gdkGLBegin()) return; glClearColor(0, 0, 0, 0); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gdkGLEnd(); } bool RenderArea::onConfigureEvent(GdkEventConfigure*) { if(!gdkGLBegin()) return false; 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(); return true; } bool RenderArea::onExposeEvent(GdkEventExpose*) { if(!gdkGLBegin()) return false; if(view) view->render(this); gdkSwapBuffers(); gdkGLEnd(); return true; } bool RenderArea::onScrollEvent(GdkEventScroll *event) { if(view) { switch(event->direction) { case GDK_SCROLL_UP: view->zoom(this, 1, event->x - get_width()/2, event->y - get_height()/2); return true; case GDK_SCROLL_DOWN: view->zoom(this, -1, event->x - get_width()/2, event->y - get_height()/2); return true; default: return false; } } return false; } bool RenderArea::onButtonPressEvent(GdkEventButton *event) { if(view && event->button == 1) view->click(this, event->x, event->y); return true; } bool RenderArea::onEnterNotifyEvent(GdkEventCrossing *event) { inWindow = true; xHover = event->x; yHover = event->y; return true; } bool RenderArea::onLeaveNotifyEvent(GdkEventCrossing*) { inWindow = false; return true; } bool RenderArea::onMotionNotifyEvent(GdkEventMotion *event) { if(!inWindow) { xHover = event->x; yHover = event->y; inWindow = true; return true; } if(view) view->move(this, xHover - event->x, yHover - event->y, event->state); xHover = event->x; yHover = event->y; return true; } } }