Modifying size of components and window in designer

Greetings,

this is my first module (Vision components) so very much still learning. However I have worked out most of everything I need except for resizing and repositioning things in the designer.

What I am trying to do is have a component when dragged into designer, position itself to absolute location in window, and also modify size and position of other already placed components, as well as set overall window size.

I can force the component to shift eg with an overridden setBounds to set desired absolute position including super.setBounds to percolate modified dimension downstream it works but then the designer marquee does not match the object anymore. Furthermore if you in the designer use jython to try and move an object eg with obj.setBounds(…) it moves and then jumps back to original position.

When you use the designer “set position and size” and set Vision.layout diag to Trace you see two events setBounds and SetPreferredBounds. What is “SetPreferredBounds”. It shows up nowhere in the docs.

Somehow I am missing something obvious.

Having the SDK is great, but the docs and examples are a little sparse to really get anywhere without a lot of “fighting the beast”. Is there anywhere on your site where users can annotate the API docs with their findings?. I could not even find the API docs on the website…I am using an older downloaded API to get at the javadoc simply.

As to the first Q: consider looking at the animation example that goes with the Simulation Aids module, from this thread. It includes jython code for manipulating component dimensions properly to allow for Ignition’s scaling and layout operations.
Second Q: Dunno. I’d like to see the API docs online too, preferably as part of the SDK manual. The links to the API in the current online files are missing.

Thanks for the quick response. I’ve downloaded and installed the Simulation Aids module and demo project. (modl and proj)

For others that may follow - you need the older project files, not the one from the latest post. Had me searching for a while.

I had already found the reshapeComponent and the newer replacement in 7.8 transform().

These are runtime options. I wish to manipulate the components at design time, so that users get WYSIWIG from the manipulations. Eg do exactly what your drag handles or _P does in the designer, but performed via the component.

The component gets resize events ok, so the hooks to initiate are present…its simply a case of me not knowing what calls to make.

I suspect that I will need to make some calls via the designer context rather then the client context.

Finally got debugging working in eclipse.

I can see what is going on…I need to get hold of the appropriate designable or LayoutManipulator to be able to perform the desired move/size.

Easier said than done.

How do you get access to these objects in runtime?

Hmmm. I don’t think I updated the SimDemo with the fully-debugged animation:[code]from com.inductiveautomation.factorypmi.application.components.util import FPMILayout
##########

Given a binding from objectScript(), move the target component to the given

coordinates at the given pixels per step and milliseconds per step.

When using scaled windows, always supply all of x, y, w, & h

animateMap = {}
def animateComponent(binding, x=None, y=None, w=None, h=None, pace=200.0, ms=250):
comp = binding.target
bounds = FPMILayout.getPreferredBounds(comp)
hash = id(binding)
p0 = animateMap.get(hash)
if p0 is None:
p0 = {}
else:
del animateMap[hash]
x0, y0, w0, h0 = (p0.get(‘x’, bounds.x), p0.get(‘y’, bounds.y), p0.get(‘w’, bounds.width), p0.get(‘h’, bounds.height))
x, y, w, h = (float(coalesce(x, x0)), float(coalesce(y, y0)), float(coalesce(w, w0)), float(coalesce(h, h0)))
deltas = (x-x0, y-y0, w-w0, h-h0)
dmax = max([abs(a) for a in deltas])
if dmax>pace:
rpace = pace/dmax
sx, sy, sw, sh = tuple([a+b*rpace for a,b in zip((x0, y0, w0, h0), deltas)])
animateMap[hash] = {‘x’: sx, ‘y’: sy, ‘w’: sw, ‘h’: sh}
system.util.invokeLater(binding.childInteractionUpdated, ms)
system.gui.reshapeComponent(comp, int(sx), int(sy), int(sw), int(sh))
return ms/rpace - ms
system.gui.reshapeComponent(comp, int(x), int(y), int(w), int(h))
return 0[/code]You’ll notice that you need to use the FPMILayout class to obtain the preferred bounds of any given component (Designer coordinates). There’s no safe way to use a component’s AWT .x, .y, .width, or .height in client contexts and have any confidence what they mean. You must use system.gui.reshapeComponent() and its variants to manipulate the preferred bounds. The preferred bounds drive AWT bounds on a variety of repaint and layout events.

This is Jython in the designer not via designer context via the SDK API which is what I was after.

The exposed context from the hook still leaves stuff hard to come by, and without docu its like stabbing yourself in the eye with your pen…the call trace gives you the calls you need, but you cannot get at the objects needed to make the call seemingly without extending class to expose private bits arrgh!

I have however hacked a workaround that works…I use a ScriptManager object to call a Jython function from the shared namespace.

eg

def moveClass(window,classname,x,y,w,h):
    components=[]
    try:
        components.append(system.gui.getWindow(window))
    except:
        return
    while len(components):
        comp=components[0].getComponents()
        t=type(components[0])
        if str(t)=='<type '%s'>"%classname:
            system.gui.transform(components[0],x,y,w,h)
            return
        for c in comp:
            components.append(c)
        components=components[1:]

I now have a component that when it is dragged on the designer in design mode totally enforces component size and position as well as window size and whatever else I wish to take over…pretty cool when you want to an easily created consistent interface for the organisation.

In the component you need code of this ilk, obviously names of things will change but it gives one the idea

ScriptManager sm=context.getScriptManager();
try {
    String cmd="shared.nav.navmodule.moveClass((\""+windowname+"\",\"com.ignition.dbw.topnav.client.TopnavComponent\",0,300,1024,100);
    sm.runCode(cmd,sm.createLocalsMap(),"XXXX");
} catch (Exception e) {
    log.debug("moveclass error");
}

In my case I am overriding the setBounds method in an AbstractVisionPanel. Doing this without invoking a tool like system.gui.reshape|transform stuffs up the marquee as the super does not seem to handle this side of things

I would call this thread as “workaround found” but not “solved” as the proper method to do this is still beyond me and judging from other forum entries others as well.

The FPMILayout class is what you should be using. Look at its methods in your IDE – it has setPreferredBounds() too, which I believe is what you are looking for.

Only partially working.

It works as expected in the doStartup() method of my component eg I can correctly position and size component here as stipulated by my bounds rectangle and have selection marquee drawn as expected.

But it all falls to pieces when I attempt to move/resize the object after having been placed. The selection marquee is once again separated from the component itself.

My test code overrides Components setBounds(Rectangle r) method which should be called when the components bounds change. (it gets called in the debugger as expected so this assumption appears ok)

@override
public void setBounds(Rectangle r) {
  //force rectangle to alternate geometry
   r.x=0;
   r.y=0;
   r.width=100;
   r.height=100;
  /*use suggested calls to effect change...this works in both a container or root container
   its a static method hence static call
  */
    FPMILayout.setPreferredBounds(this,r);
  //make sure object drawn where it is expected - always works
  super.setBounds(r);

} 

When dragging marquee…component stays put, but marquee moves to wherever you put it…eg the FPMILayout is not controlling the Marquee.

I’m sure there is a simple solution. In the meantime my workaround will have to do.