[Ann] Commander. Command pattern library

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

[Ann] Commander. Command pattern library

Denis Kudriashov
Hi.

I am glad to announce Commander library which implements command pattern based on first class objects.
In Commander every application action is implemented as separate class with #execute method and all state required for execution.

Commands are reusable objects and applications provide various ways to access them: shortcuts, context menu, buttons, etc.. This information is attached to command classes as activator objects. Currently there are three types of activators:

- CmdShortcutCommandActivator
- CmdContextMenuCommandActivator
- CmdDragAndDropCommandActivator

Activators are declared in command class side methods marked with pragma #commandActivator. For example following method will allow RenamePackageCommand to be executed by shortcut in possible system browser:  

RenamePackageCommand class>>packageBrowserShortcutActivator
      <commandActivator>
      ^CmdShortcutCommandActivator by: $r meta for: PackageBrowserContext

And for context menu it will be:  

RenamePackageCommand class>>packageBrowserMenuActivator
       <commandActivator>
       ^CmdContextMenuCommandActivator byRootGroupItemFor: PackageBrowserContext

Activators are always declared with application context where they can be applied (PackageBrowserContext in example). Application should provide such contexts with information about application state. Every widget can bring own context to interact with application as separate tool. For example system browser shows multiple panes which provide package context, class context and method context. And depending on context browser shows different menu and provides different shortcuts.


Best regards,
Denis  


Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

abergel
Was is really necessary to introduce pragmas here?

Alexandre


> On Apr 11, 2017, at 11:49 AM, Denis Kudriashov <[hidden email]> wrote:
>
> Hi.
>
> I am glad to announce Commander library which implements command pattern based on first class objects.
> In Commander every application action is implemented as separate class with #execute method and all state required for execution.
>
> Commands are reusable objects and applications provide various ways to access them: shortcuts, context menu, buttons, etc.. This information is attached to command classes as activator objects. Currently there are three types of activators:
>
> - CmdShortcutCommandActivator
> - CmdContextMenuCommandActivator
> - CmdDragAndDropCommandActivator
>
> Activators are declared in command class side methods marked with pragma #commandActivator. For example following method will allow RenamePackageCommand to be executed by shortcut in possible system browser:  
>
> RenamePackageCommand class>>packageBrowserShortcutActivator
>       <commandActivator>
>       ^CmdShortcutCommandActivator by: $r meta for: PackageBrowserContext
>
> And for context menu it will be:  
>
> RenamePackageCommand class>>packageBrowserMenuActivator
>        <commandActivator>
>        ^CmdContextMenuCommandActivator byRootGroupItemFor: PackageBrowserContext
>
> Activators are always declared with application context where they can be applied (PackageBrowserContext in example). Application should provide such contexts with information about application state. Every widget can bring own context to interact with application as separate tool. For example system browser shows multiple panes which provide package context, class context and method context. And depending on context browser shows different menu and provides different shortcuts.
>
> For more details look at my blog http://dionisiydk.blogspot.fr/2017/04/commander-command-pattern-library.html and read docs here.
>
> Best regards,
> Denis  
>
>

--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel  http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.




Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

abergel
Just in case of: I do not want my email to be read as I did not intent to.
You are doing a great work Denis.

Keep going!

Alexandre


