Tuesday, January 09, 2007

 

Back to the Pasteboard

OK, I've confirmed my suspicion that the current version of the script hits a run-time error if a locked layer holds a pasteboard item. I'm inclined to take the easy way out here and simply exclude any such layers from this game. If the user wants to add it back in, all he need do is unlock the layer and run the script again.

So, now let's get down to the hard part: how to prevent items from colliding with pages?

I think I'm going to assume that only left/right collisions are possible. I don't know enough about the dtptools plug-in that allows different sized pages, but since I don't own it and I'm writing this script as much for me as anyone else (so few people having taken any interest), I might as well not worry about things that aren't going to affect me.

So, for any item, I have three rectangles to worry about:
  1. The geometric bounds of the item
  2. The bounds of the source spread
  3. The bounds of the target spread
The only items I have to worry about are those that are wholly to the left or right of the source spread. I want them to appear the same distance to the left or right of the target spread. Notice that any item on the pasteboard above or below the pages that is not wholly to the left or right will not slide when moved to the target. Being where they are, they can't possibly collide with a page.

Of course, getting the bounds of a spread is non-trivial unless you're using Spread as the ruler origin for your document, so I'm going to have to switch to spread at the start and switch back afterwards. Hmm, that means we'd better reset the zero point too and restore it. That means that for an item to be wholly left, it's right-bounds value must be negative because the spread left bound will always be zero; still, it's probably safer to compare just in case.

Oh wait a cotton-picking minute! Because of the way that the spread-based coordinates work, the left side looks after itself. The coordinates are such that an item to the left of the spread will always be the same distance to the left. It's only the right side we have to worry about. Which means that all I have to worry about is the difference in width between the two spreads. So, perhaps I shouldn't even worry about whether or not an item is wholly right, just if it is right of the zero-X I should move it by the difference in widths.

Well, what do you know? It seems to work!
//DESCRIPTION: Moves all Pasteboard Items to Pasteboard of Current Spread

if (app.documents.length == 0) { exit() }
movePBitems(app.documents[0]);

function movePBitems(myDoc) {
  if (app.activeWindow.constructor.name == "StoryWindow") { return }
  var uO = myDoc.viewPreferences.rulerOrigin;
  var uZP = myDoc.zeroPoint;
  myDoc.viewPreferences.rulerOrigin = RulerOrigin.spreadOrigin;
  myDoc.zeroPoint = [0,0];
  myObjs = myDoc.pageItems.everyItem().parent;
  var moveables = new Array();
  for (var j = myObjs.length - 1; j >= 0; j--) {
    if (myObjs[j].constructor.name == "Page") { continue }
    moveables.push(myDoc.pageItems[j].id);
  }
  var mySpread = app.activeWindow.activeSpread;
  var targSpreadWidth = getSpreadWidth(mySpread);
  for (var j = moveables.length - 1; j >= 0; j--) {
    var myObj = myDoc.pageItems.itemByID(moveables[j]);
    var sourceSpread = myObj.parent;
    if (sourceSpread == mySpread) { continue }
    var sourceWidth = getSpreadWidth(sourceSpread);
    var Shift = 0;
    if (myObj.geometricBounds[3] > 0) {
      Shift = targSpreadWidth - sourceWidth;
    }
    var myBounds = myObj.geometricBounds;
    if (myObj.locked) { continue }
    try {
      myObj.move(mySpread);
    } catch(e) { continue } // myObj must be on locked layer
    myObj.move([myBounds[1] + Shift, myBounds[0]]);
  }
  myDoc.viewPreferences.rulerOrigin = uO;
  myDoc.zeroPoint = uZP;
  
  function getSpreadWidth(spread) {
    var my1stBounds = spread.pages[0].bounds;
    var myLastBounds = spread.pages[-1].bounds;
    return myLastBounds[3] - my1stBounds[1];
  }
} // end function movePBitems

Comments:
Wonderful!
I have tested the script with locked layers and multipage-spreads. It works very well.

Your fiddling with the position of the moved page item is fine. Good idea with the spread as ruler origin.
I have been wondering how you treat a right-hand page one as target without another page left of it. The second move-command solves this very well.

There is one thing I am wondering about. You store myDoc.pageItems.everyItem().parent to the var myObjs. Is therefor a certain reason? I expected to store myDoc.pageItems in myObjs and later to look at myObjs[j].parent.constructor.name:
if (myObjs[j].parent.constructor.name == "Page")

