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