> On Apr 11, 2017, at 12:34 PM, Alexandre Bergel <[hidden email]> wrote:
>
> Was is really necessary to introduce pragmas here?
>
> Alexandre
>
>
>> On Apr 11, 2017, at 11:49 AM, Denis Kudriashov <[hidden email]> wrote:
>>
>> Hi.
>>
>> I am glad to announce Commander library which implements command pattern based on first class objects.
>> In Commander every application action is implemented as separate class with #execute method and all state required for execution.
>>
>> Commands are reusable objects and applications provide various ways to access them: shortcuts, context menu, buttons, etc.. This information is attached to command classes as activator objects. Currently there are three types of activators:
>>
>> - CmdShortcutCommandActivator
>> - CmdContextMenuCommandActivator
>> - CmdDragAndDropCommandActivator
>>
>> Activators are declared in command class side methods marked with pragma #commandActivator. For example following method will allow RenamePackageCommand to be executed by shortcut in possible system browser:  
>>
>> RenamePackageCommand class>>packageBrowserShortcutActivator
>>      <commandActivator>
>>      ^CmdShortcutCommandActivator by: $r meta for: PackageBrowserContext
>>
>> And for context menu it will be:  
>>
>> RenamePackageCommand class>>packageBrowserMenuActivator
>>       <commandActivator>
>>       ^CmdContextMenuCommandActivator byRootGroupItemFor: PackageBrowserContext
>>
>> Activators are always declared with application context where they can be applied (PackageBrowserContext in example). Application should provide such contexts with information about application state. Every widget can bring own context to interact with application as separate tool. For example system browser shows multiple panes which provide package context, class context and method context. And depending on context browser shows different menu and provides different shortcuts.
>>
>> For more details look at my blog http://dionisiydk.blogspot.fr/2017/04/commander-command-pattern-library.html and read docs here.
>>
>> Best regards,
>> Denis  
>>
>>
>
> --
> _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
> Alexandre Bergel  http://www.bergel.eu
> ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
>
>
>
>

--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel  http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.




Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

Esteban A. Maringolo
In reply to this post by Denis Kudriashov
Nice work, I like the approach.

Did you inspire your work in how Dolphin and VAST implements menu
creation, command execution, and so on?
I find your solution similar to how Dolphin implements it, where even
each Presenter is even queried about each command by using a command
query and routing solution.

Will you use this in the context of Calypso and friends?

Regards!


Esteban A. Maringolo


2017-04-11 11:49 GMT-03:00 Denis Kudriashov <[hidden email]>:

> Hi.
>
> I am glad to announce Commander library which implements command pattern
> based on first class objects.
> In Commander every application action is implemented as separate class with
> #execute method and all state required for execution.
>
> Commands are reusable objects and applications provide various ways to
> access them: shortcuts, context menu, buttons, etc.. This information is
> attached to command classes as activator objects. Currently there are three
> types of activators:
>
> - CmdShortcutCommandActivator
> - CmdContextMenuCommandActivator
> - CmdDragAndDropCommandActivator
>
> Activators are declared in command class side methods marked with pragma
> #commandActivator. For example following method will allow
> RenamePackageCommand to be executed by shortcut in possible system browser:
>
> RenamePackageCommand class>>packageBrowserShortcutActivator
>
>       <commandActivator>
>       ^CmdShortcutCommandActivator by: $r meta for: PackageBrowserContext
>
>
> And for context menu it will be:
>
>
> RenamePackageCommand class>>packageBrowserMenuActivator
>        <commandActivator>
>        ^CmdContextMenuCommandActivator byRootGroupItemFor:
> PackageBrowserContext
>
>
> Activators are always declared with application context where they can be
> applied (PackageBrowserContext in example). Application should provide such
> contexts with information about application state. Every widget can bring
> own context to interact with application as separate tool. For example
> system browser shows multiple panes which provide package context, class
> context and method context. And depending on context browser shows different
> menu and provides different shortcuts.
>
> For more details look at my blog
> http://dionisiydk.blogspot.fr/2017/04/commander-command-pattern-library.html
> and read docs here.
>
> Best regards,
> Denis
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

Stephane Ducasse-3
Yes in calypso and friends.

On Tue, Apr 11, 2017 at 7:38 PM, Esteban A. Maringolo <[hidden email]> wrote:
Nice work, I like the approach.

Did you inspire your work in how Dolphin and VAST implements menu
creation, command execution, and so on?
I find your solution similar to how Dolphin implements it, where even
each Presenter is even queried about each command by using a command
query and routing solution.

Will you use this in the context of Calypso and friends?

