You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@netbeans.apache.org by Andreas Sewe <se...@cqse.eu> on 2018/09/03 14:18:13 UTC

Re: How to best implement action for a large number of different context types?

Hi Boris.

Andreas Sewe wrote:
> Boris Heithecker wrote:
>> I think you'll have to implement an action (extending Action or
>> AbstractAction, not ActionListener) that implements
>> "org.openide.util.ContextAwareAction". 
>> Its business method is expected to create a proxy action for the context
>> passed to it. This context is the current user selection of nodes, or
>> the content of these nodes. 
>> I guess you'd have to find various methods to extract your URI from this
>> lookup and pass it to the proxy action created. For example look-up a
>> Project and, if present, extract an URI. 
>> If no URI at all can be extracted, nevertheless return an action, but
>> its state should be disabled. 

For other readers, org.netbeans.modules.html.editor.ViewAction is a nice
example of this, but...

>> Hope it helps,
> 
> Thank you very much for this suggestion, Boris. That sounds like a good
> direction to explore.

...I'm afraid I couldn't get this to work. Here's the problem I am facing:

- My URI-taking action is a simple ActionListener and I would like to
keep it that way.

- If I now create a ContextAwareAction, I can convert whatever it finds
in the lookup into a URI in createContextAwareInstance, but then I need
to return an Action.

- But I have only an ActionListener. I looked through
org.openide.awt.Actions to see whether I can call one of the methods
that are used under the hood for the ActionListener -> Action
conversion, but they are either non-public or hardcoded to
Utilities.actionsGlobalContext(), so I can really get my URI injected
into the ActionListener.

Any suggestions how to proceed?

Best wishes,

Andreas

-- 
Dr. Andreas Sewe | sewe@cqse.eu | +49 152 56342856
CQSE GmbH | Lichtenbergstrasse 8 | 85748 Garching | www.cqse.eu
Amtsgericht Muenchen | HRB 177678 | GF: F. Deissenboeck, M. Feilkas


Re: How to best implement action for a large number of different context types?

Posted by Boris Heithecker <bo...@gmx.net>.
See the
ret.setEnabled(uri != null);
line in may above suggestion. It should disable the action dynamically
(assuming that uri == null if none is found).
What you feel is a pity (not being able to declare constructors for
different context object) may be deliberate for performance reasons. The
actions api uses reflection, and action objects need to be created quite
often.
Most features of the platform are rather well thought-out in the end, only
it's sometimes not really obvious from the start.
Good luck!
Boris


Am Mo., 3. Sep. 2018 um 17:58 Uhr schrieb Andreas Sewe <se...@cqse.eu>:

> Boris Heithecker wrote:
> > In your ContextAwareAction, you could use a delegate to your
> > ActionListener. Something like:
> >
> >        //Create an instance of your ActionListener, pass the URI
> >         MyActionListenerImpl al = new MyActionListenerImpl(uri);
> >        //Return a simple delegate
> >         AbstractAction ret =  new AbstractAction() {
> >             @Override
> >             public void actionPerformed(ActionEvent e) {
> >                 al.actionPerformed(e);
> >             }
> >
> >         };
> >       ret.setEnabled(uri != null);
>
> That's more or less what I ended up doing, only that I don't bother with
> ContextAwareAction at all. One ActionListener-based action simply
> delegates to another in its actionPerformed method. This seems simpler
> than using AbstractAction + ContextAwareAction, although it does mean
> that I cannot selectively disable if the "outer" ActionListener's
> injected input is present in the context but cannot be converted to an
> URI. Or am I missing some benefit of ContextAwareAction that I don't
> know about?
>
> At any rate, it's just a pity that I can't have additional static
> create(SomeContextObject) methods in MyActionListenerImpl, annotated
> with @ActionRegistration. That would keep all the different entrypoints
> into MyActionListenerImpl in one file.
>
> Thank you for your help.
>
> Best wishes,
>
> Andreas
>
> --
> Dr. Andreas Sewe | sewe@cqse.eu | +49 152 56342856
> CQSE GmbH | Lichtenbergstrasse 8 | 85748 Garching | www.cqse.eu
> Amtsgericht Muenchen | HRB 177678 | GF: F. Deissenboeck, M. Feilkas
>
>

-- 
Boris Heithecker


Dr. Boris Heithecker
Lüneburger Str. 30
28870 Ottersberg
Tel.: 0 42 05/ 31 58 34

