* use the GtkBuilder for the ui
[hkl3d.git] / gui / ghkl3d / hkl3d-gui-scene.cpp
blob21c964f443298681295f64c60a1b8d4d44e95081
1 /*
2 * This file is part of the hkl3d library.
3 * inspired from logo-model.c of the GtkGLExt logo models.
4 * written by Naofumi Yasufuku <naofumi@users.sourceforge.net>
6 * The hkl library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * The hkl library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with the hkl library. If not, see <http://www.gnu.org/licenses/>.
19 * Copyright (C) 2010 Synchrotron SOLEIL
20 * L'Orme des Merisiers Saint-Aubin
21 * BP 48 91192 GIF-sur-YVETTE CEDEX
23 * Authors: Oussama Sboui <oussama.sboui@synchrotron-soleil.fr>
24 * Picca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>
27 #include <iostream>
29 #include "hkl3d-gui-scene.h"
31 ///////////////////////////////////////////////////////////////////////////////
33 // OpenGL frame buffer configuration utilities.
35 ///////////////////////////////////////////////////////////////////////////////
37 struct GLConfigUtil
39 static void print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig,
40 const char* attrib_str,
41 int attrib,
42 bool is_boolean);
44 static void examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig);
48 // Print a configuration attribute.
50 void GLConfigUtil::print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig,
51 const char* attrib_str,
52 int attrib,
53 bool is_boolean)
55 int value;
57 if (glconfig->get_attrib(attrib, value)){
58 std::cout << attrib_str << " = ";
59 if (is_boolean)
60 std::cout << (value == true ? "true" : "false") << std::endl;
61 else
62 std::cout << value << std::endl;
63 }else{
64 std::cout << "*** Cannot get "
65 << attrib_str
66 << " attribute value\n";
71 // Print configuration attributes.
73 void GLConfigUtil::examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig)
75 std::cout << "\nOpenGL visual configurations :\n\n";
77 std::cout << "glconfig->is_rgba() = "
78 << (glconfig->is_rgba() ? "true" : "false")
79 << std::endl;
80 std::cout << "glconfig->is_double_buffered() = "
81 << (glconfig->is_double_buffered() ? "true" : "false")
82 << std::endl;
83 std::cout << "glconfig->is_stereo() = "
84 << (glconfig->is_stereo() ? "true" : "false")
85 << std::endl;
86 std::cout << "glconfig->has_alpha() = "
87 << (glconfig->has_alpha() ? "true" : "false")
88 << std::endl;
89 std::cout << "glconfig->has_depth_buffer() = "
90 << (glconfig->has_depth_buffer() ? "true" : "false")
91 << std::endl;
92 std::cout << "glconfig->has_stencil_buffer() = "
93 << (glconfig->has_stencil_buffer() ? "true" : "false")
94 << std::endl;
95 std::cout << "glconfig->has_accum_buffer() = "
96 << (glconfig->has_accum_buffer() ? "true" : "false")
97 << std::endl;
99 std::cout << std::endl;
101 print_gl_attrib(glconfig, "Gdk::GL::USE_GL", Gdk::GL::USE_GL, true);
102 print_gl_attrib(glconfig, "Gdk::GL::BUFFER_SIZE", Gdk::GL::BUFFER_SIZE, false);
103 print_gl_attrib(glconfig, "Gdk::GL::LEVEL", Gdk::GL::LEVEL, false);
104 print_gl_attrib(glconfig, "Gdk::GL::RGBA", Gdk::GL::RGBA, true);
105 print_gl_attrib(glconfig, "Gdk::GL::DOUBLEBUFFER", Gdk::GL::DOUBLEBUFFER, true);
106 print_gl_attrib(glconfig, "Gdk::GL::STEREO", Gdk::GL::STEREO, true);
107 print_gl_attrib(glconfig, "Gdk::GL::AUX_BUFFERS", Gdk::GL::AUX_BUFFERS, false);
108 print_gl_attrib(glconfig, "Gdk::GL::RED_SIZE", Gdk::GL::RED_SIZE, false);
109 print_gl_attrib(glconfig, "Gdk::GL::GREEN_SIZE", Gdk::GL::GREEN_SIZE, false);
110 print_gl_attrib(glconfig, "Gdk::GL::BLUE_SIZE", Gdk::GL::BLUE_SIZE, false);
111 print_gl_attrib(glconfig, "Gdk::GL::ALPHA_SIZE", Gdk::GL::ALPHA_SIZE, false);
112 print_gl_attrib(glconfig, "Gdk::GL::DEPTH_SIZE", Gdk::GL::DEPTH_SIZE, false);
113 print_gl_attrib(glconfig, "Gdk::GL::STENCIL_SIZE", Gdk::GL::STENCIL_SIZE, false);
114 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_RED_SIZE", Gdk::GL::ACCUM_RED_SIZE, false);
115 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_GREEN_SIZE", Gdk::GL::ACCUM_GREEN_SIZE, false);
116 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_BLUE_SIZE", Gdk::GL::ACCUM_BLUE_SIZE, false);
117 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_ALPHA_SIZE", Gdk::GL::ACCUM_ALPHA_SIZE, false);
119 std::cout << std::endl;
122 namespace Logo
125 // Scene class implementation.
127 const unsigned int Scene::TIMEOUT_INTERVAL = 1000;
129 const float Scene::CLEAR_COLOR[4] = { 0.5, 0.5, 0.8, 1.0 };
130 const float Scene::CLEAR_DEPTH = 1.0;
132 const float Scene::LIGHT0_POSITION[4] = { 0.0, 0.0, 30.0, 0.0 };
133 const float Scene::LIGHT0_DIFFUSE[4] = { 1.0, 1.0, 1.0, 1.0 };
134 const float Scene::LIGHT0_SPECULAR[4] = { 1.0, 1.0, 1.0, 1.0 };
136 Scene::Scene(unsigned int rot_count,
137 bool enable_anim)
138 : m_Menu(0), m_Model(rot_count, enable_anim)
141 // Configure OpenGL-capable visual.
143 Glib::RefPtr<Gdk::GL::Config> glconfig;
145 // Try double-buffered visual
146 glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB |
147 Gdk::GL::MODE_DEPTH |
148 Gdk::GL::MODE_DOUBLE);
149 if (!glconfig) {
150 std::cerr << "*** Cannot find the double-buffered visual.\n"
151 << "*** Trying single-buffered visual.\n";
153 // Try single-buffered visual
154 glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB |
155 Gdk::GL::MODE_DEPTH);
156 if (!glconfig) {
157 std::cerr << "*** Cannot find any OpenGL-capable visual.\n";
158 std::exit(1);
162 // print frame buffer attributes.
163 GLConfigUtil::examine_gl_attrib(glconfig);
166 // Set OpenGL-capability to the widget.
168 this->set_gl_capability(glconfig);
171 // Add events.
173 this->add_events(Gdk::BUTTON1_MOTION_MASK |
174 Gdk::BUTTON2_MOTION_MASK |
175 Gdk::BUTTON_PRESS_MASK |
176 Gdk::VISIBILITY_NOTIFY_MASK);
178 // View transformation signals.
179 signal_button_press_event().connect(
180 sigc::bind(sigc::mem_fun(m_View, &View::on_button_press_event), this));
181 signal_motion_notify_event().connect(
182 sigc::bind(sigc::mem_fun(m_View, &View::on_motion_notify_event), this));
185 // Popup menu.
187 m_Menu = this->create_popup_menu();
190 Scene::~Scene(void)
194 void Scene::on_realize(void)
196 // We need to call the base on_realize()
197 Gtk::DrawingArea::on_realize();
200 // Get GL::Drawable.
202 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = this->get_gl_drawable();
205 // GL calls.
207 // *** OpenGL BEGIN ***
208 if (!gldrawable->gl_begin(this->get_gl_context()))
209 return;
211 glClearColor(CLEAR_COLOR[0], CLEAR_COLOR[1], CLEAR_COLOR[2], CLEAR_COLOR[3]);
212 glClearDepth(CLEAR_DEPTH);
214 glLightfv(GL_LIGHT0, GL_POSITION, LIGHT0_POSITION);
215 glLightfv(GL_LIGHT0, GL_DIFFUSE, LIGHT0_DIFFUSE);
216 glLightfv(GL_LIGHT0, GL_SPECULAR, LIGHT0_SPECULAR);
218 glEnable(GL_LIGHTING);
219 glEnable(GL_LIGHT0);
221 glEnable(GL_DEPTH_TEST);
223 glShadeModel(GL_SMOOTH);
225 gldrawable->gl_end();
226 // *** OpenGL END ***
229 bool Scene::on_configure_event(GdkEventConfigure* event)
232 // Get GL::Drawable.
234 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = this->get_gl_drawable();
237 // GL calls.
239 // *** OpenGL BEGIN ***
240 if (!gldrawable->gl_begin(this->get_gl_context()))
241 return false;
243 m_View.frustum(this->get_width(), this->get_height());
245 gldrawable->gl_end();
246 // *** OpenGL END ***
248 return true;
251 bool Scene::on_expose_event(GdkEventExpose* event)
254 // Get GL::Drawable.
256 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable();
259 // GL calls.
261 // *** OpenGL BEGIN ***
262 if (!gldrawable->gl_begin(get_gl_context()))
263 return false;
265 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
267 glLoadIdentity();
269 // View transformation.
270 m_View.xform();
272 // Logo model.
273 m_Model.draw();
275 // Swap buffers.
276 if (gldrawable->is_double_buffered())
277 gldrawable->swap_buffers();
278 else
279 glFlush();
281 gldrawable->gl_end();
282 // *** OpenGL END ***
284 return true;
287 bool Scene::on_button_press_event(GdkEventButton* event)
289 if (event->button == 3) {
290 m_Menu->popup(event->button, event->time);
291 return true;
294 // don't block
295 return false;
298 bool Scene::on_map_event(GdkEventAny* event)
300 if (m_Model.anim_is_enabled())
301 this->timeout_add();
303 return true;
306 bool Scene::on_unmap_event(GdkEventAny* event)
308 this->timeout_remove();
310 return true;
313 bool Scene::on_visibility_notify_event(GdkEventVisibility* event)
315 if (m_Model.anim_is_enabled()) {
316 if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
317 this->timeout_remove();
318 else
319 this->timeout_add();
322 return true;
325 bool Scene::on_timeout(void)
327 // Invalidate whole window.
328 this->invalidate();
329 // Update window synchronously (fast).
330 this->update();
332 return true;
335 void Scene::timeout_add(void)
337 if (!m_ConnectionTimeout.connected())
338 m_ConnectionTimeout = Glib::signal_timeout().connect(
339 sigc::mem_fun(*this, &Scene::on_timeout), TIMEOUT_INTERVAL);
342 void Scene::timeout_remove(void)
344 if (m_ConnectionTimeout.connected())
345 m_ConnectionTimeout.disconnect();
348 void Scene::toggle_anim(void)
350 if (m_Model.anim_is_enabled()) {
351 m_Model.disable_anim();
352 this->timeout_remove();
353 }else{
354 m_Model.enable_anim();
355 this->timeout_add();
359 void Scene::init_anim(void)
361 m_View.reset();
362 m_Model.reset_anim();
364 this->invalidate();
367 Gtk::Menu* Scene::create_popup_menu(void)
369 Gtk::Menu* menu = Gtk::manage(new Gtk::Menu());
371 Gtk::Menu::MenuList& menu_list = menu->items();
373 // Toggle animation
374 menu_list.push_back(
375 Gtk::Menu_Helpers::MenuElem("Toggle Animation",
376 sigc::mem_fun(*this, &Scene::toggle_anim)));
378 // Init orientation
379 menu_list.push_back(
380 Gtk::Menu_Helpers::MenuElem("Initialize",
381 sigc::mem_fun(*this, &Scene::init_anim)));
383 // Quit
384 menu_list.push_back(
385 Gtk::Menu_Helpers::MenuElem("Quit",
386 sigc::ptr_fun(&Gtk::Main::quit)));
388 return menu;
391 } // namespace Logo