Page 1 of 1

Dynamically adding components

Posted: Fri Dec 23, 2022 12:34 am
by poetix
I have some code in the Initialize method that is meant to add a series of output jacks to the module (saves painstakingly dragging them into place in the designer). They only actually appear in the module if another output jack is added separately in the InitializeControls method, otherwise they're invisible (although you can still connect cables to them). This seems like a bug?

Re: Dynamically adding components

Posted: Fri Dec 23, 2022 6:42 am
by Aarnville
Plenty of people do that. Compare your code to the stuff that is auto-generated in InitialiseControls when you add a jack in the designer.
Or post a code snippet here.

Re: Dynamically adding components

Posted: Sat Dec 24, 2022 12:32 am
by poetix
So here's the function that makes a new jack:

Code: Select all

   private VoltageAudioJack[] jacks;
   
   private VoltageAudioJack makeJack(String displayName, String internalName, int x, int y) {
      var outputJack = new VoltageAudioJack( displayName, internalName, this, JackType.JackType_AudioOutput );
      AddComponent( outputJack );
      outputJack.SetWantsMouseNotifications( false );
      outputJack.SetPosition( x, y );
      outputJack.SetSize( 37, 37 );
      outputJack.SetSkin( "Jack Straight" );
      outputJack.SetVisible(true);
      outputJack.SetEnabled(true);
      outputJack.SetZOrder(2);
      return outputJack;
   }
 
and here it is being called in the Initialize method:

Code: Select all

      jacks = new VoltageAudioJack[16];
      
      for (int i=0; i<16; i++) {
         var radians = (double) i * Math.PI / 2.7;
         var radius = 120 - (i * 6);
         
         int x = 130 + (int) ((double) radius * Math.cos(radians));
         int y= 130 + (int) ((double) radius * Math.sin(radians));
         
         jacks[i] = makeJack("output" + i, "output" + i, x, y);
      }
      
As I said, all of these jacks are invisible unless I also manually added a single jack in the designer, which gets initialised in the InitializeControls() method, e.g.

Code: Select all

void InitializeControls()
{

      outputJack4 = new VoltageAudioJack( "outputJack4", "outputJack4", this, JackType.JackType_AudioOutput );
      AddComponent( outputJack4 );
      outputJack4.SetWantsMouseNotifications( false );
      outputJack4.SetPosition( 19, 173 );
      outputJack4.SetSize( 37, 37 );
      outputJack4.SetSkin( "Jack Straight" );
}
My guess is, most of the time, people dynamically adding components also have at least one that's being created in InitializeControls, so maybe they don't observe the problem?

Re: Dynamically adding components

Posted: Sat Dec 24, 2022 5:38 am
by UrbanCyborg
Just a guess, but the designer might be adding an import at the top of the file that's not immediately obvious.

Reid

Re: Dynamically adding components

Posted: Sat Dec 24, 2022 7:09 am
by Aarnville
Z-Order is the thing that leaps out there. Double-check them, including those of any background graphics or rectangles you may have.

If that's all good then maybe send a simplified version of your project to CA to see if they can make sense of it. It wouldn't be the first bug in the designer!

Re: Dynamically adding components

Posted: Sat Dec 24, 2022 12:17 pm
by ColinP
I came across the same problem ages ago. It seems that the graphical resource load isn't triggered by the init code as one would expect.

Often there's at least one jack socket (or more generally any GUI component) that one manually places on the panel so the bug only arises when everything is done programmatically.

If I remember correctly I got around the problem simply by manually placing one instance of each component needed in a corner of the panel and then makng it/them invisible with a call to SetVisible(). This forces the resources to load.

There might be a more elegant solution (perhaps using the Extra Skins property to fool VMD into loading the resources) but life is too short so I moved on.

Re: Dynamically adding components

Posted: Mon Dec 26, 2022 3:14 pm
by terrymcg
ColinP wrote: Sat Dec 24, 2022 12:17 pm There might be a more elegant solution (perhaps using the Extra Skins property to fool VMD into loading the resources) but life is too short so I moved on.
This should do the trick, assuming it works the same way as "Extra Resources".

Before the existence of those two new-ish properties, you needed to include a non-programmatic reference to any skin you wanted to use in the module, leading to various tiny and/or hidden solutions. The two module properties provide a much neater way of letting VM know what 'extra' things you're planning to use.

Cheers,
--
Terry McG

Re: Dynamically adding components

Posted: Sun Jan 08, 2023 6:15 pm
by SHARPmodular
The skin you use for the dynamically placed objects must be available in the module, either by placing one with that skin or adding it to the extra resources...
if you place one object using the skin you want, you can always set that specific one to invisible and then use your routine to dynamically place the number of objects you do want...