Re: How to best implement action for a large number of different context types?

Posted by Andreas Sewe <se...@cqse.eu>.
Boris Heithecker wrote:
> In your ContextAwareAction, you could use a delegate to your
> ActionListener. Something like: 
> 
>        //Create an instance of your ActionListener, pass the URI
>         MyActionListenerImpl al = new MyActionListenerImpl(uri);
>        //Return a simple delegate
>         AbstractAction ret =  new AbstractAction() {
>             @Override
>             public void actionPerformed(ActionEvent e) {
>                 al.actionPerformed(e);
>             }
>             
>         };
>       ret.setEnabled(uri != null);

That's more or less what I ended up doing, only that I don't bother with
ContextAwareAction at all. One ActionListener-based action simply
delegates to another in its actionPerformed method. This seems simpler
than using AbstractAction + ContextAwareAction, although it does mean
that I cannot selectively disable if the "outer" ActionListener's
injected input is present in the context but cannot be converted to an
URI. Or am I missing some benefit of ContextAwareAction that I don't
know about?

At any rate, it's just a pity that I can't have additional static
create(SomeContextObject) methods in MyActionListenerImpl, annotated
with @ActionRegistration. That would keep all the different entrypoints
into MyActionListenerImpl in one file.

Thank you for your help.

Best wishes,

Andreas

-- 
Dr. Andreas Sewe | sewe@cqse.eu | +49 152 56342856
CQSE GmbH | Lichtenbergstrasse 8 | 85748 Garching | www.cqse.eu
Amtsgericht Muenchen | HRB 177678 | GF: F. Deissenboeck, M. Feilkas


Re: How to best implement action for a large number of different context types?

Posted by Boris Heithecker <bo...@gmx.net>.
In your ContextAwareAction, you could use a delegate to your
ActionListener. Something like:

       //Create an instance of your ActionListener, pass the URI
        MyActionListenerImpl al = new MyActionListenerImpl(uri);
       //Return a simple delegate
        AbstractAction ret =  new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                al.actionPerformed(e);
            }

        };
      ret.setEnabled(uri != null);

Boris

Am Mo., 3. Sep. 2018 um 16:18 Uhr schrieb Andreas Sewe <se...@cqse.eu>:

> Hi Boris.
>
> Andreas Sewe wrote:
> > Boris Heithecker wrote:
> >> I think you'll have to implement an action (extending Action or
> >> AbstractAction, not ActionListener) that implements
> >> "org.openide.util.ContextAwareAction".
> >> Its business method is expected to create a proxy action for the context
> >> passed to it. This context is the current user selection of nodes, or
> >> the content of these nodes.
> >> I guess you'd have to find various methods to extract your URI from this
> >> lookup and pass it to the proxy action created. For example look-up a
> >> Project and, if present, extract an URI.
> >> If no URI at all can be extracted, nevertheless return an action, but
> >> its state should be disabled.
>
> For other readers, org.netbeans.modules.html.editor.ViewAction is a nice
> example of this, but...
>
> >> Hope it helps,
> >
> > Thank you very much for this suggestion, Boris. That sounds like a good
> > direction to explore.
>
> ...I'm afraid I couldn't get this to work. Here's the problem I am facing:
>
> - My URI-taking action is a simple ActionListener and I would like to
> keep it that way.
>
> - If I now create a ContextAwareAction, I can convert whatever it finds
> in the lookup into a URI in createContextAwareInstance, but then I need
> to return an Action.
>
> - But I have only an ActionListener. I looked through
> org.openide.awt.Actions to see whether I can call one of the methods
> that are used under the hood for the ActionListener -> Action
> conversion, but they are either non-public or hardcoded to
> Utilities.actionsGlobalContext(), so I can really get my URI injected
> into the ActionListener.
>
> Any suggestions how to proceed?
>
> Best wishes,
>
> Andreas
>
> --
> Dr. Andreas Sewe | sewe@cqse.eu | +49 152 56342856
> CQSE GmbH | Lichtenbergstrasse 8 | 85748 Garching | www.cqse.eu
> Amtsgericht Muenchen | HRB 177678 | GF: F. Deissenboeck, M. Feilkas
>
>

-- 
Boris Heithecker


Dr. Boris Heithecker
Lüneburger Str. 30
28870 Ottersberg
Tel.: 0 42 05/ 31 58 34