LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
wiebe@CARYA

VI property subpanel ref

Status: Declined

Any idea that has received less than 2 kudos within 2 years after posting will be automatically declined. 

Not sure why I can't find this idea, there are a few 'VI Ref' read property for SubPanels" posts, but couldn't find this one...

 

How about a VI property "SubPanel" , that returns the subpanel a VI is in (or Not a ref)?

 

Now I have to give all dynamic VI's a SubPanel reference, and when started, and put into a subpanel, I have to dynamically set the control value. I need the subpanel reference, for coordinate conversion, handling tabbing, getting panel images, etc.

 

Regards,

 

Wiebe.

43 Comments
AristosQueue (NI)
NI Employee (retired)

My opinion: this is a bad idea. You list a set of reasons why you need this that do not make sense to me -- and if they do make sense, in my opinion, we have a bigger issue than this would address.

 

In the vast majority of cases, the VI being hosted inside a should not need to know that it is part of a larger VI. Indeed, it would be a violation of most good design that I've seen if the VI behaved any differently when hosted than when running in its own window. If nothing else, it complicates testing of that VI.

 

wiebe: you list the following:

"I need the subpanel reference, for coordinate conversion, handling tabbing, getting panel images, etc."

 

Coordinate conversion? Please detail what you are doing that requires coordinate conversion within the hosted VI. All the coordinate conversion I've ever seen happens on the outer VI, which already knows where the subpanel is located.

 

Tabbing? The solution I've seen everyone have for this is that it is the outer VI that is in charge of the Tab key and there are user events fired to move the tabs into and out of subpanels -- in general, the subpanel just fires a user event that the outer VI is listening for that says "I got a tab key and that moved my focus back to the beginning; if you want to steal the focus for another subpanel or for the main, execute that code now." User events get passed around, not the subpanel reference. The subpanel reference would just be a proxy for the actual events that need to be shared.

 

Panel images? Why does the subpanel need an image of its caller? That's not something I've ever heard of a need for.

wiebe@CARYA
Knight of NI

AQ,

 

We do get very demanding customers sometimes. Sometimes we get the weirdest requests, and normal LabVIEW programming just does not cut it.

 

I really don't see a problem with having this property. I just want a subVI to be able to know stuff about it's "graphical parent".

 

In earlier versions you'd need to know the subpanel's VI to properly set defer panel updates. That is much better now.

 

I'll have to look for more convincing reasons. Obviously, there are workarounds. I tend to get frustrated, then make a workaround, and forget about it as soon as possible. So I forget about the really good reasons. I'm sure there are a few.

 

>Coordinate conversion? Please detail what you are doing that requires coordinate conversion within the hosted VI. All the coordinate conversion I've ever seen happens on the outer VI, which already knows where the subpanel is located.

 

We have reentrant plug ins, and each plug in has it's own menu. When right clicking, it's own *custom* menu pops up. I'm not talking about the standard menu's here. We need fancy menu's. Each popup can be responsable for it's own menu's. Now it is possible to let the main VI handle it, but it would make things complicated. I do need to get the screen coordinates in the plug, and I think I needed the main VI panel to do the conversion.

 

We also need to do custom scaling of the panels. When one subpanels slider position changes, I might want to notify the main VI, and have it notify all it's subpanel VI's that they change their object accordingly. Again, there are workarounds.

 

>Tabbing? The solution I've seen everyone have for this is that it is the outer VI that is in charge of the Tab key and there are user events fired to move the tabs into and out of subpanels -- in general, the subpanel just fires a user event that the outer VI is listening for that says "I got a tab key and that moved my focus back to the beginning; if you want to steal the focus for another subpanel or for the main, execute that code now." User events get passed around, not the subpanel reference. The subpanel reference would just be a proxy for the actual events that need to be shared.

 