Regards!


Esteban A. Maringolo


2017-04-11 11:49 GMT-03:00 Denis Kudriashov <[hidden email]>:
> Hi.
>
> I am glad to announce Commander library which implements command pattern
> based on first class objects.
> In Commander every application action is implemented as separate class with
> #execute method and all state required for execution.
>
> Commands are reusable objects and applications provide various ways to
> access them: shortcuts, context menu, buttons, etc.. This information is
> attached to command classes as activator objects. Currently there are three
> types of activators:
>
> - CmdShortcutCommandActivator
> - CmdContextMenuCommandActivator
> - CmdDragAndDropCommandActivator
>
> Activators are declared in command class side methods marked with pragma
> #commandActivator. For example following method will allow
> RenamePackageCommand to be executed by shortcut in possible system browser:
>
> RenamePackageCommand class>>packageBrowserShortcutActivator
>
>       <commandActivator>
>       ^CmdShortcutCommandActivator by: $r meta for: PackageBrowserContext
>
>
> And for context menu it will be:
>
>
> RenamePackageCommand class>>packageBrowserMenuActivator
>        <commandActivator>
>        ^CmdContextMenuCommandActivator byRootGroupItemFor:
> PackageBrowserContext
>
>
> Activators are always declared with application context where they can be
> applied (PackageBrowserContext in example). Application should provide such
> contexts with information about application state. Every widget can bring
> own context to interact with application as separate tool. For example
> system browser shows multiple panes which provide package context, class
> context and method context. And depending on context browser shows different
> menu and provides different shortcuts.
>
> For more details look at my blog
> http://dionisiydk.blogspot.fr/2017/04/commander-command-pattern-library.html
> and read docs here.
>
> Best regards,
> Denis
>
>


Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

Denis Kudriashov
In reply to this post by Esteban A. Maringolo

2017-04-11 19:38 GMT+02:00 Esteban A. Maringolo <[hidden email]>:
Nice work, I like the approach.

Thank's.
 

Did you inspire your work in how Dolphin and VAST implements menu
creation, command execution, and so on?

No. 
I actually not remember that there were first class commands in Dolphin. I remember kind of CommandDescription with selector/block inside. No hierarchy of commands. But I could be wrong.

I was more inspired by OmniBrowser and AltBrowser commands. But there were no activators idea inside.
(I never worked with VAST)
 
I find your solution similar to how Dolphin implements it, where even
each Presenter is even queried about each command by using a command
query and routing solution.

Will you use this in the context of Calypso and friends?

Yes. And Calypso extends it with specific activators:
- ClyToolbarCommandActivator to build middle bar of browser (switch browser to instance/class side are commands)
- ClyTableIconCommandActivator to decorate table rows with iconic buttons (to provide method icons like in Nautilus) 


Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

Denis Kudriashov
In reply to this post by abergel

2017-04-11 17:34 GMT+02:00 Alexandre Bergel <[hidden email]>:
Was is really necessary to introduce pragmas here?

In short: Commander needs pragma to query methods for command lookup. What alternative you could suggest? 

In details:
 
Commander caches all activators for each command class. It searches all methods which supply them using pragma and store all retrieved instances in class variable.

To lookup required commands users enumerate cached activators declared for given context:
activatorClass allDeclaredFor: aToolContext do: blockWithActivator
This process is fast and not produces any garbage.

Also activation methods are supposed to be packaged together with application which provide context for them. They can be in different package than commands.
Commands are reusable and can be extended by multiple applications with different set of activation methods.
For example in Calypso I will extract separate SystemCommands package which can be reused by other tools like inspector and debugger. And Calypso will "attach" these commands by own set of extension methods.
Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

abergel

> Was is really necessary to introduce pragmas here?
>
> In short: Commander needs pragma to query methods for command lookup. What alternative you could suggest?

I would imagine that your activatorClass can lookup the command simply as:

PackageCommand allSubclasses select: [ :c | c isEnabledFor: … ]

