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: popup.cpp 41547 2006-10-02 05:36:31Z PC $
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
51enum
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//----------------------------------------------------------------------------
66class SimpleTransientPopup: public wxPopupTransientWindow
67{
68public:
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
80private:
81    wxScrolledWindow *m_panel;
82    wxButton *m_button;
83    wxSpinCtrl *m_spinCtrl;
84    wxStaticText *m_mouseText;
85
86private:
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
94private:
95    DECLARE_CLASS(SimpleTransientPopup)
96    DECLARE_EVENT_TABLE()
97};
98
99//----------------------------------------------------------------------------
100// SimpleTransientPopup
101//----------------------------------------------------------------------------
102IMPLEMENT_CLASS(SimpleTransientPopup,wxPopupTransientWindow)
103
104BEGIN_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 )
111END_EVENT_TABLE()
112
113SimpleTransientPopup::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("wx.PopupTransientWindow is a\n")
128                          wxT("wx.PopupWindow 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->SetAutoLayout( true );
146    m_panel->SetSizer( topSizer );
147    topSizer->Fit(m_panel);
148    topSizer->Fit(this);
149}
150
151SimpleTransientPopup::~SimpleTransientPopup()
152{
153}
154
155void SimpleTransientPopup::Popup(wxWindow *focus)
156{
157    wxLogMessage( wxT("0x%lx SimpleTransientPopup::Popup"), long(this) );
158    wxPopupTransientWindow::Popup(focus ? focus : m_panel);
159}
160
161void SimpleTransientPopup::OnDismiss()
162{
163    wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnDismiss"), long(this) );
164    wxPopupTransientWindow::OnDismiss();
165}
166
167bool SimpleTransientPopup::ProcessLeftDown(wxMouseEvent& event)
168{
169    wxLogMessage( wxT("0x%lx SimpleTransientPopup::ProcessLeftDown pos(%d, %d)"), long(this), event.GetX(), event.GetY());
170    return wxPopupTransientWindow::ProcessLeftDown(event);
171}
172bool SimpleTransientPopup::Show( bool show )
173{
174    wxLogMessage( wxT("0x%lx SimpleTransientPopup::Show %d"), long(this), int(show));
175    return wxPopupTransientWindow::Show(show);
176}
177
178void SimpleTransientPopup::OnSize(wxSizeEvent &event)
179{
180    wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnSize"), long(this) );
181    event.Skip();
182}
183
184void SimpleTransientPopup::OnSetFocus(wxFocusEvent &event)
185{
186    wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnSetFocus"), long(this) );
187    event.Skip();
188}
189
190void SimpleTransientPopup::OnKillFocus(wxFocusEvent &event)
191{
192    wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnKillFocus"), long(this) );
193    event.Skip();
194}
195
196void SimpleTransientPopup::OnMouse(wxMouseEvent &event)
197{
198    wxRect rect(m_mouseText->GetRect());
199    rect.SetX(-100000);
200    rect.SetWidth(1000000);
201    wxColour colour(*wxLIGHT_GREY);
202
203    if (rect.Contains(event.GetPosition()))
204    {
205        colour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
206    wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnMouse pos(%d, %d)"), 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
217void 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
230void SimpleTransientPopup::OnSpinCtrl(wxSpinEvent& event)
231{
232    wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnSpinCtrl ID %d Value %d"), long(this), event.GetId(), event.GetInt());
233    event.Skip();
234}
235
236// ----------------------------------------------------------------------------
237// private classes
238// ----------------------------------------------------------------------------
239
240class MyDialog : public wxDialog
241{
242public:
243    MyDialog(const wxString& title);
244
245    void OnStartSimplePopup(wxCommandEvent& event);
246    void OnStartScrolledPopup(wxCommandEvent& event);
247
248private:
249    SimpleTransientPopup *m_simplePopup;
250    SimpleTransientPopup *m_scrolledPopup;
251    DECLARE_EVENT_TABLE()
252};
253
254class MyFrame : public wxFrame
255{
256public:
257    MyFrame(const wxString& title);
258    virtual ~MyFrame();
259
260    void OnQuit(wxCommandEvent& event);
261    void OnAbout(wxCommandEvent& event);
262    void OnTestDialog(wxCommandEvent& event);
263    void OnStartSimplePopup(wxCommandEvent& event);
264    void OnStartScrolledPopup(wxCommandEvent& event);
265
266private:
267    SimpleTransientPopup *m_simplePopup;
268    SimpleTransientPopup *m_scrolledPopup;
269    wxTextCtrl *m_logWin;
270    wxLog *m_logOld;
271    DECLARE_EVENT_TABLE()
272};
273
274class MyApp : public wxApp
275{
276public:
277    virtual bool OnInit();
278
279    MyFrame *m_frame;
280};
281
282// ----------------------------------------------------------------------------
283// event tables and other macros for wxWidgets
284// ----------------------------------------------------------------------------
285
286
287IMPLEMENT_APP(MyApp)
288
289// 'Main program' equivalent: the program execution "starts" here
290bool MyApp::OnInit()
291{
292    // create the main application window
293    m_frame = new MyFrame(_T("Popup wxWidgets App"));
294
295    // and show it (the frames, unlike simple controls, are not shown when
296    // created initially)
297    m_frame->Show(true);
298
299    // success: wxApp::OnRun() will be called which will enter the main message
300    // loop and the application will run. If we returned false here, the
301    // application would exit immediately.
302    return true;
303}
304
305// ----------------------------------------------------------------------------
306// main frame
307// ----------------------------------------------------------------------------
308
309BEGIN_EVENT_TABLE(MyFrame, wxFrame)
310    EVT_MENU(Minimal_Quit,  MyFrame::OnQuit)
311    EVT_MENU(Minimal_About, MyFrame::OnAbout)
312    EVT_MENU(Minimal_TestDialog, MyFrame::OnTestDialog)
313    EVT_BUTTON(Minimal_StartSimplePopup, MyFrame::OnStartSimplePopup)
314    EVT_BUTTON(Minimal_StartScrolledPopup, MyFrame::OnStartScrolledPopup)
315END_EVENT_TABLE()
316
317MyFrame::MyFrame(const wxString& title)
318       : wxFrame(NULL, wxID_ANY, title)
319{
320    m_simplePopup = m_scrolledPopup = NULL;
321
322    SetIcon(wxICON(sample));
323
324#if wxUSE_MENUS
325    wxMenu *menuFile = new wxMenu;
326
327    // the "About" item should be in the help menu
328    wxMenu *helpMenu = new wxMenu;
329    helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dialog"));
330
331    menuFile->Append(Minimal_TestDialog, _T("&Test dialog\tAlt-T"), _T("Test dialog"));
332    menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
333
334    // now append the freshly created menu to the menu bar...
335    wxMenuBar *menuBar = new wxMenuBar();
336    menuBar->Append(menuFile, _T("&File"));
337    menuBar->Append(helpMenu, _T("&Help"));
338
339    // ... and attach this menu bar to the frame
340    SetMenuBar(menuBar);
341#endif // wxUSE_MENUS
342
343#if wxUSE_STATUSBAR
344    // create a status bar just for fun (by default with 1 pane only)
345    CreateStatusBar(2);
346    SetStatusText(_T("Welcome to wxWidgets!"));
347#endif // wxUSE_STATUSBAR
348
349    wxPanel *panel = new wxPanel(this, -1);
350    wxButton *button1 = new wxButton( panel, Minimal_StartSimplePopup, wxT("Show simple popup"), wxPoint(20,20) );
351    wxButton *button2 = new wxButton( panel, Minimal_StartScrolledPopup, wxT("Show scrolled popup"), wxPoint(20,70) );
352
353    m_logWin = new wxTextCtrl( panel, wxID_ANY, wxEmptyString, wxDefaultPosition,
354                               wxDefaultSize, wxTE_MULTILINE );
355    m_logWin->SetEditable(false);
356    wxLogTextCtrl* logger = new wxLogTextCtrl( m_logWin );
357    m_logOld = logger->SetActiveTarget( logger );
358    logger->SetTimestamp( NULL );
359
360    wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
361    topSizer->Add( button1, 0, wxALL, 5 );
362    topSizer->Add( button2, 0, wxALL, 5 );
363    topSizer->Add( m_logWin, 1, wxEXPAND|wxALL, 5 );
364
365    panel->SetAutoLayout( true );
366    panel->SetSizer( topSizer );
367
368}
369
370MyFrame::~MyFrame()
371{
372    delete wxLog::SetActiveTarget(m_logOld);
373}
374
375
376// event handlers
377
378void MyFrame::OnStartSimplePopup(wxCommandEvent& event)
379{
380    wxLogMessage( wxT("================================================") );
381    delete m_simplePopup;
382    m_simplePopup = new SimpleTransientPopup( this );
383    wxWindow *btn = (wxWindow*) event.GetEventObject();
384    wxPoint pos = btn->ClientToScreen( wxPoint(0,0) );
385    wxSize sz = btn->GetSize();
386    m_simplePopup->Position( pos, sz );
387    wxLogMessage( wxT("0x%lx Simple Popup Shown pos(%d, %d) size(%d, %d)"), long(m_simplePopup), pos.x, pos.y, sz.x, sz.y );
388    m_simplePopup->Popup();
389}
390
391void MyFrame::OnStartScrolledPopup(wxCommandEvent& event)
392{
393    wxLogMessage( wxT("================================================") );
394    delete m_scrolledPopup;
395    m_scrolledPopup = new SimpleTransientPopup( this );
396    m_scrolledPopup->GetChild()->SetScrollbars(1, 1, 1000, 1000);
397    wxWindow *btn = (wxWindow*) event.GetEventObject();
398    wxPoint pos = btn->ClientToScreen( wxPoint(0,0) );
399    wxSize sz = btn->GetSize();
400    m_scrolledPopup->Position( pos, sz );
401    wxLogMessage( wxT("0x%lx Scrolled Popup Shown pos(%d, %d) size(%d, %d)"), long(m_scrolledPopup), pos.x, pos.y, sz.x, sz.y );
402    m_scrolledPopup->Popup();
403}
404
405void MyFrame::OnTestDialog(wxCommandEvent& WXUNUSED(event))
406{
407    MyDialog dialog( wxT("Test") );
408    dialog.ShowModal();
409}
410
411void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
412{
413    // true is to force the frame to close
414    Close(true);
415}
416
417void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
418{
419    wxString msg;
420    msg.Printf( _T("This is the About dialog of the popup sample.\n")
421                _T("Welcome to %s"), wxVERSION_STRING);
422
423    wxMessageBox(msg, _T("About Popup"), wxOK | wxICON_INFORMATION, this);
424}
425
426// ----------------------------------------------------------------------------
427// test dialog
428// ----------------------------------------------------------------------------
429
430BEGIN_EVENT_TABLE(MyDialog, wxDialog)
431    EVT_BUTTON(Minimal_StartSimplePopup, MyDialog::OnStartSimplePopup)
432    EVT_BUTTON(Minimal_StartScrolledPopup, MyDialog::OnStartScrolledPopup)
433END_EVENT_TABLE()
434
435MyDialog::MyDialog(const wxString& title)
436         :wxDialog(NULL, wxID_ANY, title, wxPoint(50,50), wxSize(400,300))
437{
438    m_simplePopup = m_scrolledPopup = NULL;
439    wxPanel *panel = new wxPanel(this, -1);
440
441    wxButton *button1 = new wxButton( panel, Minimal_StartSimplePopup, wxT("Show simple popup"), wxPoint(20,20) );
442    wxButton *button2 = new wxButton( panel, Minimal_StartScrolledPopup, wxT("Show scrolled popup"), wxPoint(20,60) );
443
444    wxButton *okButton = new wxButton( panel, wxID_OK, wxT("OK"), wxPoint(20,200) );
445
446    wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
447    topSizer->Add( button1, 0, wxALL, 5 );
448    topSizer->Add( button2, 0, wxALL, 5 );
449    topSizer->AddSpacer(40);
450    topSizer->Add( okButton, 0, wxALL, 5 );
451
452    panel->SetAutoLayout( true );
453    panel->SetSizer( topSizer );
454    topSizer->Fit(this);
455}
456
457void MyDialog::OnStartSimplePopup(wxCommandEvent& event)
458{
459    wxLogMessage( wxT("================================================") );
460    delete m_simplePopup;
461    m_simplePopup = new SimpleTransientPopup( this );
462    wxWindow *btn = (wxWindow*) event.GetEventObject();
463    wxPoint pos = btn->ClientToScreen( wxPoint(0,0) );
464    wxSize sz = btn->GetSize();
465    m_simplePopup->Position( pos, sz );
466    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 );
467    m_simplePopup->Popup();
468}
469
470void MyDialog::OnStartScrolledPopup(wxCommandEvent& event)
471{
472    wxLogMessage( wxT("================================================") );
473    delete m_scrolledPopup;
474    m_scrolledPopup = new SimpleTransientPopup( this );
475    m_scrolledPopup->GetChild()->SetScrollbars(1, 1, 1000, 1000);
476    wxWindow *btn = (wxWindow*) event.GetEventObject();
477    wxPoint pos = btn->ClientToScreen( wxPoint(0,0) );
478    wxSize sz = btn->GetSize();
479    m_scrolledPopup->Position( pos, sz );
480    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 );
481    m_scrolledPopup->Popup();
482}
483