And there is another thing I am wondering about: the structure of your code:
Several times you use something like "if (...) {exit}" without "else {...}"
or
"if (...) {return}" without "else {...}"
or
"if (...) {continue}" without "else {...}"

This has made it difficult for me to find the end of the if-command. Is there a certain reason that you avoid the extended syntax with "else{}" or is it just a method to save characters or time?

Thanks
Martin
 
I use everyItem() to get all the parent references in one go. I think it is a bit more efficient. It could be that a document has a huge number of pageitems so efficiency can matter.

As for the if statements, if the "true" part of the logic breaks the flow, the else is not necessary because you only get past the if when the else condition holds. So, the else isn't needed. I hate it when scripts have lots of indents, so I do all I can to keep the indents to a minimum.
 
Harbs,

As usual, I didn't think about right-to-left documents. Does the x-axis go from right-to-left in such a document? Or is it just the text that goes from right to left? Where is the spine in such a document? Is it to the left or the right? How would the script recognize that it is working on a right-to-left document?

See what a sheltered life I've led?

I'm not sure about your question about the first page because I'm not sure I understand what difference you're talking about.

Dave
 
Harbs,

I think I understand. In a right-to-left document, what is returned by:

app.documents[0].pages[0].bounds

And, assuming there's a text frame on the page, what is returned by:

app.documents[0].pages[0].textFrames[0].geometricBounds

Thanks,

Dave
 
Hi Dave,

I've been only half-hazerdly following this topic.

The first one returns:

0,0,666,468

The second one returns:

134.25,99.4285714285714,544.5,366.75

Fred
 
Thanks for the feedback, guys. But I have more questions:

Does the ME version support both Left-to-Right and Right-to-Left documents?

Harbs,

Your suggestion only works for a certain kind of document. I need something that will do the job for any document. I have an idea, but the answer to the question above will influence the way I go about it. If all documents are Right-to-Left, then we could install a Script Label on to app.characterStyles[0] that would have one of three values:

"" -- need to go calculate the orientation
"LtR" -- this is a left-to-right installation
"RtL" -- this is a right-to-left installation.

That way, the task of determining the orientation is very easy once you've done it once. If this is an installation-wide setting, then we can quickly sort things out by creating a new, hidden document and setting it up the way we need it to know the answer to the question rather than examining the individual document.

But, if the orientation is document-specific, then we can use the same trick but for each document. We should avoid making this evaluation every time the script runs. But, if it is a document-specific issue and we have a document that is single-sided or which starts with an even-numbered page, it might be a challenge to work out.

We might need to temporarily create extra spreads to do the analysis.

Dave
 
Harbs,

Oh crud! Indeed, you're right. I wonder if there's any way of working out the actual size of the pasteboard to prevent that from happening.

We cross-posted.

Thanks,

Dave
 
You are actually changing the functionality in a manner you might not realize. As I have it now, items on the pasteboard to the right, move in and out as the width of the spread changes. Your change will move the item out if needed, but won't bring it back in again for a narrower spread, making the items out there harder to get at.

That was a deliberate part of the strategy.

Did you look into what happens to an item near the extreme left of the pasteboard on a single-page spread when moving to a double-page spread (in a L-t-R document)?

I'm on a couple of urgent projects today so I don't have much time for this right now.

Dave
 
Martin,

This is the first chance I've had to catch up with what you've been doing. It's a bit hard for me to get into the LtR/RtL issues because I don't have access to RtL documents.

Looking afresh at the situation where an item drops off the edge of the pasteboard, the good news is that it doesn't disappear into the ether. It still exists even though it is off the pasteboard. Ah, but if you select all with an item off the pasteboard, it severely limits how much you can move the selection, particularly if you have items at or near both edges of the pasteboard.

Hmm, the left side of the pasteboard is much more secure than the right side (in a LtR document). If you add pages to a spread, the pages eat into the space until there is less than a page of spare space on the right, but then it adds width to the pasteboard on both sides.

I have to wonder how much effort is actually worth putting into these odd-ball cases, although that's always the problem with scripts made available to the public. Do you try to deal with every contingency or just warn them that if they do this, odd things might happen.

I gather that the version of the script you're now using has moved on quite some way from mine, so I'm not sure how much I can follow some of your later messages. Is the bug you've found because of the extra tests you've been inserting? I rather think so.

Dave
 
I just tried your experiment with my original code and with the version you posted. My original works. Your version doesn't.

I am backed up with work at the moment so I can't explore further right now. Maybe later today.

Dave
 
the settings for the first page are different from those of the other page! why???????

Free PS3
 
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?