Would this not work?
I am personally not keen of using pragma. The worth is when you have no idea what a pragma does and looking for implementors or sender does not help. Here is an example:
-=-=-=-=-=-=-=-=-=-=-=-=
 RadioButtonModel>>canDeselectByClick
        <api: #inspect>
        "Return true clicking on a selected radio button deselects it"

        ^ canDeselectByClick value
-=-=-=-=-=-=-=-=-=-=-=-=

No idea what is the effect of the #api: pragma. There is no implementor of it. I could also the example of the Fame metamodel.
Anyway, the fact that I am kind of complaining should not prevent you from moving ahead. I would be happy having Calypso in the image, even if pragmas.

Go go go!

Cheers,
Alexandre


>
> In details:
>  
> Commander caches all activators for each command class. It searches all methods which supply them using pragma and store all retrieved instances in class variable.
>
> To lookup required commands users enumerate cached activators declared for given context:
> activatorClass allDeclaredFor: aToolContext do: blockWithActivator
> This process is fast and not produces any garbage.
>
> Also activation methods are supposed to be packaged together with application which provide context for them. They can be in different package than commands.
> Commands are reusable and can be extended by multiple applications with different set of activation methods.
> For example in Calypso I will extract separate SystemCommands package which can be reused by other tools like inspector and debugger. And Calypso will "attach" these commands by own set of extension methods.

--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel  http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.




Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

Ben Coman


On Wed, Apr 12, 2017 at 6:28 AM, Alexandre Bergel <[hidden email]> wrote:

> Was is really necessary to introduce pragmas here?
>
> In short: Commander needs pragma to query methods for command lookup. What alternative you could suggest?

I would imagine that your activatorClass can lookup the command simply as:

PackageCommand allSubclasses select: [ :c | c isEnabledFor: … ]

Would this not work?
I am personally not keen of using pragma. The worth is when you have no idea what a pragma does and looking for implementors or sender does not help.

