1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk/private.cpp
3 // Purpose:     implementation of wxGTK private functions
4 // Author:      Marcin Malich
5 // Modified by:
6 // Created:     28.06.2008
7 // Copyright:   (c) 2008 Marcin Malich <me@malcom.pl>
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 #ifndef WX_PRECOMP
27     #include "wx/module.h"
28 #endif
29 
30 #include <gtk/gtk.h>
31 #include "wx/gtk/private.h"
32 
33 // ----------------------------------------------------------------------------
34 // wxGTKPrivate functions implementation
35 // ----------------------------------------------------------------------------
36 
37 namespace wxGTKPrivate
38 {
39 
40 static GtkWidget *gs_container = NULL;
41 
GetContainer()42 static GtkContainer* GetContainer()
43 {
44     if ( gs_container == NULL )
45     {
46         GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
47         gs_container = gtk_fixed_new();
48         gtk_container_add(GTK_CONTAINER(window), gs_container);
49     }
50     return GTK_CONTAINER(gs_container);
51 }
52 
GetButtonWidget()53 GtkWidget *GetButtonWidget()
54 {
55     static GtkWidget *s_button = NULL;
56 
57     if ( !s_button )
58     {
59         s_button = gtk_button_new();
60         g_object_add_weak_pointer(G_OBJECT(s_button), (void**)&s_button);
61         gtk_container_add(GetContainer(), s_button);
62         gtk_widget_realize(s_button);
63     }
64 
65     return s_button;
66 }
67 
GetNotebookWidget()68 GtkWidget *GetNotebookWidget()
69 {
70     static GtkWidget *s_notebook = NULL;
71 
72     if ( !s_notebook )
73     {
74         s_notebook = gtk_notebook_new();
75         g_object_add_weak_pointer(G_OBJECT(s_notebook), (void**)&s_notebook);
76         gtk_container_add(GetContainer(), s_notebook);
77         gtk_widget_realize(s_notebook);
78     }
79 
80     return s_notebook;
81 }
82 
GetCheckButtonWidget()83 GtkWidget *GetCheckButtonWidget()
84 {
85     static GtkWidget *s_button = NULL;
86 
87     if ( !s_button )
88     {
89         s_button = gtk_check_button_new();
90         g_object_add_weak_pointer(G_OBJECT(s_button), (void**)&s_button);
91         gtk_container_add(GetContainer(), s_button);
92         gtk_widget_realize(s_button);
93     }
94 
95     return s_button;
96 }
97 
GetComboBoxWidget()98 GtkWidget * GetComboBoxWidget()
99 {
100     static GtkWidget *s_button = NULL;
101 
102     if ( !s_button )
103     {
104         s_button = gtk_combo_box_new();
105         g_object_add_weak_pointer(G_OBJECT(s_button), (void**)&s_button);
106         gtk_container_add(GetContainer(), s_button);
107         gtk_widget_realize( s_button );
108     }
109 
110     return s_button;
111 }
112 
113 
GetEntryWidget()114 GtkWidget *GetEntryWidget()
115 {
116     static GtkWidget *s_entry = NULL;
117 
118     if ( !s_entry )
119     {
120         s_entry = gtk_entry_new();
121         g_object_add_weak_pointer(G_OBJECT(s_entry), (void**)&s_entry);
122         gtk_container_add(GetContainer(), s_entry);
123         gtk_widget_realize(s_entry);
124     }
125 
126     return s_entry;
127 }
128 
129 // This one just gets the button used by the column header. Although it's
130 // still a gtk_button the themes will typically differentiate and draw them
131 // differently if the button is in a treeview.
132 static GtkWidget *s_first_button = NULL;
133 static GtkWidget *s_other_button = NULL;
134 static GtkWidget *s_last_button = NULL;
135 
CreateHeaderButtons()136 static void CreateHeaderButtons()
137 {
138         // Get the dummy tree widget, give it a column, and then use the
139         // widget in the column header for the rendering code.
140         GtkWidget* treewidget = GetTreeWidget();
141 
142         GtkTreeViewColumn *column = gtk_tree_view_column_new();
143         gtk_tree_view_append_column(GTK_TREE_VIEW(treewidget), column);
144 #ifdef __WXGTK3__
145         s_first_button = gtk_tree_view_column_get_button(column);
146 #else
147         s_first_button = column->button;
148 #endif
149         wxASSERT(s_first_button);
150         g_object_add_weak_pointer(G_OBJECT(s_first_button), (void**)&s_first_button);
151 
152         column = gtk_tree_view_column_new();
153         gtk_tree_view_append_column(GTK_TREE_VIEW(treewidget), column);
154 #ifdef __WXGTK3__
155         s_other_button = gtk_tree_view_column_get_button(column);
156 #else
157         s_other_button = column->button;
158 #endif
159         g_object_add_weak_pointer(G_OBJECT(s_other_button), (void**)&s_other_button);
160 
161         column = gtk_tree_view_column_new();
162         gtk_tree_view_append_column(GTK_TREE_VIEW(treewidget), column);
163 #ifdef __WXGTK3__
164         s_last_button = gtk_tree_view_column_get_button(column);
165 #else
166         s_last_button = column->button;
167 #endif
168         g_object_add_weak_pointer(G_OBJECT(s_last_button), (void**)&s_last_button);
169 }
170 
GetHeaderButtonWidgetFirst()171 GtkWidget *GetHeaderButtonWidgetFirst()
172 {
173     if (!s_first_button)
174       CreateHeaderButtons();
175 
176     return s_first_button;
177 }
178 
GetHeaderButtonWidgetLast()179 GtkWidget *GetHeaderButtonWidgetLast()
180 {
181     if (!s_last_button)
182       CreateHeaderButtons();
183 
184     return s_last_button;
185 }
186 
GetHeaderButtonWidget()187 GtkWidget *GetHeaderButtonWidget()
188 {
189     if (!s_other_button)
190       CreateHeaderButtons();
191 
192     return s_other_button;
193 }
194 
GetRadioButtonWidget()195 GtkWidget * GetRadioButtonWidget()
196 {
197     static GtkWidget *s_button = NULL;
198 
199     if ( !s_button )
200     {
201         s_button = gtk_radio_button_new(NULL);
202         g_object_add_weak_pointer(G_OBJECT(s_button), (void**)&s_button);
203         gtk_container_add(GetContainer(), s_button);
204         gtk_widget_realize( s_button );
205     }
206 
207     return s_button;
208 }
209 
GetSplitterWidget(wxOrientation orient)210 GtkWidget* GetSplitterWidget(wxOrientation orient)
211 {
212     static GtkWidget* widgets[2];
213     const GtkOrientation gtkOrient =
214         orient == wxHORIZONTAL ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
215     GtkWidget*& widget = widgets[gtkOrient];
216     if (widget == NULL)
217     {
218 #ifdef __WXGTK3__
219         widget = gtk_paned_new(gtkOrient);
220 #else
221         if (orient == wxHORIZONTAL)
222             widget = gtk_hpaned_new();
223         else
224             widget = gtk_vpaned_new();
225 #endif
226         g_object_add_weak_pointer(G_OBJECT(widget), (void**)&widgets[gtkOrient]);
227         gtk_container_add(GetContainer(), widget);
228         gtk_widget_realize(widget);
229     }
230 
231     return widget;
232 }
233 
GetTextEntryWidget()234 GtkWidget * GetTextEntryWidget()
235 {
236     static GtkWidget *s_button = NULL;
237 
238     if ( !s_button )
239     {
240         s_button = gtk_entry_new();
241         g_object_add_weak_pointer(G_OBJECT(s_button), (void**)&s_button);
242         gtk_container_add(GetContainer(), s_button);
243         gtk_widget_realize( s_button );
244     }
245 
246     return s_button;
247 }
248 
GetTreeWidget()249 GtkWidget *GetTreeWidget()
250 {
251     static GtkWidget *s_tree = NULL;
252 
253     if ( !s_tree )
254     {
255         s_tree = gtk_tree_view_new();
256         g_object_add_weak_pointer(G_OBJECT(s_tree), (void**)&s_tree);
257         gtk_container_add(GetContainer(), s_tree);
258         gtk_widget_realize(s_tree);
259     }
260 
261     return s_tree;
262 }
263 
264 // Module for destroying created widgets
265 class WidgetsCleanupModule : public wxModule
266 {
267 public:
OnInit()268     virtual bool OnInit()
269     {
270         return true;
271     }
272 
OnExit()273     virtual void OnExit()
274     {
275         if ( gs_container )
276         {
277             GtkWidget* parent = gtk_widget_get_parent(gs_container);
278             gtk_widget_destroy(parent);
279             gs_container = NULL;
280         }
281     }
282 
283     DECLARE_DYNAMIC_CLASS(WidgetsCleanupModule)
284 };
285 
286 IMPLEMENT_DYNAMIC_CLASS(WidgetsCleanupModule, wxModule)
287 
288 } // wxGTKPrivate namespace
289