Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

How to get an event on block resizing ?

Contributor ,
Sep 14, 2011 Sep 14, 2011

Hi everybody,

I'm trying to catch an event after (during?) the resizing of a block. I know there are Observers and Responders. I found the serviceID for document handling, for example. But what is the one for a block resizing, a block moving, etc ?

I found a nice snippet called DocWatch, but I can't find any solution in it. Any idea ?

Thanks in advance

Rémi

TOPICS
SDK
5.2K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Mentor , Sep 24, 2011 Sep 24, 2011

Command Interceptors are meant to suppress command, not as means of notification. Please have a look at the top comment of ICommandInterceptor.h : Use with extreme caution ...

Most commands and many other objects send notifications to observers. If you for example want to receive a notification whenever a page item is resized, add your observer to the kDocBoss (as already suggested by Norio), protocol IID_IGEOMETRY_DOCUMENT and watch out for the change classID of kBoundsChangedMessage. The change

...
Translate
Community Expert ,
Sep 16, 2011 Sep 16, 2011

What specifically do you mean by block resizing, do you mean resizing of a text box please clarify.

Any how you can try using interceptor's with some debugging you will most probably hit on the interceptor that is suitable for your need.

Manan Joshi

- Efficient InDesign Solutions -

MetaDesign Solutions

http://metadesignsolutions.com/services/indesign-development.php

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Sep 16, 2011 Sep 16, 2011

Hi Manan,

What I mean with "block resizing" is, for example, clicking on a box, and then change its size, whatever type it is. My goal is catching the generated event to do some post treatment.

Is there any difference between catching this event on a text box or on a image box ?

Why should I preferably use an interceptor, instead of an observer or a responder ? What are the differences ?

Thanks in advance.

Rémi

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 16, 2011 Sep 16, 2011

Remi,

There might be a difference between resizing a textbox or a imagebox you never can be sure that the same code would work for both of them.

For trying to do this with responders you need to know the serviceid for which you need to add a responder which is difficult to get by debugging, since you had already tried with observers i asked you to go the interceptor way.

For interception you can first look for the commands that are fired while resizing the block and then add an interceptor to those command's and write your code in the interceptor. This way your debugging effort would be reduced. Observers also would work well but getting a correct protocol that is not very generic requires more debugging effort.

Manan Joshi

- Efficient InDesign Solutions -

MetaDesign Solutions

http://metadesignsolutions.com/services/indesign-development.php

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Sep 22, 2011 Sep 22, 2011

Hi Manan,

I tried to follow your idea. It seems to be the right one to do what I'd like to do. I've met technical problems though (due to my misunderstanding of some elements of the SDK).

I declared my own interceptor, extending the CPMUnkown<ICommandInterceptor>. It declares its own IID (is it correct ?). I added this interceptor implementation to the kBasicCommandProcessorBoss (what is the difference with kCommandProcessorBoss ?). In StartupShutdown service, I installed my interceptor on the command processor. My interceptor's constructor is called. But when I try to execute a command, it is not intercepted by my interceptor (The command I execute is simply modifying geometry of a box, directly on an InDesign page, with the mouse).

Here is the code :

My interceptor :

-------------------------------------------------------------------------------------------------------

class ACCommandsInterceptor : public CPMUnknown<ICommandInterceptor> {

public:

    enum {kDefaultIID = IID_ACCOMMANDSINTERCEPTOR};

    ACCommandsInterceptor(IPMUnknown* boss);

    virtual InterceptResult InterceptProcessCommand(ICommand *cmd);

    virtual InterceptResult InterceptScheduleCommand(ICommand *cmd);   

    virtual InterceptResult InterceptExecuteDynamic(ICommand * cmd);

    virtual void InstallSelf();

    virtual void DeinstallSelf();

    virtual InterceptResult InterceptExecuteImmediate(ICommand * cmd);

};

-------------------------------------------------------------------------------------------------------

The .cpp

-------------------------------------------------------------------------------------------------------

CREATE_PMINTERFACE(ACCommandsInterceptor, kACCommandsInterceptorImpl)

ACCommandsInterceptor::ACCommandsInterceptor(IPMUnknown* boss) : CPMUnknown<ICommandInterceptor>(boss){

    Logger::info("Interceptor construction");

}

ACCommandsInterceptor::InterceptResult ACCommandsInterceptor::InterceptProcessCommand(ICommand *cmd){

    Logger::info("ACCommandsInterceptor::InterceptProcessCommand");

    // TODO

    return kCmdNotHandled;

}

ACCommandsInterceptor::InterceptResult ACCommandsInterceptor::InterceptScheduleCommand(ICommand *cmd){

    Logger::info("ACCommandsInterceptor::InterceptScheduleCommand");

    // TODO

    return kCmdNotHandled;

}   

