QControl Enthusiasts

cancel
Showing results for 
Search instead for 
Did you mean: 

QControl Usability Improvements

I was thinking about how to improve usability.  One difference between QControls and XControls is what has to be dropped to begin using them.  An XControl you drop the control, the facade appears on the front panel, and just a terminal of the set data type appears on the block diagram.  
 
The QControl is currently dropped in multiple parts.  First, you drop the control (facade), then the constructor.  Next, you create the reference and wire the reference into the constructor.  To finish it off you should also make sure the deconstructor is fired when closing the using VI.
 
So, I was thinking about how I could reduce the steps on the QControl.  I could have a merge VI that has the control (facade), reference, and constructor.  However, I think it is a positive that QControls aren't tied to the facade.  You can have the same behavior between a system, modern, silver, etc. control just by the reference wired into the constructor without creating a new QControl (unlike with an XControl).
 
Some other differences between QControls and XControls are that it is not contained as just the terminal on the block diagram and the data type is not changeable.  This makes them slightly harder to work with.  However, the tradeoff is you get all built-in properties and methods,  easier use with libraries, and extensibility by using object-oriented programming.
 
So, is there any way to mimic the single terminal behavior?  Or make QControls have a settable data type?  If we would even want to?  Also, maybe could we make an invoke node work on a class wire (it would have to be some kind of special XNode)?
 
Just some thoughts.  I would love to hear your ideas as we brainstorm.  Feel free to include others you think would have ideas.
Quentin "Q" Alldredge

Chief LabVIEW Architect, Testeract | Owner, Q Software Innovations, LLC (QSI)
Director, GCentral | Admin, LabVIEW Wiki | Creator, The QControl Toolkit
Certified LabVIEW Architect | LabVIEW Champion | NI Alliance Partner



Message 1 of 34
(3,563 Views)

@TheQ wrote:
To finish it off you should also make sure the deconstructor is fired when closing the using VI.

