EVT_IDLE_ONCE

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
Post Reply
Troels
Experienced Solver
Experienced Solver
Posts: 79
Joined: Fri Jan 07, 2005 12:02 pm
Location: Denmark

EVT_IDLE_ONCE

Post by Troels » Wed Feb 13, 2008 7:05 pm

This class is useful when you need to perform a task well after your dialog is shown and in position. The first time the idle event is fired is a good time to perform such a task. The class provided here takes care of the housekeeping, deactivates itself after the first idle, leaving you to just provide a OnIdleOnce event handler. You'll need to instantiate wxIdleOnceEvtHandler though, as shown below, but it then hooks itself up and deactivates itself automatically.

Code: Select all

class MyDialog : public wxDialog
{
   wxIdleOnceEvtHandler* m_idleonce;
   MyDialog() : wxDialog() { m_idleonce = new wxIdleOnceEvtHandler(this); }
   virtual ~MyDialog() { wxDELETE(m_idleonce) }
   void OnIdleOnce(wxIdleEvent&);
};
BEGIN_EVENT_TABLE(MyDialog, wxDialog)
   EVT_IDLE_ONCE(MyDialog::OnIdleOnce)
END_EVENT_TABLE()
First version of this little piece of code is in the Code Dump thread
"Paint background image in any wxWindow, an elegant way"
http://forums.wxwidgets.org/viewtopic.php?t=10019
Now it is calling Connect instead of overriding ProcessEvent.

Edit: PushEventHandler not needed when using Connect.

Code: Select all

/////////////////////////////////////////////////////////////////////////////
// wxIdleOnceEvtHandler by Troels K
// Thanks to Volker Bartheld and Belgabor.
//
// define a new handler type that will deal with the wxEVT_IDLE event when it arrives in the queue for the *FIRST* time 

class wxIdleOnceEvtHandler : public wxEvtHandler
{
public:
   wxEvtHandler* m_target;

   wxIdleOnceEvtHandler(wxEvtHandler* target);
   bool Disconnect(void);
   bool IsFired(void) const;
   virtual ~wxIdleOnceEvtHandler();
protected:
   void Connect();
   void OnIdle(wxIdleEvent&);
};

extern const wxEventType wxEVT_IDLE_ONCE;
#define EVT_IDLE_ONCE(func) wx__DECLARE_EVT0(wxEVT_IDLE_ONCE, wxIdleEventHandler(func))

Code: Select all

/////////////////////////////////////////////////////////////////////////////
// wxIdleOnceEvtHandler
//
// define a new handler type that will deal with the wxEVT_IDLE event when it arrives in the queue for the *FIRST* time

const wxEventType wxEVT_IDLE_ONCE = wxNewEventType();

wxIdleOnceEvtHandler::wxIdleOnceEvtHandler(wxEvtHandler* target) : wxEvtHandler(), m_target(target)
{
   wxASSERT(target);
   Connect();
}

wxIdleOnceEvtHandler::~wxIdleOnceEvtHandler()
{
   if (!IsFired()) Disconnect();
}

void wxIdleOnceEvtHandler::OnIdle(wxIdleEvent& event)
{
   Disconnect(); // stop the handler
   wxEvtHandler* target = m_target;
   m_target = NULL;
   wxEvent* temp = event.Clone(); // duplicate the event
   temp->SetEventType(wxEVT_IDLE_ONCE); // set correct event type
   ::wxPostEvent(target, *temp); // and reinsert it into parent's queue
   target->ProcessPendingEvents(); // Process now
   wxDELETE(temp)
   event.Skip();
}

bool wxIdleOnceEvtHandler::IsFired(void) const
{
   return (m_target == NULL);
}

void wxIdleOnceEvtHandler::Connect()
{
   m_target->Connect(wxID_ANY, wxEVT_IDLE,
            wxIdleEventHandler(wxIdleOnceEvtHandler::OnIdle),
            NULL, this);
}

bool wxIdleOnceEvtHandler::Disconnect()
{
   return m_target->Disconnect(wxID_ANY, wxEVT_IDLE,
            wxIdleEventHandler(wxIdleOnceEvtHandler::OnIdle),
            NULL, this);
}

Post Reply