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