🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: adobe.scripting.indesign
Article #15536

Re: Please Help with auto scaling textframe

#15536
From: Dave_Saunders
Date: Mon, 24 Nov 2003 00:36
262 lines
10358 bytes
You do know that there's a command on the Object menu that can be used to do this? Although it only works for orphaned text frames, and it always compresses the frame to the top left corner.

I can't help you with VB, but here's a JavaScript I wrote to do the job. It uses the selected proxy point to determine the direction to compress the text frame. If you choose and edge point, it compresses only in the one direction.

It also doesn't care if the text frame is an orphan. Rather it checks to see if the resize affects the number of characters in the frame and warns you if it changes. There are some bugs I know about documented in the script. They're a bit esoteric. I wrote this more as a learning exercise than anything else. I also failed to use some built-in JS features because at the time I didn't know about them.

Here's the script:

//DESCRIPTION: Proxy Aware Fit Text Frame to Content
// by Dave Saunders

/* Bug Warning
   This script has the same bug as the Fit Frame to Content
   facility in the Object/Fitting submenu, which is that for
   a text frame that contains less than a paragraph and to
   which negative tracking has been applied, the fitting is
   overly aggressive because the last insertion point is to
   the left of the end of the last character.
* /

try
{
theClass = app.selection[0].constructor.name;
}
catch(e)
{
alert("Error Occurred: " + e.description);
exit();
}

//save users measurement preferences
userHoriz = app.documents[0].viewPreferences.horizontalMeasurementUnits;
userVert = app.documents[0].viewPreferences.verticalMeasurementUnits;
app.documents[0].viewPreferences.horizontalMeasurementUnits = MeasurementUnits.picas;
app.documents[0].viewPreferences.verticalMeasurementUnits = MeasurementUnits.picas;

//So, we have a selection; what is it?

if ((theClass == "Text") || (theClass == "InsertionPoint")){
 app.select (app.selection[0].parentTextFrame);
 theClass = app.selection[0].constructor.name;
}

//It still might not be a text frame:

if (theClass == "TextFrame"){
 theFrame = app.selection[0];
 if (theFrame.textFramePreferences.textColumnCount > 1){
  alert("Selected Text Frame has more than one column; no action taken.");
  myExit();
 }
 charCount = theFrame.texts[0].length;
 if (charCount == 0) {
  alert("Selected text frame is empty; no action taken.");
  myExit();
 }

theProxy = app.layoutWindows[0].transformReferencePoint;
 theBounds = theFrame.geometricBounds;

// What if the frame is overset to start with?
 // Need to limit this test by checking that this is the last text frame
 frameOverflows = false;
 if ((theFrame.overflows) && (theFrame == theFrame.parentStory.lastTextFrame)){
  //frame overflows; let's try to deal with it
  frameOverflows = true;
  pageSize = app.layoutWindows[0].activePage.bounds;
  newRight = pageSize[3] - pageSize[1] + theBounds[1];
  newBottom = pageSize[2] - pageSize[0] + theBounds[0];
  adjustBounds = new Array(theBounds[0],theBounds[1],newBottom,newRight)
  resizeFrame (theFrame, theProxy, adjustBounds);
  //before checking for overflow again, force composer to act
  newCharCount = theFrame.texts[0].length;
  if (theFrame.overflows){
   //frame still overflows, so revert
   theFrame.geometricBounds = theBounds;
  } else {
   //frame no longer overflows, so all's well
   frameOverflows = false;
   charCount = theFrame.texts[0].length;
   theBounds = theFrame.geometricBounds;
  }
 }

origHeight = theBounds[2] - theBounds[0];
 origWidth = theBounds[3] - theBounds[1];
 userJust = theFrame.textFramePreferences.verticalJustification
 theFrame.textFramePreferences.verticalJustification = VerticalJustification.topAlign;

// Let's go resizing
 newBounds = myFit();
 theFrame.textFramePreferences.verticalJustification = userJust;

resizeFrame (theFrame, theProxy, newBounds);

// If we're now overflowing but shouldn't be and corner effects is on, try to recover
 // First, force the composer to act
 charNew = theFrame.texts[0].length;

if ((theFrame.overflows) && (frameOverflows == false) && (theFrame.cornerEffect != CornerEffects.none)){
  // We should be able to recover from this
  widthAdjust = ((theFrame.cornerRadius/12) - theFrame.textFramePreferences.insetSpacing) * 4;
  if (widthAdjust > 0){
   // No point if widthAdjust is negative
   while (theFrame.overflows) {
   // This looks like an infinite loop but the fact that frameOverflows started out false
   // should mean that it can't go on for long
    adjustBounds = theFrame.geometricBounds;
    adjustBounds[3] = adjustBounds[3] + widthAdjust;
    resizeFrame (theFrame, theProxy, adjustBounds);
    charNew = theFrame.texts[0].length;
   }

// the different effects have vastly different impacts, so iterate
   myContinue = true
   while (myContinue){
    if (theFrame.overflows){
     widthAdjust = myAbs(widthAdjust/2)
    } else {
     widthAdjust = 0 - myAbs(widthAdjust/2)
    }
    adjustBounds = theFrame.geometricBounds;
    adjustBounds[3] = adjustBounds[3] + widthAdjust;
    resizeFrame (theFrame, theProxy, adjustBounds);
    charNew = theFrame.texts[0].length;
    if ((theFrame.overflows == false) && (myAbs(widthAdjust) < 0.03)){
     myContinue = false;
    }
   }



}
 }
 if ((theFrame.overflows) && (frameOverflows == true)) {
  alert("The proxy point you have active means that the overset text remains overset.")
 }

charNew = theFrame.texts[0].length
 if (charNew != charCount) {
  alert("Text in frame changed due to unexpected circumstances; text wrap? corner effects?")
 }



} else {
 alert("Please select a text frame and try again.");
}
 myExit();

function myAbs(n){
 if (n < 0){
  return (0 - n);
 } else {
  return (n)
 }
}

function resizeFrame (theFrame, theProxy, targBounds){
 // This function performs a proxy-constrained resize. The targBounds really
 // define the desired width and height.

curBounds = theFrame.geometricBounds;
 origHeight = curBounds[2] - curBounds[0];
 origWidth = curBounds[3] - curBounds[1];

if ((theProxy == AnchorPoint.leftCenterAnchor) || (theProxy == AnchorPoint.rightCenterAnchor)) {
  targBounds[2] = curBounds[2];
 } else if ((theProxy == AnchorPoint.topCenterAnchor) || (theProxy == AnchorPoint.bottomCenterAnchor)) {
  targBounds[3] = curBounds[3];
 }

changedHeight = targBounds[2] - targBounds[0];
 changedWidth = targBounds[3] - targBounds[1];

// Now move

xDelta = 0
 yDelta = 0

if ((theProxy == AnchorPoint.bottomLeftAnchor) || (theProxy == AnchorPoint.bottomCenterAnchor) || (theProxy == AnchorPoint.bottomRightAnchor)) {
  yDelta = origHeight - changedHeight;
 } else if ((theProxy == AnchorPoint.leftCenterAnchor) || (theProxy == AnchorPoint.centerAnchor) || (theProxy == AnchorPoint.rightCenterAnchor)) {
  yDelta = (origHeight - changedHeight)/2;
 }
 if ((theProxy == AnchorPoint.topRightAnchor) || (theProxy == AnchorPoint.rightCenterAnchor) || (theProxy == AnchorPoint.bottomRightAnchor)) {
  xDelta = origWidth - changedWidth;
 } else if ((theProxy == AnchorPoint.topCenterAnchor) || (theProxy == AnchorPoint.centerAnchor) || (theProxy == AnchorPoint.bottomCenterAnchor)) {
  xDelta = (origWidth - changedWidth)/2;
 }

targBounds[0] = targBounds[0] + yDelta;
 targBounds[1] = targBounds[1] + xDelta;
 targBounds[2] = targBounds[2] + yDelta;
 targBounds[3] = targBounds[3] + xDelta;

theFrame.geometricBounds = targBounds;
}

function myExit(){
 app.documents[0].viewPreferences.horizontalMeasurementUnits = userHoriz
 app.documents[0].viewPreferences.verticalMeasurementUnits = userVert
 exit();
}

function myFit(){
 lineCount = theFrame.lines.length;
 maxRight = -100000;
 for (x = 0; x < lineCount; x++){
  if (theFrame.lines[x].length > 1){
   //it's possible for the last insertion point of the last line to be overset, so:
   // There's a bug here. What if the last insertion point of the last line is in the next frame?
   // It could nonetheless have the same baseline and
   // so the wrong insertion point would be used

try
   {
    if (theFrame.lines[x].insertionPoints[-1].baseline == theFrame.lines[x].insertionPoints[-2].baseline){
     theRight = theFrame.lines[x].insertionPoints[-1].horizontalOffset;
    } else {
     theRight = theFrame.lines[x].insertionPoints[-2].horizontalOffset;
    }
   }
   catch(e)
   {
   //catch needs a parameter, even if we ignore it
     theRight = theFrame.lines[x].insertionPoints[-2].horizontalOffset;
   }
   //What follows ought to check for centered and adjust
   theRight = theRight + theFrame.lines[x].rightIndent;
   if (theRight > maxRight){
    maxRight = theRight;
   }
  }
 }
 strokeWeight = theFrame.strokeWeight/12;
 //new wrinkle: have to deal with stroke alignment
 strokeAlign = theFrame.strokeAlignment;
 if (strokeAlign == StrokeAlignment.outsideAlignment){
  strokeMult = 0;
 } else if (strokeAlign == StrokeAlignment.centerAlignment){
  strokeMult = 0.5;
 } else {
  strokeMult = 1;
 }

frameInsets = theFrame.textFramePreferences.insetSpacing;
 // note: sometimes frameInsets is a number; sometimes an array
 if (typeof (frameInset) == "number"){
  frameInsets = [frameInsets,frameInsets,frameInsets,frameInsets];
 }

bottomAdj = strokeWeight * strokeMult + frameInsets[2];
 widthAdj = strokeWeight * strokeMult * 2 + frameInsets[1] + frameInsets[3];
 newBounds = theFrame.geometricBounds;
 newBounds[2] = theFrame.texts[0].characters[-1].baseline + bottomAdj;
 newBounds[3] = maxRight + widthAdj;
 //theFrame.geometricBounds = newBounds; not needed, just return the bounds
return (newBounds)
}

Dave
Technical Details
Message-ID: <2cce8df6.0@webx.la2eafNXanI>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!fu-berlin.de!newsfeed01.sul.t-online.de!t-online.de!webx
References: <2cce8df6.-1@webx.la2eafNXanI>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f939a,dddfa87ffd4ded89,start
X-Google-Attributes: gidf939a,public
X-Google-ArrivalTime: 2003-11-23 16:37:54 PST
From: Dave_Saunders@adobeforums.com
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!fu-berlin.de!newsfeed01.sul.t-online.de!t-online.de!webx
Newsgroups: adobe.scripting.indesign
Subject: Re: Please Help with auto scaling textframe
Message-ID: <2cce8df6.0@webx.la2eafNXanI>
Date: Sun, 23 Nov 2003 16:36:11 -0800
References: <2cce8df6.-1@webx.la2eafNXanI>
Lines: 300
MIME-Version: 1.0
Content-Type: text/plain; charset="ISO-8859-1"
Content-Transfer-Encoding: 8bit