joonaspaakko/ScriptUI-Dialog-Builder-Joonas

Link preferred size to other items

joonaspaakko opened this issue · 1 comments

The sample dialog for has 4 panels where A + C share the same height and B + D share the same height. What if you could just change the height of B and D height would be mirrored?:

link-preferred-size-0

I've been thinking the actual linking should probably be completely visual. The labels for width and height could have click events that toggle linking mode on/off and then you could just select which items share the same width or height. And maybe if the active item is linked to some other item, the label would have a different color or something... I'm not really sure about that.

Something like this:
link-preferred-size-1

  • The linked sizes should probably be stored separately, so that when you unlink it, it goes back to the original size. Perhaps: linkedWidth and linkedHeight.
  • This linking could also work with 0 value and then just define the height on export.
  • The sample dialog uses horizontal fill to match width and a static height is used to make sure the panels form a nice grid.

Because SDB's dialog preview is just an approximation of ScriptUI, sometimes things move around a little. So a panel that was 100px tall in SDB, may end up like 110px in ScriptUI, even if you've defined the preferred size to be exactly 100px. This can happen if the children end up taking more space in ScriptUI because they push the parent to bigger. That is how preferred size works and that's good for most things. However, it can become an issue when you need the size to match... Mainly when making grids, I think.

I haven't locked in how I would do this linking in SDB, but since I realized that this misalignment would be an issue, I wrote some code to compensate for it. This code would be added to the bottom of the dialog right after all items are generated... obviously only if you've linked the size of any items.

The function basically reads the width or height of every item pushed into the array, gets the biggest width or height and then applies that width or height to all related items using minimumSize.

matchSize( dialog, [item1, item2, item3], 'height' );

function matchSize( dialog, array, direction ) {
  
  dialog.layout.layout();
  var max = [null, null, 0];
  
  for ( var i=0; i < array.length; i++ ) {
    var item = array[i];
    var size = item.size[(direction === 'width' ? 0 : 1)];
    max = size >= max[2] ? [ i, item, size] : max;
  }

  for ( var i=0; i < array.length; i++ ) {
    var item = array[i];
    item.minimumSize[ direction ] = max[2];
    dialog.layout.layout(true);
  }
  
}

Full example

There is no misalignment in this example, it simply has bunch of different size items. As an extra there's also 2 buttons that are made the same width with this function.

Without the function matchSize() it would look something like this in ScriptUI (Indesign 2018)
1

With the function matchSize() it would look something like this in ScriptUI (Indesign 2018)
2

/*
Code for Import https://scriptui.joonas.me — (Triple click to select):
{"activeId":0,"items":{"item-0":{"id":0,"type":"Dialog","parentId":false,"style":{"varName":null,"text":"Dialog","preferredSize":[0,0],"margins":16,"orientation":"column","spacing":10,"alignChildren":["center","top"]}},"item-1":{"id":1,"type":"Panel","parentId":7,"style":{"varName":"one","text":"One","preferredSize":[0,0],"margins":10,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-2":{"id":2,"type":"StaticText","parentId":1,"style":{"varName":null,"text":"Praesent tempus.","justify":"left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-3":{"id":3,"type":"Panel","parentId":7,"style":{"varName":"two","text":"Two","preferredSize":[0,0],"margins":10,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-4":{"id":4,"type":"StaticText","parentId":3,"style":{"varName":null,"text":"Duis semper, risus ac elementum.","justify":"left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-5":{"id":5,"type":"Panel","parentId":7,"style":{"varName":"three","text":"Three","preferredSize":[0,0],"margins":10,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-6":{"id":6,"type":"StaticText","parentId":5,"style":{"varName":null,"text":"Mauris elementum","justify":"left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-7":{"id":7,"type":"Group","parentId":15,"style":{"varName":"pParent","preferredSize":[0,0],"margins":0,"orientation":"row","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-8":{"id":8,"type":"Group","parentId":0,"style":{"varName":"pParent","preferredSize":[0,0],"margins":0,"orientation":"row","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-9":{"id":9,"type":"Panel","parentId":8,"style":{"varName":"four","text":"Four","preferredSize":[0,0],"margins":10,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-10":{"id":10,"type":"StaticText","parentId":9,"style":{"varName":null,"text":"Praesent tempus.","justify":"left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-11":{"id":11,"type":"Panel","parentId":8,"style":{"varName":"five","text":"Five","preferredSize":[0,0],"margins":10,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-12":{"id":12,"type":"StaticText","parentId":11,"style":{"varName":null,"text":"Duis semper, risus ac elementum.","justify":"left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-13":{"id":13,"type":"Panel","parentId":8,"style":{"varName":"six","text":"Six","preferredSize":[0,0],"margins":10,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-14":{"id":14,"type":"StaticText","parentId":13,"style":{"varName":null,"text":"Mauris elementum auctor arcu sit","justify":"left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-15":{"id":15,"type":"Group","parentId":0,"style":{"varName":"pGrampa","preferredSize":[0,0],"margins":0,"orientation":"row","spacing":10,"alignChildren":["left","center"],"alignment":null}},"item-16":{"id":16,"type":"Button","parentId":3,"style":{"varName":"save","text":"save or whatever","justify":"center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-17":{"id":17,"type":"Button","parentId":13,"style":{"varName":"cancel","text":"cancel","justify":"center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-18":{"id":18,"type":"Divider","parentId":3,"style":{"varName":null}},"item-19":{"id":19,"type":"Divider","parentId":3,"style":{"varName":null}},"item-20":{"id":20,"type":"Divider","parentId":3,"style":{"varName":null}},"item-21":{"id":21,"type":"Divider","parentId":3,"style":{"varName":null}}},"order":[0,15,7,1,2,3,4,19,21,20,18,16,5,6,8,9,10,11,12,13,14,17]}
*/