I usually add an auto-close feature... When creating the dynamic handler, I pass it a queue allocated in the caller. When the queue dies (even if the main is aborted, and the proper close isn't called), the dynamic VI can stop itself.

 

Not sure if QControls have that.

Message 2 of 34
(3,520 Views)

wiebe@CARYA wrote:

 

I usually add an auto-close feature... When creating the dynamic handler, I pass it a queue allocated in the caller. When the queue dies (even if the main is aborted, and the proper close isn't called), the dynamic VI can stop itself.

 

Not sure if QControls have that.


It does have an auto-close to ensure that the asynchronous Event Handler is not orphaned if the VI using the QControl stops. 

 

However, this currently doesn't apply to closing other references (i.e. the State Data DVR).  Maybe, I should add that so the deconstructor would automatically be called and therefore would not need to be added to the using VI's block diagram.

 

Would "auto-cleanup" be a desired feature?

Quentin "Q" Alldredge

Chief LabVIEW Architect, Testeract | Owner, Q Software Innovations, LLC (QSI)
Director, GCentral | Admin, LabVIEW Wiki | Creator, The QControl Toolkit
Certified LabVIEW Architect | LabVIEW Champion | NI Alliance Partner



Message 3 of 34
(3,503 Views)

@TheQ wrote:

...

Would "auto-cleanup" be a desired feature?


Absolutely. Then they could be treated just like any other control or indicator in terms of reference handling. People are used to not closing control references (and have even been explicitly told not to). Anything you can do to make them more analogous to normal G Objects would be great.

 

Edit: The more I think about it, they just can't be treated like a normal G Object, and the destructor should probably be strongly recommended. I think it might still be worth doing an auto-cleanup, just in case though.

--------------------------------------
0 Kudos
Message 4 of 34
(3,490 Views)

Totally out the box here, but what if instead of dropping all that you just dropped an invoke node called create Q Control. You then passed it the type of QControl.

You could have a merge vi with an invoke node with the correct method set already. You just drop that and select link to and then select the control?

 

Also seperate idea, maybe a quickdrop shortcut?  ctl space ctl Q , turns a control into a Q control.

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
0 Kudos
Message 5 of 34
(3,484 Views)

@ChrisStrykesAgain wrote:

Edit: The more I think about it, they just can't be treated like a normal G Object, and the destructor should probably be strongly recommended. I think it might still be worth doing an auto-cleanup, just in case though.


This is probably true.  Either way you would still have to add to the deconstructor if you added any references to the constructor (meaning: user events, queues, notifiers, etc.).  However, I could make the deconstructor dynamic dispatch and call it automatically after the Event Handler closes.  Then the cleanup could be automatic.

 

One problem this could raise is for people with existing QControls.  If they already use the current deconstructor and I closed the references already for them, those closes would error.  I would have to look if I could make it ignore a second close.

Quentin "Q" Alldredge

Chief LabVIEW Architect, Testeract | Owner, Q Software Innovations, LLC (QSI)
Director, GCentral | Admin, LabVIEW Wiki | Creator, The QControl Toolkit
Certified LabVIEW Architect | LabVIEW Champion | NI Alliance Partner



0 Kudos
Message 6 of 34
(3,479 Views)

@Taggart wrote:

Totally out the box here, but what if instead of dropping all that you just dropped an invoke node called create Q Control. You then passed it the type of QControl.

You could have a merge vi with an invoke node with the correct method set already. You just drop that and select link to and then select the control?


Currently the constructor and deconstructor are both just VIs that get called given that QControls are build as LV-OOP classes.  Then the reference to the control is required input to the constructor VI.

 

The class wire currently doesn't operate on an invoke node, as you know.  So I'm not quite sure I understand what you mean here.  I was thinking about an XNode to act like an invoke node for classes but I'm no expert on XNodes so that might not be possible.

 


Also seperate idea, maybe a quickdrop shortcut?  ctl space ctl Q , turns a control into a Q control.


A QDKS could be made. Right now you start creation of a QControl via the File->New... menu which launches a wizard to help with creating a class inheriting from the right parent class in the toolkit.  This is how you can get all built in methods and properties.

So to make a QDKS, it would recognize the currently selected control for the inheritance selection so it could bypass that step of the wizard.  It would really only save you one step though.

Quentin "Q" Alldredge

Chief LabVIEW Architect, Testeract | Owner, Q Software Innovations, LLC (QSI)
Director, GCentral | Admin, LabVIEW Wiki | Creator, The QControl Toolkit
Certified LabVIEW Architect | LabVIEW Champion | NI Alliance Partner



0 Kudos
Message 7 of 34
(3,476 Views)



@TheQ wrote:
I was thinking about how to improve usability.  One difference between QControls and XControls is what has to be dropped to begin using them.  An XControl you drop the control, the facade appears on the front panel, and just a terminal of the set data type appears on the block diagram.  
 
The QControl is currently dropped in multiple parts.  First, you drop the control (facade), then the constructor.  Next, you create the reference and wire the reference into the constructor.  To finish it off you should also make sure the deconstructor is fired when closing the using VI.
 
So, I was thinking about how I could reduce the steps on the QControl.  I could have a merge VI that has the control (facade), reference, and constructor.  However, I think it is a positive that QControls aren't tied to the facade.  You can have the same behavior between a system, modern, silver, etc. control just by the reference wired into the constructor without creating a new QControl (unlike with an XControl).
 
Some other differences between QControls and XControls are that it is not contained as just the terminal on the block diagram and the data type is not changeable.  This makes them slightly harder to work with.  However, the tradeoff is you get all built-in properties and methods,  easier use with libraries, and extensibility by using object-oriented programming.
 
So, is there any way to mimic the single terminal behavior?  Or make QControls have a settable data type?  If we would even want to?  Also, maybe could we make an invoke node work on a class wire (it would have to be some kind of special XNode)?
 
Just some thoughts.  I would love to hear your ideas as we brainstorm.  Feel free to include others you think would have ideas.

Even I struggle with what type of control reference is required for a given Q control, so I think you do need some kind of helper. I played with some different ideas, but I think the only viable option I could come up with is a merge VI, as you said. This would allow a user to easily enough switch out the control for a different style, but still show us which type of control is required.

 

I don't think there needs to be a mechanism to easily switch between "types" of Q Controls. They are generally pretty specific in their purpose and I don't think I would generally want to casually convert from one to another. It might be a nice to have, but I think development efforts would be better spent elsewhere.

 

A single terminal isn't desirable in my mind, because it doesn't make it clear enough that "hey, this is something special, you can't treat it just like any other control." I think that behavior is unavoidable, so we shouldn't try to imply anything otherwise.

 

I do really want invoke nodes. When I used Q Controls in a project earlier this year, it was a little awkward not having them.

--------------------------------------
0 Kudos
Message 8 of 34
(3,475 Views)

@TheQ wrote:

...

One problem this could raise is for people with existing QControls.  If they already use the current deconstructor and I closed the references already for them, those closes would error.  I would have to look if I could make it ignore a second close.


True. Double closes are problematic, and ref counting (my first thought) is actually pretty hard. The next thing that comes to mind is just setting a boolean in the private data of the base class that says "is valid" and the destructor would only do it's thing if it was set to true coming in, then set it to false going out.

--------------------------------------
0 Kudos
Message 9 of 34
(3,470 Views)

@ChrisStrykesAgain wrote:




Even I struggle with what type of control reference is required for a given Q control, so I think you do need some kind of helper. I played with some different ideas, but I think the only viable option I could come up with is a merge VI, as you said. This would allow a user to easily enough switch out the control for a different style, but still show us which type of control is required.


Having a Facade.ctl and putting it into a merge VI would probably be the simplest way to make this easier.  The developer would have to add the control they wanted to the Facade.ctl.  However, the wizard would script the basic control into it based on the inheritance selected.

 

Oh, but this could add some complications.  The Facade.ctl would have to be Strict Type Def which would lock-up some properties.  I guess it doesn't have to be Strict Type Def; but then where do you make changes, in the Facade.ctl or in the using VI?

 

I don't think there needs to be a mechanism to easily switch between "types" of Q Controls. They are generally pretty specific in their purpose and I don't think I would generally want to casually convert from one to another. It might be a nice to have, but I think development efforts would be better spent elsewhere.


This is only helpful if you plan to have your QControl control only a single control (lots of "controls" there hopefully that makes sense).  Then you could switch between Silver, Modern, System, etc. easily.  If it is multiple controls, or multiple controls in a cluster (i.e. my Calendar QControl) then you almost have to have a Facade.ctl.

 

A single terminal isn't desirable in my mind, because it doesn't make it clear enough that "hey, this is something special, you can't treat it just like any other control." I think that behavior is unavoidable, so we shouldn't try to imply anything otherwise.


I'm not sure how to make this happen in a non-hacky way that would still be stable.

 

I do really want invoke nodes. When I used Q Controls in a project earlier this year, it was a little awkward not having them.


I think all of us would love to be able to do this for all our LV-OOP classes.  Unless NI makes them, which for some reason I can't remember, they were reluctant to do, it would probably need to be an XNode; which are also hacky and possible unstable.  I would be willing to try, I might need help from the expert, @hooovah.

Quentin "Q" Alldredge

Chief LabVIEW Architect, Testeract | Owner, Q Software Innovations, LLC (QSI)
Director, GCentral | Admin, LabVIEW Wiki | Creator, The QControl Toolkit
Certified LabVIEW Architect | LabVIEW Champion | NI Alliance Partner



0 Kudos
Message 10 of 34
(3,468 Views)