Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Extending MGI Example "Basic Panel Actors -> Changing Panels" to dock in the Window

Solved!
Go to solution

I got in touch with the MGI Panel Actors and tried to extend an example.

 

The following changes were made to "Changing Panels.lvclass":

- Created an Event in the Actor Core (normally, I would do that in Pre Launch Init, but thats just a test), with the Name of the Panel and its Enqueuer.

- Created a "Dock In.vi" for "Changing Panels.lvclass" an a Message (Dock In Msg.lvclass)

fabznx_3-1779881900616.png

 

- Implemented that Event in the Event Structure

fabznx_0-1779881239226.png


For the Smaple Panel.lvclass:

- Added a Mouse Down Event for Label

- Sending the "Dock In Msg.lvclass" to the caller

fabznx_1-1779881339583.png


All of this works, except: The VI is not shown in the subpanel.

To get a hold of whats happening, I added Timestamps to the Event Log.

And it seems, that the Panel gets shown, but not?!.

 

First of, I added 3 Items!


Here is the Log for Item 2:

fabznx_2-1779881480333.png

at 45,501 I clicked on Undock

at 45,516 the UI did show as window
at 53,941 I double clicked the Label

at 53,952 it says Shown, but doesn't (It does not matter, if the subpanel displays a VI or not, at this point, nothing is shown in the subpanel!)
at 57,672 I clicked on Item 3 (Item 3 is displayed)

at 58,900 I clicked on Item 2 again and then it displayed in the Subpanel

Another thing I noticed is, that when debugging with Highlight Exec, it works.
Is this some sort of race-condition that I am not aware of?

I am aware, that this couples the "Smaple Panel.lvclass" to "Changing Panels.lvclass".

Since this is just a proof of concept, I can live with that.

0 Kudos
Message 1 of 15
(590 Views)

If you post your code we can help debug further, but one thing I'd recommend is to instantiate your Panel object just once. You're creating a NEW panel each time you fire the Dock In event, and there's logic internal to the Panel Manager that handles multiple Panels trying to go into the same Subpanel, so it's probably getting confused about the previous Subpanel and the new Subpanel.

 

I'm not certain this is a problem, but I'd try to change that anyway. Just move the New Subpanel outside of the Event Structure and wire the Subpanel object through, and reuse it.

 

 

Edit: On second thought, I think I see your problem- the Change Panel message needs to go to Sample Panel.lvclass, not to the caller. A Panel Actor handles its own panels, not a separate Actor's panels. You're basically telling the main panel to insert itself into its own subpanel, which it can't do.

 

Also, you're overcomplicating things a bit. You don't need to create any new messages for this, since Change Panel is already part of the Panel Manager framework. You just need to send the Subpanel to the Sample Panel class ahead of time, so it knows what panel to insert itself into when it's time to insert itself into a subpanel. (You could do this as a method or just store it in the Panel's private data before you launch it.)

0 Kudos
Message 2 of 15
(561 Views)

Thanks for the quick response. 

 

I will try the first Reccomendation tomorrow. That seems reasonable.

 

About the second thought.

The Message goes to the Sample Panel (Self Enqueuer of the Event ist the Enqueuer of the Sample Panel)

 

And you are probably right, but the point in this example is to repopulate the list of items and the array of enqueuers to be able to dock it out again. Which means, that the Sample Panel has to request the insert, and the Actor with the Subpanel(s) needs to tell the requestor where to go. At least, thats my understanding. 

 

Kind regards 

Fabian 

0 Kudos
Message 3 of 15
(550 Views)

That makes sense. Then in that case, you'll need one message for the Main panel (to let it know the new panel is there), and you might need one for the Subpanel.

 