// DIALOG
// ======
var dialog = new Window("dialog");
    dialog.text = "Dialog";
    dialog.orientation = "column";
    dialog.alignChildren = ["center","top"];
    dialog.spacing = 10;
    dialog.margins = 16;

// PGRAMPA
// =======
var pGrampa = dialog.add("group");
    pGrampa.orientation = "row";
    pGrampa.alignChildren = ["left","center"];
    pGrampa.spacing = 10;
    pGrampa.margins = 0;

// PPARENT
// =======
var pParent = pGrampa.add("group");
    pParent.orientation = "row";
    pParent.alignChildren = ["left","top"];
    pParent.spacing = 10;
    pParent.margins = 0;

// ONE
// ===
var one = pParent.add("panel");
    one.text = "One";
    one.orientation = "column";
    one.alignChildren = ["left","top"];
    one.spacing = 10;
    one.margins = 10;

var statictext1 = one.add("statictext");
    statictext1.text = "Praesent tempus.";

// TWO
// ===
var two = pParent.add("panel");
    two.text = "Two";
    two.orientation = "column";
    two.alignChildren = ["left","top"];
    two.spacing = 10;
    two.margins = 10;

var statictext2 = two.add("statictext");
    statictext2.text = "Duis semper, risus ac elementum.";

var divider1 = two.add("panel");
    divider1.alignment = "fill";

var divider2 = two.add("panel");
    divider2.alignment = "fill";

var divider3 = two.add("panel");
    divider3.alignment = "fill";

var divider4 = two.add("panel");
    divider4.alignment = "fill";

var save = two.add("button");
    save.text = "save or whatever";
    save.justify = "center";

// THREE
// =====
var three = pParent.add("panel");
    three.text = "Three";
    three.orientation = "column";
    three.alignChildren = ["left","top"];
    three.spacing = 10;
    three.margins = 10;

var statictext3 = three.add("statictext");
    statictext3.text = "Mauris elementum";

// PPARENT1
// ========
var pParent1 = dialog.add("group");
    pParent1.orientation = "row";
    pParent1.alignChildren = ["left","top"];
    pParent1.spacing = 10;
    pParent1.margins = 0;

// FOUR
// ====
var four = pParent1.add("panel");
    four.text = "Four";
    four.orientation = "column";
    four.alignChildren = ["left","top"];
    four.spacing = 10;
    four.margins = 10;

var statictext4 = four.add("statictext");
    statictext4.text = "Praesent tempus.";

// FIVE
// ====
var five = pParent1.add("panel");
    five.text = "Five";
    five.orientation = "column";
    five.alignChildren = ["left","top"];
    five.spacing = 10;
    five.margins = 10;

var statictext5 = five.add("statictext");
    statictext5.text = "Duis semper, risus ac elementum.";

// SIX
// ===
var six = pParent1.add("panel");
    six.text = "Six";
    six.orientation = "column";
    six.alignChildren = ["left","top"];
    six.spacing = 10;
    six.margins = 10;

var statictext6 = six.add("statictext");
    statictext6.text = "Mauris elementum auctor arcu sit";

var cancel = six.add("button");
    cancel.text = "cancel";
    cancel.justify = "center";


// CUSTOM SIZING

// Column 1
matchSize( dialog, [one, four], 'width' );
// Column 2
matchSize( dialog, [two, five], 'width' );
// Column 3
matchSize( dialog, [three, six], 'width' );

// Top row
matchSize( dialog, [one, two, three], 'height' );
// Bottom row
matchSize( dialog, [four, five, six], 'height' );

// Buttons
matchSize( dialog, [save, cancel], 'width' );

function matchSize( dialog, array, direction ) {
  
  dialog.layout.layout();
  var max = [null, null, 0];
  
  for ( var i=0; i < array.length; i++ ) {
    var item = array[i];
    var size = item.size[(direction === 'width' ? 0 : 1)];
    max = size >= max[2] ? [ i, item, size] : max;
  }
  
  for ( var i=0; i < array.length; i++ ) {
    var item = array[i];
    item.minimumSize[ direction ] = max[2];
    dialog.layout.layout(true);
  }
  
}

dialog.show();