ACCommandsInterceptor::InterceptResult ACCommandsInterceptor::InterceptExecuteDynamic(ICommand * cmd){

    Logger::info("ACCommandsInterceptor::InterceptExecuteDynamic");

    // TODO

    return kCmdNotHandled;

}

void ACCommandsInterceptor::InstallSelf(){

    Logger::info("ACCommandsInterceptor::InstallSelf()");

    // TODO

}

void ACCommandsInterceptor::DeinstallSelf(){

    Logger::info("ACCommandsInterceptor::DeinstallSelf()");

    // TODO

}

ACCommandsInterceptor::InterceptResult ACCommandsInterceptor::InterceptExecuteImmediate(ICommand * cmd){

    Logger::info("ACCommandsInterceptor::InterceptExecuteImmediate");

    // TODO

    return kCmdNotHandled;

}

-------------------------------------------------------------------------------------------------------

The .fr

-------------------------------------------------------------------------------------------------------

/* Add a command interceptor, to be able to add more logic treatment

    in command processing */

    AddIn{

        kBasicCommandProcessorBoss,

        kInvalidClass,

        {

            IID_ICOMMANDINTERCEPTOR, kACCommandsInterceptorImpl,

        }

    }

-------------------------------------------------------------------------------------------------------

My last problem then is the following one : How could I filter the commands I intercept ? I think I will intercept every executed command with this interceptor, while I almost just want to intercept geometry commands. Should I look at ActionFilter ? Any idea ?

Thanks in advance

Rémi

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Sep 23, 2011 Sep 23, 2011

I finally found an answer. If anyone meet the same problem, here is the solution : My problem was I did not install my Interceptor on the right command processor (The problem was outside the sources I posted). To get the right command processor, just do as follow :

InterfacePtr<ICommandProcessor> commandProcessor (GetExecutionContextSession()->QueryCommandProcessor());

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 23, 2011 Sep 23, 2011

Hi Remi,

Sorry could not answer before, but it seems that you have figured to get your interceptor working. But i would to like to add a few points

You can place your command interceptor in any boss class and use it, the typical scenario would be to place the interceptor in a startupshutdown class and then install it by calling the InstallSelf method of the cmd interceptor on startup.

Inside the InstallSelf method you can query for the command processor and call the "InstallInterceptor" method. Similarly we uninstall it in the shutdown method.

Regarding your second query regarding which command to intercept, you could look to intercept the following commands inside the "InterceptProcessCommand" method

kResizeItemsCmdBoss

kSetBoundingBoxCmdBoss

Hope this serves your purpose.

Manan Joshi

- Efficient InDesign Solutions -

MetaDesign Solutions

http://metadesignsolutions.com/services/indesign-development.php

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Sep 23, 2011 Sep 23, 2011

Hi Manan,

Thank you one more time.

The last point is, how could I know what type of command I intercept ? Technically, I mean. I can used command's name, but it seems not to be the best way to do it.

Second point, I saw many many resize commands executed when I break inside the InterceptProcessCommand method. Each time the UI is refreshed (after a mouse movement, even on a single pixel movement) due to resize modification, a resize command is executed. How could I filter this to only get the last one (once the mouse button has been released) ?

I appreciate your help.

Regards,

Rémi

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 23, 2011 Sep 23, 2011

Regarding using the name of the command, i have been using the GetClass method to get the name of the command. And this is not a wrong or a bad to do things, as you can see it being used at a lot of places even in the sdk's sample plugins.

Secondly to arrive at the correct command to intercept for your purposes you need to debug the different commands. Any how the commands i mentioned in the previous answer are called only once during the operation i suppose you could try using them

If you could specifically tell me what exactly you need to achieve, then maybe i could try some code at my end and give you a more correct answer.

Manan Joshi

- Efficient InDesign Solutions -

MetaDesign Solutions

http://metadesignsolutions.com/services/indesign-development.php

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Sep 23, 2011 Sep 23, 2011

What I am trying to do is this : When a user resizes a page item with its mouse, he clicks on the border of the item, then move its mouse, and finally release the button of its mouse. It is the moment when he releases the button that I would like to intercept the command, to get the final dimension of the page item. I don't need to receive any intermediate step in the page item resizing.

My problem is actually all the intermediate intercepted commands that I would like to ignore. The rest of the mechanism is now clear for me.

Rémi

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Sep 24, 2011 Sep 24, 2011

Command Interceptors are meant to suppress command, not as means of notification. Please have a look at the top comment of ICommandInterceptor.h : Use with extreme caution ...

Most commands and many other objects send notifications to observers. If you for example want to receive a notification whenever a page item is resized, add your observer to the kDocBoss (as already suggested by Norio), protocol IID_IGEOMETRY_DOCUMENT and watch out for the change classID of kBoundsChangedMessage. The changedBy argument then is ICommand of kResizeItemsCmdBoss right while it is performing its duties. The final of multiple notifications will see a command state of kDone rather than kNotDone.

