+ wxLogMessage( wxT("SimpleTransientPopup::OnMouse pos(%d, %d)"), event.GetX(), event.GetY());
+ event.Skip();
+}
+
+// ----------------------------------------------------------------------------
+// ComplexTransientPopup
+// we push the event handler when the mouse isn't in the popup and
+// and pop the event handler when it is so that the child gets the events.
+// ----------------------------------------------------------------------------
+
+// Use EVT_IDLE to push and pop the handler, else use a wxTimer
+#define USE_TIMER_TO_PUSHPOP 0
+
+class ComplexTransientPopup : public SimpleTransientPopup
+{
+public:
+ ComplexTransientPopup(wxWindow *parent) : SimpleTransientPopup(parent)
+ {
+ Init();
+ }
+ virtual ~ComplexTransientPopup();
+
+ virtual void Popup(wxWindow *focus = NULL);
+ virtual void Dismiss();
+ virtual bool ProcessLeftDown(wxMouseEvent& event);
+
+protected:
+
+ // safely push and pop the event handler of the child
+ void PushPopupHandler(wxWindow* child);
+ void PopPopupHandler(wxWindow* child);
+
+ void OnMouse( wxMouseEvent& event );
+ void OnKeyDown( wxKeyEvent &event );
+
+#if USE_TIMER_TO_PUSHPOP
+ // start/stop timer that pushes and pops handler when the mouse goes over
+ // the scrollbars (if any) of the child window
+ void StartTimer();
+ void StopTimer();
+ void OnTimer( wxTimerEvent& event );
+ wxTimer *m_timer; // timer for tracking mouse position
+#else // !USE_TIMER_TO_PUSHPOP
+ void OnIdle( wxIdleEvent& event );
+#endif // USE_TIMER_TO_PUSHPOP
+
+ wxPoint m_mouse; // last/current mouse position
+ bool m_popped_handler; // state of the event handler
+
+private:
+ void Init();
+ DECLARE_EVENT_TABLE()
+};
+
+//----------------------------------------------------------------------------
+// ComplexTransientPopup
+//----------------------------------------------------------------------------
+BEGIN_EVENT_TABLE(ComplexTransientPopup, SimpleTransientPopup)
+ EVT_KEY_DOWN(ComplexTransientPopup::OnKeyDown)
+ EVT_MOUSE_EVENTS(ComplexTransientPopup::OnMouse)
+#if USE_TIMER_TO_PUSHPOP
+ EVT_TIMER( wxID_ANY, ComplexTransientPopup::OnTimer )
+#endif // USE_TIMER_TO_PUSHPOP
+END_EVENT_TABLE()
+
+void ComplexTransientPopup::Init()
+{
+#if USE_TIMER_TO_PUSHPOP
+ m_timer = NULL;
+#endif // USE_TIMER_TO_PUSHPOP
+ m_popped_handler = false;
+}
+
+ComplexTransientPopup::~ComplexTransientPopup()
+{
+#if USE_TIMER_TO_PUSHPOP
+ StopTimer();
+#endif // USE_TIMER_TO_PUSHPOP
+}
+
+void ComplexTransientPopup::PushPopupHandler(wxWindow* child)
+{
+ if (child && m_handlerPopup && m_popped_handler)
+ {
+ m_popped_handler = false;
+
+ if (child->GetEventHandler() != (wxEvtHandler*)m_handlerPopup)
+ child->PushEventHandler((wxEvtHandler*)m_handlerPopup);
+ if (!child->HasCapture())
+ child->CaptureMouse();
+
+ child->SetFocus();
+ }
+}
+void ComplexTransientPopup::PopPopupHandler(wxWindow* child)
+{
+ if (child && m_handlerPopup && !m_popped_handler)
+ {
+ m_popped_handler = true;
+
+ if (child->GetEventHandler() == (wxEvtHandler*)m_handlerPopup)
+ child->PopEventHandler(false);
+ if (child->HasCapture())
+ child->ReleaseMouse();
+
+ child->SetFocus();
+ }
+}
+
+#if USE_TIMER_TO_PUSHPOP
+void ComplexTransientPopup::OnTimer( wxTimerEvent &WXUNUSED(event) )
+{
+ if (!IsShown()) return;
+
+ m_mouse = ScreenToClient(wxGetMousePosition());
+
+ wxWindow *child = GetChild();
+ if (!child) return; // nothing to do
+
+ wxRect clientRect(wxPoint(0,0), GetClientSize());
+ wxLogMessage(wxT("CTW::OnTimer mouse(%d, %d), popped %d, m_handlerPopup %d"), m_mouse.x, m_mouse.y, m_popped_handler, m_handlerPopup);
+ // pop the event handler if inside the child window or
+ // restore the event handler if not in the child window
+ if (clientRect.Inside(m_mouse))
+ PopPopupHandler(child);
+ else
+ PushPopupHandler(child);
+}
+
+void ComplexTransientPopup::StartTimer()
+{
+ if (!m_timer)
+ m_timer = new wxTimer(this, wxID_ANY);
+
+ m_timer->Start(200, false);
+}
+
+void ComplexTransientPopup::StopTimer()
+{
+ if (m_timer)
+ {
+ if (m_timer->IsRunning())
+ m_timer->Stop();
+ delete m_timer;
+ m_timer = NULL;
+ }
+}
+
+#else // USE_TIMER_TO_PUSHPOP
+void ComplexTransientPopup::OnIdle( wxIdleEvent& event )
+{
+ if (IsShown())
+ {
+ m_mouse = ScreenToClient(wxGetMousePosition());
+ wxLogMessage(wxT("CTW::OnIdle mouse(%d, %d), popped %d, m_handlerPopup %d"), m_mouse.x, m_mouse.y, m_popped_handler, m_handlerPopup);
+
+ wxWindow *child = GetChild();
+ if (!child) return; // nothing to do
+
+ wxRect clientRect(wxPoint(0,0), GetClientSize());
+ //wxPrintf(wxT("**DropDownPopup::OnIdle mouse %d %d -- %d %d %d\n"), m_mouse.x, m_mouse.y, m_popped_handler, m_child, m_handlerPopup); fflush(stdout);
+ // pop the event handler if inside the child window or
+ // restore the event handler if not in the child window
+ if (clientRect.Inside(m_mouse))
+ PopPopupHandler(child);
+ else
+ PushPopupHandler(child);
+ }
+ event.Skip();
+}
+#endif // USE_TIMER_TO_PUSHPOP
+
+void ComplexTransientPopup::OnMouse( wxMouseEvent& event )
+{
+ m_mouse = event.GetPosition();