]> git.saurik.com Git - wxWidgets.git/blob - src/mac/classic/combobox.cpp
Do not try to expand the root node in SetWindowStyle if the root node hasn't been...
[wxWidgets.git] / src / mac / classic / combobox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: combobox.cpp
3 // Purpose: wxComboBox class
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "combobox.h"
14 #endif
15
16 #include "wx/combobox.h"
17 #include "wx/button.h"
18 #include "wx/menu.h"
19 #include "wx/mac/uma.h"
20
21 IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
22
23 // composite combobox implementation by Dan "Bud" Keith bud@otsys.com
24
25
26 static int nextPopUpMenuId = 1000 ;
27 MenuHandle NewUniqueMenu()
28 {
29 MenuHandle handle = NewMenu( nextPopUpMenuId , "\pMenu" ) ;
30 nextPopUpMenuId++ ;
31 return handle ;
32 }
33
34
35 // ----------------------------------------------------------------------------
36 // constants
37 // ----------------------------------------------------------------------------
38
39 // the margin between the text control and the choice
40 static const wxCoord MARGIN = 2;
41 static const int POPUPWIDTH = 18;
42 static const int POPUPHEIGHT = 23;
43
44
45 // ----------------------------------------------------------------------------
46 // wxComboBoxText: text control forwards events to combobox
47 // ----------------------------------------------------------------------------
48
49 class wxComboBoxText : public wxTextCtrl
50 {
51 public:
52 wxComboBoxText( wxComboBox * cb )
53 : wxTextCtrl( cb , 1 )
54 {
55 m_cb = cb;
56 }
57
58 protected:
59 void OnChar( wxKeyEvent& event )
60 {
61 if ( event.GetKeyCode() == WXK_RETURN )
62 {
63 wxString value = GetValue();
64
65 if ( m_cb->GetCount() == 0 )
66 {
67 // make Enter generate "selected" event if there is only one item
68 // in the combobox - without it, it's impossible to select it at
69 // all!
70 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
71 event.SetInt( 0 );
72 event.SetString( value );
73 event.SetEventObject( m_cb );
74 m_cb->GetEventHandler()->ProcessEvent( event );
75 }
76 else
77 {
78 // add the item to the list if it's not there yet
79 if ( m_cb->FindString(value) == wxNOT_FOUND )
80 {
81 m_cb->Append(value);
82 m_cb->SetStringSelection(value);
83
84 // and generate the selected event for it
85 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
86 event.SetInt( m_cb->GetCount() - 1 );
87 event.SetString( value );
88 event.SetEventObject( m_cb );
89 m_cb->GetEventHandler()->ProcessEvent( event );
90 }
91
92 // This will invoke the dialog default action, such
93 // as the clicking the default button.
94
95 wxWindow *parent = GetParent();
96 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
97 parent = parent->GetParent() ;
98 }
99 if ( parent && parent->GetDefaultItem() )
100 {
101 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
102 wxButton);
103 if ( def && def->IsEnabled() )
104 {
105 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
106 event.SetEventObject(def);
107 def->Command(event);
108 return ;
109 }
110 }
111
112 return;
113 }
114 }
115
116 event.Skip();
117 }
118
119 private:
120 wxComboBox *m_cb;
121
122 DECLARE_EVENT_TABLE()
123 };
124
125 BEGIN_EVENT_TABLE(wxComboBoxText, wxTextCtrl)
126 EVT_CHAR( wxComboBoxText::OnChar)
127 END_EVENT_TABLE()
128
129 class wxComboBoxChoice : public wxChoice
130 {
131 public:
132 wxComboBoxChoice(wxComboBox *cb, int style)
133 : wxChoice( cb , 1 )
134 {
135 m_cb = cb;
136 }
137
138 protected:
139 void OnChoice( wxCommandEvent& e )
140 {
141 wxString s = e.GetString();
142
143 m_cb->DelegateChoice( s );
144 wxCommandEvent event2(wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
145 event2.SetInt(m_cb->GetSelection());
146 event2.SetEventObject(m_cb);
147 event2.SetString(m_cb->GetStringSelection());
148 m_cb->ProcessCommand(event2);
149 }
150
151 private:
152 wxComboBox *m_cb;
153
154 DECLARE_EVENT_TABLE()
155 };
156
157 BEGIN_EVENT_TABLE(wxComboBoxChoice, wxChoice)
158 EVT_CHOICE(-1, wxComboBoxChoice::OnChoice)
159 END_EVENT_TABLE()
160
161 wxComboBox::~wxComboBox()
162 {
163 // delete client objects
164 FreeData();
165
166 // delete the controls now, don't leave them alive even though they would
167 // still be eventually deleted by our parent - but it will be too late, the
168 // user code expects them to be gone now
169 if (m_text != NULL) {
170 delete m_text;
171 m_text = NULL;
172 }
173 if (m_choice != NULL) {
174 delete m_choice;
175 m_choice = NULL;
176 }
177 }
178
179
180 // ----------------------------------------------------------------------------
181 // geometry
182 // ----------------------------------------------------------------------------
183
184 wxSize wxComboBox::DoGetBestSize() const
185 {
186 wxSize size = m_choice->GetBestSize();
187
188 if ( m_text != NULL )
189 {
190 wxSize sizeText = m_text->GetBestSize();
191
192 size.x = POPUPWIDTH + sizeText.x + MARGIN;
193 }
194
195 return size;
196 }
197
198 void wxComboBox::DoMoveWindow(int x, int y, int width, int height) {
199 height = POPUPHEIGHT;
200
201 wxControl::DoMoveWindow(x, y, width, height);
202
203 if ( m_text == NULL )
204 {
205 m_choice->SetSize(0, 0 , width, -1);
206 }
207 else
208 {
209 wxCoord wText = width - POPUPWIDTH - MARGIN;
210 m_text->SetSize(0, 0, wText, height);
211 m_choice->SetSize(0 + wText + MARGIN, 0, POPUPWIDTH, -1);
212 }
213 }
214
215
216
217 // ----------------------------------------------------------------------------
218 // operations forwarded to the subcontrols
219 // ----------------------------------------------------------------------------
220
221 bool wxComboBox::Enable(bool enable)
222 {
223 if ( !wxControl::Enable(enable) )
224 return false;
225
226 return true;
227 }
228
229 bool wxComboBox::Show(bool show)
230 {
231 if ( !wxControl::Show(show) )
232 return false;
233
234 return true;
235 }
236
237 void wxComboBox::SetFocus()
238 {
239 if ( m_text != NULL) {
240 m_text->SetFocus();
241 }
242 }
243
244
245 void wxComboBox::DelegateTextChanged( const wxString& value )
246 {
247 SetStringSelection( value );
248 }
249
250
251 void wxComboBox::DelegateChoice( const wxString& value )
252 {
253 SetStringSelection( value );
254 }
255
256
257 bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
258 const wxString& value,
259 const wxPoint& pos,
260 const wxSize& size,
261 const wxArrayString& choices,
262 long style,
263 const wxValidator& validator,
264 const wxString& name)
265 {
266 wxCArrayString chs( choices );
267
268 return Create( parent, id, value, pos, size, chs.GetCount(),
269 chs.GetStrings(), style, validator, name );
270 }
271
272
273 bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
274 const wxString& value,
275 const wxPoint& pos,
276 const wxSize& size,
277 int n, const wxString choices[],
278 long style,
279 const wxValidator& validator,
280 const wxString& name)
281 {
282 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style ,
283 wxDefaultValidator, name) )
284 {
285 return false;
286 }
287
288 m_choice = new wxComboBoxChoice(this, style );
289
290 wxSize csize = size;
291 if ( style & wxCB_READONLY )
292 {
293 m_text = NULL;
294 }
295 else
296 {
297 m_text = new wxComboBoxText(this);
298 if ( size.y == -1 ) {
299 csize.y = m_text->GetSize().y ;
300 }
301 }
302
303 DoSetSize(pos.x, pos.y, csize.x, csize.y);
304
305 for ( int i = 0 ; i < n ; i++ )
306 {
307 m_choice->DoAppend( choices[ i ] );
308 }
309
310 return true;
311 }
312
313 wxString wxComboBox::GetValue() const
314 {
315 wxString result;
316
317 if ( m_text == NULL )
318 {
319 result = m_choice->GetString( m_choice->GetSelection() );
320 }
321 else
322 {
323 result = m_text->GetValue();
324 }
325
326 return result;
327 }
328
329 void wxComboBox::SetValue(const wxString& value)
330 {
331 int s = FindString (value);
332 if (s == wxNOT_FOUND && !HasFlag(wxCB_READONLY) )
333 {
334 m_choice->Append(value) ;
335 }
336 SetStringSelection( value ) ;
337 }
338
339 // Clipboard operations
340 void wxComboBox::Copy()
341 {
342 if ( m_text != NULL )
343 {
344 m_text->Copy();
345 }
346 }
347
348 void wxComboBox::Cut()
349 {
350 if ( m_text != NULL )
351 {
352 m_text->Cut();
353 }
354 }
355
356 void wxComboBox::Paste()
357 {
358 if ( m_text != NULL )
359 {
360 m_text->Paste();
361 }
362 }
363
364 void wxComboBox::SetEditable(bool editable)
365 {
366 if ( ( m_text == NULL ) && editable )
367 {
368 m_text = new wxComboBoxText( this );
369 }
370 else if ( ( m_text != NULL ) && !editable )
371 {
372 delete m_text;
373 m_text = NULL;
374 }
375
376 int currentX, currentY;
377 GetPosition( &currentX, &currentY );
378
379 int currentW, currentH;
380 GetSize( &currentW, &currentH );
381
382 DoMoveWindow( currentX, currentY, currentW, currentH );
383 }
384
385 void wxComboBox::SetInsertionPoint(long pos)
386 {
387 // TODO
388 }
389
390 void wxComboBox::SetInsertionPointEnd()
391 {
392 // TODO
393 }
394
395 long wxComboBox::GetInsertionPoint() const
396 {
397 // TODO
398 return 0;
399 }
400
401 wxTextPos wxComboBox::GetLastPosition() const
402 {
403 // TODO
404 return 0;
405 }
406
407 void wxComboBox::Replace(long from, long to, const wxString& value)
408 {
409 // TODO
410 }
411
412 void wxComboBox::Remove(long from, long to)
413 {
414 // TODO
415 }
416
417 void wxComboBox::SetSelection(long from, long to)
418 {
419 // TODO
420 }
421
422 int wxComboBox::DoAppend(const wxString& item)
423 {
424 return m_choice->DoAppend( item ) ;
425 }
426
427 int wxComboBox::DoInsert(const wxString& item, int pos)
428 {
429 return m_choice->DoInsert( item , pos ) ;
430 }
431
432 void wxComboBox::DoSetItemClientData(int n, void* clientData)
433 {
434 return m_choice->DoSetItemClientData( n , clientData ) ;
435 }
436
437 void* wxComboBox::DoGetItemClientData(int n) const
438 {
439 return m_choice->DoGetItemClientData( n ) ;
440 }
441
442 void wxComboBox::DoSetItemClientObject(int n, wxClientData* clientData)
443 {
444 return m_choice->DoSetItemClientObject( n , clientData ) ;
445 }
446
447 wxClientData* wxComboBox::DoGetItemClientObject(int n) const
448 {
449 return m_choice->DoGetItemClientObject( n ) ;
450 }
451
452 void wxComboBox::FreeData()
453 {
454 if ( HasClientObjectData() )
455 {
456 size_t count = GetCount();
457 for ( size_t n = 0; n < count; n++ )
458 {
459 SetClientObject( n, NULL );
460 }
461 }
462 }
463
464 void wxComboBox::Delete(int n)
465 {
466 // force client object deletion
467 if( HasClientObjectData() )
468 SetClientObject( n, NULL );
469 m_choice->Delete( n );
470 }
471
472 void wxComboBox::Clear()
473 {
474 FreeData();
475 m_choice->Clear();
476 }
477
478 int wxComboBox::GetSelection() const
479 {
480 return m_choice->GetSelection();
481 }
482
483 void wxComboBox::SetSelection(int n)
484 {
485 m_choice->SetSelection( n );
486
487 if ( m_text != NULL )
488 {
489 m_text->SetValue( GetString( n ) );
490 }
491 }
492
493 int wxComboBox::FindString(const wxString& s) const
494 {
495 return m_choice->FindString( s );
496 }
497
498 wxString wxComboBox::GetString(int n) const
499 {
500 return m_choice->GetString( n );
501 }
502
503 wxString wxComboBox::GetStringSelection() const
504 {
505 int sel = GetSelection ();
506 if (sel > -1)
507 return wxString(this->GetString (sel));
508 else
509 return wxEmptyString;
510 }
511
512 void wxComboBox::SetString(int n, const wxString& s)
513 {
514 m_choice->SetString( n , s ) ;
515 }
516
517 bool wxComboBox::IsEditable() const
518 {
519 return m_text != NULL && !HasFlag(wxCB_READONLY);
520 }
521
522 void wxComboBox::Undo()
523 {
524 if (m_text != NULL)
525 m_text->Undo();
526 }
527
528 void wxComboBox::Redo()
529 {
530 if (m_text != NULL)
531 m_text->Redo();
532 }
533
534 void wxComboBox::SelectAll()
535 {
536 if (m_text != NULL)
537 m_text->SelectAll();
538 }
539
540 bool wxComboBox::CanCopy() const
541 {
542 if (m_text != NULL)
543 return m_text->CanCopy();
544 else
545 return false;
546 }
547
548 bool wxComboBox::CanCut() const
549 {
550 if (m_text != NULL)
551 return m_text->CanCut();
552 else
553 return false;
554 }
555
556 bool wxComboBox::CanPaste() const
557 {
558 if (m_text != NULL)
559 return m_text->CanPaste();
560 else
561 return false;
562 }
563
564 bool wxComboBox::CanUndo() const
565 {
566 if (m_text != NULL)
567 return m_text->CanUndo();
568 else
569 return false;
570 }
571
572 bool wxComboBox::CanRedo() const
573 {
574 if (m_text != NULL)
575 return m_text->CanRedo();
576 else
577 return false;
578 }
579
580 void wxComboBox::MacHandleControlClick( WXWidget WXUNUSED(control) , wxInt16 WXUNUSED(controlpart) , bool WXUNUSED(mouseStillDown))
581 {
582 wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, m_windowId );
583 event.SetInt(GetSelection());
584 event.SetEventObject(this);
585 event.SetString(GetStringSelection());
586 ProcessCommand(event);
587 }
588