Article View: adobe.scripting.indesign
Article #15536Re: Please Help with auto scaling textframe
From: Dave_Saunders
Date: Mon, 24 Nov 2003 00:36
Date: Mon, 24 Nov 2003 00:36
262 lines
10358 bytes
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!webxReferences:
<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