Skip to main content
Known Participant
January 4, 2011
Question

How To Prevent Recursive (Vicious Circle) Events

  • January 4, 2011
  • 3 replies
  • 2209 views

I am using the IDScriptingEventAdapter to capture the movement of PageItem's on the page, as follows:

    var adapter:IDScriptingEventAdapter = IDScriptingEventAdapter.getInstance();
    adapter.addEventListener(com.adobe.indesign.Event.AFTER_SELECTION_ATTRIBUTE_CHANGED, listener);
    adapter.addEventListener(com.adobe.indesign.Event.AFTER_SELECTION_CHANGED, listener);

The problem is that the listener() method contains commands which themselves move PageItem's - thereby firing itself recursively in a vicuous circle - thus causing stack overflow.

I tried this, but it doesn't help:

   public function listener(event:*):void
   {
    RemoveEventListeners(); // Removes the listener which fired the event
    MoveArounfPageItems(); // Move around PgaeItem's
    AddEventListeners(); // Put the listeners back
   }

I thought that removing the listeners would help, but apparently they are put back BEFORE the moved PageItem's fire their events.

What can I do?

TIA,

mlavie

This topic has been closed for replies.

3 replies

mlavieAuthor
Known Participant
January 5, 2011

Thanks Bob for your efforts. I guess that although the events are all esse

ntially at the App/LayoutWindow/Doc level (and NOT PageItem), I could check the app.Selected array as someone here suggested.

Bob - do you know if/when Adobe plans to support PageItem-level events (aside from BEFORE/AFTER_PLACE which already works)?

AGain - thanks,

mlavie

mlavieAuthor
Known Participant
January 4, 2011

Bob,

It is my understanding that only an App or LayoutWIndow is returned as a target, and not a PageItem, despite what the documentatation says. Am I wrong? And if I am wrong, I'd really appreciate an example of how to write the "addListener()" method for such a case.

Thanks - mlavie

Bob Stucky
Adobe Employee
Adobe Employee
January 4, 2011

Sorry, I should have been more deliberate in working

that example.

You can get other objects than just App or LayoutWindow (such as Document, Image, Link, ToolBox (really!) ).

In a bit, I'll post a utility that I wrote and use for figuring out what ID events fire when, and what kinds of objects are the targets.

Bob

Harbs.
Legend
January 4, 2011

Bob Stucky wrote:

...ToolBox (really!) ).

Now, that's interesting... I really have to find the time to play with this stuff...

Harbs

Bob Stucky
Adobe Employee
Adobe Employee
January 4, 2011

This one would probably be better posted to the CS5 SDK forum!

The events you're listening for are somewhat generic - AFTER_SELECTION_ATTRIBUTE_CHANGED, for example, is fired for all sorts of things, not just the movement of a PageItem.

In your listener you'll have to put some conditions that check to see if you actually want to respond to the event. Now, if a page item moves, and then your listener moves it, you'll have a circular event loop no matter what. To solve that, you'll need to save some state information in the object itself, say with a label. Something like this should do it (not tested in any way).

public function listener( event: * ): void

     // decide if the event it something we want to handle   

     if ( event.target is TextFrame ) {

          var tf: TextFrame = event.target as TextFrame;

          var state: String = tf.extractLabel( "myMoveState" );

          // check to see if we moved it or the user did...

          if ( state == "WeMovedIt" ) {

               tf.insertLabel( "myMoveState", "WeDidNotMoveIt" );

          } else {

               tf.insertLabel( "myMoveState", "WeMovedIt" );

               functionThatMovesTheFrame( tf );

     }

}

mlavieAuthor
Known Participant
January 4, 2011

Bob,

Thanks for ther swift response.

The problem with your sugestion is, that in ActionScript (at least) only the application-level events fire (addListenerToObject() almsot never works - Harbs already pointed this out to me yesterday in a previous post). Thus - the event traget is always the app or the LayoutWindows. Also, I could find no more specifc an event than AFTER_SELECTION_ATTRIBUTE_CHANGED.

Actually - I do not re-move the same PageItem, but rather move another PageItem based on the movement in the first PageItem - but that second PageItem ends up firing the event, too.

Any ideas?

TIA - mlavie

Harbs.
Legend
January 4, 2011

APID...

Harbs