00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "wx/wxprec.h"
00012
00013 #ifdef __BORLANDC__
00014 #pragma hdrstop
00015 #endif
00016
00017 #ifndef WX_PRECOMP
00018 #include "wx/wx.h"
00019 #endif // WX_PRECOMP
00020
00021 #include "wxlua/include/wxlcallb.h"
00022
00023
00024
00025
00026 IMPLEMENT_ABSTRACT_CLASS(wxLuaEventCallback, wxObject)
00027
00028 wxLuaEventCallback::wxLuaEventCallback()
00029 : m_luafunc_ref(0),
00030 m_evtHandler(NULL), m_id(wxID_ANY), m_last_id(wxID_ANY),
00031 m_wxlBindEvent(NULL)
00032 {
00033 }
00034
00035 wxLuaEventCallback::~wxLuaEventCallback()
00036 {
00037
00038 if (m_wxlState.Ok())
00039 {
00040 m_wxlState.wxluaR_Unref(m_luafunc_ref, &wxlua_lreg_refs_key);
00041
00042 m_wxlState.RemoveTrackedEventCallback(this);
00043 }
00044 }
00045
00046 wxString wxLuaEventCallback::Connect(const wxLuaState& wxlState, int lua_func_stack_idx,
00047 wxWindowID win_id, wxWindowID last_id,
00048 wxEventType eventType, wxEvtHandler *evtHandler)
00049 {
00050
00051 wxCHECK_MSG(evtHandler != NULL, wxT("Invalid wxEvtHandler in wxLuaEventCallback::Connect()"), wxT("Invalid wxEvtHandler in wxLuaEventCallback::Connect()"));
00052 wxCHECK_MSG((m_evtHandler == NULL) && (m_luafunc_ref == 0), wxT("Attempting to reconnect a wxLuaEventCallback"), wxT("Attempting to reconnect a wxLuaEventCallback"));
00053 wxCHECK_MSG(wxlState.Ok(), wxT("Invalid wxLuaState"), wxT("Invalid wxLuaState"));
00054
00055 m_wxlState = wxlState;
00056 m_evtHandler = evtHandler;
00057 m_id = win_id;
00058 m_last_id = last_id;
00059
00060 m_wxlBindEvent = wxlState.GetBindEvent(eventType);
00061
00062
00063
00064 if (m_wxlBindEvent == NULL)
00065 {
00066 return wxString::Format(wxT("wxLua: Invalid or unknown wxEventType for wxEvtHandler::Connect() : %d, winIds %d, %d."),
00067 (int)eventType, win_id, last_id);
00068 }
00069
00070 m_wxlState.AddTrackedEventCallback(this);
00071
00072
00073 if (lua_func_stack_idx != WXLUAEVENTCALLBACK_NOROUTINE)
00074 m_luafunc_ref = m_wxlState.wxluaR_Ref(lua_func_stack_idx, &wxlua_lreg_refs_key);
00075
00076
00077
00078
00079 m_evtHandler->Connect(win_id, last_id, eventType,
00080 (wxObjectEventFunction)&wxLuaEventCallback::OnAllEvents,
00081 this);
00082 return wxEmptyString;
00083 }
00084
00085 void wxLuaEventCallback::ClearwxLuaState()
00086 {
00087 m_wxlState.UnRef();
00088 }
00089
00090 wxString wxLuaEventCallback::GetInfo() const
00091 {
00092 return wxString::Format(wxT("%s(%d) -> wxLuaEventCallback(%p, ids %d, %d)|wxEvtHandler(%p) -> %s : %s"),
00093 lua2wx(m_wxlBindEvent ? m_wxlBindEvent->name : "?").c_str(), (int)GetEventType(),
00094 this, m_id, m_last_id,
00095 m_evtHandler, m_evtHandler->GetClassInfo()->GetClassName(),
00096 m_wxlState.GetwxLuaTypeName(*m_wxlBindEvent->wxluatype).c_str());
00097 }
00098
00099 void wxLuaEventCallback::OnAllEvents(wxEvent& event)
00100 {
00101 wxEventType evtType = event.GetEventType();
00102
00103
00104
00105 wxLuaEventCallback *theCallback = (wxLuaEventCallback *)event.m_callbackUserData;
00106 wxCHECK_RET(theCallback != NULL, wxT("Invalid wxLuaEventCallback in wxEvent user data"));
00107
00108
00109 wxLuaState wxlState(theCallback->GetwxLuaState());
00110 if (wxlState.Ok())
00111 {
00112 wxlState.SetInEventType(evtType);
00113 theCallback->OnEvent(&event);
00114 wxlState.SetInEventType(wxEVT_NULL);
00115 }
00116
00117
00118 if (evtType == wxEVT_DESTROY)
00119 event.Skip(true);
00120 }
00121
00122 void wxLuaEventCallback::OnEvent(wxEvent *event)
00123 {
00124
00125
00126
00127 if (!m_wxlState.Ok())
00128 return;
00129
00130
00131 wxLuaState wxlState(m_wxlState);
00132
00133 int event_wxl_type = WXLUA_TUNKNOWN;
00134
00135
00136 if (m_wxlBindEvent != NULL)
00137 {
00138 event_wxl_type = *m_wxlBindEvent->wxluatype;
00139
00140
00141
00142
00143 if ((strcmp(m_wxlBindEvent->name, "wxScrollEvent") == 0) &&
00144 (event->GetClassInfo()->GetClassName() == wxString(wxT("wxSpinEvent"))))
00145 {
00146 const wxLuaBindClass *wxlClass = wxlState.GetBindClass("wxSpinEvent");
00147 if (wxlClass != NULL)
00148 event_wxl_type = *wxlClass->wxluatype;
00149 else
00150 event_wxl_type = *p_wxluatype_wxEvent;
00151 }
00152 }
00153 else
00154 event_wxl_type = *p_wxluatype_wxEvent;
00155
00156
00157 wxCHECK_RET(event_wxl_type != WXLUA_TUNKNOWN, wxT("Unknown wxEvent wxLua tag for : ") + wxString(event->GetClassInfo()->GetClassName()));
00158
00159 wxlState.lua_CheckStack(LUA_MINSTACK);
00160 int oldTop = wxlState.lua_GetTop();
00161 if (wxlState.wxluaR_GetRef(m_luafunc_ref, &wxlua_lreg_refs_key))
00162 {
00163 wxlState.lua_PushValue(LUA_GLOBALSINDEX);
00164 if (wxlState.lua_SetFenv(-2) != 0)
00165 {
00166
00167
00168
00169 wxlState.wxluaT_PushUserDataType(event, event_wxl_type, false);
00170 wxlState.LuaPCall(1, 0);
00171 }
00172 else
00173 wxlState.wxlua_Error("wxLua: wxEvtHandler::Connect() in wxLuaEventCallback::OnEvent(), function is not a Lua function.");
00174 }
00175 else
00176 wxlState.wxlua_Error("wxLua: wxEvtHandler::Connect() in wxLuaEventCallback::OnEvent(), function to call is not refed.");
00177
00178 wxlState.lua_SetTop(oldTop);
00179 }
00180
00181
00182
00183
00184 IMPLEMENT_ABSTRACT_CLASS(wxLuaWinDestroyCallback, wxObject)
00185
00186 wxLuaWinDestroyCallback::wxLuaWinDestroyCallback(const wxLuaState& wxlState,
00187 wxWindow* win)
00188 :m_wxlState(wxlState), m_window(win)
00189 {
00190 wxCHECK_RET(m_wxlState.Ok(), wxT("Invalid wxLuaState"));
00191 wxCHECK_RET(m_window != NULL, wxT("Invalid wxWindow"));
00192
00193 m_wxlState.AddTrackedWinDestroyCallback(this);
00194
00195
00196 m_window->Connect(m_window->GetId(), wxEVT_DESTROY,
00197 (wxObjectEventFunction)&wxLuaWinDestroyCallback::OnAllDestroyEvents,
00198 this);
00199 }
00200
00201 wxLuaWinDestroyCallback::~wxLuaWinDestroyCallback()
00202 {
00203 if (m_wxlState.Ok())
00204 {
00205 m_wxlState.RemoveTrackedWinDestroyCallback(this);
00206 m_wxlState.RemoveTrackedWindow(m_window);
00207 }
00208 }
00209
00210 void wxLuaWinDestroyCallback::ClearwxLuaState()
00211 {
00212 m_wxlState.UnRef();
00213 }
00214
00215 wxString wxLuaWinDestroyCallback::GetInfo() const
00216 {
00217 wxString winName(wxT("wxWindow?"));
00218 if (m_window && m_window->GetClassInfo())
00219 winName = m_window->GetClassInfo()->GetClassName();
00220
00221 return wxString::Format(wxT("%s(%p, id=%d)|wxLuaDestroyCallback(%p)"),
00222 winName.c_str(), m_window, m_window ? m_window->GetId() : -1,
00223 this);
00224 }
00225
00226 void wxLuaWinDestroyCallback::OnAllDestroyEvents(wxWindowDestroyEvent& event)
00227 {
00228
00229 wxLuaWinDestroyCallback *theCallback = (wxLuaWinDestroyCallback *)event.m_callbackUserData;
00230 if (theCallback && (((wxWindow*)event.GetEventObject()) == theCallback->m_window))
00231 {
00232 theCallback->OnDestroy(event);
00233 }
00234 else
00235 event.Skip();
00236 }
00237
00238 void wxLuaWinDestroyCallback::OnDestroy(wxWindowDestroyEvent& event)
00239 {
00240 event.Skip();
00241
00242
00243
00244
00245
00246 if (m_wxlState.Ok())
00247 {
00248 lua_State* L = m_wxlState.GetLuaState();
00249
00250
00251 wxluaO_untrackweakobject(L, NULL, m_window);
00252 wxlua_removederivedmethods(L, m_window);
00253
00254
00255 m_wxlState.RemoveTrackedWindow(m_window);
00256
00257 wxEvtHandler* evtHandler = m_window->GetEventHandler();
00258
00259
00260
00261
00262
00263
00264
00265 lua_pushlightuserdata(L, &wxlua_lreg_evtcallbacks_key);
00266 lua_rawget(L, LUA_REGISTRYINDEX);
00267
00268 lua_pushnil(L);
00269 while (lua_next(L, -2) != 0)
00270 {
00271
00272 wxLuaEventCallback* wxlCallback = (wxLuaEventCallback*)lua_touserdata(L, -2);
00273 wxCHECK_RET(wxlCallback, wxT("Invalid wxLuaEventCallback"));
00274
00275 if ((wxlCallback->GetEvtHandler() == evtHandler) ||
00276 (wxlCallback->GetEvtHandler() == (wxEvtHandler*)m_window))
00277 {
00278
00279
00280 m_wxlState.wxluaR_Unref(wxlCallback->GetLuaFuncRef(), &wxlua_lreg_refs_key);
00281 wxlCallback->ClearwxLuaState();
00282
00283 lua_pop(L, 1);
00284
00285
00286
00287
00288 lua_pushvalue(L, -1);
00289 lua_pushnil(L);
00290 lua_rawset(L, -4);
00291 }
00292 else
00293 lua_pop(L, 1);
00294 }
00295
00296 lua_pop(L, 1);
00297 }
00298 }