mirror of
https://github.com/id-Software/GtkRadiant.git
synced 2026-03-20 00:49:29 +01:00
The GtkRadiant sources as originally released under the GPL license.
This commit is contained in:
547
libs/gtkutil/accelerator.cpp
Normal file
547
libs/gtkutil/accelerator.cpp
Normal file
@@ -0,0 +1,547 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "accelerator.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <gtk/gtkwindow.h>
|
||||
#include <gtk/gtkaccelgroup.h>
|
||||
|
||||
#include "generic/callback.h"
|
||||
#include "generic/bitfield.h"
|
||||
|
||||
#include "pointer.h"
|
||||
#include "closure.h"
|
||||
|
||||
|
||||
|
||||
typedef std::map<Accelerator, Callback> AcceleratorMap;
|
||||
|
||||
void accelerator_map_insert(AcceleratorMap& acceleratorMap, Accelerator accelerator, const Callback& callback)
|
||||
{
|
||||
if(accelerator.key != 0)
|
||||
{
|
||||
ASSERT_MESSAGE(acceleratorMap.find(accelerator) == acceleratorMap.end(), "failed to add accelerator");
|
||||
acceleratorMap.insert(AcceleratorMap::value_type(accelerator, callback));
|
||||
}
|
||||
}
|
||||
|
||||
void accelerator_map_erase(AcceleratorMap& acceleratorMap, Accelerator accelerator)
|
||||
{
|
||||
if(accelerator.key != 0)
|
||||
{
|
||||
ASSERT_MESSAGE(acceleratorMap.find(accelerator) != acceleratorMap.end(), "failed to remove accelerator");
|
||||
acceleratorMap.erase(accelerator);
|
||||
}
|
||||
}
|
||||
|
||||
Accelerator accelerator_for_event_key(guint keyval, guint state)
|
||||
{
|
||||
keyval = gdk_keyval_to_upper(keyval);
|
||||
if(keyval == GDK_ISO_Left_Tab)
|
||||
keyval = GDK_Tab;
|
||||
return Accelerator(keyval, (GdkModifierType)(state & gtk_accelerator_get_default_mod_mask()));
|
||||
}
|
||||
|
||||
bool AcceleratorMap_activate(const AcceleratorMap& acceleratorMap, const Accelerator& accelerator)
|
||||
{
|
||||
AcceleratorMap::const_iterator i = acceleratorMap.find(accelerator);
|
||||
if(i != acceleratorMap.end())
|
||||
{
|
||||
(*i).second();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static gboolean accelerator_key_event(GtkWindow* window, GdkEventKey* event, AcceleratorMap* acceleratorMap)
|
||||
{
|
||||
return AcceleratorMap_activate(*acceleratorMap, accelerator_for_event_key(event->keyval, event->state));
|
||||
}
|
||||
|
||||
|
||||
AcceleratorMap g_special_accelerators;
|
||||
|
||||
|
||||
namespace MouseButton
|
||||
{
|
||||
enum
|
||||
{
|
||||
Left = 1 << 0,
|
||||
Right = 1 << 1,
|
||||
Middle = 1 << 2,
|
||||
};
|
||||
}
|
||||
|
||||
typedef unsigned int ButtonMask;
|
||||
|
||||
void print_buttons(ButtonMask mask)
|
||||
{
|
||||
globalOutputStream() << "button state: ";
|
||||
if((mask & MouseButton::Left) != 0)
|
||||
{
|
||||
globalOutputStream() << "Left ";
|
||||
}
|
||||
if((mask & MouseButton::Right) != 0)
|
||||
{
|
||||
globalOutputStream() << "Right ";
|
||||
}
|
||||
if((mask & MouseButton::Middle) != 0)
|
||||
{
|
||||
globalOutputStream() << "Middle ";
|
||||
}
|
||||
globalOutputStream() << "\n";
|
||||
}
|
||||
|
||||
ButtonMask ButtonMask_for_event_button(guint button)
|
||||
{
|
||||
switch(button)
|
||||
{
|
||||
case 1:
|
||||
return MouseButton::Left;
|
||||
case 2:
|
||||
return MouseButton::Middle;
|
||||
case 3:
|
||||
return MouseButton::Right;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool window_has_accel(GtkWindow* toplevel)
|
||||
{
|
||||
return g_slist_length(gtk_accel_groups_from_object(G_OBJECT(toplevel))) != 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool g_accel_enabled = true;
|
||||
}
|
||||
|
||||
bool global_accel_enabled()
|
||||
{
|
||||
return g_accel_enabled;
|
||||
}
|
||||
|
||||
|
||||
AcceleratorMap g_queuedAccelerators;
|
||||
|
||||
GClosure* accel_group_add_accelerator(GtkAccelGroup* group, Accelerator accelerator, const Callback& callback);
|
||||
|
||||
void GlobalQueuedAccelerators_commit()
|
||||
{
|
||||
for(AcceleratorMap::const_iterator i = g_queuedAccelerators.begin(); i != g_queuedAccelerators.end(); ++i)
|
||||
{
|
||||
accel_group_add_accelerator(global_accel, (*i).first, (*i).second);
|
||||
}
|
||||
g_queuedAccelerators.clear();
|
||||
}
|
||||
|
||||
void GlobalQueuedAccelerators_add(Accelerator accelerator, const Callback& callback)
|
||||
{
|
||||
g_queuedAccelerators.insert(AcceleratorMap::value_type(accelerator, callback));
|
||||
}
|
||||
|
||||
void accel_group_test(GtkWindow* toplevel, GtkAccelGroup* accel)
|
||||
{
|
||||
guint n_entries;
|
||||
gtk_accel_group_query(accel, '4', (GdkModifierType)0, &n_entries);
|
||||
globalOutputStream() << "grid4: " << n_entries << "\n";
|
||||
globalOutputStream() << "toplevel accelgroups: " << g_slist_length(gtk_accel_groups_from_object(G_OBJECT(toplevel))) << "\n";
|
||||
}
|
||||
|
||||
typedef std::set<GtkWindow*> WindowSet;
|
||||
WindowSet g_accel_windows;
|
||||
|
||||
bool Buttons_press(ButtonMask& buttons, guint button, guint state)
|
||||
{
|
||||
if(buttons == 0 && bitfield_enable(buttons, ButtonMask_for_event_button(button)) != 0)
|
||||
{
|
||||
ASSERT_MESSAGE(g_accel_enabled, "Buttons_press: accelerators not enabled");
|
||||
g_accel_enabled = false;
|
||||
for(WindowSet::iterator i = g_accel_windows.begin(); i != g_accel_windows.end(); ++i)
|
||||
{
|
||||
GtkWindow* toplevel = *i;
|
||||
ASSERT_MESSAGE(window_has_accel(toplevel), "ERROR");
|
||||
ASSERT_MESSAGE(GTK_WIDGET_TOPLEVEL(toplevel), "disabling accel for non-toplevel window");
|
||||
gtk_window_remove_accel_group(toplevel, global_accel);
|
||||
#if 0
|
||||
globalOutputStream() << reinterpret_cast<unsigned int>(toplevel) << ": disabled global accelerators\n";
|
||||
#endif
|
||||
#if 0
|
||||
accel_group_test(toplevel, global_accel);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
buttons = bitfield_enable(buttons, ButtonMask_for_event_button(button));
|
||||
#if 0
|
||||
globalOutputStream() << "Buttons_press: ";
|
||||
print_buttons(buttons);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Buttons_release(ButtonMask& buttons, guint button, guint state)
|
||||
{
|
||||
if(buttons != 0 && bitfield_disable(buttons, ButtonMask_for_event_button(button)) == 0)
|
||||
{
|
||||
ASSERT_MESSAGE(!g_accel_enabled, "Buttons_release: accelerators are enabled");
|
||||
g_accel_enabled = true;
|
||||
for(WindowSet::iterator i = g_accel_windows.begin(); i != g_accel_windows.end(); ++i)
|
||||
{
|
||||
GtkWindow* toplevel = *i;
|
||||
ASSERT_MESSAGE(!window_has_accel(toplevel), "ERROR");
|
||||
ASSERT_MESSAGE(GTK_WIDGET_TOPLEVEL(toplevel), "enabling accel for non-toplevel window");
|
||||
gtk_window_add_accel_group(toplevel, global_accel);
|
||||
#if 0
|
||||
globalOutputStream() << reinterpret_cast<unsigned int>(toplevel) << ": enabled global accelerators\n";
|
||||
#endif
|
||||
#if 0
|
||||
accel_group_test(toplevel, global_accel);
|
||||
#endif
|
||||
}
|
||||
GlobalQueuedAccelerators_commit();
|
||||
}
|
||||
buttons = bitfield_disable(buttons, ButtonMask_for_event_button(button));
|
||||
#if 0
|
||||
globalOutputStream() << "Buttons_release: ";
|
||||
print_buttons(buttons);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Buttons_releaseAll(ButtonMask& buttons)
|
||||
{
|
||||
Buttons_release(buttons, MouseButton::Left | MouseButton::Middle | MouseButton::Right, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct PressedButtons
|
||||
{
|
||||
ButtonMask buttons;
|
||||
|
||||
PressedButtons() : buttons(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
gboolean PressedButtons_button_press(GtkWidget* widget, GdkEventButton* event, PressedButtons* pressed)
|
||||
{
|
||||
if(event->type == GDK_BUTTON_PRESS)
|
||||
{
|
||||
return Buttons_press(pressed->buttons, event->button, event->state);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean PressedButtons_button_release(GtkWidget* widget, GdkEventButton* event, PressedButtons* pressed)
|
||||
{
|
||||
if(event->type == GDK_BUTTON_RELEASE)
|
||||
{
|
||||
return Buttons_release(pressed->buttons, event->button, event->state);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean PressedButtons_focus_out(GtkWidget* widget, GdkEventFocus* event, PressedButtons* pressed)
|
||||
{
|
||||
Buttons_releaseAll(pressed->buttons);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void PressedButtons_connect(PressedButtons& pressedButtons, GtkWidget* widget)
|
||||
{
|
||||
g_signal_connect(G_OBJECT(widget), "button_press_event", G_CALLBACK(PressedButtons_button_press), &pressedButtons);
|
||||
g_signal_connect(G_OBJECT(widget), "button_release_event", G_CALLBACK(PressedButtons_button_release), &pressedButtons);
|
||||
g_signal_connect(G_OBJECT(widget), "focus_out_event", G_CALLBACK(PressedButtons_focus_out), &pressedButtons);
|
||||
}
|
||||
|
||||
PressedButtons g_pressedButtons;
|
||||
|
||||
|
||||
#include <set>
|
||||
|
||||
struct PressedKeys
|
||||
{
|
||||
typedef std::set<guint> Keys;
|
||||
Keys keys;
|
||||
std::size_t refcount;
|
||||
|
||||
PressedKeys() : refcount(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
AcceleratorMap g_keydown_accelerators;
|
||||
AcceleratorMap g_keyup_accelerators;
|
||||
|
||||
bool Keys_press(PressedKeys::Keys& keys, guint keyval)
|
||||
{
|
||||
if(keys.insert(keyval).second)
|
||||
{
|
||||
return AcceleratorMap_activate(g_keydown_accelerators, accelerator_for_event_key(keyval, 0));
|
||||
}
|
||||
return g_keydown_accelerators.find(accelerator_for_event_key(keyval, 0)) != g_keydown_accelerators.end();
|
||||
}
|
||||
|
||||
bool Keys_release(PressedKeys::Keys& keys, guint keyval)
|
||||
{
|
||||
if(keys.erase(keyval) != 0)
|
||||
{
|
||||
return AcceleratorMap_activate(g_keyup_accelerators, accelerator_for_event_key(keyval, 0));
|
||||
}
|
||||
return g_keyup_accelerators.find(accelerator_for_event_key(keyval, 0)) != g_keyup_accelerators.end();
|
||||
}
|
||||
|
||||
void Keys_releaseAll(PressedKeys::Keys& keys, guint state)
|
||||
{
|
||||
for(PressedKeys::Keys::iterator i = keys.begin(); i != keys.end(); ++i)
|
||||
{
|
||||
AcceleratorMap_activate(g_keyup_accelerators, accelerator_for_event_key(*i, state));
|
||||
}
|
||||
keys.clear();
|
||||
}
|
||||
|
||||
gboolean PressedKeys_key_press(GtkWidget* widget, GdkEventKey* event, PressedKeys* pressedKeys)
|
||||
{
|
||||
//globalOutputStream() << "pressed: " << event->keyval << "\n";
|
||||
return event->state == 0 && Keys_press(pressedKeys->keys, event->keyval);
|
||||
}
|
||||
|
||||
gboolean PressedKeys_key_release(GtkWidget* widget, GdkEventKey* event, PressedKeys* pressedKeys)
|
||||
{
|
||||
//globalOutputStream() << "released: " << event->keyval << "\n";
|
||||
return Keys_release(pressedKeys->keys, event->keyval);
|
||||
}
|
||||
|
||||
gboolean PressedKeys_focus_in(GtkWidget* widget, GdkEventFocus* event, PressedKeys* pressedKeys)
|
||||
{
|
||||
++pressedKeys->refcount;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean PressedKeys_focus_out(GtkWidget* widget, GdkEventFocus* event, PressedKeys* pressedKeys)
|
||||
{
|
||||
if(--pressedKeys->refcount == 0)
|
||||
{
|
||||
Keys_releaseAll(pressedKeys->keys, 0);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PressedKeys g_pressedKeys;
|
||||
|
||||
void GlobalPressedKeys_releaseAll()
|
||||
{
|
||||
Keys_releaseAll(g_pressedKeys.keys, 0);
|
||||
}
|
||||
|
||||
void GlobalPressedKeys_connect(GtkWindow* window)
|
||||
{
|
||||
unsigned int key_press_handler = g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(PressedKeys_key_press), &g_pressedKeys);
|
||||
unsigned int key_release_handler = g_signal_connect(G_OBJECT(window), "key_release_event", G_CALLBACK(PressedKeys_key_release), &g_pressedKeys);
|
||||
g_object_set_data(G_OBJECT(window), "key_press_handler", gint_to_pointer(key_press_handler));
|
||||
g_object_set_data(G_OBJECT(window), "key_release_handler", gint_to_pointer(key_release_handler));
|
||||
unsigned int focus_in_handler = g_signal_connect(G_OBJECT(window), "focus_in_event", G_CALLBACK(PressedKeys_focus_in), &g_pressedKeys);
|
||||
unsigned int focus_out_handler = g_signal_connect(G_OBJECT(window), "focus_out_event", G_CALLBACK(PressedKeys_focus_out), &g_pressedKeys);
|
||||
g_object_set_data(G_OBJECT(window), "focus_in_handler", gint_to_pointer(focus_in_handler));
|
||||
g_object_set_data(G_OBJECT(window), "focus_out_handler", gint_to_pointer(focus_out_handler));
|
||||
}
|
||||
|
||||
void GlobalPressedKeys_disconnect(GtkWindow* window)
|
||||
{
|
||||
g_signal_handler_disconnect(G_OBJECT(window), gpointer_to_int(g_object_get_data(G_OBJECT(window), "key_press_handler")));
|
||||
g_signal_handler_disconnect(G_OBJECT(window), gpointer_to_int(g_object_get_data(G_OBJECT(window), "key_release_handler")));
|
||||
g_signal_handler_disconnect(G_OBJECT(window), gpointer_to_int(g_object_get_data(G_OBJECT(window), "focus_in_handler")));
|
||||
g_signal_handler_disconnect(G_OBJECT(window), gpointer_to_int(g_object_get_data(G_OBJECT(window), "focus_out_handler")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void special_accelerators_add(Accelerator accelerator, const Callback& callback)
|
||||
{
|
||||
accelerator_map_insert(g_special_accelerators, accelerator, callback);
|
||||
}
|
||||
void special_accelerators_remove(Accelerator accelerator)
|
||||
{
|
||||
accelerator_map_erase(g_special_accelerators, accelerator);
|
||||
}
|
||||
|
||||
void keydown_accelerators_add(Accelerator accelerator, const Callback& callback)
|
||||
{
|
||||
accelerator_map_insert(g_keydown_accelerators, accelerator, callback);
|
||||
}
|
||||
void keydown_accelerators_remove(Accelerator accelerator)
|
||||
{
|
||||
accelerator_map_erase(g_keydown_accelerators, accelerator);
|
||||
}
|
||||
|
||||
void keyup_accelerators_add(Accelerator accelerator, const Callback& callback)
|
||||
{
|
||||
accelerator_map_insert(g_keyup_accelerators, accelerator, callback);
|
||||
}
|
||||
void keyup_accelerators_remove(Accelerator accelerator)
|
||||
{
|
||||
accelerator_map_erase(g_keyup_accelerators, accelerator);
|
||||
}
|
||||
|
||||
|
||||
gboolean accel_closure_callback(GtkAccelGroup* group, GtkWidget* widget, guint key, GdkModifierType modifiers, gpointer data)
|
||||
{
|
||||
(*reinterpret_cast<Callback*>(data))();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GClosure* accel_group_add_accelerator(GtkAccelGroup* group, Accelerator accelerator, const Callback& callback)
|
||||
{
|
||||
if(accelerator.key != 0 && gtk_accelerator_valid(accelerator.key, accelerator.modifiers))
|
||||
{
|
||||
//globalOutputStream() << "adding accelerator: " << accelerator.key << " " << accelerator.modifiers << "\n";
|
||||
GClosure* closure = create_cclosure(G_CALLBACK(accel_closure_callback), callback);
|
||||
gtk_accel_group_connect(group, accelerator.key, accelerator.modifiers, GTK_ACCEL_VISIBLE, closure);
|
||||
return closure;
|
||||
}
|
||||
else
|
||||
{
|
||||
special_accelerators_add(accelerator, callback);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void accel_group_remove_accelerator(GtkAccelGroup* group, Accelerator accelerator)
|
||||
{
|
||||
if(accelerator.key != 0 && gtk_accelerator_valid(accelerator.key, accelerator.modifiers))
|
||||
{
|
||||
gtk_accel_group_disconnect_key(group, accelerator.key, accelerator.modifiers);
|
||||
}
|
||||
else
|
||||
{
|
||||
special_accelerators_remove(accelerator);
|
||||
}
|
||||
}
|
||||
|
||||
GtkAccelGroup* global_accel = 0;
|
||||
|
||||
void global_accel_init()
|
||||
{
|
||||
global_accel = gtk_accel_group_new();
|
||||
}
|
||||
|
||||
void global_accel_destroy()
|
||||
{
|
||||
g_object_unref(global_accel);
|
||||
}
|
||||
|
||||
GClosure* global_accel_group_add_accelerator(Accelerator accelerator, const Callback& callback)
|
||||
{
|
||||
if(!global_accel_enabled())
|
||||
{
|
||||
// workaround: cannot add to GtkAccelGroup while it is disabled
|
||||
GlobalQueuedAccelerators_add(accelerator, callback);
|
||||
return 0;
|
||||
}
|
||||
return accel_group_add_accelerator(global_accel, accelerator, callback);
|
||||
}
|
||||
void global_accel_group_remove_accelerator(Accelerator accelerator)
|
||||
{
|
||||
//ASSERT_MESSAGE(global_accel_enabled(), "removing accelerator while global accel is disabled");
|
||||
accel_group_remove_accelerator(global_accel, accelerator);
|
||||
}
|
||||
|
||||
/// \brief Propagates key events to the focus-widget, overriding global accelerators.
|
||||
static gboolean override_global_accelerators(GtkWindow* window, GdkEventKey* event, gpointer data)
|
||||
{
|
||||
return gtk_window_propagate_key_event(window, event);
|
||||
}
|
||||
|
||||
void global_accel_connect_window(GtkWindow* window)
|
||||
{
|
||||
#if 1
|
||||
unsigned int override_handler = g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(override_global_accelerators), 0);
|
||||
g_object_set_data(G_OBJECT(window), "override_handler", gint_to_pointer(override_handler));
|
||||
|
||||
unsigned int special_key_press_handler = g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(accelerator_key_event), &g_special_accelerators);
|
||||
g_object_set_data(G_OBJECT(window), "special_key_press_handler", gint_to_pointer(special_key_press_handler));
|
||||
|
||||
GlobalPressedKeys_connect(window);
|
||||
#else
|
||||
unsigned int key_press_handler = g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(accelerator_key_event), &g_keydown_accelerators);
|
||||
unsigned int key_release_handler = g_signal_connect(G_OBJECT(window), "key_release_event", G_CALLBACK(accelerator_key_event), &g_keyup_accelerators);
|
||||
g_object_set_data(G_OBJECT(window), "key_press_handler", gint_to_pointer(key_press_handler));
|
||||
g_object_set_data(G_OBJECT(window), "key_release_handler", gint_to_pointer(key_release_handler));
|
||||
#endif
|
||||
g_accel_windows.insert(window);
|
||||
gtk_window_add_accel_group(window, global_accel);
|
||||
}
|
||||
void global_accel_disconnect_window(GtkWindow* window)
|
||||
{
|
||||
#if 1
|
||||
GlobalPressedKeys_disconnect(window);
|
||||
|
||||
g_signal_handler_disconnect(G_OBJECT(window), gpointer_to_int(g_object_get_data(G_OBJECT(window), "override_handler")));
|
||||
g_signal_handler_disconnect(G_OBJECT(window), gpointer_to_int(g_object_get_data(G_OBJECT(window), "special_key_press_handler")));
|
||||
#else
|
||||
g_signal_handler_disconnect(G_OBJECT(window), gpointer_to_int(g_object_get_data(G_OBJECT(window), "key_press_handler")));
|
||||
g_signal_handler_disconnect(G_OBJECT(window), gpointer_to_int(g_object_get_data(G_OBJECT(window), "key_release_handler")));
|
||||
#endif
|
||||
gtk_window_remove_accel_group(window, global_accel);
|
||||
std::size_t count = g_accel_windows.erase(window);
|
||||
ASSERT_MESSAGE(count == 1, "failed to remove accel group\n");
|
||||
}
|
||||
|
||||
|
||||
GClosure* global_accel_group_find(Accelerator accelerator)
|
||||
{
|
||||
guint numEntries = 0;
|
||||
GtkAccelGroupEntry* entry = gtk_accel_group_query(global_accel, accelerator.key, accelerator.modifiers, &numEntries);
|
||||
if(numEntries != 0)
|
||||
{
|
||||
if(numEntries != 1)
|
||||
{
|
||||
char* name = gtk_accelerator_name(accelerator.key, accelerator.modifiers);
|
||||
globalErrorStream() << "accelerator already in-use: " << name << "\n";
|
||||
g_free(name);
|
||||
}
|
||||
return entry->closure;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void command_connect_accelerator(const Accelerator& accelerator, const Callback& callback)
|
||||
{
|
||||
if(accelerator.key != 0)
|
||||
{
|
||||
global_accel_group_add_accelerator(accelerator, callback);
|
||||
}
|
||||
}
|
||||
|
||||
void command_disconnect_accelerator(const Accelerator& accelerator, const Callback& callback)
|
||||
{
|
||||
if(accelerator.key != 0)
|
||||
{
|
||||
global_accel_group_remove_accelerator(accelerator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
117
libs/gtkutil/accelerator.h
Normal file
117
libs/gtkutil/accelerator.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_ACCELERATOR_H)
|
||||
#define INCLUDED_GTKUTIL_ACCELERATOR_H
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "generic/callback.h"
|
||||
|
||||
|
||||
struct Accelerator
|
||||
{
|
||||
Accelerator(guint _key)
|
||||
: key(_key), modifiers((GdkModifierType)0)
|
||||
{
|
||||
}
|
||||
Accelerator(guint _key, GdkModifierType _modifiers)
|
||||
: key(_key), modifiers(_modifiers)
|
||||
{
|
||||
}
|
||||
bool operator<(const Accelerator& other) const
|
||||
{
|
||||
return key < other.key || (!(other.key < key) && modifiers < other.modifiers);
|
||||
}
|
||||
guint key;
|
||||
GdkModifierType modifiers;
|
||||
};
|
||||
|
||||
inline Accelerator accelerator_null()
|
||||
{
|
||||
return Accelerator(0, (GdkModifierType)0);
|
||||
}
|
||||
|
||||
|
||||
void keydown_accelerators_add(Accelerator accelerator, const Callback& callback);
|
||||
void keydown_accelerators_remove(Accelerator accelerator);
|
||||
void keyup_accelerators_add(Accelerator accelerator, const Callback& callback);
|
||||
void keyup_accelerators_remove(Accelerator accelerator);
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
void global_accel_connect_window(GtkWindow* window);
|
||||
void global_accel_disconnect_window(GtkWindow* window);
|
||||
|
||||
void GlobalPressedKeys_releaseAll();
|
||||
|
||||
typedef struct _GtkAccelGroup GtkAccelGroup;
|
||||
extern GtkAccelGroup* global_accel;
|
||||
void global_accel_init();
|
||||
void global_accel_destroy();
|
||||
|
||||
GClosure* global_accel_group_find(Accelerator accelerator);
|
||||
|
||||
void command_connect_accelerator(const Accelerator& accelerator, const Callback& callback);
|
||||
void command_disconnect_accelerator(const Accelerator& accelerator, const Callback& callback);
|
||||
|
||||
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
Callback m_callback;
|
||||
const Accelerator& m_accelerator;
|
||||
Command(const Callback& callback, const Accelerator& accelerator) : m_callback(callback), m_accelerator(accelerator)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Toggle
|
||||
{
|
||||
public:
|
||||
Command m_command;
|
||||
BoolExportCallback m_exportCallback;
|
||||
Toggle(const Callback& callback, const Accelerator& accelerator, const BoolExportCallback& exportCallback) : m_command(callback, accelerator), m_exportCallback(exportCallback)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class KeyEvent
|
||||
{
|
||||
public:
|
||||
const Accelerator& m_accelerator;
|
||||
Callback m_keyDown;
|
||||
Callback m_keyUp;
|
||||
KeyEvent(const Accelerator& accelerator, const Callback& keyDown, const Callback& keyUp) : m_accelerator(accelerator), m_keyDown(keyDown), m_keyUp(keyUp)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct PressedButtons;
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
void PressedButtons_connect(PressedButtons& pressedButtons, GtkWidget* widget);
|
||||
|
||||
extern PressedButtons g_pressedButtons;
|
||||
|
||||
#endif
|
||||
137
libs/gtkutil/button.cpp
Normal file
137
libs/gtkutil/button.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "button.h"
|
||||
|
||||
#include <gtk/gtkradiobutton.h>
|
||||
|
||||
#include "stream/textstream.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "generic/callback.h"
|
||||
|
||||
#include "image.h"
|
||||
#include "pointer.h"
|
||||
|
||||
void clicked_closure_callback(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
(*reinterpret_cast<Callback*>(data))();
|
||||
}
|
||||
|
||||
void button_connect_callback(GtkButton* button, const Callback& callback)
|
||||
{
|
||||
#if 1
|
||||
g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(callback.getThunk()), callback.getEnvironment());
|
||||
#else
|
||||
g_signal_connect_closure(G_OBJECT(button), "clicked", create_cclosure(G_CALLBACK(clicked_closure_callback), callback), FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
guint toggle_button_connect_callback(GtkToggleButton* button, const Callback& callback)
|
||||
{
|
||||
#if 1
|
||||
guint handler = g_signal_connect_swapped(G_OBJECT(button), "toggled", G_CALLBACK(callback.getThunk()), callback.getEnvironment());
|
||||
#else
|
||||
guint handler = g_signal_connect_closure(G_OBJECT(button), "toggled", create_cclosure(G_CALLBACK(clicked_closure_callback), callback), TRUE);
|
||||
#endif
|
||||
g_object_set_data(G_OBJECT(button), "handler", gint_to_pointer(handler));
|
||||
return handler;
|
||||
}
|
||||
|
||||
void button_set_icon(GtkButton* button, const char* icon)
|
||||
{
|
||||
GtkImage* image = new_local_image(icon);
|
||||
gtk_widget_show(GTK_WIDGET(image));
|
||||
gtk_container_add(GTK_CONTAINER(button), GTK_WIDGET(image));
|
||||
}
|
||||
|
||||
void toggle_button_set_active_no_signal(GtkToggleButton* button, gboolean active)
|
||||
{
|
||||
//globalOutputStream() << "set active: " << active << "\n";
|
||||
guint handler_id = gpointer_to_int(g_object_get_data(G_OBJECT(button), "handler"));
|
||||
//guint signal_id = g_signal_lookup("toggled", G_OBJECT_TYPE (button));
|
||||
//globalOutputStream() << "signal_id: " << signal_id << "\n";
|
||||
//guint found = g_signal_handler_find(G_OBJECT(button), G_SIGNAL_MATCH_ID, signal_id, 0, 0, 0, 0);
|
||||
//globalOutputStream() << " handler found: " << found << "\n";
|
||||
g_signal_handler_block(G_OBJECT(button), handler_id);
|
||||
gtk_toggle_button_set_active(button, active);
|
||||
g_signal_handler_unblock(G_OBJECT(button), handler_id);
|
||||
}
|
||||
|
||||
|
||||
void radio_button_print_state(GtkRadioButton* button)
|
||||
{
|
||||
globalOutputStream() << "toggle button: ";
|
||||
for(GSList* radio = gtk_radio_button_group(button); radio != 0; radio = g_slist_next(radio))
|
||||
{
|
||||
globalOutputStream() << gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio->data));
|
||||
}
|
||||
globalOutputStream() << "\n";
|
||||
}
|
||||
|
||||
GtkToggleButton* radio_button_get_nth(GtkRadioButton* radio, int index)
|
||||
{
|
||||
GSList *group = gtk_radio_button_group(radio);
|
||||
return GTK_TOGGLE_BUTTON(g_slist_nth_data(group, g_slist_length(group) - index - 1));
|
||||
}
|
||||
|
||||
void radio_button_set_active(GtkRadioButton* radio, int index)
|
||||
{
|
||||
//radio_button_print_state(radio);
|
||||
gtk_toggle_button_set_active(radio_button_get_nth(radio, index), TRUE);
|
||||
//radio_button_print_state(radio);
|
||||
}
|
||||
|
||||
void radio_button_set_active_no_signal(GtkRadioButton* radio, int index)
|
||||
{
|
||||
{
|
||||
for(GSList* l = gtk_radio_button_get_group(radio); l != 0; l = g_slist_next(l))
|
||||
{
|
||||
g_signal_handler_block(G_OBJECT(l->data), gpointer_to_int(g_object_get_data(G_OBJECT(l->data), "handler")));
|
||||
}
|
||||
}
|
||||
radio_button_set_active(radio, index);
|
||||
{
|
||||
for(GSList* l = gtk_radio_button_get_group(radio); l != 0; l = g_slist_next(l))
|
||||
{
|
||||
g_signal_handler_unblock(G_OBJECT(l->data), gpointer_to_int(g_object_get_data(G_OBJECT(l->data), "handler")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int radio_button_get_active(GtkRadioButton* radio)
|
||||
{
|
||||
//radio_button_print_state(radio);
|
||||
GSList *group = gtk_radio_button_group(radio);
|
||||
int index = g_slist_length(group) - 1;
|
||||
for (; group != 0; group = g_slist_next(group))
|
||||
{
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group->data)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
index--;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
43
libs/gtkutil/button.h
Normal file
43
libs/gtkutil/button.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_BUTTON_H)
|
||||
#define INCLUDED_GTKUTIL_BUTTON_H
|
||||
|
||||
typedef struct _GtkButton GtkButton;
|
||||
typedef struct _GtkToggleButton GtkToggleButton;
|
||||
typedef struct _GtkRadioButton GtkRadioButton;
|
||||
typedef int gint;
|
||||
typedef gint gboolean;
|
||||
typedef unsigned int guint;
|
||||
class Callback;
|
||||
|
||||
void button_connect_callback(GtkButton* button, const Callback& callback);
|
||||
guint toggle_button_connect_callback(GtkToggleButton* button, const Callback& callback);
|
||||
|
||||
void button_set_icon(GtkButton* button, const char* icon);
|
||||
void toggle_button_set_active_no_signal(GtkToggleButton* item, gboolean active);
|
||||
|
||||
void radio_button_set_active(GtkRadioButton* radio, int index);
|
||||
void radio_button_set_active_no_signal(GtkRadioButton* radio, int index);
|
||||
int radio_button_get_active(GtkRadioButton* radio);
|
||||
|
||||
#endif
|
||||
162
libs/gtkutil/clipboard.cpp
Normal file
162
libs/gtkutil/clipboard.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "clipboard.h"
|
||||
|
||||
#include "stream/memstream.h"
|
||||
#include "stream/textstream.h"
|
||||
|
||||
|
||||
/// \file
|
||||
/// \brief Platform-independent GTK clipboard support.
|
||||
/// \todo Using GDK_SELECTION_CLIPBOARD fails on win32, so we use the win32 API directly for now.
|
||||
#if defined (__linux__) || defined (__APPLE__)
|
||||
|
||||
#include <gtk/gtkclipboard.h>
|
||||
|
||||
enum
|
||||
{
|
||||
RADIANT_CLIPPINGS = 23,
|
||||
};
|
||||
|
||||
static const GtkTargetEntry clipboard_targets[] = {
|
||||
{ "RADIANT_CLIPPINGS", 0, RADIANT_CLIPPINGS, },
|
||||
};
|
||||
|
||||
static void clipboard_get (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data)
|
||||
{
|
||||
std::size_t len = *reinterpret_cast<std::size_t*>(data);
|
||||
const char* buffer = (len != 0) ? reinterpret_cast<const char*>(data) + sizeof(std::size_t) : 0;
|
||||
|
||||
GdkAtom type = GDK_NONE;
|
||||
if(info == clipboard_targets[0].info)
|
||||
{
|
||||
type = gdk_atom_intern(clipboard_targets[0].target, FALSE);
|
||||
}
|
||||
|
||||
gtk_selection_data_set (selection_data, type, 8, reinterpret_cast<const guchar*>(buffer), static_cast<gint>(len));
|
||||
}
|
||||
|
||||
static void clipboard_clear (GtkClipboard *clipboard, gpointer data)
|
||||
{
|
||||
delete [] reinterpret_cast<const char*>(data);
|
||||
}
|
||||
|
||||
static void clipboard_received (GtkClipboard *clipboard, GtkSelectionData *data, gpointer user_data)
|
||||
{
|
||||
if (data->length < 0)
|
||||
{
|
||||
globalErrorStream() << "Error retrieving selection\n";
|
||||
}
|
||||
else if(strcmp(gdk_atom_name(data->type), clipboard_targets[0].target) == 0)
|
||||
{
|
||||
BufferInputStream istream(reinterpret_cast<const char*>(data->data), data->length);
|
||||
(*reinterpret_cast<ClipboardPasteFunc*>(user_data))(istream);
|
||||
}
|
||||
}
|
||||
|
||||
void clipboard_copy(ClipboardCopyFunc copy)
|
||||
{
|
||||
GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
||||
|
||||
BufferOutputStream ostream;
|
||||
copy(ostream);
|
||||
std::size_t length = ostream.size();
|
||||
char* data = new char[length + sizeof(std::size_t)];
|
||||
*reinterpret_cast<std::size_t*>(data) = length;
|
||||
memcpy(data + sizeof(std::size_t), ostream.data(), length);
|
||||
|
||||
gtk_clipboard_set_with_data (clipboard, clipboard_targets, 1, clipboard_get, clipboard_clear, data);
|
||||
}
|
||||
|
||||
ClipboardPasteFunc g_clipboardPasteFunc = 0;
|
||||
void clipboard_paste(ClipboardPasteFunc paste)
|
||||
{
|
||||
GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
||||
|
||||
g_clipboardPasteFunc = paste;
|
||||
gtk_clipboard_request_contents (clipboard, gdk_atom_intern(clipboard_targets[0].target, FALSE), clipboard_received, &g_clipboardPasteFunc);
|
||||
}
|
||||
|
||||
#elif defined(WIN32)
|
||||
|
||||
const char* c_clipboard_format = "RadiantClippings";
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
void clipboard_copy(ClipboardCopyFunc copy)
|
||||
{
|
||||
BufferOutputStream ostream;
|
||||
copy(ostream);
|
||||
|
||||
bool bClipped = false;
|
||||
UINT nClipboard = ::RegisterClipboardFormat(c_clipboard_format);
|
||||
if (nClipboard > 0)
|
||||
{
|
||||
if (::OpenClipboard(0))
|
||||
{
|
||||
EmptyClipboard();
|
||||
std::size_t length = ostream.size();
|
||||
HANDLE h = ::GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, length + sizeof(std::size_t));
|
||||
if (h != 0)
|
||||
{
|
||||
char *buffer = reinterpret_cast<char*>(::GlobalLock(h));
|
||||
*reinterpret_cast<std::size_t*>(buffer) = length;
|
||||
buffer += sizeof(std::size_t);
|
||||
memcpy(buffer, ostream.data(), length);
|
||||
::GlobalUnlock(h);
|
||||
::SetClipboardData(nClipboard, h);
|
||||
::CloseClipboard();
|
||||
bClipped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bClipped)
|
||||
{
|
||||
globalOutputStream() << "Unable to register Windows clipboard formats, copy/paste between editors will not be possible\n";
|
||||
}
|
||||
}
|
||||
|
||||
void clipboard_paste(ClipboardPasteFunc paste)
|
||||
{
|
||||
UINT nClipboard = ::RegisterClipboardFormat(c_clipboard_format);
|
||||
if (nClipboard > 0 && ::OpenClipboard(0))
|
||||
{
|
||||
if(IsClipboardFormatAvailable(nClipboard))
|
||||
{
|
||||
HANDLE h = ::GetClipboardData(nClipboard);
|
||||
if(h)
|
||||
{
|
||||
const char *buffer = reinterpret_cast<const char*>(::GlobalLock(h));
|
||||
std::size_t length = *reinterpret_cast<const std::size_t*>(buffer);
|
||||
buffer += sizeof(std::size_t);
|
||||
BufferInputStream istream(buffer, length);
|
||||
paste(istream);
|
||||
::GlobalUnlock(h);
|
||||
}
|
||||
}
|
||||
::CloseClipboard();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
33
libs/gtkutil/clipboard.h
Normal file
33
libs/gtkutil/clipboard.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_CLIPBOARD_H)
|
||||
#define INCLUDED_GTKUTIL_CLIPBOARD_H
|
||||
|
||||
class TextOutputStream;
|
||||
typedef void(*ClipboardCopyFunc)(TextOutputStream&);
|
||||
void clipboard_copy(ClipboardCopyFunc copy);
|
||||
|
||||
class TextInputStream;
|
||||
typedef void(*ClipboardPasteFunc)(TextInputStream&);
|
||||
void clipboard_paste(ClipboardPasteFunc paste);
|
||||
|
||||
#endif
|
||||
23
libs/gtkutil/closure.cpp
Normal file
23
libs/gtkutil/closure.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "closure.h"
|
||||
|
||||
77
libs/gtkutil/closure.h
Normal file
77
libs/gtkutil/closure.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_CLOSURE_H)
|
||||
#define INCLUDED_GTKUTIL_CLOSURE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "generic/callback.h"
|
||||
|
||||
inline void closure_destroy(gpointer data, GClosure* closure)
|
||||
{
|
||||
delete reinterpret_cast<Callback*>(data);
|
||||
}
|
||||
|
||||
inline GClosure* create_cclosure(GCallback func, const Callback& callback)
|
||||
{
|
||||
return g_cclosure_new(func, new Callback(callback), closure_destroy);
|
||||
}
|
||||
|
||||
inline GValue GValue_default()
|
||||
{
|
||||
GValue value;
|
||||
value.g_type = 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline gint object_get_int_property(GObject* object, const char* property)
|
||||
{
|
||||
GValue gvalue = GValue_default();
|
||||
g_value_init(&gvalue, G_TYPE_INT);
|
||||
g_object_get_property(object, property, &gvalue);
|
||||
return g_value_get_int(&gvalue);
|
||||
}
|
||||
|
||||
inline void object_set_int_property(GObject* object, const char* property, gint value)
|
||||
{
|
||||
GValue gvalue = GValue_default();
|
||||
g_value_init(&gvalue, G_TYPE_INT);
|
||||
g_value_set_int(&gvalue, value);
|
||||
g_object_set_property(object, property, &gvalue);
|
||||
}
|
||||
|
||||
inline gboolean object_get_boolean_property(GObject* object, const char* property)
|
||||
{
|
||||
GValue gvalue = GValue_default();
|
||||
g_value_init(&gvalue, G_TYPE_BOOLEAN);
|
||||
g_object_get_property(object, property, &gvalue);
|
||||
return g_value_get_boolean(&gvalue);
|
||||
}
|
||||
|
||||
inline void object_set_boolean_property(GObject* object, const char* property, gboolean value)
|
||||
{
|
||||
GValue gvalue = GValue_default();
|
||||
g_value_init(&gvalue, G_TYPE_BOOLEAN);
|
||||
g_value_set_boolean(&gvalue, value);
|
||||
g_object_set_property(object, property, &gvalue);
|
||||
}
|
||||
|
||||
#endif
|
||||
23
libs/gtkutil/container.cpp
Normal file
23
libs/gtkutil/container.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "container.h"
|
||||
|
||||
43
libs/gtkutil/container.h
Normal file
43
libs/gtkutil/container.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_CONTAINER_H)
|
||||
#define INCLUDED_GTKUTIL_CONTAINER_H
|
||||
|
||||
#include <gtk/gtkcontainer.h>
|
||||
|
||||
inline GtkWidget* container_add_widget(GtkContainer* container, GtkWidget* widget)
|
||||
{
|
||||
gtk_container_add(container, widget);
|
||||
return widget;
|
||||
}
|
||||
|
||||
inline void container_remove(GtkWidget* item, gpointer data)
|
||||
{
|
||||
gtk_container_remove(GTK_CONTAINER(data), item);
|
||||
}
|
||||
|
||||
inline void container_remove_all(GtkContainer* container)
|
||||
{
|
||||
gtk_container_foreach(container, container_remove, container);
|
||||
}
|
||||
|
||||
#endif
|
||||
97
libs/gtkutil/cursor.cpp
Normal file
97
libs/gtkutil/cursor.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "cursor.h"
|
||||
|
||||
#include "stream/textstream.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <gdk/gdkcursor.h>
|
||||
#include <gdk/gdkpixmap.h>
|
||||
|
||||
|
||||
GdkCursor* create_blank_cursor()
|
||||
{
|
||||
GdkPixmap *pixmap;
|
||||
GdkBitmap *mask;
|
||||
char buffer [(32 * 32)/8];
|
||||
memset (buffer, 0, (32 * 32)/8);
|
||||
GdkColor white = {0, 0xffff, 0xffff, 0xffff};
|
||||
GdkColor black = {0, 0x0000, 0x0000, 0x0000};
|
||||
pixmap = gdk_bitmap_create_from_data(0, buffer, 32, 32);
|
||||
mask = gdk_bitmap_create_from_data(0, buffer, 32, 32);
|
||||
GdkCursor *cursor = gdk_cursor_new_from_pixmap(pixmap, mask, &white, &black, 1, 1);
|
||||
gdk_drawable_unref(pixmap);
|
||||
gdk_drawable_unref(mask);
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
void blank_cursor(GtkWidget* widget)
|
||||
{
|
||||
GdkCursor* cursor = create_blank_cursor();
|
||||
gdk_window_set_cursor (widget->window, cursor);
|
||||
gdk_cursor_unref(cursor);
|
||||
}
|
||||
|
||||
void default_cursor(GtkWidget* widget)
|
||||
{
|
||||
gdk_window_set_cursor(widget->window, 0);
|
||||
}
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#include <gdk/gdkwin32.h>
|
||||
|
||||
void Sys_GetCursorPos(GtkWindow* window, int *x, int *y)
|
||||
{
|
||||
POINT pos;
|
||||
GetCursorPos(&pos);
|
||||
ScreenToClient((HWND)GDK_WINDOW_HWND(GTK_WIDGET(window)->window), &pos);
|
||||
*x = pos.x;
|
||||
*y = pos.y;
|
||||
}
|
||||
|
||||
void Sys_SetCursorPos(GtkWindow* window, int x, int y)
|
||||
{
|
||||
POINT pos;
|
||||
pos.x = x;
|
||||
pos.y = y;
|
||||
ClientToScreen((HWND)GDK_WINDOW_HWND(GTK_WIDGET(window)->window), &pos);
|
||||
SetCursorPos(pos.x, pos.y);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
void Sys_GetCursorPos(GtkWindow* window, int *x, int *y)
|
||||
{
|
||||
gdk_display_get_pointer(gdk_display_get_default(), 0, x, y, 0);
|
||||
}
|
||||
|
||||
void Sys_SetCursorPos(GtkWindow* window, int x, int y)
|
||||
{
|
||||
XWarpPointer(GDK_DISPLAY(), None, GDK_ROOT_WINDOW(), 0, 0, 0, 0, x, y);
|
||||
}
|
||||
|
||||
#endif
|
||||
193
libs/gtkutil/cursor.h
Normal file
193
libs/gtkutil/cursor.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_CURSOR_H)
|
||||
#define INCLUDED_GTKUTIL_CURSOR_H
|
||||
|
||||
#include <glib/gmain.h>
|
||||
#include <gdk/gdkevents.h>
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
typedef struct _GdkCursor GdkCursor;
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
|
||||
GdkCursor* create_blank_cursor();
|
||||
void blank_cursor(GtkWidget* widget);
|
||||
void default_cursor(GtkWidget* widget);
|
||||
void Sys_GetCursorPos(GtkWindow* window, int *x, int *y);
|
||||
void Sys_SetCursorPos(GtkWindow* window, int x, int y);
|
||||
|
||||
|
||||
|
||||
class DeferredMotion
|
||||
{
|
||||
guint m_handler;
|
||||
typedef void(*MotionFunction)(gdouble x, gdouble y, guint state, void* data);
|
||||
MotionFunction m_function;
|
||||
void* m_data;
|
||||
gdouble m_x;
|
||||
gdouble m_y;
|
||||
guint m_state;
|
||||
|
||||
static gboolean deferred(DeferredMotion* self)
|
||||
{
|
||||
self->m_handler = 0;
|
||||
self->m_function(self->m_x, self->m_y, self->m_state, self->m_data);
|
||||
return FALSE;
|
||||
}
|
||||
public:
|
||||
DeferredMotion(MotionFunction function, void* data) : m_handler(0), m_function(function), m_data(data)
|
||||
{
|
||||
}
|
||||
void motion(gdouble x, gdouble y, guint state)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_state = state;
|
||||
if(m_handler == 0)
|
||||
{
|
||||
m_handler = g_idle_add((GSourceFunc)deferred, this);
|
||||
}
|
||||
}
|
||||
static gboolean gtk_motion(GtkWidget *widget, GdkEventMotion *event, DeferredMotion* self)
|
||||
{
|
||||
self->motion(event->x, event->y, event->state);
|
||||
return FALSE;
|
||||
}
|
||||
};
|
||||
|
||||
class DeferredMotionDelta
|
||||
{
|
||||
int m_delta_x;
|
||||
int m_delta_y;
|
||||
guint m_motion_handler;
|
||||
typedef void (*MotionDeltaFunction)(int x, int y, void* data);
|
||||
MotionDeltaFunction m_function;
|
||||
void* m_data;
|
||||
|
||||
static gboolean deferred_motion(gpointer data)
|
||||
{
|
||||
reinterpret_cast<DeferredMotionDelta*>(data)->m_function(
|
||||
reinterpret_cast<DeferredMotionDelta*>(data)->m_delta_x,
|
||||
reinterpret_cast<DeferredMotionDelta*>(data)->m_delta_y,
|
||||
reinterpret_cast<DeferredMotionDelta*>(data)->m_data
|
||||
);
|
||||
reinterpret_cast<DeferredMotionDelta*>(data)->m_motion_handler = 0;
|
||||
reinterpret_cast<DeferredMotionDelta*>(data)->m_delta_x = 0;
|
||||
reinterpret_cast<DeferredMotionDelta*>(data)->m_delta_y = 0;
|
||||
return FALSE;
|
||||
}
|
||||
public:
|
||||
DeferredMotionDelta(MotionDeltaFunction function, void* data) : m_delta_x(0), m_delta_y(0), m_motion_handler(0), m_function(function), m_data(data)
|
||||
{
|
||||
}
|
||||
void flush()
|
||||
{
|
||||
if(m_motion_handler != 0)
|
||||
{
|
||||
g_source_remove(m_motion_handler);
|
||||
deferred_motion(this);
|
||||
}
|
||||
}
|
||||
void motion_delta(int x, int y, unsigned int state)
|
||||
{
|
||||
m_delta_x += x;
|
||||
m_delta_y += y;
|
||||
if(m_motion_handler == 0)
|
||||
{
|
||||
m_motion_handler = g_idle_add(deferred_motion, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class FreezePointer
|
||||
{
|
||||
unsigned int handle_motion;
|
||||
int recorded_x, recorded_y;
|
||||
typedef void (*MotionDeltaFunction)(int x, int y, unsigned int state, void* data);
|
||||
MotionDeltaFunction m_function;
|
||||
void* m_data;
|
||||
public:
|
||||
FreezePointer() : handle_motion(0), m_function(0), m_data(0)
|
||||
{
|
||||
}
|
||||
static gboolean motion_delta(GtkWidget *widget, GdkEventMotion *event, FreezePointer* self)
|
||||
{
|
||||
int current_x, current_y;
|
||||
Sys_GetCursorPos(GTK_WINDOW(widget), ¤t_x, ¤t_y);
|
||||
int dx = current_x - self->recorded_x;
|
||||
int dy = current_y - self->recorded_y;
|
||||
if(dx != 0 || dy != 0)
|
||||
{
|
||||
//globalOutputStream() << "motion x: " << dx << ", y: " << dy << "\n";
|
||||
Sys_SetCursorPos(GTK_WINDOW(widget), self->recorded_x, self->recorded_y);
|
||||
self->m_function(dx, dy, event->state, self->m_data);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void freeze_pointer(GtkWindow* window, MotionDeltaFunction function, void* data)
|
||||
{
|
||||
ASSERT_MESSAGE(m_function == 0, "can't freeze pointer");
|
||||
|
||||
const GdkEventMask mask = static_cast<GdkEventMask>(GDK_POINTER_MOTION_MASK
|
||||
| GDK_POINTER_MOTION_HINT_MASK
|
||||
| GDK_BUTTON_MOTION_MASK
|
||||
| GDK_BUTTON1_MOTION_MASK
|
||||
| GDK_BUTTON2_MOTION_MASK
|
||||
| GDK_BUTTON3_MOTION_MASK
|
||||
| GDK_BUTTON_PRESS_MASK
|
||||
| GDK_BUTTON_RELEASE_MASK
|
||||
| GDK_VISIBILITY_NOTIFY_MASK);
|
||||
|
||||
GdkCursor* cursor = create_blank_cursor();
|
||||
//GdkGrabStatus status =
|
||||
gdk_pointer_grab(GTK_WIDGET(window)->window, TRUE, mask, 0, cursor, GDK_CURRENT_TIME);
|
||||
gdk_cursor_unref(cursor);
|
||||
|
||||
Sys_GetCursorPos(window, &recorded_x, &recorded_y);
|
||||
|
||||
Sys_SetCursorPos(window, recorded_x, recorded_y);
|
||||
|
||||
m_function = function;
|
||||
m_data = data;
|
||||
|
||||
handle_motion = g_signal_connect(G_OBJECT(window), "motion_notify_event", G_CALLBACK(motion_delta), this);
|
||||
}
|
||||
|
||||
void unfreeze_pointer(GtkWindow* window)
|
||||
{
|
||||
g_signal_handler_disconnect(G_OBJECT(window), handle_motion);
|
||||
|
||||
m_function = 0;
|
||||
m_data = 0;
|
||||
|
||||
Sys_SetCursorPos(window, recorded_x, recorded_y);
|
||||
|
||||
gdk_pointer_ungrab(GDK_CURRENT_TIME);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
303
libs/gtkutil/dialog.cpp
Normal file
303
libs/gtkutil/dialog.cpp
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "dialog.h"
|
||||
|
||||
#include <gtk/gtkmain.h>
|
||||
#include <gtk/gtkalignment.h>
|
||||
#include <gtk/gtkhbox.h>
|
||||
#include <gtk/gtkvbox.h>
|
||||
#include <gtk/gtkradiobutton.h>
|
||||
#include <gtk/gtkframe.h>
|
||||
#include <gtk/gtktable.h>
|
||||
#include <gtk/gtkentry.h>
|
||||
#include <gtk/gtkbutton.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
|
||||
#include "button.h"
|
||||
#include "window.h"
|
||||
|
||||
GtkVBox* create_dialog_vbox(int spacing, int border)
|
||||
{
|
||||
GtkVBox* vbox = GTK_VBOX(gtk_vbox_new(FALSE, spacing));
|
||||
gtk_widget_show(GTK_WIDGET(vbox));
|
||||
gtk_container_set_border_width(GTK_CONTAINER(vbox), border);
|
||||
return vbox;
|
||||
}
|
||||
|
||||
GtkHBox* create_dialog_hbox(int spacing, int border)
|
||||
{
|
||||
GtkHBox* hbox = GTK_HBOX(gtk_hbox_new(FALSE, spacing));
|
||||
gtk_widget_show(GTK_WIDGET(hbox));
|
||||
gtk_container_set_border_width(GTK_CONTAINER(hbox), border);
|
||||
return hbox;
|
||||
}
|
||||
|
||||
GtkFrame* create_dialog_frame(const char* label, GtkShadowType shadow)
|
||||
{
|
||||
GtkFrame* frame = GTK_FRAME(gtk_frame_new(label));
|
||||
gtk_widget_show(GTK_WIDGET(frame));
|
||||
gtk_frame_set_shadow_type(frame, shadow);
|
||||
return frame;
|
||||
}
|
||||
|
||||
GtkTable* create_dialog_table(unsigned int rows, unsigned int columns, unsigned int row_spacing, unsigned int col_spacing, int border)
|
||||
{
|
||||
GtkTable* table = GTK_TABLE(gtk_table_new(rows, columns, FALSE));
|
||||
gtk_widget_show(GTK_WIDGET(table));
|
||||
gtk_table_set_row_spacings(table, row_spacing);
|
||||
gtk_table_set_col_spacings(table, col_spacing);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(table), border);
|
||||
return table;
|
||||
}
|
||||
|
||||
GtkButton* create_dialog_button(const char* label, GCallback func, gpointer data)
|
||||
{
|
||||
GtkButton* button = GTK_BUTTON(gtk_button_new_with_label(label));
|
||||
gtk_widget_set_size_request(GTK_WIDGET(button), 64, -1);
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
g_signal_connect(G_OBJECT(button), "clicked", func, data);
|
||||
return button;
|
||||
}
|
||||
|
||||
GtkWindow* create_dialog_window(GtkWindow* parent, const char* title, GCallback func, gpointer data, int default_w, int default_h)
|
||||
{
|
||||
GtkWindow* window = create_floating_window(title, parent);
|
||||
gtk_window_set_default_size(window, default_w, default_h);
|
||||
gtk_window_set_position(window, GTK_WIN_POS_CENTER_ON_PARENT);
|
||||
g_signal_connect(G_OBJECT(window), "delete_event", func, data);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
gboolean modal_dialog_button_clicked(GtkWidget *widget, ModalDialogButton* button)
|
||||
{
|
||||
button->m_dialog.loop = false;
|
||||
button->m_dialog.ret = button->m_value;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean modal_dialog_delete(GtkWidget *widget, GdkEvent* event, ModalDialog* dialog)
|
||||
{
|
||||
dialog->loop = 0;
|
||||
dialog->ret = eIDCANCEL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EMessageBoxReturn modal_dialog_show(GtkWindow* window, ModalDialog& dialog)
|
||||
{
|
||||
gtk_grab_add(GTK_WIDGET(window));
|
||||
gtk_widget_show(GTK_WIDGET(window));
|
||||
|
||||
dialog.loop = true;
|
||||
while(dialog.loop)
|
||||
{
|
||||
gtk_main_iteration();
|
||||
}
|
||||
|
||||
gtk_widget_hide(GTK_WIDGET(window));
|
||||
gtk_grab_remove(GTK_WIDGET(window));
|
||||
|
||||
return dialog.ret;
|
||||
}
|
||||
|
||||
GtkButton* create_modal_dialog_button(const char* label, ModalDialogButton& button)
|
||||
{
|
||||
return create_dialog_button(label, G_CALLBACK(modal_dialog_button_clicked), &button);
|
||||
}
|
||||
|
||||
GtkWindow* create_modal_dialog_window(GtkWindow* parent, const char* title, ModalDialog& dialog, int default_w, int default_h)
|
||||
{
|
||||
return create_dialog_window(parent, title, G_CALLBACK(modal_dialog_delete), &dialog, default_w, default_h);
|
||||
}
|
||||
|
||||
GtkWindow* create_fixedsize_modal_dialog_window(GtkWindow* parent, const char* title, ModalDialog& dialog, int width, int height)
|
||||
{
|
||||
GtkWindow* window = create_modal_dialog_window(parent, title, dialog, width, height);
|
||||
|
||||
gtk_window_set_resizable(window, FALSE);
|
||||
gtk_window_set_modal(window, TRUE);
|
||||
gtk_window_set_position(window, GTK_WIN_POS_CENTER);
|
||||
|
||||
window_remove_minmax(window);
|
||||
|
||||
//gtk_widget_set_size_request(GTK_WIDGET(window), width, height);
|
||||
//gtk_window_set_default_size(window, width, height);
|
||||
//gtk_window_resize(window, width, height);
|
||||
//GdkGeometry geometry = { width, height, -1, -1, width, height, -1, -1, -1, -1, GDK_GRAVITY_STATIC, };
|
||||
//gtk_window_set_geometry_hints(window, GTK_WIDGET(window), &geometry, (GdkWindowHints)(GDK_HINT_POS|GDK_HINT_MIN_SIZE|GDK_HINT_BASE_SIZE));
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
gboolean dialog_button_ok(GtkWidget *widget, ModalDialog* data)
|
||||
{
|
||||
data->loop = false;
|
||||
data->ret = eIDOK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean dialog_button_cancel(GtkWidget *widget, ModalDialog* data)
|
||||
{
|
||||
data->loop = false;
|
||||
data->ret = eIDCANCEL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean dialog_button_yes(GtkWidget *widget, ModalDialog* data)
|
||||
{
|
||||
data->loop = false;
|
||||
data->ret = eIDYES;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean dialog_button_no(GtkWidget *widget, ModalDialog* data)
|
||||
{
|
||||
data->loop = false;
|
||||
data->ret = eIDNO;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean dialog_delete_callback(GtkWidget *widget, GdkEventAny* event, ModalDialog* data)
|
||||
{
|
||||
gtk_widget_hide(widget);
|
||||
data->loop = false;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkWindow* create_simple_modal_dialog_window(const char* title, ModalDialog& dialog, GtkWidget* contents)
|
||||
{
|
||||
GtkWindow* window = create_fixedsize_modal_dialog_window(0, title, dialog);
|
||||
|
||||
GtkVBox* vbox1 = create_dialog_vbox(8, 4);
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox1));
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(vbox1), contents);
|
||||
|
||||
GtkAlignment* alignment = GTK_ALIGNMENT(gtk_alignment_new(0.5, 0.0, 0.0, 0.0));
|
||||
gtk_widget_show(GTK_WIDGET(alignment));
|
||||
gtk_box_pack_start(GTK_BOX(vbox1), GTK_WIDGET(alignment), FALSE, FALSE, 0);
|
||||
|
||||
GtkButton* button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &dialog);
|
||||
gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(button));
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
RadioHBox RadioHBox_new(StringArrayRange names)
|
||||
{
|
||||
GtkHBox* hbox = GTK_HBOX(gtk_hbox_new(TRUE, 4));
|
||||
gtk_widget_show(GTK_WIDGET(hbox));
|
||||
|
||||
GSList* group = 0;
|
||||
GtkRadioButton* radio = 0;
|
||||
for(StringArrayRange::Iterator i = names.begin; i != names.end; ++i)
|
||||
{
|
||||
radio = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label(group, *i));
|
||||
gtk_widget_show(GTK_WIDGET(radio));
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(radio), FALSE, FALSE, 0);
|
||||
|
||||
group = gtk_radio_button_get_group(radio);
|
||||
}
|
||||
|
||||
return RadioHBox(hbox, radio);
|
||||
}
|
||||
|
||||
|
||||
PathEntry PathEntry_new()
|
||||
{
|
||||
GtkFrame* frame = GTK_FRAME(gtk_frame_new(NULL));
|
||||
gtk_widget_show(GTK_WIDGET(frame));
|
||||
gtk_frame_set_shadow_type(frame, GTK_SHADOW_IN);
|
||||
|
||||
// path entry
|
||||
GtkHBox* hbox = GTK_HBOX(gtk_hbox_new(FALSE, 0));
|
||||
gtk_widget_show(GTK_WIDGET(hbox));
|
||||
|
||||
GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
|
||||
gtk_entry_set_has_frame(entry, FALSE);
|
||||
gtk_widget_show(GTK_WIDGET(entry));
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry), TRUE, TRUE, 0);
|
||||
|
||||
// browse button
|
||||
GtkButton* button = GTK_BUTTON(gtk_button_new());
|
||||
button_set_icon(button, "ellipsis.bmp");
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
gtk_box_pack_end(GTK_BOX(hbox), GTK_WIDGET(button), FALSE, FALSE, 0);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(hbox));
|
||||
|
||||
return PathEntry(frame, entry, button);
|
||||
}
|
||||
|
||||
void PathEntry_setPath(PathEntry& self, const char* path)
|
||||
{
|
||||
gtk_entry_set_text(self.m_entry, path);
|
||||
}
|
||||
typedef ReferenceCaller1<PathEntry, const char*, PathEntry_setPath> PathEntrySetPathCaller;
|
||||
|
||||
void BrowsedPathEntry_clicked(GtkWidget* widget, BrowsedPathEntry* self)
|
||||
{
|
||||
self->m_browse(PathEntrySetPathCaller(self->m_entry));
|
||||
}
|
||||
|
||||
BrowsedPathEntry::BrowsedPathEntry(const BrowseCallback& browse) :
|
||||
m_entry(PathEntry_new()),
|
||||
m_browse(browse)
|
||||
{
|
||||
g_signal_connect(G_OBJECT(m_entry.m_button), "clicked", G_CALLBACK(BrowsedPathEntry_clicked), this);
|
||||
}
|
||||
|
||||
|
||||
GtkLabel* DialogLabel_new(const char* name)
|
||||
{
|
||||
GtkLabel* label = GTK_LABEL(gtk_label_new(name));
|
||||
gtk_widget_show(GTK_WIDGET(label));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
|
||||
gtk_label_set_justify(label, GTK_JUSTIFY_LEFT);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
GtkTable* DialogRow_new(const char* name, GtkWidget* widget)
|
||||
{
|
||||
GtkTable* table = GTK_TABLE(gtk_table_new(1, 3, TRUE));
|
||||
gtk_widget_show(GTK_WIDGET(table));
|
||||
|
||||
gtk_table_set_col_spacings(table, 4);
|
||||
gtk_table_set_row_spacings(table, 0);
|
||||
|
||||
gtk_table_attach(table, GTK_WIDGET(DialogLabel_new(name)), 0, 1, 0, 1,
|
||||
(GtkAttachOptions) (GTK_EXPAND|GTK_FILL),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
|
||||
gtk_table_attach(table, widget, 1, 3, 0, 1,
|
||||
(GtkAttachOptions) (GTK_EXPAND|GTK_FILL),
|
||||
(GtkAttachOptions) (0), 0, 0);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void DialogVBox_packRow(GtkVBox* vbox, GtkWidget* row)
|
||||
{
|
||||
gtk_box_pack_start(GTK_BOX(vbox), row, FALSE, FALSE, 0);
|
||||
}
|
||||
|
||||
145
libs/gtkutil/dialog.h
Normal file
145
libs/gtkutil/dialog.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_DIALOG_H)
|
||||
#define INCLUDED_GTKUTIL_DIALOG_H
|
||||
|
||||
#include "generic/callback.h"
|
||||
#include "generic/arrayrange.h"
|
||||
#include "qerplugin.h"
|
||||
#include <gtk/gtkenums.h>
|
||||
|
||||
typedef int gint;
|
||||
typedef gint gboolean;
|
||||
typedef struct _GdkEventAny GdkEventAny;
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkHBox GtkHBox;
|
||||
typedef struct _GtkVBox GtkVBox;
|
||||
typedef struct _GtkRadioButton GtkRadioButton;
|
||||
typedef struct _GtkFrame GtkFrame;
|
||||
typedef struct _GtkEntry GtkEntry;
|
||||
typedef struct _GtkButton GtkButton;
|
||||
typedef struct _GtkLabel GtkLabel;
|
||||
typedef struct _GtkTable GtkTable;
|
||||
|
||||
|
||||
struct ModalDialog
|
||||
{
|
||||
ModalDialog()
|
||||
: loop(true), ret(eIDCANCEL)
|
||||
{
|
||||
}
|
||||
bool loop;
|
||||
EMessageBoxReturn ret;
|
||||
};
|
||||
|
||||
struct ModalDialogButton
|
||||
{
|
||||
ModalDialogButton(ModalDialog& dialog, EMessageBoxReturn value)
|
||||
: m_dialog(dialog), m_value(value)
|
||||
{
|
||||
}
|
||||
ModalDialog& m_dialog;
|
||||
EMessageBoxReturn m_value;
|
||||
};
|
||||
|
||||
typedef void (*GCallback)(void);
|
||||
typedef void* gpointer;
|
||||
typedef struct _GtkWindow GtkWindow;
|
||||
typedef struct _GtkTable GtkTable;
|
||||
typedef struct _GtkButton GtkButton;
|
||||
typedef struct _GtkVBox GtkVBox;
|
||||
typedef struct _GtkHBox GtkHBox;
|
||||
typedef struct _GtkFrame GtkFrame;
|
||||
|
||||
GtkWindow* create_fixedsize_modal_window(GtkWindow* parent, const char* title, int width, int height);
|
||||
|
||||
GtkWindow* create_dialog_window(GtkWindow* parent, const char* title, GCallback func, gpointer data, int default_w = -1, int default_h = -1);
|
||||
GtkTable* create_dialog_table(unsigned int rows, unsigned int columns, unsigned int row_spacing, unsigned int col_spacing, int border = 0);
|
||||
GtkButton* create_dialog_button(const char* label, GCallback func, gpointer data);
|
||||
GtkVBox* create_dialog_vbox(int spacing, int border = 0);
|
||||
GtkHBox* create_dialog_hbox(int spacing, int border = 0);
|
||||
GtkFrame* create_dialog_frame(const char* label, GtkShadowType shadow = GTK_SHADOW_ETCHED_IN);
|
||||
|
||||
GtkButton* create_modal_dialog_button(const char* label, ModalDialogButton& button);
|
||||
GtkWindow* create_modal_dialog_window(GtkWindow* parent, const char* title, ModalDialog& dialog, int default_w = -1, int default_h = -1);
|
||||
GtkWindow* create_fixedsize_modal_dialog_window(GtkWindow* parent, const char* title, ModalDialog& dialog, int width = -1, int height = -1);
|
||||
EMessageBoxReturn modal_dialog_show(GtkWindow* window, ModalDialog& dialog);
|
||||
|
||||
|
||||
gboolean dialog_button_ok(GtkWidget *widget, ModalDialog* data);
|
||||
gboolean dialog_button_cancel(GtkWidget *widget, ModalDialog* data);
|
||||
gboolean dialog_button_yes(GtkWidget *widget, ModalDialog* data);
|
||||
gboolean dialog_button_no(GtkWidget *widget, ModalDialog* data);
|
||||
gboolean dialog_delete_callback(GtkWidget *widget, GdkEventAny* event, ModalDialog* data);
|
||||
|
||||
GtkWindow* create_simple_modal_dialog_window(const char* title, ModalDialog& dialog, GtkWidget* contents);
|
||||
|
||||
class RadioHBox
|
||||
{
|
||||
public:
|
||||
GtkHBox* m_hbox;
|
||||
GtkRadioButton* m_radio;
|
||||
RadioHBox(GtkHBox* hbox, GtkRadioButton* radio) :
|
||||
m_hbox(hbox),
|
||||
m_radio(radio)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
RadioHBox RadioHBox_new(StringArrayRange names);
|
||||
|
||||
|
||||
class PathEntry
|
||||
{
|
||||
public:
|
||||
GtkFrame* m_frame;
|
||||
GtkEntry* m_entry;
|
||||
GtkButton* m_button;
|
||||
PathEntry(GtkFrame* frame, GtkEntry* entry, GtkButton* button) :
|
||||
m_frame(frame),
|
||||
m_entry(entry),
|
||||
m_button(button)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
PathEntry PathEntry_new();
|
||||
|
||||
class BrowsedPathEntry
|
||||
{
|
||||
public:
|
||||
typedef Callback1<const char*> SetPathCallback;
|
||||
typedef Callback1<const SetPathCallback&> BrowseCallback;
|
||||
|
||||
PathEntry m_entry;
|
||||
BrowseCallback m_browse;
|
||||
|
||||
BrowsedPathEntry(const BrowseCallback& browse);
|
||||
};
|
||||
|
||||
GtkLabel* DialogLabel_new(const char* name);
|
||||
GtkTable* DialogRow_new(const char* name, GtkWidget* widget);
|
||||
typedef struct _GtkVBox GtkVBox;
|
||||
void DialogVBox_packRow(GtkVBox* vbox, GtkWidget* row);
|
||||
|
||||
|
||||
#endif
|
||||
23
libs/gtkutil/entry.cpp
Normal file
23
libs/gtkutil/entry.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "entry.h"
|
||||
|
||||
63
libs/gtkutil/entry.h
Normal file
63
libs/gtkutil/entry.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_ENTRY_H)
|
||||
#define INCLUDED_GTKUTIL_ENTRY_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <gtk/gtkentry.h>
|
||||
|
||||
inline void entry_set_string(GtkEntry* entry, const char* string)
|
||||
{
|
||||
gtk_entry_set_text(entry, string);
|
||||
}
|
||||
|
||||
inline void entry_set_int(GtkEntry* entry, int i)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf(buf, "%d", i);
|
||||
entry_set_string(entry, buf);
|
||||
}
|
||||
|
||||
inline void entry_set_float(GtkEntry* entry, float f)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf(buf, "%g", f);
|
||||
entry_set_string(entry, buf);
|
||||
}
|
||||
|
||||
inline const char* entry_get_string(GtkEntry* entry)
|
||||
{
|
||||
return gtk_entry_get_text(entry);
|
||||
}
|
||||
|
||||
inline int entry_get_int(GtkEntry* entry)
|
||||
{
|
||||
return atoi(entry_get_string(entry));
|
||||
}
|
||||
|
||||
inline double entry_get_float(GtkEntry* entry)
|
||||
{
|
||||
return atof(entry_get_string(entry));
|
||||
}
|
||||
|
||||
#endif
|
||||
486
libs/gtkutil/filechooser.cpp
Normal file
486
libs/gtkutil/filechooser.cpp
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "filechooser.h"
|
||||
|
||||
#include "ifiletypes.h"
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
#include <gtk/gtkfilechooser.h>
|
||||
#include <gtk/gtkfilechooserdialog.h>
|
||||
#include <gtk/gtkstock.h>
|
||||
|
||||
#include "string/string.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "container/array.h"
|
||||
#include "os/path.h"
|
||||
#include "os/file.h"
|
||||
|
||||
#include "messagebox.h"
|
||||
|
||||
|
||||
struct filetype_pair_t
|
||||
{
|
||||
filetype_pair_t()
|
||||
: m_moduleName("")
|
||||
{
|
||||
}
|
||||
filetype_pair_t(const char* moduleName, filetype_t type)
|
||||
: m_moduleName(moduleName), m_type(type)
|
||||
{
|
||||
}
|
||||
const char* m_moduleName;
|
||||
filetype_t m_type;
|
||||
};
|
||||
|
||||
class FileTypeList : public IFileTypeList
|
||||
{
|
||||
struct filetype_copy_t
|
||||
{
|
||||
filetype_copy_t(const filetype_pair_t& other)
|
||||
: m_moduleName(other.m_moduleName), m_name(other.m_type.name), m_pattern(other.m_type.pattern)
|
||||
{
|
||||
}
|
||||
CopiedString m_moduleName;
|
||||
CopiedString m_name;
|
||||
CopiedString m_pattern;
|
||||
};
|
||||
|
||||
typedef std::list<filetype_copy_t> Types;
|
||||
Types m_types;
|
||||
public:
|
||||
|
||||
typedef Types::const_iterator const_iterator;
|
||||
const_iterator begin() const
|
||||
{
|
||||
return m_types.begin();
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
return m_types.end();
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_types.size();
|
||||
}
|
||||
|
||||
void addType(const char* moduleName, filetype_t type)
|
||||
{
|
||||
m_types.push_back(filetype_pair_t(moduleName, type));
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
class Win32Filters
|
||||
{
|
||||
const FileTypeList& m_types;
|
||||
Array<char> m_filters;
|
||||
public:
|
||||
Win32Filters(const FileTypeList& typeList) : m_types(typeList)
|
||||
{
|
||||
std::size_t len = 0;
|
||||
for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i)
|
||||
{
|
||||
len = len + strlen((*i).m_name.c_str()) + strlen((*i).m_pattern.c_str()) * 2 + 5;
|
||||
}
|
||||
m_filters.resize(len + 1); // length + null char
|
||||
char *w = m_filters.data();
|
||||
for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i)
|
||||
{
|
||||
for(const char *r = (*i).m_name.c_str(); *r!='\0'; r++, w++)
|
||||
{
|
||||
*w = *r;
|
||||
}
|
||||
*w++ = ' ';
|
||||
*w++ = '(';
|
||||
for(const char *r = (*i).m_pattern.c_str(); *r!='\0'; r++, w++)
|
||||
{
|
||||
*w = *r;
|
||||
}
|
||||
*w++ = ')';
|
||||
*w++ = '\0';
|
||||
for(const char *r = (*i).m_pattern.c_str(); *r!='\0'; r++, w++)
|
||||
{
|
||||
*w = (*r == ',') ? ';' : *r;
|
||||
}
|
||||
*w++ = '\0';
|
||||
}
|
||||
m_filters[len] = '\0';
|
||||
}
|
||||
filetype_pair_t getType(const char *filter) const
|
||||
{
|
||||
for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i)
|
||||
{
|
||||
if(string_equal((*i).m_pattern.c_str(), filter))
|
||||
{
|
||||
return filetype_pair_t((*i).m_moduleName.c_str(), filetype_t((*i).m_name.c_str(), (*i).m_pattern.c_str()));
|
||||
}
|
||||
}
|
||||
return filetype_pair_t();
|
||||
}
|
||||
const char* getFilters() const
|
||||
{
|
||||
return m_filters.data();
|
||||
}
|
||||
};
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <gdk/gdkwin32.h>
|
||||
#include <commdlg.h>
|
||||
|
||||
static char szFile[MAX_PATH]; /* filename string */
|
||||
|
||||
|
||||
#define FILEDLG_CUSTOM_FILTER_LENGTH 64
|
||||
// to be used with the advanced file selector
|
||||
|
||||
const char* file_dialog_show_win32(GtkWidget* parent, bool open, const char* title, const char* path, const char* pattern)
|
||||
{
|
||||
const char* r;
|
||||
char* w;
|
||||
filetype_t type;
|
||||
FileTypeList typelist;
|
||||
|
||||
if(pattern == 0)
|
||||
{
|
||||
pattern = "*";
|
||||
}
|
||||
|
||||
GlobalFiletypes().getTypeList(pattern, &typelist);
|
||||
|
||||
Win32Filters filters(typelist);
|
||||
|
||||
// win32 dialog stores the selected "save as type" extension in the second null-terminated string
|
||||
char customfilter[FILEDLG_CUSTOM_FILTER_LENGTH];
|
||||
|
||||
static OPENFILENAME ofn; /* common dialog box structure */
|
||||
static char szDirName[MAX_PATH]; /* directory string */
|
||||
static char szFile[MAX_PATH]; /* filename string */
|
||||
static char szFileTitle[MAX_PATH]; /* file title string */
|
||||
static int i, cbString; /* integer count variables */
|
||||
static HANDLE hf; /* file handle */
|
||||
|
||||
// do that the native way
|
||||
/* Place the terminating null character in the szFile. */
|
||||
szFile[0] = '\0';
|
||||
customfilter[0] = customfilter[1] = customfilter[2] = '\0';
|
||||
|
||||
/* Set the members of the OPENFILENAME structure. */
|
||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||
ofn.hwndOwner = (HWND)GDK_WINDOW_HWND(parent->window);
|
||||
ofn.nFilterIndex = 0;
|
||||
ofn.lpstrFilter = filters.getFilters();
|
||||
ofn.lpstrCustomFilter = customfilter;
|
||||
ofn.nMaxCustFilter = sizeof(customfilter);
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.nMaxFile = sizeof(szFile);
|
||||
ofn.lpstrFileTitle = 0; // we don't need to get the name of the file
|
||||
if(path)
|
||||
{
|
||||
// szDirName: Radiant uses unix convention for paths internally
|
||||
// Win32 (of course) and Gtk (who would have thought) expect the '\\' convention
|
||||
// copy path, replacing dir separators as appropriate
|
||||
for(r=path, w=szDirName; *r!='\0'; r++)
|
||||
*w++ = (*r=='/') ? '\\' : *r;
|
||||
// terminate string
|
||||
*w = '\0';
|
||||
ofn.lpstrInitialDir = szDirName;
|
||||
}
|
||||
else ofn.lpstrInitialDir = 0;
|
||||
ofn.lpstrTitle = title;
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
|
||||
/* Display the Open dialog box. */
|
||||
// it's open or close depending on 'open' parameter
|
||||
if (open)
|
||||
{
|
||||
if (!GetOpenFileName(&ofn))
|
||||
return 0; // canceled
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GetSaveFileName(&ofn))
|
||||
return 0; // canceled
|
||||
}
|
||||
|
||||
if(!string_equal(pattern, "*"))
|
||||
{
|
||||
type = filters.getType(customfilter+1).m_type;
|
||||
}
|
||||
|
||||
// don't return an empty filename
|
||||
if(szFile[0] == '\0') return 0;
|
||||
|
||||
// convert back to unix format
|
||||
for(w=szFile; *w!='\0'; w++)
|
||||
{
|
||||
if(*w=='\\')
|
||||
{
|
||||
*w = '/';
|
||||
}
|
||||
}
|
||||
// when saving, force an extension depending on filetype
|
||||
/* \todo SPoG - file_dialog should return filetype information separately.. not force file extension.. */
|
||||
if(!open && !string_equal(pattern, "*"))
|
||||
{
|
||||
// last ext separator
|
||||
const char* extension = path_get_extension(szFile);
|
||||
// no extension
|
||||
if(string_empty(extension))
|
||||
{
|
||||
strcat(szFile, type.pattern+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(szFile + (extension - szFile), type.pattern+2);
|
||||
}
|
||||
}
|
||||
|
||||
return szFile;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
class GTKMasks
|
||||
{
|
||||
const FileTypeList& m_types;
|
||||
public:
|
||||
std::vector<CopiedString> m_filters;
|
||||
std::vector<CopiedString> m_masks;
|
||||
|
||||
GTKMasks(const FileTypeList& types) : m_types(types)
|
||||
{
|
||||
m_masks.reserve(m_types.size());
|
||||
for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i)
|
||||
{
|
||||
std::size_t len = strlen((*i).m_name.c_str()) + strlen((*i).m_pattern.c_str()) + 3;
|
||||
StringOutputStream buffer(len + 1); // length + null char
|
||||
|
||||
buffer << (*i).m_name.c_str() << " <" << (*i).m_pattern.c_str() << ">";
|
||||
|
||||
m_masks.push_back(buffer.c_str());
|
||||
}
|
||||
|
||||
m_filters.reserve(m_types.size());
|
||||
for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i)
|
||||
{
|
||||
m_filters.push_back((*i).m_pattern);
|
||||
}
|
||||
}
|
||||
|
||||
filetype_pair_t GetTypeForGTKMask(const char *mask) const
|
||||
{
|
||||
std::vector<CopiedString>::const_iterator j = m_masks.begin();
|
||||
for(FileTypeList::const_iterator i = m_types.begin(); i != m_types.end(); ++i, ++j)
|
||||
{
|
||||
if(string_equal((*j).c_str(), mask))
|
||||
{
|
||||
return filetype_pair_t((*i).m_moduleName.c_str(), filetype_t((*i).m_name.c_str(), (*i).m_pattern.c_str()));
|
||||
}
|
||||
}
|
||||
return filetype_pair_t();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static char g_file_dialog_file[1024];
|
||||
|
||||
const char* file_dialog_show(GtkWidget* parent, bool open, const char* title, const char* path, const char* pattern)
|
||||
{
|
||||
filetype_t type;
|
||||
|
||||
if(pattern == 0)
|
||||
{
|
||||
pattern = "*";
|
||||
}
|
||||
|
||||
FileTypeList typelist;
|
||||
GlobalFiletypes().getTypeList(pattern, &typelist);
|
||||
|
||||
GTKMasks masks(typelist);
|
||||
|
||||
if (title == 0)
|
||||
title = open ? "Open File" : "Save File";
|
||||
|
||||
GtkWidget* dialog;
|
||||
if (open)
|
||||
{
|
||||
dialog = gtk_file_chooser_dialog_new(title,
|
||||
GTK_WINDOW(parent),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
dialog = gtk_file_chooser_dialog_new(title,
|
||||
GTK_WINDOW(parent),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "unnamed");
|
||||
}
|
||||
|
||||
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
|
||||
gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
|
||||
|
||||
// we expect an actual path below, if the path is 0 we might crash
|
||||
if (path != 0 && !string_empty(path))
|
||||
{
|
||||
ASSERT_MESSAGE(path_is_absolute(path), "file_dialog_show: path not absolute: " << makeQuoted(path));
|
||||
|
||||
Array<char> new_path(strlen(path)+1);
|
||||
|
||||
// copy path, replacing dir separators as appropriate
|
||||
Array<char>::iterator w = new_path.begin();
|
||||
for(const char* r = path; *r != '\0'; ++r)
|
||||
{
|
||||
*w++ = (*r == '/') ? G_DIR_SEPARATOR : *r;
|
||||
}
|
||||
// remove separator from end of path if required
|
||||
if(*(w-1) == G_DIR_SEPARATOR)
|
||||
{
|
||||
--w;
|
||||
}
|
||||
// terminate string
|
||||
*w = '\0';
|
||||
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), new_path.data());
|
||||
}
|
||||
|
||||
// we should add all important paths as shortcut folder...
|
||||
// gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(dialog), "/tmp/", NULL);
|
||||
|
||||
|
||||
for(std::size_t i = 0; i < masks.m_filters.size(); ++i)
|
||||
{
|
||||
GtkFileFilter* filter = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(filter, masks.m_filters[i].c_str());
|
||||
gtk_file_filter_set_name(filter, masks.m_masks[i].c_str());
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
|
||||
}
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
strcpy(g_file_dialog_file, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)));
|
||||
|
||||
if(!string_equal(pattern, "*"))
|
||||
{
|
||||
GtkFileFilter* filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
|
||||
if(filter != 0) // no filter set? some file-chooser implementations may allow the user to set no filter, which we treat as 'all files'
|
||||
{
|
||||
type = masks.GetTypeForGTKMask(gtk_file_filter_get_name(filter)).m_type;
|
||||
// last ext separator
|
||||
const char* extension = path_get_extension(g_file_dialog_file);
|
||||
// no extension
|
||||
if(string_empty(extension))
|
||||
{
|
||||
strcat(g_file_dialog_file, type.pattern+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(g_file_dialog_file + (extension - g_file_dialog_file), type.pattern+2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert back to unix format
|
||||
for(char* w = g_file_dialog_file; *w!='\0'; w++)
|
||||
{
|
||||
if(*w=='\\')
|
||||
{
|
||||
*w = '/';
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_file_dialog_file[0] = '\0';
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
|
||||
// don't return an empty filename
|
||||
if(g_file_dialog_file[0] == '\0') return NULL;
|
||||
|
||||
return g_file_dialog_file;
|
||||
}
|
||||
|
||||
char* dir_dialog(GtkWidget* parent, const char* title, const char* path)
|
||||
{
|
||||
GtkWidget* dialog = gtk_file_chooser_dialog_new(title,
|
||||
GTK_WINDOW(parent),
|
||||
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
|
||||
gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
|
||||
|
||||
if(!string_empty(path))
|
||||
{
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
}
|
||||
|
||||
char* filename = 0;
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
bool g_FileChooser_nativeGUI = true;
|
||||
#endif
|
||||
|
||||
const char* file_dialog(GtkWidget* parent, bool open, const char* title, const char* path, const char* pattern)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
const char* file =
|
||||
#ifdef WIN32
|
||||
g_FileChooser_nativeGUI
|
||||
? file_dialog_show_win32(parent, open, title, path, pattern) :
|
||||
#endif
|
||||
file_dialog_show(parent, open, title, path, pattern);
|
||||
|
||||
if(open
|
||||
|| !file_exists(file)
|
||||
|| gtk_MessageBox(parent, "The file specified already exists.\nDo you want to replace it?", title, eMB_NOYES, eMB_ICONQUESTION) == eIDYES)
|
||||
{
|
||||
return file;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
libs/gtkutil/filechooser.h
Normal file
42
libs/gtkutil/filechooser.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_FILECHOOSER_H)
|
||||
#define INCLUDED_GTKUTIL_FILECHOOSER_H
|
||||
|
||||
/// \file
|
||||
/// GTK+ file-chooser dialogs.
|
||||
|
||||
#ifdef WIN32
|
||||
extern bool g_FileChooser_nativeGUI;
|
||||
#endif
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
const char* file_dialog(GtkWidget *parent, bool open, const char* title, const char* path = 0, const char* pattern = 0);
|
||||
|
||||
|
||||
/// \brief Prompts the user to browse for a directory.
|
||||
/// The prompt window will be transient to \p parent.
|
||||
/// The directory will initially default to \p path, which must be an absolute path.
|
||||
/// The returned string is allocated with \c g_malloc and must be freed with \c g_free.
|
||||
char* dir_dialog(GtkWidget *parent, const char* title = "Choose Directory", const char* path = "");
|
||||
|
||||
#endif
|
||||
35
libs/gtkutil/frame.cpp
Normal file
35
libs/gtkutil/frame.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "frame.h"
|
||||
|
||||
#include <gtk/gtkframe.h>
|
||||
|
||||
GtkFrame* create_framed_widget(GtkWidget* widget)
|
||||
{
|
||||
GtkFrame* frame = GTK_FRAME(gtk_frame_new(0));
|
||||
gtk_widget_show(GTK_WIDGET(frame));
|
||||
gtk_frame_set_shadow_type(frame, GTK_SHADOW_IN);
|
||||
gtk_container_add (GTK_CONTAINER(frame), widget);
|
||||
gtk_widget_show(GTK_WIDGET(widget));
|
||||
return frame;
|
||||
}
|
||||
|
||||
29
libs/gtkutil/frame.h
Normal file
29
libs/gtkutil/frame.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_FRAME_H)
|
||||
#define INCLUDED_GTKUTIL_FRAME_H
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkFrame GtkFrame;
|
||||
GtkFrame* create_framed_widget(GtkWidget* widget);
|
||||
|
||||
#endif
|
||||
56
libs/gtkutil/glfont.cpp
Normal file
56
libs/gtkutil/glfont.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "glfont.h"
|
||||
|
||||
#include "igl.h"
|
||||
#include <gtk/gtkglwidget.h>
|
||||
|
||||
GLFont glfont_create(const char* font_string)
|
||||
{
|
||||
GLuint font_list_base = glGenLists (256);
|
||||
gint font_height = 0;
|
||||
|
||||
PangoFontDescription* font_desc = pango_font_description_from_string (font_string);
|
||||
|
||||
PangoFont* font = gdk_gl_font_use_pango_font (font_desc, 0, 256, font_list_base);
|
||||
|
||||
if(font != 0)
|
||||
{
|
||||
PangoFontMetrics* font_metrics = pango_font_get_metrics (font, 0);
|
||||
|
||||
font_height = pango_font_metrics_get_ascent (font_metrics) +
|
||||
pango_font_metrics_get_descent (font_metrics);
|
||||
font_height = PANGO_PIXELS (font_height);
|
||||
|
||||
pango_font_metrics_unref (font_metrics);
|
||||
}
|
||||
|
||||
pango_font_description_free (font_desc);
|
||||
|
||||
return GLFont(font_list_base, font_height);
|
||||
}
|
||||
|
||||
void glfont_release(GLFont& font)
|
||||
{
|
||||
glDeleteLists(font.getDisplayList(), 256);
|
||||
font = GLFont(0, 0);
|
||||
}
|
||||
48
libs/gtkutil/glfont.h
Normal file
48
libs/gtkutil/glfont.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_GLFONT_H)
|
||||
#define INCLUDED_GTKUTIL_GLFONT_H
|
||||
|
||||
typedef unsigned int GLuint;
|
||||
|
||||
class GLFont
|
||||
{
|
||||
GLuint m_displayList;
|
||||
int m_pixelHeight;
|
||||
public:
|
||||
GLFont(GLuint displayList, int pixelHeight) : m_displayList(displayList), m_pixelHeight(pixelHeight)
|
||||
{
|
||||
}
|
||||
GLuint getDisplayList() const
|
||||
{
|
||||
return m_displayList;
|
||||
}
|
||||
int getPixelHeight() const
|
||||
{
|
||||
return m_pixelHeight;
|
||||
}
|
||||
};
|
||||
|
||||
GLFont glfont_create(const char* font_string);
|
||||
void glfont_release(GLFont& font);
|
||||
|
||||
#endif
|
||||
274
libs/gtkutil/glwidget.cpp
Normal file
274
libs/gtkutil/glwidget.cpp
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// OpenGL widget based on GtkGLExt
|
||||
|
||||
#include "glwidget.h"
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
|
||||
#include "igl.h"
|
||||
|
||||
#include <gtk/gtkdrawingarea.h>
|
||||
#include <gtk/gtkglwidget.h>
|
||||
|
||||
#include "pointer.h"
|
||||
|
||||
void (*GLWidget_sharedContextCreated)() = 0;
|
||||
void (*GLWidget_sharedContextDestroyed)() = 0;
|
||||
|
||||
|
||||
typedef int* attribs_t;
|
||||
struct config_t
|
||||
{
|
||||
const char* name;
|
||||
attribs_t attribs;
|
||||
};
|
||||
typedef const config_t* configs_iterator;
|
||||
|
||||
int config_rgba32[] = {
|
||||
GDK_GL_RGBA,
|
||||
GDK_GL_DOUBLEBUFFER,
|
||||
GDK_GL_BUFFER_SIZE, 24,
|
||||
GDK_GL_ATTRIB_LIST_NONE,
|
||||
};
|
||||
|
||||
int config_rgba[] = {
|
||||
GDK_GL_RGBA,
|
||||
GDK_GL_DOUBLEBUFFER,
|
||||
GDK_GL_BUFFER_SIZE, 16,
|
||||
GDK_GL_ATTRIB_LIST_NONE,
|
||||
};
|
||||
|
||||
const config_t configs[] = {
|
||||
{
|
||||
"colour-buffer = 32bpp, depth-buffer = none",
|
||||
config_rgba32,
|
||||
},
|
||||
{
|
||||
"colour-buffer = 16bpp, depth-buffer = none",
|
||||
config_rgba,
|
||||
}
|
||||
};
|
||||
|
||||
GdkGLConfig* glconfig_new()
|
||||
{
|
||||
GdkGLConfig* glconfig = 0;
|
||||
|
||||
for(configs_iterator i = configs, end = configs + 2; i != end; ++i)
|
||||
{
|
||||
glconfig = gdk_gl_config_new((*i).attribs);
|
||||
if(glconfig != 0)
|
||||
{
|
||||
globalOutputStream() << "OpenGL window configuration: " << (*i).name << "\n";
|
||||
return glconfig;
|
||||
}
|
||||
}
|
||||
|
||||
globalOutputStream() << "OpenGL window configuration: colour-buffer = auto, depth-buffer = none\n";
|
||||
return gdk_gl_config_new_by_mode((GdkGLConfigMode)(GDK_GL_MODE_RGBA | GDK_GL_MODE_DOUBLE));
|
||||
}
|
||||
|
||||
int config_rgba32_depth32[] = {
|
||||
GDK_GL_RGBA,
|
||||
GDK_GL_DOUBLEBUFFER,
|
||||
GDK_GL_BUFFER_SIZE, 24,
|
||||
GDK_GL_DEPTH_SIZE, 32,
|
||||
GDK_GL_ATTRIB_LIST_NONE,
|
||||
};
|
||||
|
||||
int config_rgba32_depth24[] = {
|
||||
GDK_GL_RGBA,
|
||||
GDK_GL_DOUBLEBUFFER,
|
||||
GDK_GL_BUFFER_SIZE, 24,
|
||||
GDK_GL_DEPTH_SIZE, 24,
|
||||
GDK_GL_ATTRIB_LIST_NONE,
|
||||
};
|
||||
|
||||
int config_rgba32_depth16[] = {
|
||||
GDK_GL_RGBA,
|
||||
GDK_GL_DOUBLEBUFFER,
|
||||
GDK_GL_BUFFER_SIZE, 24,
|
||||
GDK_GL_DEPTH_SIZE, 16,
|
||||
GDK_GL_ATTRIB_LIST_NONE,
|
||||
};
|
||||
|
||||
int config_rgba32_depth[] = {
|
||||
GDK_GL_RGBA,
|
||||
GDK_GL_DOUBLEBUFFER,
|
||||
GDK_GL_BUFFER_SIZE, 24,
|
||||
GDK_GL_DEPTH_SIZE, 1,
|
||||
GDK_GL_ATTRIB_LIST_NONE,
|
||||
};
|
||||
|
||||
int config_rgba_depth16[] = {
|
||||
GDK_GL_RGBA,
|
||||
GDK_GL_DOUBLEBUFFER,
|
||||
GDK_GL_BUFFER_SIZE, 16,
|
||||
GDK_GL_DEPTH_SIZE, 16,
|
||||
GDK_GL_ATTRIB_LIST_NONE,
|
||||
};
|
||||
|
||||
int config_rgba_depth[] = {
|
||||
GDK_GL_RGBA,
|
||||
GDK_GL_DOUBLEBUFFER,
|
||||
GDK_GL_BUFFER_SIZE, 16,
|
||||
GDK_GL_DEPTH_SIZE, 1,
|
||||
GDK_GL_ATTRIB_LIST_NONE,
|
||||
};
|
||||
|
||||
const config_t configs_with_depth[] =
|
||||
{
|
||||
{
|
||||
"colour-buffer = 32bpp, depth-buffer = 32bpp",
|
||||
config_rgba32_depth32,
|
||||
},
|
||||
{
|
||||
"colour-buffer = 32bpp, depth-buffer = 24bpp",
|
||||
config_rgba32_depth24,
|
||||
},
|
||||
{
|
||||
"colour-buffer = 32bpp, depth-buffer = 16bpp",
|
||||
config_rgba32_depth16,
|
||||
},
|
||||
{
|
||||
"colour-buffer = 32bpp, depth-buffer = auto",
|
||||
config_rgba32_depth,
|
||||
},
|
||||
{
|
||||
"colour-buffer = 16bpp, depth-buffer = 16bpp",
|
||||
config_rgba_depth16,
|
||||
},
|
||||
{
|
||||
"colour-buffer = auto, depth-buffer = auto",
|
||||
config_rgba_depth,
|
||||
},
|
||||
};
|
||||
|
||||
GdkGLConfig* glconfig_new_with_depth()
|
||||
{
|
||||
GdkGLConfig* glconfig = 0;
|
||||
|
||||
for(configs_iterator i = configs_with_depth, end = configs_with_depth + 6; i != end; ++i)
|
||||
{
|
||||
glconfig = gdk_gl_config_new((*i).attribs);
|
||||
if(glconfig != 0)
|
||||
{
|
||||
globalOutputStream() << "OpenGL window configuration: " << (*i).name << "\n";
|
||||
return glconfig;
|
||||
}
|
||||
}
|
||||
|
||||
globalOutputStream() << "OpenGL window configuration: colour-buffer = auto, depth-buffer = auto (fallback)\n";
|
||||
return gdk_gl_config_new_by_mode((GdkGLConfigMode)(GDK_GL_MODE_RGBA | GDK_GL_MODE_DOUBLE | GDK_GL_MODE_DEPTH));
|
||||
}
|
||||
|
||||
unsigned int g_context_count = 0;
|
||||
|
||||
namespace
|
||||
{
|
||||
GtkWidget* g_shared = 0;
|
||||
}
|
||||
|
||||
gint glwidget_context_created(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
if(++g_context_count == 1)
|
||||
{
|
||||
g_shared = widget;
|
||||
gtk_widget_ref(g_shared);
|
||||
|
||||
glwidget_make_current(g_shared);
|
||||
GlobalOpenGL().contextValid = true;
|
||||
|
||||
GLWidget_sharedContextCreated();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gint glwidget_context_destroyed(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
if(--g_context_count == 0)
|
||||
{
|
||||
GlobalOpenGL().contextValid = false;
|
||||
|
||||
GLWidget_sharedContextDestroyed();
|
||||
|
||||
gtk_widget_unref(g_shared);
|
||||
g_shared = 0;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean glwidget_enable_gl(GtkWidget* widget, GtkWidget* widget2, gpointer data)
|
||||
{
|
||||
if(widget2 == 0 && !gtk_widget_is_gl_capable(widget))
|
||||
{
|
||||
GdkGLConfig* glconfig = (g_object_get_data(G_OBJECT(widget), "zbuffer")) ? glconfig_new_with_depth() : glconfig_new();
|
||||
ASSERT_MESSAGE(glconfig != 0, "failed to create OpenGL config");
|
||||
|
||||
gtk_widget_set_gl_capability(widget, glconfig, g_shared != 0 ? gtk_widget_get_gl_context(g_shared) : 0, TRUE, GDK_GL_RGBA_TYPE);
|
||||
|
||||
gtk_widget_realize(widget);
|
||||
if(g_shared == 0)
|
||||
{
|
||||
g_shared = widget;
|
||||
}
|
||||
|
||||
// free glconfig?
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GtkWidget* glwidget_new(gboolean zbuffer)
|
||||
{
|
||||
GtkWidget* widget = gtk_drawing_area_new();
|
||||
|
||||
g_object_set_data(G_OBJECT(widget), "zbuffer", gint_to_pointer(zbuffer));
|
||||
|
||||
g_signal_connect(G_OBJECT(widget), "hierarchy-changed", G_CALLBACK(glwidget_enable_gl), 0);
|
||||
|
||||
g_signal_connect(G_OBJECT(widget), "realize", G_CALLBACK(glwidget_context_created), 0);
|
||||
g_signal_connect(G_OBJECT(widget), "unrealize", G_CALLBACK(glwidget_context_destroyed), 0);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
void glwidget_destroy_context (GtkWidget *widget)
|
||||
{
|
||||
}
|
||||
|
||||
void glwidget_create_context (GtkWidget *widget)
|
||||
{
|
||||
}
|
||||
|
||||
void glwidget_swap_buffers (GtkWidget *widget)
|
||||
{
|
||||
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
|
||||
gdk_gl_drawable_swap_buffers (gldrawable);
|
||||
}
|
||||
|
||||
gboolean glwidget_make_current (GtkWidget *widget)
|
||||
{
|
||||
GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
|
||||
GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
|
||||
return gdk_gl_drawable_gl_begin (gldrawable, glcontext);
|
||||
}
|
||||
|
||||
39
libs/gtkutil/glwidget.h
Normal file
39
libs/gtkutil/glwidget.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_GLWIDGET_H)
|
||||
#define INCLUDED_GTKUTIL_GLWIDGET_H
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef int gint;
|
||||
typedef gint gboolean;
|
||||
|
||||
GtkWidget* glwidget_new(gboolean zbuffer);
|
||||
void glwidget_swap_buffers(GtkWidget* widget);
|
||||
gboolean glwidget_make_current(GtkWidget* widget);
|
||||
void glwidget_destroy_context(GtkWidget* widget);
|
||||
void glwidget_create_context(GtkWidget* widget);
|
||||
|
||||
extern void (*GLWidget_sharedContextCreated)();
|
||||
extern void (*GLWidget_sharedContextDestroyed)();
|
||||
|
||||
|
||||
#endif
|
||||
255
libs/gtkutil/gtkutil.vcproj
Normal file
255
libs/gtkutil/gtkutil.vcproj
Normal file
@@ -0,0 +1,255 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="gtkutil"
|
||||
ProjectGUID="{68E2C6B6-96CA-4BBD-A485-FEE6F2E65407}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../include;../;"../../../STLPort-4.6/stlport";"../../../gtk2-2.4/lib/glib-2.0/include";"../../../gtk2-2.4/include/glib-2.0";"../../../gtk2-2.4/lib/gtk-2.0/include";"../../../gtk2-2.4/include/gtk-2.0";"../../../gtk2-2.4/include/gtk-2.0/gdk";"../../../gtk2-2.4/include/pango-1.0";"../../../gtk2-2.4/include/atk-1.0";"../../../gtk2-2.4/lib/gtkglext-1.0/include";"../../../gtk2-2.4/include/gtkglext-1.0""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||
StringPooling="TRUE"
|
||||
MinimalRebuild="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
BrowseInformation="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/gtkutil.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
OptimizeForWindowsApplication="TRUE"
|
||||
AdditionalIncludeDirectories="../../include;../;"../../../STLPort-4.6/stlport";"../../../gtk2-2.4/lib/glib-2.0/include";"../../../gtk2-2.4/include/glib-2.0";"../../../gtk2-2.4/lib/gtk-2.0/include";"../../../gtk2-2.4/include/gtk-2.0";"../../../gtk2-2.4/include/gtk-2.0/gdk";"../../../gtk2-2.4/include/pango-1.0";"../../../gtk2-2.4/include/atk-1.0";"../../../gtk2-2.4/lib/gtkglext-1.0/include";"../../../gtk2-2.4/include/gtkglext-1.0""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
StringPooling="TRUE"
|
||||
ExceptionHandling="FALSE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
DisableSpecificWarnings="4610;4510;4512;4505;4100;4127"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/gtkutil.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\accelerator.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\accelerator.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\button.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\button.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\clipboard.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\clipboard.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\closure.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\closure.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\container.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\container.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cursor.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cursor.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dialog.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dialog.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\entry.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\entry.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filechooser.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filechooser.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\frame.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\frame.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\glfont.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\glfont.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\glwidget.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\glwidget.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\idledraw.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\idledraw.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\image.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\image.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\menu.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\menu.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\messagebox.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\messagebox.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\nonmodal.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\nonmodal.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\paned.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\paned.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pointer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\pointer.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\toolbar.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\toolbar.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\widget.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\widget.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\window.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\window.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\xorrectangle.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\xorrectangle.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
23
libs/gtkutil/idledraw.cpp
Normal file
23
libs/gtkutil/idledraw.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "idledraw.h"
|
||||
|
||||
69
libs/gtkutil/idledraw.h
Normal file
69
libs/gtkutil/idledraw.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_IDLEDRAW_H)
|
||||
#define INCLUDED_GTKUTIL_IDLEDRAW_H
|
||||
|
||||
#include <glib/gmain.h>
|
||||
|
||||
#include "generic/callback.h"
|
||||
|
||||
class IdleDraw
|
||||
{
|
||||
Callback m_draw;
|
||||
unsigned int m_handler;
|
||||
static gboolean draw(gpointer data)
|
||||
{
|
||||
reinterpret_cast<IdleDraw*>(data)->m_draw();
|
||||
reinterpret_cast<IdleDraw*>(data)->m_handler = 0;
|
||||
return FALSE;
|
||||
}
|
||||
public:
|
||||
IdleDraw(const Callback& draw) : m_draw(draw), m_handler(0)
|
||||
{
|
||||
}
|
||||
~IdleDraw()
|
||||
{
|
||||
if(m_handler != 0)
|
||||
{
|
||||
g_source_remove(m_handler);
|
||||
}
|
||||
}
|
||||
void queueDraw()
|
||||
{
|
||||
if(m_handler == 0)
|
||||
{
|
||||
m_handler = g_idle_add(&draw, this);
|
||||
}
|
||||
}
|
||||
typedef MemberCaller<IdleDraw, &IdleDraw::queueDraw> QueueDrawCaller;
|
||||
|
||||
void flush()
|
||||
{
|
||||
if(m_handler != 0)
|
||||
{
|
||||
draw(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
96
libs/gtkutil/image.cpp
Normal file
96
libs/gtkutil/image.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "image.h"
|
||||
|
||||
#include <gtk/gtkimage.h>
|
||||
#include <gtk/gtkstock.h>
|
||||
|
||||
#include "string/string.h"
|
||||
#include "stream/stringstream.h"
|
||||
#include "stream/textstream.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
CopiedString g_bitmapsPath;
|
||||
}
|
||||
|
||||
void BitmapsPath_set(const char* path)
|
||||
{
|
||||
g_bitmapsPath = path;
|
||||
}
|
||||
|
||||
GdkPixbuf* pixbuf_new_from_file_with_mask(const char* filename)
|
||||
{
|
||||
GdkPixbuf* rgb = gdk_pixbuf_new_from_file(filename, 0);
|
||||
if(rgb == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkPixbuf* rgba = gdk_pixbuf_add_alpha(rgb, TRUE, 255, 0, 255);
|
||||
gdk_pixbuf_unref(rgb);
|
||||
return rgba;
|
||||
}
|
||||
}
|
||||
|
||||
GtkImage* image_new_from_file_with_mask(const char* filename)
|
||||
{
|
||||
GdkPixbuf* rgba = pixbuf_new_from_file_with_mask(filename);
|
||||
if(rgba == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkImage* image = GTK_IMAGE(gtk_image_new_from_pixbuf(rgba));
|
||||
gdk_pixbuf_unref(rgba);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
GtkImage* image_new_missing()
|
||||
{
|
||||
return GTK_IMAGE(gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_SMALL_TOOLBAR));
|
||||
}
|
||||
|
||||
GtkImage* new_image(const char* filename)
|
||||
{
|
||||
{
|
||||
GtkImage* image = image_new_from_file_with_mask(filename);
|
||||
if(image != 0)
|
||||
{
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
return image_new_missing();
|
||||
}
|
||||
|
||||
GtkImage* new_local_image(const char* filename)
|
||||
{
|
||||
StringOutputStream fullPath(256);
|
||||
fullPath << g_bitmapsPath.c_str() << filename;
|
||||
return new_image(fullPath.c_str());
|
||||
}
|
||||
|
||||
36
libs/gtkutil/image.h
Normal file
36
libs/gtkutil/image.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_IMAGE_H)
|
||||
#define INCLUDED_GTKUTIL_IMAGE_H
|
||||
|
||||
void BitmapsPath_set(const char* path);
|
||||
|
||||
typedef struct _GtkImage GtkImage;
|
||||
typedef struct _GdkPixbuf GdkPixbuf;
|
||||
|
||||
GdkPixbuf* pixbuf_new_from_file_with_mask(const char* filename);
|
||||
GtkImage* image_new_from_file_with_mask(const char* filename);
|
||||
GtkImage* image_new_missing();
|
||||
GtkImage* new_image(const char* filename); // filename is full path to image file
|
||||
GtkImage* new_local_image(const char* filename); // filename is relative to local bitmaps path
|
||||
|
||||
#endif
|
||||
311
libs/gtkutil/menu.cpp
Normal file
311
libs/gtkutil/menu.cpp
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <gtk/gtkmenu.h>
|
||||
#include <gtk/gtkmenubar.h>
|
||||
#include <gtk/gtkradiomenuitem.h>
|
||||
#include <gtk/gtktearoffmenuitem.h>
|
||||
#include <gtk/gtkaccellabel.h>
|
||||
|
||||
#include "generic/callback.h"
|
||||
|
||||
#include "accelerator.h"
|
||||
#include "closure.h"
|
||||
#include "container.h"
|
||||
#include "pointer.h"
|
||||
|
||||
void menu_add_item(GtkMenu* menu, GtkMenuItem* item)
|
||||
{
|
||||
gtk_container_add(GTK_CONTAINER(menu), GTK_WIDGET(item));
|
||||
}
|
||||
|
||||
GtkMenuItem* menu_separator(GtkMenu* menu)
|
||||
{
|
||||
GtkMenuItem* menu_item = GTK_MENU_ITEM(gtk_menu_item_new());
|
||||
container_add_widget(GTK_CONTAINER(menu), GTK_WIDGET(menu_item));
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE);
|
||||
gtk_widget_show(GTK_WIDGET(menu_item));
|
||||
return menu_item;
|
||||
}
|
||||
|
||||
GtkTearoffMenuItem* menu_tearoff(GtkMenu* menu)
|
||||
{
|
||||
GtkTearoffMenuItem* menu_item = GTK_TEAROFF_MENU_ITEM(gtk_tearoff_menu_item_new());
|
||||
container_add_widget(GTK_CONTAINER(menu), GTK_WIDGET(menu_item));
|
||||
// gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE); -- controls whether menu is detachable
|
||||
gtk_widget_show(GTK_WIDGET(menu_item));
|
||||
return menu_item;
|
||||
}
|
||||
|
||||
GtkMenuItem* new_sub_menu_item_with_mnemonic(const char* mnemonic)
|
||||
{
|
||||
GtkMenuItem* item = GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(mnemonic));
|
||||
gtk_widget_show(GTK_WIDGET(item));
|
||||
|
||||
GtkWidget* sub_menu = gtk_menu_new();
|
||||
gtk_menu_item_set_submenu(item, sub_menu);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
GtkMenu* create_sub_menu_with_mnemonic(GtkMenuShell* parent, const char* mnemonic)
|
||||
{
|
||||
GtkMenuItem* item = new_sub_menu_item_with_mnemonic(mnemonic);
|
||||
container_add_widget(GTK_CONTAINER(parent), GTK_WIDGET(item));
|
||||
return GTK_MENU(gtk_menu_item_get_submenu(item));
|
||||
}
|
||||
|
||||
GtkMenu* create_sub_menu_with_mnemonic(GtkMenuBar* bar, const char* mnemonic)
|
||||
{
|
||||
return create_sub_menu_with_mnemonic(GTK_MENU_SHELL(bar), mnemonic);
|
||||
}
|
||||
|
||||
GtkMenu* create_sub_menu_with_mnemonic(GtkMenu* parent, const char* mnemonic)
|
||||
{
|
||||
return create_sub_menu_with_mnemonic(GTK_MENU_SHELL(parent), mnemonic);
|
||||
}
|
||||
|
||||
void activate_closure_callback(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
(*reinterpret_cast<Callback*>(data))();
|
||||
}
|
||||
|
||||
guint menu_item_connect_callback(GtkMenuItem* item, const Callback& callback)
|
||||
{
|
||||
#if 1
|
||||
return g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(callback.getThunk()), callback.getEnvironment());
|
||||
#else
|
||||
return g_signal_connect_closure(G_OBJECT(item), "activate", create_cclosure(G_CALLBACK(activate_closure_callback), callback), FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
guint check_menu_item_connect_callback(GtkCheckMenuItem* item, const Callback& callback)
|
||||
{
|
||||
#if 1
|
||||
guint handler = g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(callback.getThunk()), callback.getEnvironment());
|
||||
#else
|
||||
guint handler = g_signal_connect_closure(G_OBJECT(item), "toggled", create_cclosure(G_CALLBACK(activate_closure_callback), callback), TRUE);
|
||||
#endif
|
||||
g_object_set_data(G_OBJECT(item), "handler", gint_to_pointer(handler));
|
||||
return handler;
|
||||
}
|
||||
|
||||
GtkMenuItem* new_menu_item_with_mnemonic(const char *mnemonic, const Callback& callback)
|
||||
{
|
||||
GtkMenuItem* item = GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(mnemonic));
|
||||
gtk_widget_show(GTK_WIDGET(item));
|
||||
menu_item_connect_callback(item, callback);
|
||||
return item;
|
||||
}
|
||||
|
||||
GtkMenuItem* create_menu_item_with_mnemonic(GtkMenu* menu, const char *mnemonic, const Callback& callback)
|
||||
{
|
||||
GtkMenuItem* item = new_menu_item_with_mnemonic(mnemonic, callback);
|
||||
container_add_widget(GTK_CONTAINER(menu), GTK_WIDGET(item));
|
||||
return item;
|
||||
}
|
||||
|
||||
GtkCheckMenuItem* new_check_menu_item_with_mnemonic(const char* mnemonic, const Callback& callback)
|
||||
{
|
||||
GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(gtk_check_menu_item_new_with_mnemonic(mnemonic));
|
||||
gtk_widget_show(GTK_WIDGET(item));
|
||||
check_menu_item_connect_callback(item, callback);
|
||||
return item;
|
||||
}
|
||||
|
||||
GtkCheckMenuItem* create_check_menu_item_with_mnemonic(GtkMenu* menu, const char* mnemonic, const Callback& callback)
|
||||
{
|
||||
GtkCheckMenuItem* item = new_check_menu_item_with_mnemonic(mnemonic, callback);
|
||||
container_add_widget(GTK_CONTAINER(menu), GTK_WIDGET(item));
|
||||
return item;
|
||||
}
|
||||
|
||||
GtkRadioMenuItem* new_radio_menu_item_with_mnemonic(GSList** group, const char* mnemonic, const Callback& callback)
|
||||
{
|
||||
GtkRadioMenuItem* item = GTK_RADIO_MENU_ITEM(gtk_radio_menu_item_new_with_mnemonic(*group, mnemonic));
|
||||
if(*group == 0)
|
||||
{
|
||||
gtk_check_menu_item_set_state(GTK_CHECK_MENU_ITEM(item), TRUE);
|
||||
}
|
||||
*group = gtk_radio_menu_item_group(item);
|
||||
gtk_widget_show(GTK_WIDGET(item));
|
||||
check_menu_item_connect_callback(GTK_CHECK_MENU_ITEM(item), callback);
|
||||
return item;
|
||||
}
|
||||
|
||||
GtkRadioMenuItem* create_radio_menu_item_with_mnemonic(GtkMenu* menu, GSList** group, const char* mnemonic, const Callback& callback)
|
||||
{
|
||||
GtkRadioMenuItem* item = new_radio_menu_item_with_mnemonic(group, mnemonic, callback);
|
||||
container_add_widget(GTK_CONTAINER(menu), GTK_WIDGET(item));
|
||||
return item;
|
||||
}
|
||||
|
||||
void check_menu_item_set_active_no_signal(GtkCheckMenuItem* item, gboolean active)
|
||||
{
|
||||
guint handler_id = gpointer_to_int(g_object_get_data(G_OBJECT(item), "handler"));
|
||||
g_signal_handler_block(G_OBJECT(item), handler_id);
|
||||
gtk_check_menu_item_set_active(item, active);
|
||||
g_signal_handler_unblock(G_OBJECT(item), handler_id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void radio_menu_item_set_active_no_signal(GtkRadioMenuItem* item, gboolean active)
|
||||
{
|
||||
{
|
||||
for(GSList* l = gtk_radio_menu_item_get_group(item); l != 0; l = g_slist_next(l))
|
||||
{
|
||||
g_signal_handler_block(G_OBJECT(l->data), gpointer_to_int(g_object_get_data(G_OBJECT(l->data), "handler")));
|
||||
}
|
||||
}
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), active);
|
||||
{
|
||||
for(GSList* l = gtk_radio_menu_item_get_group(item); l != 0; l = g_slist_next(l))
|
||||
{
|
||||
g_signal_handler_unblock(G_OBJECT(l->data), gpointer_to_int(g_object_get_data(G_OBJECT(l->data), "handler")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void menu_item_set_accelerator(GtkMenuItem* item, GClosure* closure)
|
||||
{
|
||||
GtkAccelLabel* accel_label = GTK_ACCEL_LABEL(gtk_bin_get_child(GTK_BIN(item)));
|
||||
gtk_accel_label_set_accel_closure(accel_label, closure);
|
||||
}
|
||||
|
||||
void accelerator_name(const Accelerator& accelerator, GString* gstring)
|
||||
{
|
||||
gboolean had_mod = FALSE;
|
||||
if (accelerator.modifiers & GDK_SHIFT_MASK)
|
||||
{
|
||||
g_string_append (gstring, "Shift");
|
||||
had_mod = TRUE;
|
||||
}
|
||||
if (accelerator.modifiers & GDK_CONTROL_MASK)
|
||||
{
|
||||
if (had_mod)
|
||||
g_string_append (gstring, "+");
|
||||
g_string_append (gstring, "Ctrl");
|
||||
had_mod = TRUE;
|
||||
}
|
||||
if (accelerator.modifiers & GDK_MOD1_MASK)
|
||||
{
|
||||
if (had_mod)
|
||||
g_string_append (gstring, "+");
|
||||
g_string_append (gstring, "Alt");
|
||||
had_mod = TRUE;
|
||||
}
|
||||
|
||||
if (had_mod)
|
||||
g_string_append (gstring, "+");
|
||||
if (accelerator.key < 0x80 || (accelerator.key > 0x80 && accelerator.key <= 0xff))
|
||||
{
|
||||
switch (accelerator.key)
|
||||
{
|
||||
case ' ':
|
||||
g_string_append (gstring, "Space");
|
||||
break;
|
||||
case '\\':
|
||||
g_string_append (gstring, "Backslash");
|
||||
break;
|
||||
default:
|
||||
g_string_append_c (gstring, gchar(toupper(accelerator.key)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar *tmp;
|
||||
|
||||
tmp = gtk_accelerator_name (accelerator.key, (GdkModifierType)0);
|
||||
if (tmp[0] != 0 && tmp[1] == 0)
|
||||
tmp[0] = gchar(toupper(tmp[0]));
|
||||
g_string_append (gstring, tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_item_set_accelerator(GtkMenuItem* item, Accelerator accelerator)
|
||||
{
|
||||
GtkAccelLabel* accel_label = GTK_ACCEL_LABEL(gtk_bin_get_child(GTK_BIN(item)));
|
||||
|
||||
g_free (accel_label->accel_string);
|
||||
accel_label->accel_string = 0;
|
||||
|
||||
GString* gstring = g_string_new (accel_label->accel_string);
|
||||
g_string_append (gstring, " ");
|
||||
|
||||
accelerator_name(accelerator, gstring);
|
||||
|
||||
g_free (accel_label->accel_string);
|
||||
accel_label->accel_string = gstring->str;
|
||||
g_string_free (gstring, FALSE);
|
||||
|
||||
if (!accel_label->accel_string)
|
||||
accel_label->accel_string = g_strdup ("");
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (accel_label));
|
||||
}
|
||||
|
||||
void menu_item_add_accelerator(GtkMenuItem* item, Accelerator accelerator)
|
||||
{
|
||||
if(accelerator.key != 0)
|
||||
{
|
||||
GClosure* closure = global_accel_group_find(accelerator);
|
||||
if(closure != 0)
|
||||
{
|
||||
menu_item_set_accelerator(item, closure);
|
||||
}
|
||||
else
|
||||
{
|
||||
menu_item_set_accelerator(item, accelerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GtkMenuItem* create_menu_item_with_mnemonic(GtkMenu* menu, const char* mnemonic, const Command& command)
|
||||
{
|
||||
GtkMenuItem* item = create_menu_item_with_mnemonic(menu, mnemonic, command.m_callback);
|
||||
menu_item_add_accelerator(item, command.m_accelerator);
|
||||
return item;
|
||||
}
|
||||
|
||||
void check_menu_item_set_active_callback(GtkCheckMenuItem& item, bool enabled)
|
||||
{
|
||||
check_menu_item_set_active_no_signal(&item, enabled);
|
||||
}
|
||||
typedef ReferenceCaller1<GtkCheckMenuItem, bool, check_menu_item_set_active_callback> CheckMenuItemSetActiveCaller;
|
||||
|
||||
GtkCheckMenuItem* create_check_menu_item_with_mnemonic(GtkMenu* menu, const char* mnemonic, const Toggle& toggle)
|
||||
{
|
||||
GtkCheckMenuItem* item = create_check_menu_item_with_mnemonic(menu, mnemonic, toggle.m_command.m_callback);
|
||||
menu_item_add_accelerator(GTK_MENU_ITEM(item), toggle.m_command.m_accelerator);
|
||||
toggle.m_exportCallback(CheckMenuItemSetActiveCaller(*item));
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
57
libs/gtkutil/menu.h
Normal file
57
libs/gtkutil/menu.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_MENU_H)
|
||||
#define INCLUDED_GTKUTIL_MENU_H
|
||||
|
||||
class Callback;
|
||||
typedef int gint;
|
||||
typedef gint gboolean;
|
||||
typedef struct _GSList GSList;
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
typedef struct _GtkMenuBar GtkMenuBar;
|
||||
typedef struct _GtkMenuItem GtkMenuItem;
|
||||
typedef struct _GtkCheckMenuItem GtkCheckMenuItem;
|
||||
typedef struct _GtkRadioMenuItem GtkRadioMenuItem;
|
||||
typedef struct _GtkTearoffMenuItem GtkTearoffMenuItem;
|
||||
|
||||
void menu_add_item(GtkMenu* menu, GtkMenuItem* item);
|
||||
GtkMenuItem* menu_separator(GtkMenu* menu);
|
||||
GtkTearoffMenuItem* menu_tearoff(GtkMenu* menu);
|
||||
GtkMenuItem* new_sub_menu_item_with_mnemonic(const char* mnemonic);
|
||||
GtkMenu* create_sub_menu_with_mnemonic(GtkMenuBar* bar, const char* mnemonic);
|
||||
GtkMenu* create_sub_menu_with_mnemonic(GtkMenu* parent, const char* mnemonic);
|
||||
GtkMenuItem* create_menu_item_with_mnemonic(GtkMenu* menu, const char* mnemonic, const Callback& callback);
|
||||
GtkCheckMenuItem* create_check_menu_item_with_mnemonic(GtkMenu* menu, const char* mnemonic, const Callback& callback);
|
||||
GtkRadioMenuItem* create_radio_menu_item_with_mnemonic(GtkMenu* menu, GSList** group, const char* mnemonic, const Callback& callback);
|
||||
|
||||
class Command;
|
||||
GtkMenuItem* create_menu_item_with_mnemonic(GtkMenu* menu, const char* mnemonic, const Command& command);
|
||||
class Toggle;
|
||||
GtkCheckMenuItem* create_check_menu_item_with_mnemonic(GtkMenu* menu, const char* mnemonic, const Toggle& toggle);
|
||||
|
||||
|
||||
typedef struct _GtkCheckMenuItem GtkCheckMenuItem;
|
||||
void check_menu_item_set_active_no_signal(GtkCheckMenuItem* item, gboolean active);
|
||||
typedef struct _GtkRadioMenuItem GtkRadioMenuItem;
|
||||
void radio_menu_item_set_active_no_signal(GtkRadioMenuItem* item, gboolean active);
|
||||
|
||||
#endif
|
||||
213
libs/gtkutil/messagebox.cpp
Normal file
213
libs/gtkutil/messagebox.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "messagebox.h"
|
||||
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <gtk/gtkmain.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
#include <gtk/gtkhbox.h>
|
||||
#include <gtk/gtkvbox.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
#include <gtk/gtkalignment.h>
|
||||
#include <gtk/gtkbutton.h>
|
||||
#include <gtk/gtkimage.h>
|
||||
#include <gtk/gtkstock.h>
|
||||
|
||||
#include "dialog.h"
|
||||
#include "widget.h"
|
||||
|
||||
GtkWidget* create_padding(int width, int height)
|
||||
{
|
||||
GtkWidget* widget = gtk_alignment_new(0.0, 0.0, 0.0, 0.0);
|
||||
gtk_widget_show(widget);
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
return widget;
|
||||
}
|
||||
|
||||
const char* messagebox_stock_icon(EMessageBoxIcon type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
case eMB_ICONDEFAULT:
|
||||
return GTK_STOCK_DIALOG_INFO;
|
||||
case eMB_ICONERROR:
|
||||
return GTK_STOCK_DIALOG_ERROR;
|
||||
case eMB_ICONWARNING:
|
||||
return GTK_STOCK_DIALOG_WARNING;
|
||||
case eMB_ICONQUESTION:
|
||||
return GTK_STOCK_DIALOG_QUESTION;
|
||||
case eMB_ICONASTERISK:
|
||||
return GTK_STOCK_DIALOG_INFO;
|
||||
}
|
||||
}
|
||||
|
||||
EMessageBoxReturn gtk_MessageBox (GtkWidget *parent, const char* text, const char* title, EMessageBoxType type, EMessageBoxIcon icon)
|
||||
{
|
||||
ModalDialog dialog;
|
||||
ModalDialogButton ok_button(dialog, eIDOK);
|
||||
ModalDialogButton cancel_button(dialog, eIDCANCEL);
|
||||
ModalDialogButton yes_button(dialog, eIDYES);
|
||||
ModalDialogButton no_button(dialog, eIDNO);
|
||||
|
||||
GtkWindow* parentWindow = parent != 0 ? GTK_WINDOW(parent) : 0;
|
||||
|
||||
GtkWindow* window = create_fixedsize_modal_dialog_window(parentWindow, title, dialog, 400, 100);
|
||||
|
||||
if(parentWindow != 0)
|
||||
{
|
||||
//g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(floating_window_delete_present), parent);
|
||||
gtk_window_deiconify(parentWindow);
|
||||
}
|
||||
|
||||
GtkAccelGroup* accel = gtk_accel_group_new();
|
||||
gtk_window_add_accel_group(window, accel);
|
||||
|
||||
GtkVBox* vbox = create_dialog_vbox(8, 8);
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox));
|
||||
|
||||
|
||||
GtkHBox* hboxDummy = create_dialog_hbox(0, 0);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hboxDummy), FALSE, FALSE, 0);
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(hboxDummy), create_padding(0, 50), FALSE, FALSE, 0); // HACK to force minimum height
|
||||
|
||||
GtkHBox* iconBox = create_dialog_hbox(16, 0);
|
||||
gtk_box_pack_start(GTK_BOX(hboxDummy), GTK_WIDGET(iconBox), FALSE, FALSE, 0);
|
||||
|
||||
GtkImage* image = GTK_IMAGE(gtk_image_new_from_stock(messagebox_stock_icon(icon), GTK_ICON_SIZE_DIALOG));
|
||||
gtk_widget_show(GTK_WIDGET(image));
|
||||
gtk_box_pack_start(GTK_BOX(iconBox), GTK_WIDGET(image), FALSE, FALSE, 0);
|
||||
|
||||
GtkLabel* label = GTK_LABEL(gtk_label_new(text));
|
||||
gtk_widget_show(GTK_WIDGET(label));
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
||||
gtk_label_set_justify(label, GTK_JUSTIFY_LEFT);
|
||||
gtk_label_set_line_wrap(label, TRUE);
|
||||
gtk_box_pack_start(GTK_BOX(iconBox), GTK_WIDGET(label), TRUE, TRUE, 0);
|
||||
|
||||
|
||||
GtkVBox* vboxDummy = create_dialog_vbox(0, 0);
|
||||
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(vboxDummy), FALSE, FALSE, 0);
|
||||
|
||||
GtkAlignment* alignment = GTK_ALIGNMENT(gtk_alignment_new(0.5, 0.0, 0.0, 0.0));
|
||||
gtk_widget_show(GTK_WIDGET(alignment));
|
||||
gtk_box_pack_start(GTK_BOX(vboxDummy), GTK_WIDGET(alignment), FALSE, FALSE, 0);
|
||||
|
||||
GtkHBox* hbox = create_dialog_hbox(8, 0);
|
||||
gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(hbox));
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(vboxDummy), create_padding(400, 0), FALSE, FALSE, 0); // HACK to force minimum width
|
||||
|
||||
|
||||
if (type == eMB_OK)
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("OK", ok_button);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), TRUE, FALSE, 0);
|
||||
gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);
|
||||
gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);
|
||||
widget_make_default(GTK_WIDGET(button));
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
|
||||
dialog.ret = eIDOK;
|
||||
}
|
||||
else if (type == eMB_OKCANCEL)
|
||||
{
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("OK", ok_button);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), TRUE, FALSE, 0);
|
||||
gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);
|
||||
widget_make_default(GTK_WIDGET(button));
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
}
|
||||
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("OK", cancel_button);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), TRUE, FALSE, 0);
|
||||
gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
}
|
||||
|
||||
dialog.ret = eIDCANCEL;
|
||||
}
|
||||
else if (type == eMB_YESNOCANCEL)
|
||||
{
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("Yes", yes_button);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), TRUE, FALSE, 0);
|
||||
widget_make_default(GTK_WIDGET(button));
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
}
|
||||
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("No", no_button);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), TRUE, FALSE, 0);
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
}
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("Cancel", cancel_button);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), TRUE, FALSE, 0);
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
}
|
||||
|
||||
dialog.ret = eIDCANCEL;
|
||||
}
|
||||
else if (type == eMB_NOYES)
|
||||
{
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("No", no_button);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), TRUE, FALSE, 0);
|
||||
widget_make_default(GTK_WIDGET(button));
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
}
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("Yes", yes_button);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), TRUE, FALSE, 0);
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
}
|
||||
|
||||
dialog.ret = eIDNO;
|
||||
}
|
||||
else /* if (type == eMB_YESNO) */
|
||||
{
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("Yes", yes_button);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), TRUE, FALSE, 0);
|
||||
widget_make_default(GTK_WIDGET(button));
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
}
|
||||
|
||||
{
|
||||
GtkButton* button = create_modal_dialog_button("No", no_button);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button), TRUE, FALSE, 0);
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
}
|
||||
dialog.ret = eIDNO;
|
||||
}
|
||||
|
||||
modal_dialog_show(window, dialog);
|
||||
|
||||
gtk_widget_destroy(GTK_WIDGET(window));
|
||||
|
||||
return dialog.ret;
|
||||
}
|
||||
|
||||
31
libs/gtkutil/messagebox.h
Normal file
31
libs/gtkutil/messagebox.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_MESSAGEBOX_H)
|
||||
#define INCLUDED_GTKUTIL_MESSAGEBOX_H
|
||||
|
||||
#include "qerplugin.h"
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
/// \brief Shows a modal message-box.
|
||||
EMessageBoxReturn gtk_MessageBox(GtkWidget *parent, const char* text, const char* title = "GtkRadiant", EMessageBoxType type = eMB_OK, EMessageBoxIcon icon = eMB_ICONDEFAULT);
|
||||
|
||||
#endif
|
||||
23
libs/gtkutil/nonmodal.cpp
Normal file
23
libs/gtkutil/nonmodal.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "nonmodal.h"
|
||||
|
||||
186
libs/gtkutil/nonmodal.h
Normal file
186
libs/gtkutil/nonmodal.h
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_NONMODAL_H)
|
||||
#define INCLUDED_GTKUTIL_NONMODAL_H
|
||||
|
||||
#include <gtk/gtkwindow.h>
|
||||
#include <gtk/gtkspinbutton.h>
|
||||
#include <gtk/gtkradiobutton.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "generic/callback.h"
|
||||
|
||||
#include "pointer.h"
|
||||
#include "button.h"
|
||||
|
||||
typedef struct _GtkEntry GtkEntry;
|
||||
|
||||
|
||||
inline gboolean escape_clear_focus_widget(GtkWidget* widget, GdkEventKey* event, gpointer data)
|
||||
{
|
||||
if(event->keyval == GDK_Escape)
|
||||
{
|
||||
gtk_window_set_focus(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(widget))), NULL);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
inline void widget_connect_escape_clear_focus_widget(GtkWidget* widget)
|
||||
{
|
||||
g_signal_connect(G_OBJECT(widget), "key_press_event", G_CALLBACK(escape_clear_focus_widget), 0);
|
||||
}
|
||||
|
||||
|
||||
class NonModalEntry
|
||||
{
|
||||
bool m_editing;
|
||||
Callback m_apply;
|
||||
Callback m_cancel;
|
||||
|
||||
static gboolean focus_in(GtkEntry* entry, GdkEventFocus *event, NonModalEntry* self)
|
||||
{
|
||||
self->m_editing = false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean focus_out(GtkEntry* entry, GdkEventFocus *event, NonModalEntry* self)
|
||||
{
|
||||
if(self->m_editing && GTK_WIDGET_VISIBLE(entry))
|
||||
{
|
||||
self->m_apply();
|
||||
}
|
||||
self->m_editing = false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean changed(GtkEntry* entry, NonModalEntry* self)
|
||||
{
|
||||
self->m_editing = true;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean enter(GtkEntry* entry, GdkEventKey* event, NonModalEntry* self)
|
||||
{
|
||||
if(event->keyval == GDK_Return)
|
||||
{
|
||||
self->m_apply();
|
||||
self->m_editing = false;
|
||||
gtk_window_set_focus(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(entry))), NULL);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean escape(GtkEntry* entry, GdkEventKey* event, NonModalEntry* self)
|
||||
{
|
||||
if(event->keyval == GDK_Escape)
|
||||
{
|
||||
self->m_cancel();
|
||||
self->m_editing = false;
|
||||
gtk_window_set_focus(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(entry))), NULL);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
public:
|
||||
NonModalEntry(const Callback& apply, const Callback& cancel) : m_editing(false), m_apply(apply), m_cancel(cancel)
|
||||
{
|
||||
}
|
||||
void connect(GtkEntry* entry)
|
||||
{
|
||||
g_signal_connect(G_OBJECT(entry), "focus_in_event", G_CALLBACK(focus_in), this);
|
||||
g_signal_connect(G_OBJECT(entry), "focus_out_event", G_CALLBACK(focus_out), this);
|
||||
g_signal_connect(G_OBJECT(entry), "key_press_event", G_CALLBACK(enter), this);
|
||||
g_signal_connect(G_OBJECT(entry), "key_press_event", G_CALLBACK(escape), this);
|
||||
g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(changed), this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class NonModalSpinner
|
||||
{
|
||||
Callback m_apply;
|
||||
Callback m_cancel;
|
||||
|
||||
static gboolean changed(GtkSpinButton* spin, NonModalSpinner* self)
|
||||
{
|
||||
self->m_apply();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean enter(GtkSpinButton* spin, GdkEventKey* event, NonModalSpinner* self)
|
||||
{
|
||||
if(event->keyval == GDK_Return)
|
||||
{
|
||||
gtk_window_set_focus(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(spin))), NULL);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean escape(GtkSpinButton* spin, GdkEventKey* event, NonModalSpinner* self)
|
||||
{
|
||||
if(event->keyval == GDK_Escape)
|
||||
{
|
||||
self->m_cancel();
|
||||
gtk_window_set_focus(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(spin))), NULL);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
public:
|
||||
NonModalSpinner(const Callback& apply, const Callback& cancel) : m_apply(apply), m_cancel(cancel)
|
||||
{
|
||||
}
|
||||
void connect(GtkSpinButton* spin)
|
||||
{
|
||||
guint handler = g_signal_connect(G_OBJECT(gtk_spin_button_get_adjustment(spin)), "value_changed", G_CALLBACK(changed), this);
|
||||
g_object_set_data(G_OBJECT(spin), "handler", gint_to_pointer(handler));
|
||||
g_signal_connect(G_OBJECT(spin), "key_press_event", G_CALLBACK(enter), this);
|
||||
g_signal_connect(G_OBJECT(spin), "key_press_event", G_CALLBACK(escape), this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class NonModalRadio
|
||||
{
|
||||
Callback m_changed;
|
||||
|
||||
public:
|
||||
NonModalRadio(const Callback& changed) : m_changed(changed)
|
||||
{
|
||||
}
|
||||
void connect(GtkRadioButton* radio)
|
||||
{
|
||||
GSList* group = gtk_radio_button_group(radio);
|
||||
for(; group != 0; group = g_slist_next(group))
|
||||
{
|
||||
toggle_button_connect_callback(GTK_TOGGLE_BUTTON(group->data), m_changed);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
100
libs/gtkutil/paned.cpp
Normal file
100
libs/gtkutil/paned.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "paned.h"
|
||||
|
||||
#include <gtk/gtkhpaned.h>
|
||||
#include <gtk/gtkvpaned.h>
|
||||
|
||||
#include "frame.h"
|
||||
|
||||
|
||||
class PanedState
|
||||
{
|
||||
public:
|
||||
float position;
|
||||
int size;
|
||||
};
|
||||
|
||||
gboolean hpaned_allocate(GtkWidget* widget, GtkAllocation* allocation, PanedState* paned)
|
||||
{
|
||||
if(paned->size != allocation->width)
|
||||
{
|
||||
paned->size = allocation->width;
|
||||
gtk_paned_set_position (GTK_PANED (widget), static_cast<int>(paned->size * paned->position));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean vpaned_allocate(GtkWidget* widget, GtkAllocation* allocation, PanedState* paned)
|
||||
{
|
||||
if(paned->size != allocation->height)
|
||||
{
|
||||
paned->size = allocation->height;
|
||||
gtk_paned_set_position (GTK_PANED (widget), static_cast<int>(paned->size * paned->position));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean paned_position(GtkWidget* widget, gpointer dummy, PanedState* paned)
|
||||
{
|
||||
if(paned->size != -1)
|
||||
paned->position = gtk_paned_get_position (GTK_PANED (widget)) / static_cast<float>(paned->size);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PanedState g_hpaned = { 0.5f, -1, };
|
||||
PanedState g_vpaned1 = { 0.5f, -1, };
|
||||
PanedState g_vpaned2 = { 0.5f, -1, };
|
||||
|
||||
GtkHPaned* create_split_views(GtkWidget* topleft, GtkWidget* topright, GtkWidget* botleft, GtkWidget* botright)
|
||||
{
|
||||
GtkHPaned* hsplit = GTK_HPANED(gtk_hpaned_new());
|
||||
gtk_widget_show(GTK_WIDGET(hsplit));
|
||||
|
||||
g_signal_connect(G_OBJECT(hsplit), "size_allocate", G_CALLBACK(hpaned_allocate), &g_hpaned);
|
||||
g_signal_connect(G_OBJECT(hsplit), "notify::position", G_CALLBACK(paned_position), &g_hpaned);
|
||||
|
||||
{
|
||||
GtkVPaned* vsplit = GTK_VPANED(gtk_vpaned_new());
|
||||
gtk_paned_add1(GTK_PANED(hsplit), GTK_WIDGET(vsplit));
|
||||
gtk_widget_show(GTK_WIDGET(vsplit));
|
||||
|
||||
g_signal_connect(G_OBJECT(vsplit), "size_allocate", G_CALLBACK(vpaned_allocate), &g_vpaned1);
|
||||
g_signal_connect(G_OBJECT(vsplit), "notify::position", G_CALLBACK(paned_position), &g_vpaned1);
|
||||
|
||||
gtk_paned_add1(GTK_PANED(vsplit), GTK_WIDGET(create_framed_widget(topleft)));
|
||||
gtk_paned_add2(GTK_PANED(vsplit), GTK_WIDGET(create_framed_widget(topright)));
|
||||
}
|
||||
{
|
||||
GtkVPaned* vsplit = GTK_VPANED(gtk_vpaned_new());
|
||||
gtk_paned_add2(GTK_PANED(hsplit), GTK_WIDGET(vsplit));
|
||||
gtk_widget_show(GTK_WIDGET(vsplit));
|
||||
|
||||
g_signal_connect(G_OBJECT(vsplit), "size_allocate", G_CALLBACK(vpaned_allocate), &g_vpaned2);
|
||||
g_signal_connect(G_OBJECT(vsplit), "notify::position", G_CALLBACK(paned_position), &g_vpaned2);
|
||||
|
||||
gtk_paned_add1(GTK_PANED(vsplit), GTK_WIDGET(create_framed_widget(botleft)));
|
||||
gtk_paned_add2(GTK_PANED(vsplit), GTK_WIDGET(create_framed_widget(botright)));
|
||||
}
|
||||
return hsplit;
|
||||
}
|
||||
|
||||
29
libs/gtkutil/paned.h
Normal file
29
libs/gtkutil/paned.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_PANED_H)
|
||||
#define INCLUDED_GTKUTIL_PANED_H
|
||||
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
typedef struct _GtkHPaned GtkHPaned;
|
||||
GtkHPaned* create_split_views(GtkWidget* topleft, GtkWidget* topright, GtkWidget* botleft, GtkWidget* botright);
|
||||
|
||||
#endif
|
||||
23
libs/gtkutil/pointer.cpp
Normal file
23
libs/gtkutil/pointer.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "pointer.h"
|
||||
|
||||
40
libs/gtkutil/pointer.h
Normal file
40
libs/gtkutil/pointer.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_POINTER_H)
|
||||
#define INCLUDED_GTKUTIL_POINTER_H
|
||||
|
||||
typedef int gint;
|
||||
typedef void* gpointer;
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
inline gint gpointer_to_int(gpointer p)
|
||||
{
|
||||
return gint(std::size_t(p));
|
||||
}
|
||||
|
||||
inline gpointer gint_to_pointer(gint i)
|
||||
{
|
||||
return gpointer(std::size_t(i));
|
||||
}
|
||||
|
||||
#endif
|
||||
78
libs/gtkutil/toolbar.cpp
Normal file
78
libs/gtkutil/toolbar.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "toolbar.h"
|
||||
|
||||
#include <gtk/gtktoolbar.h>
|
||||
#include <gtk/gtktogglebutton.h>
|
||||
|
||||
#include "generic/callback.h"
|
||||
|
||||
#include "accelerator.h"
|
||||
#include "button.h"
|
||||
#include "closure.h"
|
||||
#include "pointer.h"
|
||||
|
||||
|
||||
void toolbar_append(GtkToolbar* toolbar, GtkButton* button, const char* description)
|
||||
{
|
||||
gtk_widget_show(GTK_WIDGET(button));
|
||||
gtk_button_set_relief(button, GTK_RELIEF_NONE);
|
||||
GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(button), GTK_CAN_FOCUS);
|
||||
GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(button), GTK_CAN_DEFAULT);
|
||||
gtk_toolbar_append_element(toolbar, GTK_TOOLBAR_CHILD_WIDGET, GTK_WIDGET(button), "", description, "", 0, 0, 0);
|
||||
}
|
||||
|
||||
GtkButton* toolbar_append_button(GtkToolbar* toolbar, const char* description, const char* icon, const Callback& callback)
|
||||
{
|
||||
GtkButton* button = GTK_BUTTON(gtk_button_new());
|
||||
button_set_icon(button, icon);
|
||||
button_connect_callback(button, callback);
|
||||
toolbar_append(toolbar, button, description);
|
||||
return button;
|
||||
}
|
||||
|
||||
GtkToggleButton* toolbar_append_toggle_button(GtkToolbar* toolbar, const char* description, const char* icon, const Callback& callback)
|
||||
{
|
||||
GtkToggleButton* button = GTK_TOGGLE_BUTTON(gtk_toggle_button_new());
|
||||
button_set_icon(GTK_BUTTON(button), icon);
|
||||
toggle_button_connect_callback(button, callback);
|
||||
toolbar_append(toolbar, GTK_BUTTON(button), description);
|
||||
return button;
|
||||
}
|
||||
|
||||
GtkButton* toolbar_append_button(GtkToolbar* toolbar, const char* description, const char* icon, const Command& command)
|
||||
{
|
||||
return toolbar_append_button(toolbar, description, icon, command.m_callback);
|
||||
}
|
||||
|
||||
void toggle_button_set_active_callback(GtkToggleButton& button, bool active)
|
||||
{
|
||||
toggle_button_set_active_no_signal(&button, active);
|
||||
}
|
||||
typedef ReferenceCaller1<GtkToggleButton, bool, toggle_button_set_active_callback> ToggleButtonSetActiveCaller;
|
||||
|
||||
GtkToggleButton* toolbar_append_toggle_button(GtkToolbar* toolbar, const char* description, const char* icon, const Toggle& toggle)
|
||||
{
|
||||
GtkToggleButton* button = toolbar_append_toggle_button(toolbar, description, icon, toggle.m_command.m_callback);
|
||||
toggle.m_exportCallback(ToggleButtonSetActiveCaller(*button));
|
||||
return button;
|
||||
}
|
||||
37
libs/gtkutil/toolbar.h
Normal file
37
libs/gtkutil/toolbar.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_TOOLBAR_H)
|
||||
#define INCLUDED_GTKUTIL_TOOLBAR_H
|
||||
|
||||
class Callback;
|
||||
typedef struct _GtkButton GtkButton;
|
||||
typedef struct _GtkToggleButton GtkToggleButton;
|
||||
typedef struct _GtkToolbar GtkToolbar;
|
||||
class Command;
|
||||
class Toggle;
|
||||
|
||||
GtkButton* toolbar_append_button(GtkToolbar* toolbar, const char* description, const char* icon, const Callback& callback);
|
||||
GtkButton* toolbar_append_button(GtkToolbar* toolbar, const char* description, const char* icon, const Command& command);
|
||||
GtkToggleButton* toolbar_append_toggle_button(GtkToolbar* toolbar, const char* description, const char* icon, const Callback& callback);
|
||||
GtkToggleButton* toolbar_append_toggle_button(GtkToolbar* toolbar, const char* description, const char* icon, const Toggle& toggle);
|
||||
|
||||
#endif
|
||||
23
libs/gtkutil/widget.cpp
Normal file
23
libs/gtkutil/widget.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "widget.h"
|
||||
|
||||
165
libs/gtkutil/widget.h
Normal file
165
libs/gtkutil/widget.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_WIDGET_H)
|
||||
#define INCLUDED_GTKUTIL_WIDGET_H
|
||||
|
||||
#include <list>
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include "generic/callback.h"
|
||||
#include "warnings.h"
|
||||
|
||||
inline void widget_set_visible(GtkWidget* widget, bool shown)
|
||||
{
|
||||
if(shown)
|
||||
{
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide(widget);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool widget_is_visible(GtkWidget* widget)
|
||||
{
|
||||
return GTK_WIDGET_VISIBLE(widget) != FALSE;
|
||||
}
|
||||
|
||||
inline void widget_toggle_visible(GtkWidget* widget)
|
||||
{
|
||||
widget_set_visible(widget, !widget_is_visible(widget));
|
||||
}
|
||||
|
||||
class ToggleItem
|
||||
{
|
||||
BoolExportCallback m_exportCallback;
|
||||
typedef std::list<BoolImportCallback> ImportCallbacks;
|
||||
ImportCallbacks m_importCallbacks;
|
||||
public:
|
||||
ToggleItem(const BoolExportCallback& exportCallback) : m_exportCallback(exportCallback)
|
||||
{
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
for(ImportCallbacks::iterator i = m_importCallbacks.begin(); i != m_importCallbacks.end(); ++i)
|
||||
{
|
||||
m_exportCallback(*i);
|
||||
}
|
||||
}
|
||||
|
||||
void addCallback(const BoolImportCallback& callback)
|
||||
{
|
||||
m_importCallbacks.push_back(callback);
|
||||
m_exportCallback(callback);
|
||||
}
|
||||
typedef MemberCaller1<ToggleItem, const BoolImportCallback&, &ToggleItem::addCallback> AddCallbackCaller;
|
||||
};
|
||||
|
||||
class ToggleShown
|
||||
{
|
||||
bool m_shownDeferred;
|
||||
|
||||
ToggleShown(const ToggleShown& other); // NOT COPYABLE
|
||||
ToggleShown& operator=(const ToggleShown& other); // NOT ASSIGNABLE
|
||||
|
||||
static gboolean notify_visible(GtkWidget* widget, gpointer dummy, ToggleShown* self)
|
||||
{
|
||||
self->update();
|
||||
return FALSE;
|
||||
}
|
||||
static gboolean destroy(GtkWidget* widget, ToggleShown* self)
|
||||
{
|
||||
self->m_shownDeferred = GTK_WIDGET_VISIBLE(self->m_widget) != FALSE;
|
||||
self->m_widget = 0;
|
||||
return FALSE;
|
||||
}
|
||||
public:
|
||||
GtkWidget* m_widget;
|
||||
ToggleItem m_item;
|
||||
|
||||
ToggleShown(bool shown)
|
||||
: m_shownDeferred(shown), m_widget(0), m_item(ActiveCaller(*this))
|
||||
{
|
||||
}
|
||||
void update()
|
||||
{
|
||||
m_item.update();
|
||||
}
|
||||
bool active() const
|
||||
{
|
||||
if(m_widget == 0)
|
||||
{
|
||||
return m_shownDeferred;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GTK_WIDGET_VISIBLE(m_widget) != FALSE;
|
||||
}
|
||||
}
|
||||
void exportActive(const BoolImportCallback& importCallback)
|
||||
{
|
||||
importCallback(active());
|
||||
}
|
||||
typedef MemberCaller1<ToggleShown, const BoolImportCallback&, &ToggleShown::exportActive> ActiveCaller;
|
||||
void set(bool shown)
|
||||
{
|
||||
if(m_widget == 0)
|
||||
{
|
||||
m_shownDeferred = shown;
|
||||
}
|
||||
else
|
||||
{
|
||||
widget_set_visible(m_widget, shown);
|
||||
}
|
||||
}
|
||||
void toggle()
|
||||
{
|
||||
widget_toggle_visible(m_widget);
|
||||
}
|
||||
typedef MemberCaller<ToggleShown, &ToggleShown::toggle> ToggleCaller;
|
||||
void connect(GtkWidget* widget)
|
||||
{
|
||||
m_widget = widget;
|
||||
widget_set_visible(m_widget, m_shownDeferred);
|
||||
g_signal_connect(G_OBJECT(m_widget), "notify::visible", G_CALLBACK(notify_visible), this);
|
||||
g_signal_connect(G_OBJECT(m_widget), "destroy", G_CALLBACK(destroy), this);
|
||||
update();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline void widget_queue_draw(GtkWidget& widget)
|
||||
{
|
||||
gtk_widget_queue_draw(&widget);
|
||||
}
|
||||
typedef ReferenceCaller<GtkWidget, widget_queue_draw> WidgetQueueDrawCaller;
|
||||
|
||||
|
||||
inline void widget_make_default(GtkWidget* widget)
|
||||
{
|
||||
GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_DEFAULT);
|
||||
gtk_widget_grab_default(widget);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
170
libs/gtkutil/window.cpp
Normal file
170
libs/gtkutil/window.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "window.h"
|
||||
|
||||
#include <gtk/gtkscrolledwindow.h>
|
||||
|
||||
#include "pointer.h"
|
||||
#include "accelerator.h"
|
||||
|
||||
inline void CHECK_RESTORE(GtkWidget* w)
|
||||
{
|
||||
if(gpointer_to_int(g_object_get_data(G_OBJECT(w), "was_mapped")) != 0)
|
||||
{
|
||||
gtk_widget_show(w);
|
||||
}
|
||||
}
|
||||
|
||||
inline void CHECK_MINIMIZE(GtkWidget* w)
|
||||
{
|
||||
g_object_set_data(G_OBJECT(w), "was_mapped", gint_to_pointer(GTK_WIDGET_VISIBLE(w)));
|
||||
gtk_widget_hide(w);
|
||||
}
|
||||
|
||||
static gboolean main_window_iconified(GtkWidget* widget, GdkEventWindowState* event, gpointer data)
|
||||
{
|
||||
if((event->changed_mask & (GDK_WINDOW_STATE_ICONIFIED|GDK_WINDOW_STATE_WITHDRAWN)) != 0)
|
||||
{
|
||||
if((event->new_window_state & (GDK_WINDOW_STATE_ICONIFIED|GDK_WINDOW_STATE_WITHDRAWN)) != 0)
|
||||
{
|
||||
CHECK_MINIMIZE(GTK_WIDGET(data));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_RESTORE(GTK_WIDGET(data));
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
unsigned int connect_floating(GtkWindow* main_window, GtkWindow* floating)
|
||||
{
|
||||
return g_signal_connect(G_OBJECT(main_window), "window_state_event", G_CALLBACK(main_window_iconified), floating);
|
||||
}
|
||||
|
||||
gboolean destroy_disconnect_floating(GtkWindow* widget, gpointer data)
|
||||
{
|
||||
g_signal_handler_disconnect(G_OBJECT(data), gpointer_to_int(g_object_get_data(G_OBJECT(widget), "floating_handler")));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean floating_window_delete_present(GtkWindow* floating, GdkEventFocus *event, GtkWindow* main_window)
|
||||
{
|
||||
if(gtk_window_is_active(floating) || gtk_window_is_active(main_window))
|
||||
{
|
||||
gtk_window_present(main_window);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
guint connect_floating_window_delete_present(GtkWindow* floating, GtkWindow* main_window)
|
||||
{
|
||||
return g_signal_connect(G_OBJECT(floating), "delete_event", G_CALLBACK(floating_window_delete_present), main_window);
|
||||
}
|
||||
|
||||
gboolean floating_window_destroy_present(GtkWindow* floating, GtkWindow* main_window)
|
||||
{
|
||||
if(gtk_window_is_active(floating) || gtk_window_is_active(main_window))
|
||||
{
|
||||
gtk_window_present(main_window);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
guint connect_floating_window_destroy_present(GtkWindow* floating, GtkWindow* main_window)
|
||||
{
|
||||
return g_signal_connect(G_OBJECT(floating), "destroy", G_CALLBACK(floating_window_destroy_present), main_window);
|
||||
}
|
||||
|
||||
GtkWindow* create_floating_window(const char* title, GtkWindow* parent)
|
||||
{
|
||||
GtkWindow* window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
|
||||
gtk_window_set_title(window, title);
|
||||
|
||||
if(parent != 0)
|
||||
{
|
||||
gtk_window_set_transient_for(window, parent);
|
||||
connect_floating_window_destroy_present(window, parent);
|
||||
g_object_set_data(G_OBJECT(window), "floating_handler", gint_to_pointer(connect_floating(parent, window)));
|
||||
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy_disconnect_floating), parent);
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
void destroy_floating_window(GtkWindow* window)
|
||||
{
|
||||
gtk_widget_destroy(GTK_WIDGET(window));
|
||||
}
|
||||
|
||||
gint window_realize_remove_sysmenu(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
gdk_window_set_decorations(widget->window, (GdkWMDecoration)(GDK_DECOR_ALL|GDK_DECOR_MENU));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean persistent_floating_window_delete(GtkWindow* floating, GdkEvent *event, GtkWindow* main_window)
|
||||
{
|
||||
gtk_widget_hide(GTK_WIDGET(floating));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkWindow* create_persistent_floating_window(const char* title, GtkWindow* main_window)
|
||||
{
|
||||
GtkWindow* window = GTK_WINDOW(create_floating_window(title, main_window));
|
||||
|
||||
gtk_widget_set_events(GTK_WIDGET(window), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
|
||||
|
||||
connect_floating_window_delete_present(window, main_window);
|
||||
g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(persistent_floating_window_delete), 0);
|
||||
|
||||
#if 0
|
||||
if(g_multimon_globals.m_bStartOnPrimMon && g_multimon_globals.m_bNoSysMenuPopups)
|
||||
g_signal_connect(G_OBJECT(window), "realize", G_CALLBACK(window_realize_remove_sysmenu), 0);
|
||||
#endif
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
gint window_realize_remove_minmax(GtkWidget* widget, gpointer data)
|
||||
{
|
||||
gdk_window_set_decorations(widget->window, (GdkWMDecoration)(GDK_DECOR_ALL|GDK_DECOR_MINIMIZE|GDK_DECOR_MAXIMIZE));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void window_remove_minmax(GtkWindow* window)
|
||||
{
|
||||
g_signal_connect(G_OBJECT(window), "realize", G_CALLBACK(window_realize_remove_minmax), 0);
|
||||
}
|
||||
|
||||
|
||||
GtkScrolledWindow* create_scrolled_window(GtkPolicyType hscrollbar_policy, GtkPolicyType vscrollbar_policy, int border)
|
||||
{
|
||||
GtkScrolledWindow* scr = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(0, 0));
|
||||
gtk_widget_show(GTK_WIDGET(scr));
|
||||
gtk_scrolled_window_set_policy(scr, hscrollbar_policy, vscrollbar_policy);
|
||||
gtk_scrolled_window_set_shadow_type(scr, GTK_SHADOW_IN);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(scr), border);
|
||||
return scr;
|
||||
}
|
||||
|
||||
|
||||
174
libs/gtkutil/window.h
Normal file
174
libs/gtkutil/window.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_GTKUTIL_WINDOW_H)
|
||||
#define INCLUDED_GTKUTIL_WINDOW_H
|
||||
|
||||
#include <gtk/gtkwindow.h>
|
||||
|
||||
#include "debugging/debugging.h"
|
||||
#include "generic/callback.h"
|
||||
#include "widget.h"
|
||||
|
||||
inline gboolean window_focus_in_clear_focus_widget(GtkWidget* widget, GdkEventKey* event, gpointer data)
|
||||
{
|
||||
gtk_window_set_focus(GTK_WINDOW(widget), NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
inline guint window_connect_focus_in_clear_focus_widget(GtkWindow* window)
|
||||
{
|
||||
return g_signal_connect(G_OBJECT(window), "focus_in_event", G_CALLBACK(window_focus_in_clear_focus_widget), NULL);
|
||||
}
|
||||
|
||||
|
||||
unsigned int connect_floating(GtkWindow* main_window, GtkWindow* floating);
|
||||
GtkWindow* create_floating_window(const char* title, GtkWindow* parent);
|
||||
void destroy_floating_window(GtkWindow* window);
|
||||
|
||||
GtkWindow* create_persistent_floating_window(const char* title, GtkWindow* main_window);
|
||||
gboolean persistent_floating_window_delete(GtkWindow* floating, GdkEvent *event, GtkWindow* main_window);
|
||||
|
||||
void window_remove_minmax(GtkWindow* window);
|
||||
|
||||
typedef struct _GtkScrolledWindow GtkScrolledWindow;
|
||||
GtkScrolledWindow* create_scrolled_window(GtkPolicyType hscrollbar_policy, GtkPolicyType vscrollbar_policy, int border = 0);
|
||||
|
||||
|
||||
struct WindowPosition
|
||||
{
|
||||
int x, y, w, h;
|
||||
|
||||
WindowPosition()
|
||||
{
|
||||
}
|
||||
WindowPosition(int _x, int _y, int _w, int _h)
|
||||
: x(_x), y(_y), w(_w), h(_h)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
const WindowPosition c_default_window_pos(50, 25, 400, 300);
|
||||
|
||||
inline void window_get_position(GtkWindow* window, WindowPosition& position)
|
||||
{
|
||||
ASSERT_MESSAGE(window != 0, "error saving window position");
|
||||
|
||||
gtk_window_get_position(window, &position.x, &position.y);
|
||||
gtk_window_get_size(window, &position.w, &position.h);
|
||||
}
|
||||
|
||||
inline void window_set_position(GtkWindow* window, const WindowPosition& position)
|
||||
{
|
||||
gtk_window_set_gravity(window, GDK_GRAVITY_STATIC);
|
||||
|
||||
GdkScreen* screen = gdk_screen_get_default();
|
||||
if(position.x < 0
|
||||
|| position.y < 0
|
||||
|| position.x > gdk_screen_get_width(screen)
|
||||
|| position.y > gdk_screen_get_height(screen))
|
||||
{
|
||||
gtk_window_set_position(window, GTK_WIN_POS_CENTER_ON_PARENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_window_move(window, position.x, position.y);
|
||||
}
|
||||
|
||||
gtk_window_set_default_size(window, position.w, position.h);
|
||||
}
|
||||
|
||||
inline void WindowPosition_Parse(WindowPosition& position, const char* value)
|
||||
{
|
||||
if(sscanf(value, "%d %d %d %d", &position.x, &position.y, &position.w, &position.h) != 4)
|
||||
{
|
||||
position = WindowPosition(c_default_window_pos); // ensure sane default value for window position
|
||||
}
|
||||
}
|
||||
typedef ReferenceCaller1<WindowPosition, const char*, WindowPosition_Parse> WindowPositionImportStringCaller;
|
||||
|
||||
inline void WindowPosition_Write(const WindowPosition& position, const StringImportCallback& importCallback)
|
||||
{
|
||||
char buffer[64];
|
||||
sprintf(buffer, "%d %d %d %d", position.x, position.y, position.w, position.h);
|
||||
importCallback(buffer);
|
||||
}
|
||||
typedef ConstReferenceCaller1<WindowPosition, const StringImportCallback&, WindowPosition_Write> WindowPositionExportStringCaller;
|
||||
|
||||
|
||||
|
||||
class WindowPositionTracker
|
||||
{
|
||||
WindowPosition m_position;
|
||||
|
||||
static gboolean configure(GtkWidget* widget, GdkEventConfigure *event, WindowPositionTracker* self)
|
||||
{
|
||||
self->m_position = WindowPosition(event->x, event->y, event->width, event->height);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
public:
|
||||
WindowPositionTracker()
|
||||
: m_position(c_default_window_pos)
|
||||
{
|
||||
}
|
||||
|
||||
void sync(GtkWindow* window)
|
||||
{
|
||||
window_set_position(window, m_position);
|
||||
}
|
||||
|
||||
void connect(GtkWindow* window)
|
||||
{
|
||||
sync(window);
|
||||
g_signal_connect(G_OBJECT(window), "configure_event", G_CALLBACK(configure), this);
|
||||
}
|
||||
|
||||
const WindowPosition& getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
//hack
|
||||
void setPosition(const WindowPosition& position)
|
||||
{
|
||||
m_position = position;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline void WindowPositionTracker_importString(WindowPositionTracker& self, const char* value)
|
||||
{
|
||||
WindowPosition position;
|
||||
WindowPosition_Parse(position, value);
|
||||
self.setPosition(position);
|
||||
}
|
||||
typedef ReferenceCaller1<WindowPositionTracker, const char*, WindowPositionTracker_importString> WindowPositionTrackerImportStringCaller;
|
||||
|
||||
inline void WindowPositionTracker_exportString(const WindowPositionTracker& self, const StringImportCallback& importer)
|
||||
{
|
||||
WindowPosition_Write(self.getPosition(), importer);
|
||||
}
|
||||
typedef ConstReferenceCaller1<WindowPositionTracker, const StringImportCallback&, WindowPositionTracker_exportString> WindowPositionTrackerExportStringCaller;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
23
libs/gtkutil/xorrectangle.cpp
Normal file
23
libs/gtkutil/xorrectangle.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "xorrectangle.h"
|
||||
|
||||
125
libs/gtkutil/xorrectangle.h
Normal file
125
libs/gtkutil/xorrectangle.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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 GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined (INCLUDED_XORRECTANGLE_H)
|
||||
#define INCLUDED_XORRECTANGLE_H
|
||||
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include "math/vector.h"
|
||||
|
||||
class rectangle_t
|
||||
{
|
||||
public:
|
||||
rectangle_t()
|
||||
: x(0), y(0), w(0), h(0)
|
||||
{}
|
||||
rectangle_t(float _x, float _y, float _w, float _h)
|
||||
: x(_x), y(_y), w(_w), h(_h)
|
||||
{}
|
||||
float x;
|
||||
float y;
|
||||
float w;
|
||||
float h;
|
||||
};
|
||||
|
||||
struct Coord2D
|
||||
{
|
||||
float x, y;
|
||||
Coord2D(float _x, float _y)
|
||||
: x(_x), y(_y)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline Coord2D coord2d_device2screen(const Coord2D& coord, unsigned int width, unsigned int height)
|
||||
{
|
||||
return Coord2D(((coord.x + 1.0f) * 0.5f) * width, ((coord.y + 1.0f) * 0.5f) * height);
|
||||
}
|
||||
|
||||
inline rectangle_t rectangle_from_area(const float min[2], const float max[2], unsigned int width, unsigned int height)
|
||||
{
|
||||
Coord2D botleft(coord2d_device2screen(Coord2D(min[0], min[1]), width, height));
|
||||
Coord2D topright(coord2d_device2screen(Coord2D(max[0], max[1]), width, height));
|
||||
return rectangle_t(botleft.x, botleft.y, topright.x - botleft.x, topright.y - botleft.y);
|
||||
}
|
||||
|
||||
class XORRectangle
|
||||
{
|
||||
|
||||
rectangle_t m_rectangle;
|
||||
|
||||
GtkWidget* m_widget;
|
||||
GdkGC* m_gc;
|
||||
|
||||
bool initialised() const
|
||||
{
|
||||
return m_gc != 0;
|
||||
}
|
||||
void lazy_init()
|
||||
{
|
||||
if(!initialised())
|
||||
{
|
||||
m_gc = gdk_gc_new(m_widget->window);
|
||||
|
||||
GdkColor color = { 0, 0xffff, 0xffff, 0xffff, };
|
||||
GdkColormap* colormap = gdk_window_get_colormap(m_widget->window);
|
||||
gdk_colormap_alloc_color (colormap, &color, FALSE, TRUE);
|
||||
gdk_gc_copy(m_gc, m_widget->style->white_gc);
|
||||
gdk_gc_set_foreground(m_gc, &color);
|
||||
gdk_gc_set_background(m_gc, &color);
|
||||
|
||||
gdk_gc_set_function(m_gc, GDK_INVERT);
|
||||
}
|
||||
}
|
||||
void draw() const
|
||||
{
|
||||
const int x = float_to_integer(m_rectangle.x);
|
||||
const int y = float_to_integer(m_rectangle.y);
|
||||
const int w = float_to_integer(m_rectangle.w);
|
||||
const int h = float_to_integer(m_rectangle.h);
|
||||
gdk_draw_rectangle(m_widget->window, m_gc, FALSE, x, -(h) - (y - m_widget->allocation.height), w, h);
|
||||
}
|
||||
|
||||
public:
|
||||
XORRectangle(GtkWidget* widget) : m_widget(widget), m_gc(0)
|
||||
{
|
||||
}
|
||||
~XORRectangle()
|
||||
{
|
||||
if(initialised())
|
||||
{
|
||||
gdk_gc_unref(m_gc);
|
||||
}
|
||||
}
|
||||
void set(rectangle_t rectangle)
|
||||
{
|
||||
if(GTK_WIDGET_REALIZED(m_widget))
|
||||
{
|
||||
lazy_init();
|
||||
draw();
|
||||
m_rectangle = rectangle;
|
||||
draw();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user