On Mon, May 18, 2009 at 3:26 AM, Youen Toupin <youen.tou...@wanadoo.fr>wrote:
> John Labenski a écrit :
> >
>
> I know it doesn't make sense to resume a coroutine from itself (didn't
> even know it was possible to execute something from a yielded
> coroutine), that's not what I'm trying to do. What I was trying to do is
> to create the dialog from the coroutine, then yield, and when a button
> is pressed, it executes some code from the main thread, that resumes the
> coroutine. This would allow for example to create code like
>
> answer = promptUser( "Some question" )
>
> The promptUser function creates the dialog, registers a callback on a
> button click event, then yield (so it must be called from a coroutine).
> When the button is clicked, it resumes the promptUser function, which
> gets the answer from a text control, destroys the dialog box, and
> returns the result.
>
> The only problem is that, in the current implementation, I need to call
> the Connect function from the main thread to register my callback, so I
> can't write such a promptUser function that contains everything to
> create the dialog, I will have to create the dialog from the main
> thread, and promptUser will simply show/hide it when needed. This does
> not allow to call multiple promptUser in parallel, for example. And if
> my dialog is complicated and needs to be created differently depending
> on promptUser parameters, it will become more complicated to implement.
> More generally, it creates a dependency between my promptUser function,
> and some initialization code that need to be executed from the main thread.
>
I think that all you need to do is to shuffle around your existing code to
pull out the dialog creation from the coroutine code, I also demonstrate how
to pass data around without using globals.
function MyEventHandler(event)
local o = event:GetEventObject()
-- side note: to typecast the wxObject to what it really is use
-- local button = o:DynamicCast("wxButton")
-- can also use
-- local w = o:DynamicCast("wxWindow")
-- local parent = w:GetParent() and so on 'till you get the window you
want
local co = o.data.co -- This is your coroutine!
coroutine.resume(co, ...)
end
function promptUser(...)
local data = {}
local dialog = wx.wxDialog(....)
dialog.data = data
local button = wx.wxButton(dialog, 10, "Press me!")
button.data = data -- see above about w:GetParent() for alternative
populate dialog...
dialog:Connect(...)
-- tuck the coroutine into the data so the callback function can find it
data.co = coroutine.create(function() code for your worker function end,
dialog)
data.extra_data = "This is the data I really want to pass around"
return dialog
end
Note that you can pass whatever params you want into your promptUser()
function to customize the creation and also note that you can pass the data
as a parameter for resume() like this to exchange data:
coroutine.resume(dialog.co, dialog.data)
--------------------------
Alternatively, you can do exactly what you had before and simply connect to
the button after you create the dialog in the coroutine. wxWidgets doesn't
care or know what coroutine you're in since they're all in the same C
thread.
Or, you can use the code you originally had, but use wxPostEvent(...) to
send your own event from the Lua coroutine back to a function created and
connected in the main thread.
Finally, if all you're doing is trying to create dialogs to get user input
you wouldn't bother with coroutines since wxWidgets has an event loop. The
only use of a coroutine would be for some long calculation, but again this
is usually performed with idle events (wxEVT_IDLE) to allow the GUI to
refresh.
>
> Maybe the good solution for this problem would be to have the
> possibility to decide from which thread the function must be called,
> when it is registered on the button click event (with an extra parameter
> of the Connect function for example). It would give more possibilities
> to the user, while staying simple (no obligation to provide the
> additional parameter) and backward compatible (the default behavior
> would be to call the function from the thread that registered it).
>
I don't think that there is any reason to make the C code switch threads
when it is just as well if you do it yourself in Lua as in the example
above. It's nearly identical to your original code, all that's changed is
that the function that creates the dialog is not run in the coroutine, but
simply calls coroutine.create() at the end.
>
> There is another problem, however : I don't know if it is a good idea to
> create a dialog at the moment it is needed. I'm not used enough to
> wxWidgets to know if it can introduce some uncomfortable lag in the
> application.
>
You can create dozens and dozens of GUI elements with no noticeable lag. You
may notice that on a very slow machine the controls.wx.lua may be slow to
start, but that is because we are connecting to every imagineable event for
every control created. It is not a realistic benchmark.
Regards,
John
------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables
unlimited royalty-free distribution of the report engine
for externally facing server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
wxlua-users mailing list
wxlua-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wxlua-users