The other way to look at it is we need to improve implementor/sender lookups around pragmas
(speaking very generically. I don't know what the gaps are.)

cheers -ben

 
Here is an example:
-=-=-=-=-=-=-=-=-=-=-=-=
 RadioButtonModel>>canDeselectByClick
        <api: #inspect>
        "Return true clicking on a selected radio button deselects it"

        ^ canDeselectByClick value
-=-=-=-=-=-=-=-=-=-=-=-=

No idea what is the effect of the #api: pragma. There is no implementor of it. I could also the example of the Fame metamodel.
Anyway, the fact that I am kind of complaining should not prevent you from moving ahead. I would be happy having Calypso in the image, even if pragmas.

Go go go!

Cheers,
Alexandre


>
> In details:
>
> Commander caches all activators for each command class. It searches all methods which supply them using pragma and store all retrieved instances in class variable.
>
> To lookup required commands users enumerate cached activators declared for given context:
> activatorClass allDeclaredFor: aToolContext do: blockWithActivator
> This process is fast and not produces any garbage.
>
> Also activation methods are supposed to be packaged together with application which provide context for them. They can be in different package than commands.
> Commands are reusable and can be extended by multiple applications with different set of activation methods.
> For example in Calypso I will extract separate SystemCommands package which can be reused by other tools like inspector and debugger. And Calypso will "attach" these commands by own set of extension methods.

--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel  http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.





Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

Denis Kudriashov
In reply to this post by abergel

2017-04-12 0:28 GMT+02:00 Alexandre Bergel <[hidden email]>:
I would imagine that your activatorClass can lookup the command simply as:

PackageCommand allSubclasses select: [ :c | c isEnabledFor: … ]

This approach restricts command implementation and queries to single hierarchy which is not scale.
For example in Calypso there is ShowClassRefsCommand which is shown as toolbar button in both system and method browsers. But this command is in ClassCommand hierarchy because it operates on collection of classes.
We can lookup both MethodCommands and ClassCommands in method browser. But then we will have a lot of commands which we do not need in method browser.

Another example is "browse" command which is accessed by cmd+b and from context menu of any browser pane. 
  
Here is how they all connected to Calypso browsers:
 
ClyShowClassRefCommand class>>systemBrowserToolbarActivator
<commandActivator>
^ClyToolbarCommandActivator byItemOf: ClyButtonToolbarGroup for: ClyClassSystemBrowserContext

ClyShowClassRefCommand class>methodBrowserToolbarActivator
<commandActivator>
^ClyToolbarCommandActivator byItemOf: ClyButtonToolbarGroup for: ClyMethodBrowserContext

ClySpawnSystemBrowserCommand class>>browserShortcutActivator
<commandActivator>
^CmdShortcutCommandActivator by: $b meta for: ClyBrowserContext

ClySpawnSystemBrowserCommand class>>browserMenuActivator
<commandActivator>
^CmdContextMenuCommandActivator byRootGroupItemFor: ClyBrowserContext 

(ClyBrowserContext is superclass of any Calypso browser contexts)
Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

abergel
I see. But why not to let the class subscribe to what it needs?
Maybe something like:

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Command subclass: #ClyShowClassRefCommand

ClyShowClassRefCommand class>>registerFor: aCommandActivator
aCommandActivator add: self for: ClyButtonToolbarGroup.
aCommandActivator add: self for: ClyBrowserContext.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

This is just a suggestion.

Alexandre
-- 
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
Alexandre Bergel  http://www.bergel.eu
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.



On Apr 12, 2017, at 6:54 AM, Denis Kudriashov <[hidden email]> wrote:


2017-04-12 0:28 GMT+02:00 Alexandre Bergel <[hidden email]>:
I would imagine that your activatorClass can lookup the command simply as:

PackageCommand allSubclasses select: [ :c | c isEnabledFor: … ]

This approach restricts command implementation and queries to single hierarchy which is not scale.
For example in Calypso there is ShowClassRefsCommand which is shown as toolbar button in both system and method browsers. But this command is in ClassCommand hierarchy because it operates on collection of classes.
We can lookup both MethodCommands and ClassCommands in method browser. But then we will have a lot of commands which we do not need in method browser.

Another example is "browse" command which is accessed by cmd+b and from context menu of any browser pane. 
  
Here is how they all connected to Calypso browsers:
 
ClyShowClassRefCommand class>>systemBrowserToolbarActivator
<commandActivator>
^ClyToolbarCommandActivator byItemOf: ClyButtonToolbarGroup for: ClyClassSystemBrowserContext

ClyShowClassRefCommand class>methodBrowserToolbarActivator
<commandActivator>
^ClyToolbarCommandActivator byItemOf: ClyButtonToolbarGroup for: ClyMethodBrowserContext

ClySpawnSystemBrowserCommand class>>browserShortcutActivator
<commandActivator>
^CmdShortcutCommandActivator by: $b meta for: ClyBrowserContext

ClySpawnSystemBrowserCommand class>>browserMenuActivator
<commandActivator>
^CmdContextMenuCommandActivator byRootGroupItemFor: ClyBrowserContext 

(ClyBrowserContext is superclass of any Calypso browser contexts)

Reply | Threaded
Open this post in threaded view
|

Re: [Ann] Commander. Command pattern library

Denis Kudriashov

2017-04-12 15:27 GMT+02:00 Alexandre Bergel <[hidden email]>:
I see. But why not to let the class subscribe to what it needs?
Maybe something like:

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Command subclass: #ClyShowClassRefCommand

I guess you mean:
 
ClyShowClassRefCommand class>>registerFor: aCommandActivator
aCommandActivator add: self for: ClyClassSystemBrowserContext.
aCommandActivator add: self for: ClyMethodBrowserContext.

How different applications will extend such registration? Probably they will need multiple version of #registerFor:. And system will need to find them somehow. For example by pragma. No?