Couple ways I can think of to do that- first, you could do a "request insertion" message that the Sample Panel sends to the Main panel, and the Main panel would then send back a "Change Panel" message with the new panel. This wouldn't require a new message for the Caller, though you'd need to send a self-addressed message so Main knows where to send the message to (you'd include the Enqueuer in the message).

 

Second, you could also just assume that the Main panel always allows an Insertion, and give the subpanel Panel reference (not the subpanel reference itself, but the Subpanel.lvclass object). Then, when you want to Dock, you can call the method "Change panel" on the Subpanel, then send a message to Main to let it know it's been Docked.

 

You don't REQUIRE a new message for the Subpanel for this, but it's probably a good idea to wrap it up anyway. Your Sample Panel would be able to fire an event on its Actor Core that (for method 1) sends the "Let me insert into your subpanel" message to Main, or (for method 2) sends itself the Change Panel message and sends it caller the "Hey, I'm coming" message.

 

All that said- I'd recommend wrapping this functionality up into other classes/interfaces so your other Panel Actors can inherit from those. You really don't want a normal Actor to have to worry about this sort of thing.

 

Also, currently the method "Change Panel" is a static dispatch VI in the Panel Manager library. If you change that to Dynamic Dispatch, you could add an override to call other functions when the panel changes.

0 Kudos
Message 4 of 15
(539 Views)

Yep, that first approach is exactly what I was trying to do.

Dock In is sent from Sample Panel to Main (along with its name and Enqueuer). Main forwards that Data to its Helper Loop, which then Sends Change Panel back to the Sample Panel via its Enqueuer.

 

Of course i would do things different in a propper app, like putting the array of enqueuers in the Actor Data or create an Interface for the Dock In Message for the Sample Panel to send and for Main to override.

 

I just want to mention that all of this is included as an example. I just added a few things. And the example is therefore IMHO a bit misleading, regarding the Subpanel Ref creation. I just duplicated the "new Item" case, and thought, well should work.. 

 

---

Now that I think of it, shared clone reentrancy might explain why it works for the example but not for the added functionality, since the same clone is called in the "new item" case and a different in the "dock in" case. That may lead to different Subpanel Classes even if the Subpanel Ref is the same.

 

Edit: This is not true in my case. Just made a little test and both refs are the same. Shared Reentrancy is not the issue!

---

 

 

 

Kind regards 

Fabian 

0 Kudos
Message 5 of 15
(519 Views)

FWIW I'm not sure if it's a problem to re-create the subpanel object each time. I just know there's something in there that tracks subpanels, so re-creating things might leave dangling references. Unfortunately I don't have time to dig into it right now, but I bet you could figure it out- look inside the Swap Panel methods and see what it's doing. It might just keep track of the most recently inserted VI or something, in which case it doesn't matter at all.

0 Kudos
Message 6 of 15
(503 Views)

The Problem is not solved.

 

I moved the creation of the Subpanel.lvclass outside of the Helper-Loop.
Unfortunatelly, this did not solve the issue.

 

The Timestamp Event Log looks the same.

fabznx_0-1779942038401.png

 

Code is attached.

See the Example under: "2. Basic Panel Actors.lvlib > 3. Changing Panels > Changing Panels Launcher.vi"

 

 

The weird part still is, that the Sample Panel registers the "<Panel.My Panel>" User Event for "Shown".

When selecting another Item in the list, it also registers the "Hidden" State.

Also, when I use Highlight Execution on the "Changing Panels.lvclass > Actor Core.vi" it works. 

 

Inserting a "Stall Data Flow" just before the "Send Show Panel.vi" works too, but isn't something that I would suggest doing in a customer-application.

fabznx_1-1779943529283.png

 

Either way, I can undock the Item again, even if it is not displayed in the subpanel.
Whats going on here?

0 Kudos
Message 7 of 15
(482 Views)
Solution
Accepted by topic author fabznx

Aha, boy that was a tricky one! Thanks for posting the code- it let me figure it out.

 

The good news- The issue is in the toolkit and example, not your code.

 

The bad news- The issue is in the toolkit and example, not your code.

 

😉

 

(Though there is one issue with your code- I believe you need Autoshow to be True on your Subpanel panel)

BertMcMahan_4-1779994507867.png

 

 

Basically, the problem lies in how the Subpanel.lvclass loads and unloads things. A subpanel can't load a front panel if it's already open- so, the toolkit uses the FP.Close method to close the front panel inside Subpanel.lvclass:Show core:

 

BertMcMahan_1-1779994125059.png

 

 

Unfortunately, it appears that FP.Close returns before the Front Panel actually closes. There's a VERY brief instance of time where the front panel is still open, and when the Subpanel tries to load that panel, it throws an error.

 

One fix is to add a Stall Data Flow between those two items:

 

BertMcMahan_2-1779994225459.png

 

The second way to fix it would be to use the FP.State property, which DOES appear to block until the panel is actually hidden:

 

BertMcMahan_6-1779994649665.png

 

 

The third option would be to add a manual "Send Hide Panel" to your panel before sending Change Panel, along with a tiny delay between them. That will give the panel enough time to actually close before trying to Insert it into the subpanel:

 

BertMcMahan_5-1779994594563.png

 

 

I would argue this is a bug in the toolkit, and that it should probably switch from using FP.Close to setting FP.State. I'll see if I can file a bug in their issue tracker on their Gitlab page.

 

0 Kudos
Message 8 of 15
(457 Views)

Wow, would have never guessed, that the problem is the fp.close.

 

I'll update my local install and also the unmonitored version from Allen, which I tend to use for future PPL Builds.

 

 

As for the Autoshow, For the example - I think - it doesn't really matter, since the Listbox is triggered via Val (sgnl). But it would be a good practice for this Scenario to have it being set to True.

 

Edit: Sidenote: I am stricly against any hard delays in my actors, since I want them to be as responsive as possible. I guess that it is not allways avoidable, but I try to NOT use delays.

 

Thanks a lot for resolving that issue.

0 Kudos
Message 9 of 15
(441 Views)

@fabznx wrote:

Wow, would have never guessed, that the problem is the fp.close.

 

I'll update my local install and also the unmonitored version from Allen, which I tend to use for future PPL Builds.

 

 

As for the Autoshow, For the example - I think - it doesn't really matter, since the Listbox is triggered via Val (sgnl). But it would be a good practice for this Scenario to have it being set to True.

 

Edit: Sidenote: I am stricly against any hard delays in my actors, since I want them to be as responsive as possible. I guess that it is not allways avoidable, but I try to NOT use delays.

 

Thanks a lot for resolving that issue.


Sorry, who is Allen?

 

And yes, I would not normally advise any hard delays. This is more of an "if you can't/don't want to mod the toolkit, you can fix it this way" approach. This being only 20 ms, happening ONLY when you dock a window, and occurring in a helper loop (so your message handling loop is never locked) makes it "not that bad", IMHO.

 

I did submit an Issue to their Gitlab earlier today BTW.

0 Kudos
Message 10 of 15
(405 Views)