13 Replies Latest reply on Mar 2, 2015 6:11 AM by Laubender

    ScriptUI : drawString() alignment

    UQg Level 4

      I'm trying to make some ScriptUI title, made of a short line (stroked path), followed by a text using drawString(), and then another stroked path.

      The whole thing should look like, roughly, the bright screenshot (ESTK CC2014), where it works fine.

      However in the main app (for me, After Effects, CC 2014), the alignment is wrong.

       

      I'm afraid this is on of the many CC new features that can't be fixed, but if someone has a workaround, or can spot my mistake, please let me know.

       

      Xavier.

       

      drawString_AE.pngdrawString_ESTK.png

       

       

      function drawTitle(drawState){
          // 'this' is expected to be an empty group, with a property called "_text" : a string
          // the function is the onDraw callback for that group
          // it will draw on the same line, centered vertically:
          //    (1) a 8px long horizontal line, 
          //    (2) followed by  this._text, in fontsize = 10, 
          //    (3) and finally another horizontal line (with "fill alignment")
              
          var gfx = this.graphics;
          
          if (gfx.font.size!==10) gfx.font  = ScriptUI.newFont(gfx.font.name, gfx.font.style, 10);
          
          var pen = gfx.newPen(gfx.PenType.SOLID_COLOR, [0.25,0.8,0.9], 1);
          var textSize = gfx.measureString(this._text, gfx.font);
          
          var y0 = this.size[1]>>1;            // vertical center of "this"
          var y1 = y0 - (textSize[1]>>1);        // ordinate at which the text should be drawn
          var x, y;
      
          x=0; y= y0;
          // draw first path
          gfx.newPath();
          gfx.moveTo(x,y);
          x+= 8;
          gfx.lineTo(x,y);
          gfx.strokePath(pen);
          
          // draw text
          x+=2;
          y= y1;
          gfx.moveTo(x, y);
          gfx.drawString(this._text, pen, x, y);
          
          // draw second path
          x += textSize[0]+2;
          y= y0;            
          gfx.newPath();
          gfx.moveTo(x,y);
          x = this.size[0];
          gfx.lineTo(x,y);
          gfx.strokePath(pen);
          
          return;
          };
          //
          
      var ooo = new Window("dialog", "drawString()");
      var WIDTH = 100;
      var HEIGHT = 18+4;
      var MARGINS = 10;
      var decoration = "group{size : "+[WIDTH, HEIGHT].toSource()+", st : StaticText{text : 'value: ', location : [0,2], size: [50, 18]}, et : EditText{text : '100 ', location : [55,2], size: [45, 18]}}";
      
      var row1 = ooo.add(decoration);
      row1.location = [MARGINS, MARGINS];
      
      var title = ooo.add("group");
      title._text = "Some title";
      title.onDraw = drawTitle;
      title.size = [WIDTH, 20];
      title.location = [MARGINS, row1.bounds[3]];
      
      var row2 = ooo.add(decoration);
      row2.location = [MARGINS, title.bounds[3]];
      
      ooo.show();
      
        • 1. Re: ScriptUI : drawString() alignment
          Peter Kahrel Adobe Community Professional & MVP

          As Marc mentioned a few days ago, in CC you can't use font, font size, colours, and many other things related to graphics.

           

          Peter

          • 2. Re: ScriptUI : drawString() alignment
            Trevorׅ Adobe Community Professional

            Hi Xavier,

             

            2 workarounds:

            1) As CC on all platforms is consistent you can make a list of all the element types like radio buttons, statictexts, editboxes etc. and there vertical offsets and add them to each element.

             

            2) My by far preferred method is to replace all the built in widgets with png sprite ones. In you case just draw a line or 2 in fireworks or whatever and use that / them.  Marc has a sprite button function on his sites.

             

            /******************* Method 1 - Use regular SUI Elements and Vertical Adjustments - pain in the neck ****************************/
            var isCC = parseInt(app.version) >= 9,
                radiobuttonAlignFix,
                editTextAlignFix,
                checkboxAlignFix,
                staticTextAlignFix;
            if (isCC) {
                radiobuttonAlignFix = 2;
                editTextAlignFix = 0;
                checkboxAlignFix = 2;
                staticTextAlignFix = 1;
            }
            else radiobuttonAlignFix = editTextAlignFix = checkboxAlignFix = staticTextAlignFix = 0; // depending on if coordinates are specified this needs to be set.
            var w = new Window('dialog'),
                g = w.add('group'),
                st = g.add('statictext', undefined, "Are theses aligned?"),
                cb = g.add('checkbox'),
                rb = g.add('radiobutton'),
                et = g.add('edittext', undefined, "Were theses aligned?");
            
            if (isCC) w.onShow = function () {
                st.location.y += staticTextAlignFix;
                cb.location.y += checkboxAlignFix;
                rb.location.y += radiobuttonAlignFix;
                et.location.y += editTextAlignFix;
            }
            
            /******************* Method 2 - Use PNGs - easy peasy ****************************/
            var blackLine = ScriptUI.newImage("\u0089PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x00!\x00\x00\x00\x01\b\x06\x00\x00\x00PH\u00C7Y\x00\x00\x00\x04sBIT\b\b\b\b|\bd\u0088\x00\x00\x00\tpHYs\x00\x00\x0E\u009C\x00\x00\x0E\u009C\x01\x07\u0094S\u00DD\x00\x00\x00\x1CtEXtSoftware\x00Adobe Fireworks CS6\u00E8\u00BC\u00B2\u008C\x00\x00\x00\x16tEXtCreation Time\x0003/01/15\u00FE\u00F8_V\x00\x00\x00\x10IDAT\b\u0099cd``\u00F8\u00CF0\u00C0\x00\x00\u0081\u0089\x01\x01\u00BB\u00ED\x118\x00\x00\x00\x00IEND\u00AEB`\u0082");
            var g2 = w.add('group'),
                l1 = g2.add('image', undefined, blackLine),
                st2 = g2.add('statictext', undefined, "Are theses aligned?"),
                l2 = g2.add('image', undefined, blackLine);
            w.show ();
            
            • 3. Re: ScriptUI : drawString() alignment
              Trevorׅ Adobe Community Professional

              Hi Xavier,

               

              I admit I was being a bit enigmatic when I wrote one "In you case just draw a line or 2 in fireworks or whatever and use that / them."

              The one line method is as follows.

               

              Peter, what color does the text come out by you?

               

              // Method for center aligning lines by Trevor www.creative-scripts.com (hopefully coming very soon) https://forums.adobe.com/message/7240999#7240999
              
              var w = new Window('dialog');
              
              // this blackLine is a binary encoding of a 20 * 20 png can use different pngs
              var blackLine = ScriptUI.newImage("\u0089PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x00\x14\x00\x00\x00\x14\b\x06\x00\x00\x00\u008D\u0089\x1D\r\x00\x00\x00\x04sBIT\b\b\b\b|\bd\u0088\x00\x00\x00\tpHYs\x00\x00\x0E\u009C\x00\x00\x0E\u009C\x01\x07\u0094S\u00DD\x00\x00\x00\x1CtEXtSoftware\x00Adobe Fireworks CS6\u00E8\u00BC\u00B2\u008C\x00\x00\x00\x16tEXtCreation Time\x0003/01/15\u00FE\u00F8_V\x00\x00\x00\"IDAT8\u008Dcd``\u00F8\u00CF@E\u00C0DM\u00C3F\r\x1C5p\u00D4\u00C0Q\x03G\r\x1CJ\x06\x02\x00\u00CE\u00EE\x01'\u0086y$W\x00\x00\x00\x00IEND\u00AEB`\u0082");
              var g = w.add('group'),
                  l1 = makeSizeImage (g, blackLine, 20, 1),
                  et = g.add('edittext', undefined, "Are theses aligned?"),
                  st = g.add('statictext', undefined, "Are theses aligned?"),
                  l2 = makeSizeImage (g, blackLine, 80,5),
                  l3 = makeSizeImage (g, blackLine, 40,11);
                  l4 = makeSizeImage (g, blackLine);
              
              g.spacing = 3;
              et.graphics.foregroundColor = st.graphics.foregroundColor = w.graphics.newPen(w.graphics.PenType.SOLID_COLOR,[0, .5, 1],1);
              function makeSizeImage (_parent, png, _width, _height) {
                  var newImage = _parent.add('image', undefined, png);
                  $.writeln(png.size)
                  _height = _height || png.size.height;
                  _width = _width || png.size.width;
                  newImage.size = [_width, _height];
                  newImage.onDraw = function () {this.graphics.drawImage (png, 0, 0, _width, _height);};
                  return newImage;
              }
              w.show ();
              
              • 4. Re: ScriptUI : drawString() alignment
                Trevorׅ Adobe Community Professional

                _2015-03-02_09-08-27.png

                Changed the png color for the screenshot.

                • 5. Re: ScriptUI : drawString() alignment
                  Laubender Adobe Community Professional & MVP

                  @Trevor – I tested your code in answer #3.

                  Here some results:

                   

                  InDesign CC v9.3.0, CC 2014.2, Illustrator CC 2014 v18.1.1 on MacBook Pro OSX 10.7.5:

                   

                  Trevor-OSX-10.7.5-CC-2014.2.png

                   

                  InDesign CS6 v8.1.0, CS 5.5, Illustrator CS5.1 v15.1.0 on MacBook Pro OSX 10.7.5:

                   

                  Trevor-OSX-10.7.5-CS6-v8.1.0.png

                   

                  Uwe

                  • 6. Re: ScriptUI : drawString() alignment
                    Laubender Adobe Community Professional & MVP

                    With DarkUI set to max InDesign CC 2014.2 will show the following:

                     

                    Trevor-CC-2014.2-DarkUIenabled.png

                     

                    Uwe

                    • 7. Re: ScriptUI : drawString() alignment
                      Trevorׅ Adobe Community Professional

                      Hi Uwe,

                       

                      Just one note regarding Illustrator as you mentioned it.

                      It is a much more sensitive program than ID so it's better to have scripts write a resource file from a string rather than just using the ScriptUI.newImage method.

                      At this point I'm not experienced with After Effects scripting so I don't know what method to use there.

                       

                      Either way in my opinion it's a better way to go than using the various draw methods unless one needs variable sized diagonals etc.

                       

                      Regards

                       

                      Trevor

                       

                      P.s. I also changed the color of my UI for the screenshot

                      • 8. Re: ScriptUI : drawString() alignment
                        Laubender Adobe Community Professional & MVP

                        Hi Trevor,

                         

                        In InDesign and Illustrator usually I use brightness set to 100% for my UI.

                        I do not much work in AfterEffects, but usually I leave it the "Standard" there.

                        For teaching PhotoShop CS6 I always switch to max brightness, because my students in the back of the room would have problems decipher small details of the UI when projected to the screen in my back.

                         

                        I can see a benefit by working with Dark UI in AfterEffects and (sometimes) in PhotoShop.

                         

                        For ScriptUI it is a fiasco…

                         

                        Uwe

                        • 9. Re: ScriptUI : drawString() alignment
                          Laubender Adobe Community Professional & MVP

                          @Trevor – see also the difference of the length of the text in your Windows version vs. the Mac OS.

                          The question mark is cut on Mac OSX.

                           

                          Uwe

                          • 10. Re: ScriptUI : drawString() alignment
                            UQg Level 4

                            Hi Trevor,

                            thanks much for all the efforts.

                            The image + text idea works fine.

                            I'm still a bit disappointed though, I was trying to find a more flexible solution, that is, one that does not rely on any predefined input like an image.

                            The drawPath+drawString method looked promising, it is actually possible to change font size and color on custom strings, i just don't understand why the string is plot that far off from what i asked.

                             

                            I've also noticed those alignment changes for regular widgets like checkboxes, radiobuttons and static texts. Pain in the neck indeed.

                             

                            @Peter: i moved to CC only recently. I takes a bit of time to understand which parts of ScriptUI have been screwed, somehow.

                             

                            Xavier.

                            • 11. Re: ScriptUI : drawString() alignment
                              UQg Level 4

                              Ok, so after some more trial, i got this (empirical stuff):

                               

                              Before CC, group.graphics.drawString("Hello", x, y) would plot the string "Hello" so that the top left corner of the "H" appears at coordinate (x,y) of the group.

                               

                              Since CC, group.graphics.drawString("Hello", x, y) plots the string "Hello" so that the top left corner of the "H" appears at coordinate (x, y+group.size[1]/2) of the group: there is an automatic vertical offset equal to half the group's height.

                               

                              So for instance, group.graphics.drawString("Hello", x, 0) will plot the string so that the top left corner of the H is on the vertical center of the group.

                              Therefore, to center a text vertically, one has to subtract half of the text height.

                              And one would expect that

                               

                              group.graphics.drawString("Hello", x, Math.floor(-textSize[1])/2);    // text is centered vertically
                              
                              
                              
                              

                               

                              actually centers the string vertically (where textSize = group.graphics.measureString("Hello"))

                               

                              But this is were things start to be really clumsy, as unlike in previous versions, the text width and height calculated by measureString are not the exact width and height of the string, they include bottom and right margins (and no left and top margins) that are really hard to figure out.

                              For instance, group.graphics.measureString("Some string") with a font size of 10 gives [48,12] in ESTK and in previous versions of the suite, and [56,15] in CC2014.

                              So one should not subtract Math.floor(textSize[1])/2, but "a bit less".

                              Hence i give up

                               

                              Best answer @Trevor, thanks!

                               

                              Xavier.

                              • 12. Re: ScriptUI : drawString() alignment
                                Trevorׅ Adobe Community Professional

                                Hi Xavier and Uwe,

                                 

                                Xavier,

                                 

                                Glad to help.  As I wrote I use pngs for all the widgets I can as there functionality and layout is so much easier to deal with (once one has set up the basic functions to copy from script to script) than the native SUI elements.  I find it a complete waste of time doing all the hacks to try get the native SUI stuff to work as desired.

                                Peter's got a method of binary conversion of png's (actually all files as it happens) in his guide.

                                 

                                Uwe,

                                 

                                Yes I did notice the difference.  It is not so simple! .

                                Take a look at the following script and the screenshots on Windows and Mac.  As you put it, a fiasco!

                                 

                                var w = new Window ('dialog'),
                                    g1 = w.add('group'),
                                    g2 = w.add('group'),
                                    g3 = w.add('group')
                                    g4 = w.add('group')
                                    et1 = g1.add('edittext', undefined, "Better ?"),
                                    et2 = makeFittedEditText(g2, "onDraw Text Method, Better ?"),
                                    et3 = g3.add('edittext', undefined, "onDraw Width Method, Better ?"),
                                    et4 = g4.add('edittext',  undefined, "Character Method, Better ?");
                                et4.characters = 20;
                                g1.add('statictext', undefined, "No, this is with no fixes");
                                g2.add('statictext', undefined, "No on Windows the height got messed up and so did the alignment, OK for Mac");
                                g3.add('statictext', undefined, "Yes ;-)");
                                g4.add('statictext', undefined, "Would go for this character setting method at least 99% of the time :-)");
                                w.add('statictext', undefined, "Not bothering with measure string method");
                                
                                g1.alignment = g2.alignment = g3.alignment = g4.alignment = 'fill';
                                
                                et3.onDraw = function () {this.size.width =this.size.width + 4;
                                    this.onDraw = null;
                                    }
                                w.show ();
                                
                                function makeFittedEditText (_parent, _string) {
                                        e = _parent.add('edittext', undefined, _string + "_");
                                        e.onDraw = function () {this.text = _string}
                                    return e;
                                }
                                

                                 

                                _2015-03-02_15-05-13.png

                                Screen Shot 2015-03-02 at 15.02.03.png

                                • 13. Re: ScriptUI : drawString() alignment
                                  Laubender Adobe Community Professional & MVP

                                  Trevor,

                                  of course its not that easy, because totally different fonts are used to render the text.

                                  Their X height could be different, even their baseline positions relative to their X height.

                                   

                                  I think, both of the OS implementations got it wrong:

                                  Mac OSX: No room for descenders

                                  Windows OS: No room for ascenders

                                   

                                  The best would be Adobe would use the same base font on every platform and model all SUI rendering of text around it.

                                  I'm not too much into ScriptUI, its something like love-hate relationship for me ;-)

                                   

                                  Uwe