77938c64e3d7b8205a155f1849dac22aa2a8c735
[xonotic/netradiant.git] / libs / gtkutil / widget.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #if !defined( INCLUDED_GTKUTIL_WIDGET_H )
23 #define INCLUDED_GTKUTIL_WIDGET_H
24
25 #include <list>
26 #include <gtk/gtk.h>
27 #include "generic/callback.h"
28 #include "warnings.h"
29 #include "debugging/debugging.h"
30
31 inline void widget_set_visible( ui::Widget widget, bool shown ){
32         if ( shown ) {
33                 widget.show();
34         }
35         else
36         {
37                 gtk_widget_hide( widget );
38         }
39 }
40
41 inline bool widget_is_visible( ui::Widget widget ){
42         return gtk_widget_get_visible( widget ) != FALSE;
43 }
44
45 inline void widget_toggle_visible( ui::Widget widget ){
46         widget_set_visible( widget, !widget_is_visible( widget ) );
47 }
48
49 class ToggleItem
50 {
51 BoolExportCallback m_exportCallback;
52 typedef std::list<BoolImportCallback> ImportCallbacks;
53 ImportCallbacks m_importCallbacks;
54 public:
55 ToggleItem( const BoolExportCallback& exportCallback ) : m_exportCallback( exportCallback ){
56 }
57
58 void update(){
59         for ( ImportCallbacks::iterator i = m_importCallbacks.begin(); i != m_importCallbacks.end(); ++i )
60         {
61                 m_exportCallback( *i );
62         }
63 }
64
65 void addCallback( const BoolImportCallback& callback ){
66         m_importCallbacks.push_back( callback );
67         m_exportCallback( callback );
68 }
69 typedef MemberCaller1<ToggleItem, const BoolImportCallback&, &ToggleItem::addCallback> AddCallbackCaller;
70 };
71
72 class ToggleShown
73 {
74 bool m_shownDeferred;
75
76 ToggleShown( const ToggleShown& other ); // NOT COPYABLE
77 ToggleShown& operator=( const ToggleShown& other ); // NOT ASSIGNABLE
78
79 static gboolean notify_visible( ui::Widget widget, gpointer dummy, ToggleShown* self ){
80         self->update();
81         return FALSE;
82 }
83 static gboolean destroy( ui::Widget widget, ToggleShown* self ){
84         self->m_shownDeferred = gtk_widget_get_visible( self->m_widget ) != FALSE;
85         self->m_widget = ui::Widget(nullptr);
86         return FALSE;
87 }
88 public:
89 ui::Widget m_widget;
90 ToggleItem m_item;
91
92 ToggleShown( bool shown )
93         : m_shownDeferred( shown ), m_widget( 0 ), m_item( ActiveCaller( *this ) ){
94 }
95 void update(){
96         m_item.update();
97 }
98 bool active() const {
99         if ( !m_widget ) {
100                 return m_shownDeferred;
101         }
102         else
103         {
104                 return gtk_widget_get_visible( m_widget ) != FALSE;
105         }
106 }
107 void exportActive( const BoolImportCallback& importCallback ){
108         importCallback( active() );
109 }
110 typedef MemberCaller1<ToggleShown, const BoolImportCallback&, &ToggleShown::exportActive> ActiveCaller;
111 void set( bool shown ){
112         if ( !m_widget ) {
113                 m_shownDeferred = shown;
114         }
115         else
116         {
117                 widget_set_visible( m_widget, shown );
118         }
119 }
120 void toggle(){
121         widget_toggle_visible( m_widget );
122 }
123 typedef MemberCaller<ToggleShown, &ToggleShown::toggle> ToggleCaller;
124 void connect( ui::Widget widget ){
125         m_widget = widget;
126         widget_set_visible( m_widget, m_shownDeferred );
127         g_signal_connect( G_OBJECT( m_widget ), "notify::visible", G_CALLBACK( notify_visible ), this );
128         g_signal_connect( G_OBJECT( m_widget ), "destroy", G_CALLBACK( destroy ), this );
129         update();
130 }
131 };
132
133
134 inline void widget_queue_draw( GtkWidget& widget ){
135         gtk_widget_queue_draw( &widget );
136 }
137 typedef ReferenceCaller<GtkWidget, widget_queue_draw> WidgetQueueDrawCaller;
138
139
140 inline void widget_make_default( ui::Widget widget ){
141         gtk_widget_set_can_default( widget, true );
142         gtk_widget_grab_default( widget );
143 }
144
145 class WidgetFocusPrinter
146 {
147 const char* m_name;
148
149 static gboolean focus_in( ui::Widget widget, GdkEventFocus *event, WidgetFocusPrinter* self ){
150         globalOutputStream() << self->m_name << " takes focus\n";
151         return FALSE;
152 }
153 static gboolean focus_out( ui::Widget widget, GdkEventFocus *event, WidgetFocusPrinter* self ){
154         globalOutputStream() << self->m_name << " loses focus\n";
155         return FALSE;
156 }
157 public:
158 WidgetFocusPrinter( const char* name ) : m_name( name ){
159 }
160 void connect( ui::Widget widget ){
161         g_signal_connect( G_OBJECT( widget ), "focus_in_event", G_CALLBACK( focus_in ), this );
162         g_signal_connect( G_OBJECT( widget ), "focus_out_event", G_CALLBACK( focus_out ), this );
163 }
164 };
165
166 #endif