1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk/bmpcbox.cpp
3 // Purpose:     wxBitmapComboBox
4 // Author:      Jaakko Salli
5 // Created:     2008-05-19
6 // Copyright:   (c) 2008 Jaakko Salli
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 // ============================================================================
11 // declarations
12 // ============================================================================
13 
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17 
18 #include "wx/wxprec.h"
19 
20 #ifdef __BORLANDC__
21     #pragma hdrstop
22 #endif
23 
24 #if wxUSE_BITMAPCOMBOBOX
25 
26 #include "wx/bmpcbox.h"
27 
28 #ifndef WX_PRECOMP
29     #include "wx/log.h"
30 #endif
31 
32 #include <gtk/gtk.h>
33 #include "wx/gtk/private.h"
34 
35 // ============================================================================
36 // implementation
37 // ============================================================================
38 
39 
IMPLEMENT_DYNAMIC_CLASS(wxBitmapComboBox,wxComboBox)40 IMPLEMENT_DYNAMIC_CLASS(wxBitmapComboBox, wxComboBox)
41 
42 
43 // ----------------------------------------------------------------------------
44 // wxBitmapComboBox creation
45 // ----------------------------------------------------------------------------
46 
47 void wxBitmapComboBox::Init()
48 {
49     m_bitmapCellIndex = 0;
50     m_stringCellIndex = 1;
51     m_bitmapSize = wxSize(-1, -1);
52 }
53 
wxBitmapComboBox(wxWindow * parent,wxWindowID id,const wxString & value,const wxPoint & pos,const wxSize & size,const wxArrayString & choices,long style,const wxValidator & validator,const wxString & name)54 wxBitmapComboBox::wxBitmapComboBox(wxWindow *parent,
55                                   wxWindowID id,
56                                   const wxString& value,
57                                   const wxPoint& pos,
58                                   const wxSize& size,
59                                   const wxArrayString& choices,
60                                   long style,
61                                   const wxValidator& validator,
62                                   const wxString& name)
63     : wxComboBox(),
64       wxBitmapComboBoxBase()
65 {
66     Init();
67 
68     Create(parent,id,value,pos,size,choices,style,validator,name);
69 }
70 
Create(wxWindow * parent,wxWindowID id,const wxString & value,const wxPoint & pos,const wxSize & size,const wxArrayString & choices,long style,const wxValidator & validator,const wxString & name)71 bool wxBitmapComboBox::Create(wxWindow *parent,
72                               wxWindowID id,
73                               const wxString& value,
74                               const wxPoint& pos,
75                               const wxSize& size,
76                               const wxArrayString& choices,
77                               long style,
78                               const wxValidator& validator,
79                               const wxString& name)
80 {
81     wxCArrayString chs(choices);
82     return Create(parent, id, value, pos, size, chs.GetCount(),
83                   chs.GetStrings(), style, validator, name);
84 }
85 
Create(wxWindow * parent,wxWindowID id,const wxString & value,const wxPoint & pos,const wxSize & size,int n,const wxString choices[],long style,const wxValidator & validator,const wxString & name)86 bool wxBitmapComboBox::Create(wxWindow *parent,
87                               wxWindowID id,
88                               const wxString& value,
89                               const wxPoint& pos,
90                               const wxSize& size,
91                               int n,
92                               const wxString choices[],
93                               long style,
94                               const wxValidator& validator,
95                               const wxString& name)
96 {
97     if ( !wxComboBox::Create(parent, id, value, pos, size,
98                              n, choices, style, validator, name) )
99         return false;
100 
101     // Select 'value' in entry-less mode
102     if ( !GetEntry() )
103     {
104         int i = FindString(value);
105         if (i != wxNOT_FOUND)
106             SetSelection(i);
107     }
108 
109     return true;
110 }
111 
GTKCreateComboBoxWidget()112 void wxBitmapComboBox::GTKCreateComboBoxWidget()
113 {
114     GtkListStore *store;
115 
116     store = gtk_list_store_new( 2, G_TYPE_OBJECT, G_TYPE_STRING );
117 
118     if ( HasFlag(wxCB_READONLY) )
119     {
120         m_widget = gtk_combo_box_new_with_model( GTK_TREE_MODEL(store) );
121     }
122     else
123     {
124 #ifdef __WXGTK3__
125         m_widget = gtk_combo_box_new_with_model_and_entry(GTK_TREE_MODEL(store));
126         gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(m_widget), m_stringCellIndex);
127 #else
128         m_widget = gtk_combo_box_entry_new_with_model( GTK_TREE_MODEL(store), m_stringCellIndex );
129 #endif
130         m_entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(m_widget)));
131         g_object_add_weak_pointer(G_OBJECT(m_entry), (void**)&m_entry);
132         gtk_editable_set_editable(GTK_EDITABLE(m_entry), true);
133     }
134     g_object_ref(m_widget);
135 
136     // This must be called as gtk_combo_box_entry_new_with_model adds
137     // automatically adds one text column.
138     gtk_cell_layout_clear( GTK_CELL_LAYOUT(m_widget) );
139 
140     GtkCellRenderer* imageRenderer = gtk_cell_renderer_pixbuf_new();
141     gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(m_widget),
142                                 imageRenderer, FALSE);
143     gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(m_widget),
144                                    imageRenderer, "pixbuf", 0);
145 
146     GtkCellRenderer* textRenderer = gtk_cell_renderer_text_new();
147     gtk_cell_layout_pack_end( GTK_CELL_LAYOUT(m_widget),
148                               textRenderer, TRUE );
149     gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(m_widget),
150                                    textRenderer, "text", 1);
151 }
152 
~wxBitmapComboBox()153 wxBitmapComboBox::~wxBitmapComboBox()
154 {
155 }
156 
GetConnectWidget()157 GtkWidget* wxBitmapComboBox::GetConnectWidget()
158 {
159     if ( GetEntry() )
160         return wxComboBox::GetConnectWidget();
161 
162     return wxChoice::GetConnectWidget();
163 }
164 
GTKGetWindow(wxArrayGdkWindows & windows) const165 GdkWindow *wxBitmapComboBox::GTKGetWindow(wxArrayGdkWindows& windows) const
166 {
167     if ( GetEntry() )
168         return wxComboBox::GTKGetWindow(windows);
169 
170     return wxChoice::GTKGetWindow(windows);
171 }
172 
DoGetBestSize() const173 wxSize wxBitmapComboBox::DoGetBestSize() const
174 {
175     wxSize best = wxComboBox::DoGetBestSize();
176 
177     int delta = GetBitmapSize().y - GetCharHeight();
178     if ( delta > 0 )
179     {
180         best.y += delta;
181         CacheBestSize(best);
182     }
183     return best;
184 }
185 
186 // ----------------------------------------------------------------------------
187 // Item manipulation
188 // ----------------------------------------------------------------------------
189 
SetItemBitmap(unsigned int n,const wxBitmap & bitmap)190 void wxBitmapComboBox::SetItemBitmap(unsigned int n, const wxBitmap& bitmap)
191 {
192     if ( bitmap.IsOk() )
193     {
194         if ( m_bitmapSize.x < 0 )
195         {
196             m_bitmapSize.x = bitmap.GetWidth();
197             m_bitmapSize.y = bitmap.GetHeight();
198         }
199 
200         GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
201         GtkTreeModel *model = gtk_combo_box_get_model( combobox );
202         GtkTreeIter iter;
203 
204         if ( gtk_tree_model_iter_nth_child( model, &iter, NULL, n ) )
205         {
206             GValue value0 = G_VALUE_INIT;
207             g_value_init( &value0, G_TYPE_OBJECT );
208             g_value_set_object( &value0, bitmap.GetPixbuf() );
209             gtk_list_store_set_value( GTK_LIST_STORE(model), &iter,
210                                       m_bitmapCellIndex, &value0 );
211             g_value_unset( &value0 );
212         }
213     }
214 }
215 
GetItemBitmap(unsigned int n) const216 wxBitmap wxBitmapComboBox::GetItemBitmap(unsigned int n) const
217 {
218     wxBitmap bitmap;
219 
220     GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
221     GtkTreeModel *model = gtk_combo_box_get_model( combobox );
222     GtkTreeIter iter;
223 
224     if (gtk_tree_model_iter_nth_child (model, &iter, NULL, n))
225     {
226         GValue value = G_VALUE_INIT;
227         gtk_tree_model_get_value( model, &iter,
228                                   m_bitmapCellIndex, &value );
229         GdkPixbuf* pixbuf = (GdkPixbuf*) g_value_get_object( &value );
230         if ( pixbuf )
231         {
232             g_object_ref( pixbuf );
233             bitmap = wxBitmap(pixbuf);
234         }
235         g_value_unset( &value );
236     }
237 
238     return bitmap;
239 }
240 
Append(const wxString & item,const wxBitmap & bitmap)241 int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap)
242 {
243     const int n = wxComboBox::Append(item);
244     if ( n != wxNOT_FOUND )
245         SetItemBitmap(n, bitmap);
246     return n;
247 }
248 
Append(const wxString & item,const wxBitmap & bitmap,void * clientData)249 int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
250                              void *clientData)
251 {
252     const int n = wxComboBox::Append(item, clientData);
253     if ( n != wxNOT_FOUND )
254         SetItemBitmap(n, bitmap);
255     return n;
256 }
257 
Append(const wxString & item,const wxBitmap & bitmap,wxClientData * clientData)258 int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
259                              wxClientData *clientData)
260 {
261     const int n = wxComboBox::Append(item, clientData);
262     if ( n != wxNOT_FOUND )
263         SetItemBitmap(n, bitmap);
264     return n;
265 }
266 
Insert(const wxString & item,const wxBitmap & bitmap,unsigned int pos)267 int wxBitmapComboBox::Insert(const wxString& item,
268                              const wxBitmap& bitmap,
269                              unsigned int pos)
270 {
271     const int n = wxComboBox::Insert(item, pos);
272     if ( n != wxNOT_FOUND )
273         SetItemBitmap(n, bitmap);
274     return n;
275 }
276 
Insert(const wxString & item,const wxBitmap & bitmap,unsigned int pos,wxClientData * clientData)277 int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
278                              unsigned int pos, wxClientData *clientData)
279 {
280     const int n = wxComboBox::Insert(item, pos, clientData);
281     if ( n != wxNOT_FOUND )
282         SetItemBitmap(n, bitmap);
283     return n;
284 }
285 
Insert(const wxString & item,const wxBitmap & bitmap,unsigned int pos,void * clientData)286 int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
287                              unsigned int pos, void *clientData)
288 {
289     const int n = wxComboBox::Insert(item, pos, clientData);
290     if ( n != wxNOT_FOUND )
291         SetItemBitmap(n, bitmap);
292     return n;
293 }
294 
GTKInsertComboBoxTextItem(unsigned int n,const wxString & text)295 void wxBitmapComboBox::GTKInsertComboBoxTextItem( unsigned int n, const wxString& text )
296 {
297     GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
298     GtkTreeModel *model = gtk_combo_box_get_model( combobox );
299     GtkListStore *store = GTK_LIST_STORE( model );
300     GtkTreeIter iter;
301 
302     gtk_list_store_insert( store, &iter, n );
303 
304     GValue value = G_VALUE_INIT;
305     g_value_init( &value, G_TYPE_STRING );
306     g_value_set_string( &value, wxGTK_CONV( text ) );
307     gtk_list_store_set_value( store, &iter, m_stringCellIndex, &value );
308     g_value_unset( &value );
309 }
310 
311 // ----------------------------------------------------------------------------
312 // wxTextEntry interface override
313 // ----------------------------------------------------------------------------
314 
WriteText(const wxString & value)315 void wxBitmapComboBox::WriteText(const wxString& value)
316 {
317     if ( GetEntry() )
318         wxComboBox::WriteText(value);
319     else
320         SetStringSelection(value);
321 }
322 
GetValue() const323 wxString wxBitmapComboBox::GetValue() const
324 {
325     if ( GetEntry() )
326         return wxComboBox::GetValue();
327 
328     return GetStringSelection();
329 }
330 
Remove(long from,long to)331 void wxBitmapComboBox::Remove(long from, long to)
332 {
333     if ( GetEntry() )
334         wxComboBox::Remove(from, to);
335 }
336 
SetInsertionPoint(long pos)337 void wxBitmapComboBox::SetInsertionPoint(long pos)
338 {
339     if ( GetEntry() )
340         wxComboBox::SetInsertionPoint(pos);
341 }
342 
GetInsertionPoint() const343 long wxBitmapComboBox::GetInsertionPoint() const
344 {
345     if ( GetEntry() )
346         return wxComboBox::GetInsertionPoint();
347 
348     return 0;
349  }
GetLastPosition() const350 long wxBitmapComboBox::GetLastPosition() const
351 {
352     if ( GetEntry() )
353         return wxComboBox::GetLastPosition();
354 
355     return 0;
356  }
357 
SetSelection(long from,long to)358 void wxBitmapComboBox::SetSelection(long from, long to)
359 {
360     if ( GetEntry() )
361         wxComboBox::SetSelection(from, to);
362 }
363 
GetSelection(long * from,long * to) const364 void wxBitmapComboBox::GetSelection(long *from, long *to) const
365 {
366     if ( GetEntry() )
367         wxComboBox::GetSelection(from, to);
368 }
369 
IsEditable() const370 bool wxBitmapComboBox::IsEditable() const
371 {
372     if ( GetEntry() )
373         return wxTextEntry::IsEditable();
374 
375     return false;
376 }
377 
SetEditable(bool editable)378 void wxBitmapComboBox::SetEditable(bool editable)
379 {
380     if ( GetEntry() )
381         wxComboBox::SetEditable(editable);
382 }
383 
384 #endif // wxUSE_BITMAPCOMBOBOX
385