Updating listviews...

Discuss GUI programming with the RapaGUI plugin here
User avatar
Allanon
Posts: 732
Joined: Sun Feb 14, 2010 7:53 pm
Location: Italy
Contact:

Re: Updating listviews...

Post by Allanon »

@Flinx
Looking better at your code I realized that the recursive code returns immediately, it places only one callback in the stack that, when it is executed executed, it places another callback and so on... while mine places all the callbacks in the stack at once...
it's still not clear to me why my example doesn't not work... maybe my supposition is true: widget are updated only when all the events has been served :?:
Flinx
Posts: 192
Joined: Sun Feb 14, 2021 9:54 am
Location: Germany

Re: Updating listviews...

Post by Flinx »

Allanon wrote: Fri Feb 02, 2024 6:56 pm @Flinx
maybe my supposition is true: widget are updated only when all the events has been served
I'm not sure either. Maybe we'll get a more educated answer.
User avatar
airsoftsoftwair
Posts: 5446
Joined: Fri Feb 12, 2010 2:33 pm
Location: Germany
Contact:

Re: Updating listviews...

Post by airsoftsoftwair »

Flinx is doing it the right way. I somehow missed his answer and came up with this:

Code: Select all

@REQUIRE "RapaGUI"

Function p_Func(msg)

	Local t = msg.userdata
	DebugPrint("--> ", t.n)
        Wait(50,#MILLISECONDS)
        moai.DoMethod("lv", "insert", GetTime(True) .. ": " .. "Hello!\n", "bottom")

        t.n = t.n + 1
        If t.n <= t.limit Then RunCallback(p_Func, t)

EndFunction

Function msgHandler(msg)
	Switch msg.action
    ; Parse RapaGUI events
    Case "RapaGUI"
      
      ; Filter actions by attributes
      Switch msg.attribute

        ; Check button presses
        Case "Pressed"
          ; Check buttons
          Switch msg.id
            Case "go"
	      Local state = {n = 1, limit = 10}
              RunCallback(p_Func, state)            
          EndSwitch
      EndSwitch
  EndSwitch

EndFunction

moai.CreateApp([[<?xml version="1.0" encoding="iso-8859-1"?>
<application id="app">
	<menubar id="menu">

		<menu title="_File">
			<item id="mn_about">_About...</item>
			<item/>
			<item id="mn_quit">_Quit</item>
		</menu>
	</menubar>

	<window title="TEST LV" id="window" menubar="menu">
		<vgroup frame="true" frametitle="Update Test">
      <texteditor id="lv" readonly="true">
      </texteditor>
      <button id="go">GO</button>            
    </vgroup>
  </window>
</application>
]])

; listen to these events!
InstallEventHandler({
  RapaGUI     = msgHandler
  })
  
; Welcome message
moai.DoMethod("lv", "insert", GetTime(True) .. ": " .. "Hello!\n", "bottom")

; Let's go!
Repeat
  DebugPrint("Before Wait Event")
  WaitEvent
  DebugPrint("After Wait Event")
  
Forever 
As you can see, it's pretty much the same idea except I'm not calling Listview.Redraw() because this is unnecessary. This is perfectly safe. There is no recursion. It's just pushing the next callback from the callback but it won't be called until the next event loop cycle. So there is always only one callback on the stack. No risk of any overflows here. That's how it should be done, always push the next callback *from* the callback to ensure the event loop has time to refresh.
User avatar
Allanon
Posts: 732
Joined: Sun Feb 14, 2010 7:53 pm
Location: Italy
Contact:

Re: Updating listviews...

Post by Allanon »

Yup, that's fine, I've replied to myself because I saw that the code wasn't affecting the stack ;)
I've fixed my script to work as I wanted, thank you for the help :)
...to be honest I don't really like this way of structuring the code to give some feedback to the user during a loop :P
airsoftsoftwair wrote: Sun Feb 04, 2024 10:03 pm Flinx is doing it the right way. I somehow missed his answer and came up with this:

Code: Select all

@REQUIRE "RapaGUI"

Function p_Func(msg)

	Local t = msg.userdata
	DebugPrint("--> ", t.n)
        Wait(50,#MILLISECONDS)
        moai.DoMethod("lv", "insert", GetTime(True) .. ": " .. "Hello!\n", "bottom")

        t.n = t.n + 1
        If t.n <= t.limit Then RunCallback(p_Func, t)

EndFunction

Function msgHandler(msg)
	Switch msg.action
    ; Parse RapaGUI events
    Case "RapaGUI"
      
      ; Filter actions by attributes
      Switch msg.attribute

        ; Check button presses
        Case "Pressed"
          ; Check buttons
          Switch msg.id
            Case "go"
	      Local state = {n = 1, limit = 10}
              RunCallback(p_Func, state)            
          EndSwitch
      EndSwitch
  EndSwitch

EndFunction

moai.CreateApp([[<?xml version="1.0" encoding="iso-8859-1"?>
<application id="app">
	<menubar id="menu">

		<menu title="_File">
			<item id="mn_about">_About...</item>
			<item/>
			<item id="mn_quit">_Quit</item>
		</menu>
	</menubar>

	<window title="TEST LV" id="window" menubar="menu">
		<vgroup frame="true" frametitle="Update Test">
      <texteditor id="lv" readonly="true">
      </texteditor>
      <button id="go">GO</button>            
    </vgroup>
  </window>
</application>
]])

; listen to these events!
InstallEventHandler({
  RapaGUI     = msgHandler
  })
  
; Welcome message
moai.DoMethod("lv", "insert", GetTime(True) .. ": " .. "Hello!\n", "bottom")

; Let's go!
Repeat
  DebugPrint("Before Wait Event")
  WaitEvent
  DebugPrint("After Wait Event")
  
Forever 
As you can see, it's pretty much the same idea except I'm not calling Listview.Redraw() because this is unnecessary. This is perfectly safe. There is no recursion. It's just pushing the next callback from the callback but it won't be called until the next event loop cycle. So there is always only one callback on the stack. No risk of any overflows here. That's how it should be done, always push the next callback *from* the callback to ensure the event loop has time to refresh.
User avatar
airsoftsoftwair
Posts: 5446
Joined: Fri Feb 12, 2010 2:33 pm
Location: Germany
Contact:

Re: Updating listviews...

Post by airsoftsoftwair »

Allanon wrote: Thu Feb 08, 2024 12:32 pm ...to be honest I don't really like this way of structuring the code to give some feedback to the user during a loop :P
I can understand that but I'm afraid there's not really a way around this because that's how modern GUIs are designed. When designing RapaGUI I really thought about this a lot but if I wanted RapaGUI to work around this, the script would have to run on its own thread and then delegate all GUI calls to the main thread but this has the potential to trigger lots of issues so it's not really a good idea.

My idea was to tie RapaGUI as closely as possible to the underlying GUI system but of course this has the consequence that some things aren't as convenient as you're used to, e.g. your feedback situation. Remember that RapaGUI is quite a beast because it also runs on systems like Android where all GUI stuff must be done in Java. This is all very complex stuff and on Android you'll also run into the very same issue because the GUI won't refresh until the main loop is hit again. It's just how those GUI systems work and I don't think it can be made more convenient without making all hell break loose ;)
User avatar
Allanon
Posts: 732
Joined: Sun Feb 14, 2010 7:53 pm
Location: Italy
Contact:

Re: Updating listviews...

Post by Allanon »

Thank you for your reply, don't get me wrong, it's not a complain about how it has been implemented but instead just a feeling, but now that I got how it works I'll live with it. :)
Thanks again for your efforts in Hollywood-land ;)
airsoftsoftwair wrote: Sun Feb 11, 2024 9:50 pm
Allanon wrote: Thu Feb 08, 2024 12:32 pm ...to be honest I don't really like this way of structuring the code to give some feedback to the user during a loop :P
I can understand that but I'm afraid there's not really a way around this because that's how modern GUIs are designed. When designing RapaGUI I really thought about this a lot but if I wanted RapaGUI to work around this, the script would have to run on its own thread and then delegate all GUI calls to the main thread but this has the potential to trigger lots of issues so it's not really a good idea.

My idea was to tie RapaGUI as closely as possible to the underlying GUI system but of course this has the consequence that some things aren't as convenient as you're used to, e.g. your feedback situation. Remember that RapaGUI is quite a beast because it also runs on systems like Android where all GUI stuff must be done in Java. This is all very complex stuff and on Android you'll also run into the very same issue because the GUI won't refresh until the main loop is hit again. It's just how those GUI systems work and I don't think it can be made more convenient without making all hell break loose ;)
Post Reply