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