Add wxControl::GetSizeFromTextSize() to size the control to its text.
[wxWidgets.git] / samples / popup / popup.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: popup.cpp
3 // Purpose: Popup wxWidgets sample
4 // Author: Robert Roebling
5 // Modified by:
6 // Created: 2005-02-04
7 // RCS-ID: $Id$
8 // Copyright: (c) 2005 Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers)
29 #ifndef WX_PRECOMP
30 #include "wx/wx.h"
31 #endif
32
33 #include "wx/popupwin.h"
34 #include "wx/spinctrl.h"
35
36 // ----------------------------------------------------------------------------
37 // resources
38 // ----------------------------------------------------------------------------
39
40 // the application icon (under Windows and OS/2 it is in resources and even
41 // though we could still include the XPM here it would be unused)
42 #ifndef wxHAS_IMAGES_IN_RESOURCES
43 #include "../sample.xpm"
44 #endif
45
46 // ----------------------------------------------------------------------------
47 // constants
48 // ----------------------------------------------------------------------------
49
50 // IDs for the controls and the menu commands
51 enum
52 {
53 Minimal_Quit = wxID_EXIT,
54 Minimal_About = wxID_ABOUT,
55 Minimal_TestDialog,
56 Minimal_StartSimplePopup,
57 Minimal_StartScrolledPopup,
58 Minimal_LogWindow,
59 Minimal_PopupButton,
60 Minimal_PopupSpinctrl
61 };
62
63 //----------------------------------------------------------------------------
64 // SimpleTransientPopup
65 //----------------------------------------------------------------------------
66 class SimpleTransientPopup: public wxPopupTransientWindow
67 {
68 public:
69 SimpleTransientPopup( wxWindow *parent );
70 virtual ~SimpleTransientPopup();
71
72 // wxPopupTransientWindow virtual methods are all overridden to log them
73 virtual void Popup(wxWindow *focus = NULL);
74 virtual void OnDismiss();
75 virtual bool ProcessLeftDown(wxMouseEvent& event);
76 virtual bool Show( bool show = true );
77
78 wxScrolledWindow* GetChild() { return m_panel; }
79
80 private:
81 wxScrolledWindow *m_panel;
82 wxButton *m_button;
83 wxSpinCtrl *m_spinCtrl;
84 wxStaticText *m_mouseText;
85
86 private:
87 void OnMouse( wxMouseEvent &event );
88 void OnSize( wxSizeEvent &event );
89 void OnSetFocus( wxFocusEvent &event );
90 void OnKillFocus( wxFocusEvent &event );
91 void OnButton( wxCommandEvent& event );
92 void OnSpinCtrl( wxSpinEvent& event );
93
94 private:
95 DECLARE_CLASS(SimpleTransientPopup)
96 DECLARE_EVENT_TABLE()
97 };
98
99 //----------------------------------------------------------------------------
100 // SimpleTransientPopup
101 //----------------------------------------------------------------------------
102 IMPLEMENT_CLASS(SimpleTransientPopup,wxPopupTransientWindow)
103
104 BEGIN_EVENT_TABLE(SimpleTransientPopup,wxPopupTransientWindow)
105 EVT_MOUSE_EVENTS( SimpleTransientPopup::OnMouse )
106 EVT_SIZE( SimpleTransientPopup::OnSize )
107 EVT_SET_FOCUS( SimpleTransientPopup::OnSetFocus )
108 EVT_KILL_FOCUS( SimpleTransientPopup::OnKillFocus )
109 EVT_BUTTON( Minimal_PopupButton, SimpleTransientPopup::OnButton )
110 EVT_SPINCTRL( Minimal_PopupSpinctrl, SimpleTransientPopup::OnSpinCtrl )
111 END_EVENT_TABLE()
112
113 SimpleTransientPopup::SimpleTransientPopup( wxWindow *parent )
114 :wxPopupTransientWindow( parent )
115 {
116 m_panel = new wxScrolledWindow( this, wxID_ANY );
117 m_panel->SetBackgroundColour( *wxLIGHT_GREY );
118
119 // Keep this code to verify if mouse events work, they're required if
120 // you're making a control like a combobox where the items are highlighted
121 // under the cursor, the m_panel is set focus in the Popup() function
122 m_panel->Connect(wxEVT_MOTION,
123 wxMouseEventHandler(SimpleTransientPopup::OnMouse),
124 NULL, this);
125
126 wxStaticText *text = new wxStaticText( m_panel, wxID_ANY,
127 wxT("wxPopupTransientWindow is a\n")
128 wxT("wxPopupWindow which disappears\n")
129 wxT("automatically when the user\n")
130 wxT("clicks the mouse outside it or if it\n")
131 wxT("(or its first child) loses focus in \n")
132 wxT("any other way.") );
133
134 m_button = new wxButton(m_panel, Minimal_PopupButton, wxT("Press Me"));
135 m_spinCtrl = new wxSpinCtrl(m_panel, Minimal_PopupSpinctrl, wxT("Hello"));
136 m_mouseText = new wxStaticText(m_panel, wxID_ANY,
137 wxT("<- Test Mouse ->"));
138
139 wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
140 topSizer->Add( text, 0, wxALL, 5 );
141 topSizer->Add( m_button, 0, wxALL, 5 );
142 topSizer->Add( m_spinCtrl, 0, wxALL, 5 );
143 topSizer->Add( m_mouseText, 0, wxCENTRE|wxALL, 5 );
144
145 m_panel->SetSizer( topSizer );
146 topSizer->Fit(m_panel);
147 topSizer->Fit(this);
148 }
149
150 SimpleTransientPopup::~SimpleTransientPopup()
151 {
152 }
153
154 void SimpleTransientPopup::Popup(wxWindow* WXUNUSED(focus))
155 {
156 wxLogMessage( wxT("0x%lx SimpleTransientPopup::Popup"), long(this) );
157 wxPopupTransientWindow::Popup();
158 }
159
160 void SimpleTransientPopup::OnDismiss()
161 {
162 wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnDismiss"), long(this) );
163 wxPopupTransientWindow::OnDismiss();
164 }
165
166 bool SimpleTransientPopup::ProcessLeftDown(wxMouseEvent& event)
167 {
168 wxLogMessage( wxT("0x%lx SimpleTransientPopup::ProcessLeftDown pos(%d, %d)"), long(this), event.GetX(), event.GetY());
169 return wxPopupTransientWindow::ProcessLeftDown(event);
170 }
171 bool SimpleTransientPopup::Show( bool show )
172 {
173 wxLogMessage( wxT("0x%lx SimpleTransientPopup::Show %d"), long(this), int(show));
174 return wxPopupTransientWindow::Show(show);
175 }
176
177 void SimpleTransientPopup::OnSize(wxSizeEvent &event)
178 {
179 wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnSize"), long(this) );
180 event.Skip();
181 }
182
183 void SimpleTransientPopup::OnSetFocus(wxFocusEvent &event)
184 {
185 wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnSetFocus"), long(this) );
186 event.Skip();
187 }
188
189 void SimpleTransientPopup::OnKillFocus(wxFocusEvent &event)
190 {
191 wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnKillFocus"), long(this) );
192 event.Skip();
193 }
194
195 void SimpleTransientPopup::OnMouse(wxMouseEvent &event)
196 {
197 wxRect rect(m_mouseText->GetRect());
198 rect.SetX(-100000);
199 rect.SetWidth(1000000);
200 wxColour colour(*wxLIGHT_GREY);
201
202 if (rect.Contains(event.GetPosition()))
203 {
204 colour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
205 wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnMouse pos(%d, %d)"),
206 long(event.GetEventObject()), event.GetX(), event.GetY());
207 }
208
209 if (colour != m_mouseText->GetBackgroundColour())
210 {
211 m_mouseText->SetBackgroundColour(colour);
212 m_mouseText->Refresh();
213 }
214 event.Skip();
215 }
216
217 void SimpleTransientPopup::OnButton(wxCommandEvent& event)
218 {
219 wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnButton ID %d"), long(this), event.GetId());
220
221 wxButton *button = wxDynamicCast(event.GetEventObject(), wxButton);
222 if (button->GetLabel() == wxT("Press Me"))
223 button->SetLabel(wxT("Pressed"));
224 else
225 button->SetLabel(wxT("Press Me"));
226
227 event.Skip();
228 }
229
230 void SimpleTransientPopup::OnSpinCtrl(wxSpinEvent& event)
231 {
232 wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnSpinCtrl ID %d Value %d"),
233 long(this), event.GetId(), event.GetInt());
234 event.Skip();
235 }
236
237 // ----------------------------------------------------------------------------
238 // private classes
239 // ----------------------------------------------------------------------------
240
241 class MyDialog : public wxDialog
242 {
243 public:
244 MyDialog(const wxString& title);
245
246 void OnStartSimplePopup(wxCommandEvent& event);
247 void OnStartScrolledPopup(wxCommandEvent& event);
248
249 private:
250 SimpleTransientPopup *m_simplePopup;
251 SimpleTransientPopup *m_scrolledPopup;
252 DECLARE_EVENT_TABLE()
253 };
254
255 class MyFrame : public wxFrame
256 {
257 public:
258 MyFrame(const wxString& title);
259 virtual ~MyFrame();
260
261 void OnQuit(wxCommandEvent& event);
262 void OnAbout(wxCommandEvent& event);
263 void OnTestDialog(wxCommandEvent& event);
264 void OnStartSimplePopup(wxCommandEvent& event);
265 void OnStartScrolledPopup(wxCommandEvent& event);
266 void OnActivate(wxActivateEvent& event);
267
268 private:
269 SimpleTransientPopup *m_simplePopup;
270 SimpleTransientPopup *m_scrolledPopup;
271 wxTextCtrl *m_logWin;
272 wxLog *m_logOld;
273 DECLARE_EVENT_TABLE()
274 };
275
276 class MyApp : public wxApp
277 {
278 public:
279 virtual bool OnInit();
280
281 MyFrame *m_frame;
282 };
283
284 // ----------------------------------------------------------------------------
285 // event tables and other macros for wxWidgets
286 // ----------------------------------------------------------------------------
287
288
289 IMPLEMENT_APP(MyApp)
290
291 // 'Main program' equivalent: the program execution "starts" here
292 bool MyApp::OnInit()
293 {
294 if ( !wxApp::OnInit() )
295 return false;
296
297 // create the main application window
298 m_frame = new MyFrame(wxT("Popup wxWidgets App"));
299
300 // and show it (the frames, unlike simple controls, are not shown when
301 // created initially)
302 m_frame->Show(true);
303
304 // success: wxApp::OnRun() will be called which will enter the main message
305 // loop and the application will run. If we returned false here, the
306 // application would exit immediately.
307 return true;
308 }
309
310 // ----------------------------------------------------------------------------
311 // main frame
312 // ----------------------------------------------------------------------------
313
314 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
315 EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
316 EVT_MENU(Minimal_About, MyFrame::OnAbout)
317 EVT_MENU(Minimal_TestDialog, MyFrame::OnTestDialog)
318 EVT_ACTIVATE(MyFrame::OnActivate)
319 EVT_BUTTON(Minimal_StartSimplePopup, MyFrame::OnStartSimplePopup)
320 EVT_BUTTON(Minimal_StartScrolledPopup, MyFrame::OnStartScrolledPopup)
321 END_EVENT_TABLE()
322
323 MyFrame::MyFrame(const wxString& title)
324 : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(500,300))
325 {
326 m_simplePopup = m_scrolledPopup = NULL;
327
328 SetIcon(wxICON(sample));
329
330 #if wxUSE_MENUS
331 wxMenu *menuFile = new wxMenu;
332
333 // the "About" item should be in the help menu
334 wxMenu *helpMenu = new wxMenu;
335 helpMenu->Append(Minimal_About, wxT("&About\tF1"), wxT("Show about dialog"));
336
337 menuFile->Append(Minimal_TestDialog, wxT("&Test dialog\tAlt-T"), wxT("Test dialog"));
338 menuFile->Append(Minimal_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
339
340 // now append the freshly created menu to the menu bar...
341 wxMenuBar *menuBar = new wxMenuBar();
342 menuBar->Append(menuFile, wxT("&File"));
343 menuBar->Append(helpMenu, wxT("&Help"));
344
345 // ... and attach this menu bar to the frame
346 SetMenuBar(menuBar);
347 #endif // wxUSE_MENUS
348
349 #if wxUSE_STATUSBAR
350 // create a status bar just for fun (by default with 1 pane only)
351 CreateStatusBar(2);
352 SetStatusText(wxT("Welcome to wxWidgets!"));
353 #endif // wxUSE_STATUSBAR
354
355 wxPanel *panel = new wxPanel(this, -1);
356 wxButton *button1 = new wxButton( panel, Minimal_StartSimplePopup, wxT("Show simple popup"), wxPoint(20,20) );
357 wxButton *button2 = new wxButton( panel, Minimal_StartScrolledPopup, wxT("Show scrolled popup"), wxPoint(20,70) );
358
359 m_logWin = new wxTextCtrl( panel, wxID_ANY, wxEmptyString, wxDefaultPosition,
360 wxDefaultSize, wxTE_MULTILINE );
361 m_logWin->SetEditable(false);
362 wxLogTextCtrl* logger = new wxLogTextCtrl( m_logWin );
363 m_logOld = logger->SetActiveTarget( logger );
364 logger->DisableTimestamp();
365
366 wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
367 topSizer->Add( button1, 0, wxALL, 5 );
368 topSizer->Add( button2, 0, wxALL, 5 );
369 topSizer->Add( m_logWin, 1, wxEXPAND|wxALL, 5 );
370
371 panel->SetSizer( topSizer );
372
373 }
374
375 MyFrame::~MyFrame()
376 {
377 delete wxLog::SetActiveTarget(m_logOld);
378 }
379
380
381 // event handlers
382
383 void MyFrame::OnActivate(wxActivateEvent& WXUNUSED(event))
384 {
385 wxLogMessage( wxT("In activate...") );
386 }
387
388 void MyFrame::OnStartSimplePopup(wxCommandEvent& event)
389 {
390 wxLogMessage( wxT("================================================") );
391 delete m_simplePopup;
392 m_simplePopup = new SimpleTransientPopup( this );
393 wxWindow *btn = (wxWindow*) event.GetEventObject();
394 wxPoint pos = btn->ClientToScreen( wxPoint(0,0) );
395 wxSize sz = btn->GetSize();
396 m_simplePopup->Position( pos, sz );
397 wxLogMessage( wxT("0x%lx Simple Popup Shown pos(%d, %d) size(%d, %d)"), long(m_simplePopup), pos.x, pos.y, sz.x, sz.y );
398 m_simplePopup->Popup();
399 }
400
401 void MyFrame::OnStartScrolledPopup(wxCommandEvent& event)
402 {
403 wxLogMessage( wxT("================================================") );
404 delete m_scrolledPopup;
405 m_scrolledPopup = new SimpleTransientPopup( this );
406 m_scrolledPopup->GetChild()->SetScrollbars(1, 1, 1000, 1000);
407 wxWindow *btn = (wxWindow*) event.GetEventObject();
408 wxPoint pos = btn->ClientToScreen( wxPoint(0,0) );
409 wxSize sz = btn->GetSize();
410 m_scrolledPopup->Position( pos, sz );
411 wxLogMessage( wxT("0x%lx Scrolled Popup Shown pos(%d, %d) size(%d, %d)"), long(m_scrolledPopup), pos.x, pos.y, sz.x, sz.y );
412 m_scrolledPopup->Popup();
413 }
414
415 void MyFrame::OnTestDialog(wxCommandEvent& WXUNUSED(event))
416 {
417 MyDialog dialog( wxT("Test") );
418 dialog.ShowModal();
419 }
420
421 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
422 {
423 // true is to force the frame to close
424 Close(true);
425 }
426
427 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
428 {
429 wxString msg;
430 msg.Printf( wxT("This is the About dialog of the popup sample.\n")
431 wxT("Welcome to %s"), wxVERSION_STRING);
432
433 wxMessageBox(msg, wxT("About Popup"), wxOK | wxICON_INFORMATION, this);
434 }
435
436 // ----------------------------------------------------------------------------
437 // test dialog
438 // ----------------------------------------------------------------------------
439
440 BEGIN_EVENT_TABLE(MyDialog, wxDialog)
441 EVT_BUTTON(Minimal_StartSimplePopup, MyDialog::OnStartSimplePopup)
442 EVT_BUTTON(Minimal_StartScrolledPopup, MyDialog::OnStartScrolledPopup)
443 END_EVENT_TABLE()
444
445 MyDialog::MyDialog(const wxString& title)
446 :wxDialog(NULL, wxID_ANY, title, wxPoint(50,50), wxSize(400,300))
447 {
448 m_simplePopup = m_scrolledPopup = NULL;
449 wxPanel *panel = new wxPanel(this, -1);
450
451 wxButton *button1 = new wxButton( panel, Minimal_StartSimplePopup, wxT("Show simple popup"), wxPoint(20,20) );
452 wxButton *button2 = new wxButton( panel, Minimal_StartScrolledPopup, wxT("Show scrolled popup"), wxPoint(20,60) );
453
454 wxButton *okButton = new wxButton( panel, wxID_OK, wxT("OK"), wxPoint(20,200) );
455
456 wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
457 topSizer->Add( button1, 0, wxALL, 5 );
458 topSizer->Add( button2, 0, wxALL, 5 );
459 topSizer->AddSpacer(40);
460 topSizer->Add( okButton, 0, wxALL, 5 );
461
462 panel->SetSizerAndFit( topSizer );
463 }
464
465 void MyDialog::OnStartSimplePopup(wxCommandEvent& event)
466 {
467 wxLogMessage( wxT("================================================") );
468 delete m_simplePopup;
469 m_simplePopup = new SimpleTransientPopup( this );
470 wxWindow *btn = (wxWindow*) event.GetEventObject();
471 wxPoint pos = btn->ClientToScreen( wxPoint(0,0) );
472 wxSize sz = btn->GetSize();
473 m_simplePopup->Position( pos, sz );
474 wxLogMessage( wxT("0x%lx Dialog Simple Popup Shown pos(%d, %d) size(%d, %d)"), long(m_simplePopup), pos.x, pos.y, sz.x, sz.y );
475 m_simplePopup->Popup();
476 }
477
478 void MyDialog::OnStartScrolledPopup(wxCommandEvent& event)
479 {
480 wxLogMessage( wxT("================================================") );
481 delete m_scrolledPopup;
482 m_scrolledPopup = new SimpleTransientPopup( this );
483 m_scrolledPopup->GetChild()->SetScrollbars(1, 1, 1000, 1000);
484 wxWindow *btn = (wxWindow*) event.GetEventObject();
485 wxPoint pos = btn->ClientToScreen( wxPoint(0,0) );
486 wxSize sz = btn->GetSize();
487 m_scrolledPopup->Position( pos, sz );
488 wxLogMessage( wxT("0x%lx Dialog Scrolled Popup Shown pos(%d, %d) size(%d, %d)"), long(m_scrolledPopup), pos.x, pos.y, sz.x, sz.y );
489 m_scrolledPopup->Popup();
490 }