But what if the Vi that is beeing tabbed can be in or out the subpanel (or when the VI has a lot of instances in and out of subpanels, or even nested in subpanel's subpanels)? If it's out, you don't want the event to be send to the main VI. Again, there are solutions, but it would make life a lot easier if the VI could check it.

 

Tabbing can be implmented in several ways. All of them are really complicated if you want them to work really well. I also want to tab into tables, listboxes, clusters, 1D and 2D arrays etc. I just want the handle the subpanel issues the easiest way possible.

 

In general, I want my VI's to run the same in and out a subpanel. But I also want my main VI (with the subpanels) as dumb as possible. I do not want the main VI to have any knowledge about the plug ins. I do not even want to keep track which plug ins are open and if they are in a subpanel or not.

 

You might also want a control (stop button) to appear when the VI is outside a subpanel, and to disappear when it's inside a subpanel. The stand alone VI needs a stop to stop just itself. The main VI has it's own stop button so it should not be visible. Sure, I can work around it...

 

>Panel images? Why does the subpanel need an image of its caller? That's not something I've ever heard of a need for.

 

If you have plug ins that need to trigger the making of images of the entire Vi it's in? Sure I can use (jet another) user event (and add more global knowledge to the main VI). A subVI that recurses though all parents and that it's picture is a lot easier.

 

Regards,

 

Wiebe.

 

 

AristosQueue (NI)
NI Employee (retired)

wiebe@CARYA wrote:
I really don't see a problem with having this property. I just want a subVI to be able to know stuff about it's "graphical parent".

The problem is you are coupling functionality. Knowledge of the graphical parent poses the same threat to a system's architecture as global variables and any other module encapsulation boundary. It creates code that has weird and unpredictable side effects when other parts of the system are edited (because something depends upon a particular graphical state). Such code is very hard to test because you have to spin up the whole system in order to test it properly. LabVIEW R&D tries to minimize the number of hack properties and methods that we expose. For one thing, supporting those hacks means we ourselves have to hack our back end architectures -- if there's going to be a property GraphicalParent on class VirtualInstrument, that means VirtualInstrument is going to need a way to find its graphical parent. For another thing, we don't like encouraging bad architectures -- people tend to think that just because LV comes with a particular feature that it is a good idea to use that feature... and this property would fall in that category.

 

A lot of your solutions strike me as "working too hard". I'm going to pick just one that seems the easiest to address:


wiebe@CARYA wrote:
If you have plug ins that need to trigger the making of images of the entire Vi it's in? Sure I can use (jet another) user event (and add more global knowledge to the main VI). A subVI that recurses though all parents and that it's picture is a lot easier.

A plug-in that triggers taking images of the entire VI? What kind of user interface plug-in would even *know* about the rest of the VI to know that a picture should be taken?

I bold faced that phrase because that's what we're talking about when we are discussing subpanels. The fact that you're looking for this tells me that your subpanels are not just plugging in UI elements, they're plugging in functionality to the system -- in other words, if we consider a typical Model-Controller-View system, they are plug-ins for both the View and the Model. If you stretch your architecture that far, you definitely end up with the need for hacks like asking a VI for its graphical parent.

 

So, yes, if you're going to have an operation on the whole VI, that should be something that the master VI has an event for that the subpanels can trigger. When you launch one of your subpanels, you give them a bundle of user event refnums that the host has created and let them trigger events whenever they need to do something. This serves several purposes:

  1. It means that multiple subpanels can fire the same event as needed. Maybe you want to have the button that takes a snapshot on two of your three subpanels. Those two just fire the event from the Value Changed event frame of their respective buttons.
  2. It means that you have a well-defined state for operations on your caller VI. You click the button on Subpanel Alpha to take a snapshot -- but what if a separate subpanel Beta has suspended panel updates (which could have happened in the moment between your button being pressed and Alpha's Value Changed event being handed)? Or if another subpanel is in the middle of moving its values around. By posting to the caller, the events come in in a well-defined order from the view point of the system overall.
  3. Your code gets a lot cleaner to figure out for a new hire on your team. You have code that takes an image of the whole panel and writes it to some file? Which module is that probably in? I would guess the main VI... but it would take a long time to search through all of the plug-ins to find which one has that code. And finding all callers of that code is even trickier.

Basically, in any UI system, anything the subpanels actually execute on should be entirely encapsulated within that subpanel or should be a triggered event to the system as a whole. Now, that may include creating plug-ins for BOTH your user interface AND for your system. That's a common solution.

 

I assure you -- architectures that avoid doing operations on the graphical parent (in any context, including subpanels) lead to easier-to-write and easier-to-read code.

wiebe@CARYA
Knight of NI

I hope I'm not coming over too hard and agressive. I'm Dutch, and we tend to be blunt. The text medium makes it wurse.

 

Some statements are "reductio ad absurdum", I know.

 

>The problem is you are coupling functionality.

 

I could not disagree more. You are saying: make a "sub VI that works" is coupling the code. Instead, I have to make a user event, send that event, catch the event in another VI, send back something (sending it means it is handled asynchoniously, and that could be a problem). And that is not coupling the code?

 

What if I want to run the VI when it's not in a subpanel, or when the main VI is not running? It's not possible, because they are coupled.

 

And another argument was that it's hard to test. Well, when you put the code in a sub VI, you can test the plug in on it's own. With user events, you always need a main VI to be running. I like my objects to be not coupled to anything (if possible, within reason).

 

>Knowledge of the graphical parent poses the same threat to a system's architecture as global variables and any other module encapsulation boundary.

 

Just that having the option poses the thread of abuse, does not mean there are good uses for it as well.

 

I needed this a few times. In a 800+ system, you really do not want to add jet another user event for something silly like this.

 

>It creates code that has weird and unpredictable side effects when other parts of the system are edited (because something depends upon a particular graphical state).

 

In my experience, the weird effects are a lot harder to track and occur more often with complicated constructions. And a sub VI that does the job is a lot less complicated then sending user events.

 

I need this feature so I can make code work, regardless of the particular graphical state. In other words, i need to know the praticular graphical state.

 

Such code is very hard to test because you have to spin up the whole system in order to test it properly.


Exactly the opposite. A standalone VI is a lot easier to test (, even if it depends on some external state), then a VI that sends user events into space.

 

>LabVIEW R&D tries to minimize the number of hack properties and methods that we expose.

 

It's not a hack until proven guilty.

 

>For one thing, supporting those hacks means we ourselves have to hack our back end architectures -- if there's going to be a property GraphicalParent on class VirtualInstrument, that means VirtualInstrument is going to need a way to find its graphical parent.

 

So you are explaining to me how easy this is to do in a LabVIEW program (I'm not convinced), and it turns out to be really hard implement do in LabVIEW. That's just hilairious.

 

The fact that it is a lot of work to implement, has nothing to do with the idea being usefull or not.

 

>For another thing, we don't like encouraging bad architectures -- people tend to think that just because LV comes with a particular feature that it is a good idea to use that feature... and this property would fall in that category.

 

First you say you can't imagine you need this property. How is it then that it encourages bad architectures? It's not like I'm suggesting some über-global like the shared variable.

 

I can only say that if you ever need it (and I hope you will), it's really anoying you have to spend hours (, or even 20 minutes), creating a work around for this. Don't forget to update the design document (another 20 minutes)!

 

>A lot of your solutions strike me as "working too hard".

 

Not really. Good programmers are lazy programmers. And I am lazy (that does not imply I am good (modes ponens)).

 

When I get a request or requirement, I always say: sure LabVIEW can do that. Where others say: no, that is not possible... I'm not giving up on LabVIEW.

 

And again: making a subVI that works is a lot less hard work, then making a user event, catching it in the master, synchronise, etc. I do need to work hard, because I can't make a simple subVI that does the job.

 

>I'm going to pick just one that seems the easiest to address:

 

The harder ones are probably more relevant.


>A plug-in that triggers taking images of the entire VI?

 

Yes. A user selects a "print screen" from a menu plugin, and now the menu plug in wants to take the entire image.

 

>What kind of user interface plug-in would even *know* about the rest of the VI to know that a picture should be taken?

 

Exactly. No user interface plug-in knows that. Because there is no property for it.

 

>So, yes, if you're going to have an operation on the whole VI, that should be something that the master VI has an event for that the subpanels can trigger.

 

Again, I disagree. I do most certainly do not want everything global that any plug in can do, to be handled by the master VI. What if I get a new requirement? My master VI is a fixed framework, distributed to 50 customers. Now a new feature is needed by one plugin, and instead of distributing the plugin, I need to redistribute the entire framework.

 

I want my main VI as thin as possible, and when a button is pressed, I (sometimes) want to see what it does, instead of throwing the action in to event space.

 

It's not just that you need the subpanel for operations on the whole VI. That might indeed be off in the main VI. Often I need the state of the object itself, globally, including the subpanel position.

 

Have you ever tried converting a subpanel coordinate into a screen coordinate? You really suggest to pass that as a user event?

 

>When you launch one of your subpanels, you give them a bundle of user event refnums that the host has created and let them trigger events whenever they need to do something. This serves several purposes:

 

Not always a good idea. First, all pugins get all event refnums. I'm using a buffer VI for each user event. Now you can search for the VI to see which code uses each event. Also, when one user event changes, only the ones using the event will be updated in SCC.

 

  1. It means that multiple subpanels can fire the same event as needed. Maybe you want to have the button that takes a snapshot on two of your three subpanels. Those two just fire the event from the Value Changed event frame of their respective buttons.

Same if a subVI handles this action. Just put the subVI on the appropriete locations. This is easier to read.

 

  1. It means that you have a well-defined state for operations on your caller VI. You click the button on Subpanel Alpha to take a snapshot -- but what if a separate subpanel Beta has suspended panel updates (which could have happened in the moment between your button being pressed and Alpha's Value Changed event being handed)? Or if another subpanel is in the middle of moving its values around. By posting to the caller, the events come in in a well-defined order from the view point of the system overall.

Since any plug in can register for any event, every plug in can use the well-defined order of events. No need to do that in the main. For me, this doesn't happen to often.

 

This structure is usefull, when you have a lot of plugins that need the exact same functionality. Then you can make a user event, and the main handles it. But if you have a 50 plugins, and they want to do 50 different things, it's a real pain to make 50 user events. Does not make any sense to me at all.

 

 

 

 

 

wiebe@CARYA
Knight of NI
  1. Your code gets a lot cleaner to figure out for a new hire on your team. You have code that takes an image of the whole panel and writes it to some file? Which module is that probably in? I would guess the main VI... but it would take a long time to search through all of the plug-ins to find which one has that code. 

That is just not true.

 

He'd say: "when I click this button, an image is taken. Where is the button? Ah, it's action is in it's value change event".

 

Finding all callers: "Right click the VI, Find all instances"

 

Let's now say he has made it's own program. He wants to add a feature to take an image:

 

He'd say: "Ah, that is nice, I can just drop this VI".

 

Instead of: "Oh. This other program has the feature. I now need to copy some things from it's main VI into mine. And I need some type defs and sub VI's. Then I need to drop the event somewhere. That is complicated, I just passed CLAD.".

 

>And finding all callers of that code is even trickier.

 

If anything, finding all plug-ins that trigger a user event is very hard. Hopefully, it's done in a subVI. Hopefully, it's the only subVI that uses it. You never know. If not, good luck finding all triggers of the user event. Not everyone has programming OCD, people find creative ways to screw things up.

 

>I assure you -- architectures that avoid doing operations on the graphical parent (in any context, including subpanels) lead to easier-to-write and easier-to-read code.

 

You make it sound like I have a choise. These are requirements. In a recent typical case, we got a requirement that states: "here is a program developed in c# (during 10 man-year), make LabVIEW look the same".

 

When a plug in is in a subpanel, and it wants, for instance, show, hide, or move itself (it's subpanel). Now this is not an operation on the graphical parent, but an operation on itself. In my design philosophy an object show be able to show or hide itself. I do not want to add this logic to the master VI.

 

Isn't the idea (one idea) of OOP that object contain their data and state? If a subpanel VI is an object, it is not desireable to delegate state changes to another object, if you'd ask me... So I make this class, and instead of it being (re)usable on it's own, I have to make a manual that explains that to use it, you need to add a user event, add a main VI that handles it, etc. Not a good idea.

 

At least if the property was there, I can make the choise myself.

 

 


 

I'm sure we can debate this for ever. We're now debating architecture, and not really the idea. If you don't support it, I'm sure it will not be created, even if it gets kudo's.

 

I can only say I really hope you get a customer or colleage asking for this soon. Then you have to tell to him (hopefully by emain or by phone):

 

"No, a VI is not allowed to know where it is, so I can't send you a VI that does the job. Instead, you need change your architecture, add a user event, handle the user event somewhere else, get back results somehow. Did you take the advanced course jet?"

Intaris
Proven Zealot

Your collection of user events being passed around are your interface.  I wouldn't count that to be increasing coupling because without an interface you have nothing.

 

I like my objects to be not coupled to anything (if possible, within reason).

 

If you need functionality, it needs to be reflected iny our API.  How about a User Event called "Ping" which the master simply responds to (Boolean) if it's running and doesn't if it's not.  Then you make a sub-VI which Pings the master and voila, you now know if your sub-VI is running stand-alone or not.

 

Or I just let wikipedia weave its magic. http://en.wikipedia.org/wiki/Loose_coupling  on the 15. May 2014 at 12:37 GMT

 

Strong coupling occurs when a dependent class contains a pointer directly to a concrete class which provides the required behavior. The dependency cannot be substituted, or its "signature" changed, without requiring a change to the dependent class. Loose coupling occurs when the dependent class contains a pointer only to an interface, which can then be implemented by one or many concrete classes. The dependent class's dependency is to a "contract" specified by the interface; a defined list of methods and/or properties that implementing classes must provide. Any class that implements the interface can thus satisfy the dependency of a dependent class without having to change the class. This allows for extensibility in software design; a new class implementing an interface can be written to replace a current dependency in some or all situations, without requiring a change to the dependent class; the new and old classes can be interchanged freely. Strong coupling does not allow this.

wiebe@CARYA
Knight of NI

>Your collection of user events being passed around are your interface. 

 

Not per see. There are perfectly valid designs that do not use user events at all.

 

Ideally, I want to use user events for application specific interaction. I do not want to add a user event just because a property is missing.

 

>I wouldn't count that to be increasing coupling because without an interface you have nothing.

 

So because we have an interface, we are going to use it for passing silly administrative data?

 

Loose coupling is still coupling, especially compared to no coupling at all (which is possible if we could just make a subvi to do the job). Loose coupling allows "replacing a current dependancy", but there still is a requirement for a dependancy. Even if we can change the main VI, we still require a main VI.

 

To me, this 's a really weird discusion. We used to have only attribute nodes, and where not capable to passing references at all. With the creating of references, we can modify and read state of objects anywhere. When it became possible to pass references (to a subVI), nobody complained that "only the master VI should be able to modify these objects, think of how this can be abused!". This property only adds to the possibilities.

 

All I want is to know (for example) where someone clicked on the screen! It could be sooo easy. I want to put this function in a class, or library. That's not possible because it needs a framework of user events.

 

I am surelly capable of making a user event or any other work around. I just hope not too many newbees switch away from LabVIEW for missing properties like this.

 

 

wiebe@CARYA
Knight of NI

If you need functionality, it needs to be reflected iny our API.  How about a User Event called "Ping" which the master simply responds to (Boolean) if it's running and doesn't if it's not.  Then you make a sub-VI which Pings the master and voila, you now know if your sub-VI is running stand-alone or not.

 

Yes, this sounds almost as easy as creating a tiny sub vi.

wiebe@CARYA
Knight of NI
wiebe@CARYA
Knight of NI

Here's another:

 

http://forums.ni.com/t5/LabVIEW/Can-t-get-top-level-VI-ref-from-subpanel-VI/m-p/2154540/highlight/tr...

 

Now the fix, to pass the reference to the Vi when started makes a lot more sense to most people than user events. It has exactly the same risk of abuse. But it is still anoying you have to do it.