From Jeremy Moles, osgviewerGTK example
This commit is contained in:
@@ -211,6 +211,16 @@ FIND_PACKAGE(ZLIB)
|
||||
FIND_PACKAGE(GDAL)
|
||||
FIND_PACKAGE(CURL)
|
||||
|
||||
INCLUDE(FindPkgConfig)
|
||||
|
||||
PKG_CHECK_MODULES(GTK gtk+-2.0)
|
||||
|
||||
IF(WIN32)
|
||||
PKG_CHECK_MODULES(GTKGL gtkglext-win32-1.0)
|
||||
ELSE(WIN32)
|
||||
PKG_CHECK_MODULES(GTKGL gtkglext-x11-1.0)
|
||||
ENDIF(WIN32)
|
||||
|
||||
SET(wxWidgets_USE_LIBS base core gl net)
|
||||
FIND_PACKAGE(wxWidgets)
|
||||
|
||||
|
||||
@@ -113,6 +113,10 @@ IF(DYNAMIC_OPENSCENEGRAPH)
|
||||
ADD_SUBDIRECTORY(osgviewerSDL)
|
||||
ENDIF(SDL_FOUND)
|
||||
|
||||
IF (GTKGL_FOUND)
|
||||
ADD_SUBDIRECTORY(osgviewerGTK)
|
||||
ENDIF(GTKGL_FOUND)
|
||||
|
||||
IF (FOX_FOUND)
|
||||
ADD_SUBDIRECTORY(osgviewerFOX)
|
||||
ENDIF(FOX_FOUND)
|
||||
|
||||
8
examples/osgviewerGTK/CMakeLists.txt
Normal file
8
examples/osgviewerGTK/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
SET(TARGET_SRC osggtkdrawingarea.cpp osgviewerGTK.cpp)
|
||||
SET(TARGET_H osggtkdrawingarea.h)
|
||||
|
||||
INCLUDE_DIRECTORIES(${GTK_INCLUDE_DIRS} ${GTKGL_INCLUDE_DIRS})
|
||||
LINK_DIRECTORIES(${GTK_LIBRARY_DIRS} ${GTKGL_LIBRARY_DIRS})
|
||||
LINK_LIBRARIES(osgViewer ${GTK_LIBRARIES} ${GTKGL_LIBRARIES})
|
||||
|
||||
SETUP_EXAMPLE(osgviewerGTK)
|
||||
148
examples/osgviewerGTK/osggtkdrawingarea.cpp
Normal file
148
examples/osgviewerGTK/osggtkdrawingarea.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
// by: Jeremy Moles <jeremy@emperorlinux.com> 2007
|
||||
|
||||
#include "osggtkdrawingarea.h"
|
||||
|
||||
OSGGTKDrawingArea::OSGGTKDrawingArea():
|
||||
_widget (gtk_drawing_area_new()),
|
||||
_glconfig (0),
|
||||
_context (0),
|
||||
_drawable (0),
|
||||
_state (0),
|
||||
_queue (*getEventQueue()) {
|
||||
setCameraManipulator(new osgGA::TrackballManipulator());
|
||||
}
|
||||
|
||||
OSGGTKDrawingArea::~OSGGTKDrawingArea() {
|
||||
}
|
||||
|
||||
bool OSGGTKDrawingArea::createWidget(int width, int height) {
|
||||
_glconfig = gdk_gl_config_new_by_mode(static_cast<GdkGLConfigMode>(
|
||||
GDK_GL_MODE_RGBA |
|
||||
GDK_GL_MODE_DEPTH |
|
||||
GDK_GL_MODE_DOUBLE
|
||||
));
|
||||
|
||||
if(not _glconfig) {
|
||||
osg::notify(osg::FATAL) << "Fail!" << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
gtk_widget_set_size_request(_widget, width, height);
|
||||
|
||||
gtk_widget_set_gl_capability(
|
||||
_widget,
|
||||
_glconfig,
|
||||
0,
|
||||
true,
|
||||
GDK_GL_RGBA_TYPE
|
||||
);
|
||||
|
||||
gtk_widget_add_events(
|
||||
_widget,
|
||||
GDK_BUTTON1_MOTION_MASK |
|
||||
GDK_BUTTON2_MOTION_MASK |
|
||||
GDK_BUTTON3_MOTION_MASK |
|
||||
GDK_POINTER_MOTION_MASK |
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_VISIBILITY_NOTIFY_MASK
|
||||
);
|
||||
|
||||
// We do this so that we don't have to suck up ALL the input to the
|
||||
// window, but instead just when the drawing area is focused.
|
||||
g_object_set(_widget, "can-focus", true, NULL);
|
||||
|
||||
_connect("realize", G_CALLBACK(&OSGGTKDrawingArea::_srealize));
|
||||
_connect("unrealize", G_CALLBACK(&OSGGTKDrawingArea::_sunrealize));
|
||||
_connect("expose_event", G_CALLBACK(&OSGGTKDrawingArea::_sexpose_event));
|
||||
_connect("configure_event", G_CALLBACK(&OSGGTKDrawingArea::_sconfigure_event));
|
||||
_connect("motion_notify_event", G_CALLBACK(&OSGGTKDrawingArea::_smotion_notify_event));
|
||||
_connect("button_press_event", G_CALLBACK(&OSGGTKDrawingArea::_sbutton_press_event));
|
||||
_connect("button_release_event", G_CALLBACK(&OSGGTKDrawingArea::_sbutton_press_event));
|
||||
_connect("key_press_event", G_CALLBACK(&OSGGTKDrawingArea::_skey_press_event));
|
||||
|
||||
setUpViewerAsEmbeddedInWindow(0, 0, width, height);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OSGGTKDrawingArea::_realize(GtkWidget* widget) {
|
||||
_context = gtk_widget_get_gl_context(widget);
|
||||
_drawable = gtk_widget_get_gl_drawable(widget);
|
||||
|
||||
gtkRealize();
|
||||
}
|
||||
|
||||
void OSGGTKDrawingArea::_unrealize(GtkWidget* widget) {
|
||||
gtkUnrealize();
|
||||
}
|
||||
|
||||
bool OSGGTKDrawingArea::_expose_event(GtkWidget* widget, GdkEventExpose* event) {
|
||||
if(not gtkGLBegin()) return false;
|
||||
|
||||
frame();
|
||||
|
||||
gtkGLSwap();
|
||||
gtkGLEnd();
|
||||
|
||||
return gtkExpose();
|
||||
}
|
||||
|
||||
bool OSGGTKDrawingArea::_configure_event(GtkWidget* widget, GdkEventConfigure* event) {
|
||||
gtkGLBegin();
|
||||
|
||||
_queue.windowResize(0, 0, event->width, event->height);
|
||||
|
||||
gtkGLEnd();
|
||||
|
||||
return gtkConfigure(event->width, event->height);
|
||||
}
|
||||
|
||||
bool OSGGTKDrawingArea::_motion_notify_event(GtkWidget* widget, GdkEventMotion* event) {
|
||||
_state = event->state;
|
||||
|
||||
_queue.mouseMotion(event->x, event->y);
|
||||
|
||||
return gtkMotionNotify(event->x, event->y);
|
||||
}
|
||||
|
||||
bool OSGGTKDrawingArea::_button_press_event(GtkWidget* widget, GdkEventButton* event) {
|
||||
_state = event->state;
|
||||
|
||||
if(event->type == GDK_BUTTON_PRESS) {
|
||||
if(event->button == 1) gtk_widget_grab_focus(_widget);
|
||||
|
||||
_queue.mouseButtonPress(event->x, event->y, event->button);
|
||||
|
||||
return gtkButtonPress(event->x, event->y, event->button);
|
||||
}
|
||||
|
||||
else if(event->type == GDK_BUTTON_RELEASE) {
|
||||
_queue.mouseButtonRelease(event->x, event->y, event->button);
|
||||
|
||||
return gtkButtonRelease(event->x, event->y, event->button);
|
||||
}
|
||||
|
||||
else return false;
|
||||
}
|
||||
|
||||
bool OSGGTKDrawingArea::_key_press_event(GtkWidget* widget, GdkEventKey* event) {
|
||||
_state = event->state;
|
||||
|
||||
if(event->type == GDK_KEY_PRESS) {
|
||||
_queue.keyPress(event->keyval);
|
||||
|
||||
return gtkKeyPress(event->keyval);
|
||||
}
|
||||
|
||||
else if(event->type == GDK_KEY_RELEASE) {
|
||||
_queue.keyRelease(event->keyval);
|
||||
|
||||
return gtkKeyRelease(event->keyval);
|
||||
}
|
||||
|
||||
else return false;
|
||||
}
|
||||
207
examples/osgviewerGTK/osggtkdrawingarea.h
Normal file
207
examples/osgviewerGTK/osggtkdrawingarea.h
Normal file
@@ -0,0 +1,207 @@
|
||||
// by: Jeremy Moles <jeremy@emperorlinux.com> 2007
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtk/gtkgl.h>
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
// This is an implementation of SimpleViewer that is designed to be subclassed
|
||||
// and used as a GtkDrawingArea in a GTK application. Because of the implemention
|
||||
// of GTK, I was unable to derive from GtkWidget and instead had to "wrap" it.
|
||||
// Conceptually, however, you can think of an OSGGTKDrawingArea as both an OSG
|
||||
// Viewer AND GtkDrawingArea.
|
||||
//
|
||||
// While it is possible to use this class directly, it won't end up doing anything
|
||||
// interesting without calls to queueDraw, which ideally are done in the user's
|
||||
// subclass implementation (see: osgviewerGTK).
|
||||
class OSGGTKDrawingArea : public osgViewer::Viewer {
|
||||
GtkWidget* _widget;
|
||||
GdkGLConfig* _glconfig;
|
||||
GdkGLContext* _context;
|
||||
GdkGLDrawable* _drawable;
|
||||
|
||||
unsigned int _state;
|
||||
|
||||
osgGA::EventQueue& _queue;
|
||||
|
||||
static OSGGTKDrawingArea* _self(gpointer self) {
|
||||
return static_cast<OSGGTKDrawingArea*>(self);
|
||||
}
|
||||
|
||||
// A simple helper function to connect us to the various GTK signals.
|
||||
void _connect(const char* name, GCallback callback) {
|
||||
g_signal_connect(G_OBJECT(_widget), name, callback, this);
|
||||
}
|
||||
|
||||
void _realize (GtkWidget*);
|
||||
void _unrealize (GtkWidget*);
|
||||
bool _expose_event (GtkWidget*, GdkEventExpose*);
|
||||
bool _configure_event (GtkWidget*, GdkEventConfigure*);
|
||||
bool _motion_notify_event (GtkWidget*, GdkEventMotion*);
|
||||
bool _button_press_event (GtkWidget*, GdkEventButton*);
|
||||
bool _key_press_event (GtkWidget*, GdkEventKey*);
|
||||
|
||||
// The following functions are static "wrappers" so that we can invoke the
|
||||
// bound methods of a class instance by passing the "this" pointer as the
|
||||
// self argument and invoking it explicitly.
|
||||
static void _srealize(GtkWidget* widget, gpointer self) {
|
||||
_self(self)->_realize(widget);
|
||||
}
|
||||
|
||||
static void _sunrealize(GtkWidget* widget, gpointer self) {
|
||||
_self(self)->_unrealize(widget);
|
||||
}
|
||||
|
||||
static bool _sexpose_event(GtkWidget* widget, GdkEventExpose* expose, gpointer self) {
|
||||
return _self(self)->_expose_event(widget, expose);
|
||||
}
|
||||
|
||||
static bool _sconfigure_event(
|
||||
GtkWidget* widget,
|
||||
GdkEventConfigure* event,
|
||||
gpointer self
|
||||
) {
|
||||
return _self(self)->_configure_event(widget, event);
|
||||
}
|
||||
|
||||
static bool _smotion_notify_event(
|
||||
GtkWidget* widget,
|
||||
GdkEventMotion* event,
|
||||
gpointer self
|
||||
) {
|
||||
return _self(self)->_motion_notify_event(widget, event);
|
||||
}
|
||||
|
||||
static bool _sbutton_press_event(
|
||||
GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
gpointer self
|
||||
) {
|
||||
return _self(self)->_button_press_event(widget, event);
|
||||
}
|
||||
|
||||
static bool _skey_press_event(
|
||||
GtkWidget* widget,
|
||||
GdkEventKey* event,
|
||||
gpointer self
|
||||
) {
|
||||
return _self(self)->_key_press_event(widget, event);
|
||||
}
|
||||
|
||||
protected:
|
||||
// You can override these in your subclass if you'd like. :)
|
||||
// Right now they're fairly uninformative, but they could be easily extended.
|
||||
// Note that the "state" information isn't passed around to each function
|
||||
// but is instead stored and abstracted internally. See below.
|
||||
|
||||
virtual void gtkRealize () {};
|
||||
virtual void gtkUnrealize () {};
|
||||
virtual bool gtkExpose () {
|
||||
return true;
|
||||
};
|
||||
|
||||
// The new width and height.
|
||||
virtual bool gtkConfigure(int, int) {
|
||||
return true;
|
||||
};
|
||||
|
||||
// The "normalized" coordinates of the mouse.
|
||||
virtual bool gtkMotionNotify(double, double) {
|
||||
return true;
|
||||
};
|
||||
|
||||
// The "normalized" coordinates of the mouse and the mouse button code on down.
|
||||
virtual bool gtkButtonPress(double, double, unsigned int) {
|
||||
return true;
|
||||
};
|
||||
|
||||
// The "normalized" coordinates of the mouse and mouse button code on release.
|
||||
virtual bool gtkButtonRelease(double, double, unsigned int) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The X key value on down.
|
||||
virtual bool gtkKeyPress(unsigned int) {
|
||||
return true;
|
||||
};
|
||||
|
||||
// The X key value on release.
|
||||
virtual bool gtkKeyRelease(unsigned int) {
|
||||
return true;
|
||||
};
|
||||
|
||||
// These functions wrap state tests of the most recent state in the
|
||||
// GtkDrawingArea.
|
||||
|
||||
inline bool stateShift() {
|
||||
return _state & GDK_SHIFT_MASK;
|
||||
}
|
||||
|
||||
inline bool stateLock() {
|
||||
return _state & GDK_LOCK_MASK;
|
||||
}
|
||||
|
||||
inline bool stateControl() {
|
||||
return _state & GDK_CONTROL_MASK;
|
||||
}
|
||||
|
||||
inline bool stateMod() {
|
||||
return _state & (
|
||||
GDK_MOD1_MASK |
|
||||
GDK_MOD2_MASK |
|
||||
GDK_MOD3_MASK |
|
||||
GDK_MOD4_MASK |
|
||||
GDK_MOD5_MASK
|
||||
);
|
||||
}
|
||||
|
||||
inline bool stateButton() {
|
||||
return _state & (
|
||||
GDK_BUTTON1_MASK |
|
||||
GDK_BUTTON2_MASK |
|
||||
GDK_BUTTON3_MASK |
|
||||
GDK_BUTTON4_MASK |
|
||||
GDK_BUTTON5_MASK
|
||||
);
|
||||
}
|
||||
|
||||
public:
|
||||
OSGGTKDrawingArea ();
|
||||
~OSGGTKDrawingArea ();
|
||||
|
||||
bool createWidget(int, int);
|
||||
|
||||
GtkWidget* getWidget() {
|
||||
return _widget;
|
||||
}
|
||||
|
||||
bool gtkGLBegin() {
|
||||
if(_drawable and _context) return gdk_gl_drawable_gl_begin(_drawable, _context);
|
||||
|
||||
else return false;
|
||||
}
|
||||
|
||||
void gtkGLEnd() {
|
||||
if(_drawable) gdk_gl_drawable_gl_end(_drawable);
|
||||
}
|
||||
|
||||
// Because of GTK's internal double buffering, I'm not sure if we're really
|
||||
// taking advantage of OpenGL's internal swapping.
|
||||
bool gtkGLSwap() {
|
||||
if(_drawable and gdk_gl_drawable_is_double_buffered(_drawable)) {
|
||||
gdk_gl_drawable_swap_buffers(_drawable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
else {
|
||||
glFlush();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void queueDraw() {
|
||||
gtk_widget_queue_draw(_widget);
|
||||
}
|
||||
};
|
||||
234
examples/osgviewerGTK/osgviewerGTK.cpp
Normal file
234
examples/osgviewerGTK/osgviewerGTK.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
// by: Jeremy Moles <jeremy@emperorlinux.com> 2007
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <osg/Stats>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include "osggtkdrawingarea.h"
|
||||
|
||||
const char* HELP_TEXT =
|
||||
"Use CTRL or SHIFT plus right-click to pull up a fake menu.\n"
|
||||
"Use the standard TrackballManipulator keys to rotate the loaded\n"
|
||||
"model (with caveats; the model won't keep rotating).\n"
|
||||
"\n"
|
||||
"<b>OpenSceneGraph Project, 2008</b>"
|
||||
;
|
||||
|
||||
// If you want to see how to connect class method to callbacks, take a look at the
|
||||
// implementation of OSGGTKDrawingArea. It's dirty, but it's the only way I could
|
||||
// come up with.
|
||||
bool activate(GtkWidget* widget, gpointer) {
|
||||
GtkWidget* label = gtk_bin_get_child(GTK_BIN(widget));
|
||||
|
||||
std::cout << "MENU: " << gtk_label_get_label(GTK_LABEL(label)) << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Our derived OSGGTKDrawingArea "widget." Redraws occur while the mouse buttons
|
||||
// are held down and mouse motion is detected.
|
||||
//
|
||||
// This is the easiest way to demonstrate the use of OSGGTKDrawingArea. We override
|
||||
// a few of the event methods to setup our menu and to issue redraws. Note that an
|
||||
// unmodified OSGGTKDrawingArea never calls queueDraw, so OSG is never asked to render
|
||||
// itself.
|
||||
class ExampleOSGGTKDrawingArea : public OSGGTKDrawingArea {
|
||||
GtkWidget* _menu;
|
||||
|
||||
unsigned int _tid;
|
||||
|
||||
// A helper function to easily setup our menu entries.
|
||||
void _menuAdd(const std::string& title) {
|
||||
GtkWidget* item = gtk_menu_item_new_with_label(title.c_str());
|
||||
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(_menu), item);
|
||||
|
||||
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(activate), 0);
|
||||
}
|
||||
|
||||
bool _clicked(GtkWidget* widget) {
|
||||
const char* text = gtk_label_get_label(
|
||||
GTK_LABEL(gtk_bin_get_child(GTK_BIN(widget)))
|
||||
);
|
||||
|
||||
if(not std::strncmp(text, "Close", 5)) gtk_main_quit();
|
||||
|
||||
else if(not std::strncmp(text, "Open File", 9)) {
|
||||
GtkWidget* of = gtk_file_chooser_dialog_new(
|
||||
"Please select an OSG file...",
|
||||
GTK_WINDOW(gtk_widget_get_toplevel(getWidget())),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL,
|
||||
GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN,
|
||||
GTK_RESPONSE_ACCEPT,
|
||||
NULL
|
||||
);
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(of)) == GTK_RESPONSE_ACCEPT) {
|
||||
char* file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(of));
|
||||
|
||||
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(file);
|
||||
|
||||
if(model.valid()) {
|
||||
setSceneData(model.get());
|
||||
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
g_free(file);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(of);
|
||||
}
|
||||
|
||||
// Assume we're wanting FPS toggling.
|
||||
else {
|
||||
if(not _tid) {
|
||||
_tid = g_timeout_add(
|
||||
15,
|
||||
(GSourceFunc)(ExampleOSGGTKDrawingArea::timeout),
|
||||
this
|
||||
);
|
||||
|
||||
gtk_button_set_label(GTK_BUTTON(widget), "Toggle 60 FPS (off)");
|
||||
}
|
||||
|
||||
else {
|
||||
g_source_remove(_tid);
|
||||
gtk_button_set_label(GTK_BUTTON(widget), "Toggle 60 FPS (on)");
|
||||
|
||||
_tid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Check right-click release to see if we need to popup our menu.
|
||||
bool gtkButtonRelease(double, double, unsigned int button) {
|
||||
if(button == 3 and (stateControl() or stateShift())) gtk_menu_popup(
|
||||
GTK_MENU(_menu),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
button,
|
||||
0
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Our "main" drawing pump. Since our app is just a model viewer, we use
|
||||
// click+motion as our criteria for issuing OpenGL refreshes.
|
||||
bool gtkMotionNotify(double, double) {
|
||||
if(stateButton()) queueDraw();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
ExampleOSGGTKDrawingArea():
|
||||
OSGGTKDrawingArea (),
|
||||
_menu (gtk_menu_new()),
|
||||
_tid (0) {
|
||||
_menuAdd("Option");
|
||||
_menuAdd("Another Option");
|
||||
_menuAdd("Still More Options");
|
||||
|
||||
gtk_widget_show_all(_menu);
|
||||
|
||||
getCamera()->setStats(new osg::Stats("omg"));
|
||||
}
|
||||
|
||||
~ExampleOSGGTKDrawingArea() {}
|
||||
|
||||
// Public so that we can use this as a callback in main().
|
||||
static bool clicked(GtkWidget* widget, gpointer self) {
|
||||
return static_cast<ExampleOSGGTKDrawingArea*>(self)->_clicked(widget);
|
||||
}
|
||||
|
||||
//static gboolean timeout(GtkWidget* widget) {
|
||||
static bool timeout(void* self) {
|
||||
static_cast<ExampleOSGGTKDrawingArea*>(self)->queueDraw();
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Our main() function! FINALLY! Most of this code is GTK stuff, so it's mostly boilerplate.
|
||||
// If we wanted to get real jiggy with it we could use Glade and cut down about 20 lines of
|
||||
// code or so.
|
||||
int main(int argc, char** argv) {
|
||||
gtk_init(&argc, &argv);
|
||||
gtk_gl_init(&argc, &argv);
|
||||
|
||||
ExampleOSGGTKDrawingArea da;
|
||||
|
||||
if(da.createWidget(640, 480)) {
|
||||
if(argc >= 2) {
|
||||
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(argv[1]);
|
||||
|
||||
if(model.valid()) da.setSceneData(model.get());
|
||||
}
|
||||
|
||||
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
GtkWidget* vbox1 = gtk_vbox_new(false, 3);
|
||||
GtkWidget* vbox2 = gtk_vbox_new(false, 3);
|
||||
GtkWidget* hbox = gtk_hbox_new(false, 3);
|
||||
GtkWidget* label = gtk_label_new("");
|
||||
GtkWidget* buttons[] = {
|
||||
gtk_button_new_with_label("Open File"),
|
||||
gtk_button_new_with_label("Toggle 60 FPS (on)"),
|
||||
gtk_button_new_with_label("Close")
|
||||
};
|
||||
|
||||
gtk_label_set_use_markup(GTK_LABEL(label), true);
|
||||
gtk_label_set_label(GTK_LABEL(label), HELP_TEXT);
|
||||
|
||||
for(unsigned int i = 0; i < sizeof(buttons) / sizeof(GtkWidget*); i++) {
|
||||
gtk_box_pack_start(
|
||||
GTK_BOX(vbox2),
|
||||
buttons[i],
|
||||
false,
|
||||
false,
|
||||
0
|
||||
);
|
||||
|
||||
g_signal_connect(
|
||||
G_OBJECT(buttons[i]),
|
||||
"clicked",
|
||||
G_CALLBACK(ExampleOSGGTKDrawingArea::clicked),
|
||||
&da
|
||||
);
|
||||
}
|
||||
|
||||
gtk_window_set_title(GTK_WINDOW(window), "osgviewerGTK");
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vbox2, true, true, 2);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), label, true, true, 2);
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(vbox1), da.getWidget(), true, true, 2);
|
||||
gtk_box_pack_start(GTK_BOX(vbox1), hbox, false, false, 2);
|
||||
|
||||
gtk_container_set_reallocate_redraws(GTK_CONTAINER(window), true);
|
||||
gtk_container_add(GTK_CONTAINER(window), vbox1);
|
||||
|
||||
g_signal_connect(
|
||||
G_OBJECT(window),
|
||||
"delete_event",
|
||||
G_CALLBACK(gtk_main_quit),
|
||||
0
|
||||
);
|
||||
|
||||
gtk_widget_show_all(window);
|
||||
gtk_main();
|
||||
}
|
||||
|
||||
else return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user