This will also yield resizes e.g. via the control strip width/height numeric fields or by scriping.

If instead you want only the UI moment when the user releases the mouse (later than the command), that would be an observer on kLayoutWidgetBoss (that's the main area of the window) with the protocol IID_IDYNAMICTRACKERDATA, notified e.g. by kTextBBoxResizeTrackerBoss. The IID_IDYNAMICTRACKERDATA interface on the tracker should have a state of kEndTracking ...

Dirk

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Sep 24, 2011 Sep 24, 2011

As Dirk say,

I am using CObserver is added to kDocBoss.

myDocObserver can get kBoundsChangedMessage and kLocationChangedMessage as ClassID by CObserver::Update method.

PMIID from resizing page items is IID_IGEOMETRY_DOCUMENT, PMIID from moving page items is IID_ITRANSFORM_DOCUMENT.

When the command has done, ICommand::GetCommandState() is ICommand::kDone.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 25, 2011 Sep 25, 2011

Dirk,

Thanks for the valuable insight you and Norio gave on the problem at hand. But i would like to raise a point, i agree that observers are meant to work in response to a notification generated, but this does not mean that we can rule out the use of Command intercpetors altogether except for supressing the command.

Dirk what you mentioned that interceptors are meant to suppress commands, then i would like to add that if this would only have been the point then the return vlaue from the interceptor methods would not have been

kCmdNotHandled

kCmdNotHandledSkipInterceptors

kCmdHandled  //Only this return value is in effect supressing the command

I mean sure we should go the observer and the responder way but should not rule out the interceptor altogether. Moreover getting the right protocol for the observer takes more debugging effort and even if we do get a protocol that notifies in our case we need to arrive at one that is not too generic for our case.

I just gave a possibilty that we can even go the interceptor way, when Remi could not get the problem solved through responders and observers. Please correct me and guide me to a better understanding if i am wrong in using these concepts

Thanks in advance.

Manan Joshi

- Efficient InDesign Solutions -

MetaDesign Solutions

http://metadesignsolutions.com/services/indesign-development.php

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Sep 26, 2011 Sep 26, 2011

Manan,

I am no Adobe engineer, I just hang out here and speak for my understanding of common sense.

If you have a look at the object model, within InDesign production code command interceptors are only aggregated by modal dialogs with their cancel/undo buttons. The other use cases are the panel editor and some debug aid from SDK. Even if there were not the previously quoted warning from the header, to me that's as strong an indicator as it can be.

One disadvantage of command interceptors is that you have to wade through every command that comes along. If you use the feature for notifications, the majority will not be your business, so you pass them on to the next command interceptor. You will just waste CPU cycles, translated as a major speed penalty rather than efficiency.

Besides command interceptors obviously intercept before processing, so for practical use you have to guess the outcome of the command.

The special case (the other result code) to interfere with other command interceptors is even more esoteric.

Dirk

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Sep 27, 2011 Sep 27, 2011

Dirk,

Thanks for your help, your first solution is exactly what I was looking for. Observers best match my needs, because I wanted to know when the command had been processed. I really appreciated your help.

Manan, your solution is not the right one for my need here, but I will use it anyway for another feature. Thanks to you too.

Regards,

Rémi

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
May 24, 2012 May 24, 2012

I everyone,

I come back on that point, because I last met another annoying problem, similar to this one :

http://forums.adobe.com/message/4335461#4335461

While resizing, I receive every intermediate notification, not only the final one. Is there a mean to avoid receiving them ? The post told about a workaround, using IEventUtils->IsMouseButtonDown, but I'm quite sure it is not the proper way to do it.

What is the right solution ?

Regards,

Rémi

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
May 24, 2012 May 24, 2012

Check ICommand::GetCommandState()

Dirk

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
May 24, 2012 May 24, 2012

Hi Dirk,

I tried it. Every intermediate command is kDone... Any other idea ?

Rémi

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
May 25, 2012 May 25, 2012

Do you have any group with multiple items that would require multiple commands?

As previously mentioned, Transform and Resize are separate commands, combined with a sequence. Could it be that you just watch those two commands? Have a look at the ::GetClass() of the commands ...

Dirk

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
May 27, 2012 May 27, 2012
LATEST

I made my try on a ingle item, without any group. I'm quite sure I filtered the right command :

if (::GetClass(command) == kResizeItemsCmdBoss)

I have another place where I check for moving (

::GetClass(command) == kMoveRelativeCmdBoss)

I doubt there could be interferences... Is there another point I need to check ?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Sep 19, 2011 Sep 19, 2011

I am using myDocObserver.

I can get the kBoundsChangedMessage.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines