eclipse-archived / triquetrum

Triquetrum project
Other
13 stars 14 forks source link

Support dynamic creation of palette #350

Open laeubi opened 4 years ago

laeubi commented 4 years ago

Currently one needs to add an extension point for each palette item. If one wraps a collection of items unknown in advance (e.g. wrapping services into actors) it would be nice to have some kind of dynamism here.

I see two possible options:

  1. ModelElementClassProvider service registrations could carry the metadata required as service-properties, this would also allow to register the same actor class multiple times (currently each actor has to have its own class name to be used with the extension point), e.g. groupName="My Dynamic Group" displayName="The Actor" ... and so on ...
  2. Add some kind of GroupProviderService that is queried for the necessary information by given an actor class, e.g. GroupProviderService#getGroupName(Object actor); GroupProviderService#getDisplayName(Object actor); ... and so on ...

of course it would also be possible to combine both approaches.

laeubi commented 4 years ago

@cxbrooks Can you tell how complex that would be and if this possibly could make it into the next release?

cxbrooks commented 4 years ago

I have no experience with that code, so I'm not likely to do the work myself. However, I'd happily include changes written by someone else in the release.

There are some notes at http://wiki.eclipse.org/Triquetrum/Extending_Triquetrum that might be of interest.

laeubi commented 4 years ago

@cxbrooks thanks for the info, I have taken a look at the code and it seems possible to inject data from different source here but found that Ptolemy actors are identified in the model by their class name and it seems there is no concept of an "actor-id". That would mean that each actor has to be implemented as its own class and it is not possible to wrap existing classes easily with a generic actor class implementation?

Do you know if I'm missing something?

cxbrooks commented 4 years ago

Yes, each Ptolemy actor is a separate Java class. They do all inherit from ptolemy.actor.Actor. Wrapping existing classes in a generic actor class that invokes the methods of the actual actor via reflection would be possible. I'm not sure if this helps, but for example, we use Tcl (as in Tcl/Tk) as an interpreted language to build models using actors by instantiating the actor, setting parameters, connecting ports and then invoking run. All of these steps are done by invoking methods via reflection.

erwindl0 commented 4 years ago

In our Passerelle product, built on Ptolemy, we introduced a "ServiceBasedActor" generic actor implementation. I started something similar in Triquetrum with org.eclipse.triquetrum.processing.actor.TaskBasedActor.

It's built on the concept of submitting a Task that is then picked up by a task broker and service implementation based on configured task type.

So if you can wrap existing logic/classes in OSGi services that implement org.eclipse.triquetrum.processing.service.TaskProcessingService, this approach for a generic actor may be of help.

There is some info on this approach on https://wiki.eclipse.org/Triquetrum/Task-based_processing Trial/example implementations can be found in org.eclipse.triquetrum.processing.service.impl.example and org.eclipse.triquetrum.processing.test.

There are also actor implementations where the actual actor logic can be implemented in Python or Javascript, as another approach to have a limited palette and then extra configuration in the actor itself to pick the desired behaviour/implementation.

laeubi commented 4 years ago

Yes OSGi Services are definatly possible, will each task get its won palette entry? Or will there be only one "Task" and the actuall class to be used is a config property?

erwindl0 commented 4 years ago

The Task type is then a configuration property. So there would be only one palette entry by default.

The role of the actor implementation shifts in this way from the default strategy in Ptolemy. By default in PtII the actor is a well-defined component with its specific responsibility/behaviour (i.e. one separate actor implementation per required functionality). But with this task/service-based approach the actor's role becomes mainly input/result data-binding within a data processing flow.

As such the PtII/Triquetrum model becomes just one of the available options to orchestrate a sequence of tasks.

From our experience, it may still be handy to have some specific actor implementations for specific/complex task types or at least to have custom configuration panels. Then you would still see those as separate palette entries (and need to add them in the plugin.xmls to get there).

laeubi commented 4 years ago

Yeah there might be more than one specialization but think for example about 'StorelessUnivariateStatistic' there are different implementations and I just don't write the same actor over and over again with just one class exchanged. Or even an UnivarianteFunction....

But it would still be good to have each one as one palette item (as I simply can iterate over a list of implementations and create new StorelessUnivariateStatisticWrapper(...).

Do you think that would be possible or are the palette items strictly bound to the Ptolemy Actor model? What I have in mind would be something like a Service interface that provides the following attributes:

and then appears in the palette as if

This would greatly simplify the integration of existing functionality into Triquetrum.

erwindl0 commented 4 years ago

Hi Christoph,

Ok, that is a different approach and is indeed possible, already now in Triquetrum.

The plugin.xml-based approach is handled in org.eclipse.triquetrum.workflow.editor.palette.TriqPaletteBehavior.handlePaletteEntry(PaletteContainer, IConfigurationElement, IConfigurationElement)

You can define a palette group for which the individual entries can be provided by custom implementations of org.eclipse.triquetrum.workflow.editor.palette.spi.PaletteEntryProvider. (cfr lines 122-137 in TriqPaletteBehavior)

One such implementation is already in Triquetrum: org.eclipse.triquetrum.workflow.editor.palette.UserLibraryPaletteEntryProvider.

This adds dynamic entries to the palette, based on previously created models that the user wants to reuse as compositeactors / submodels.

An example of how to configure this is in /org.eclipse.triquetrum.workflow.editor/plugin.xml

cheers

erwin

laeubi commented 4 years ago

@erwindl0 many thanks that sounds like exactly what I'm looking for! I'll hopefully be able to try this out next week and will give feedback.

laeubi commented 4 years ago

@erwindl0 I'm now able to create dynamic entries in the palette

public class MyPaletteEntryProvider implements PaletteEntryProvider {

    public MyPaletteEntryProvider() {
        System.out.println("Provider created!");
    }

    @Override
    public IConfigurationElement[] getPaletteEntries() {
        PaletteGroup group = new PaletteGroup("Test Me");

        createEntry("Entry 1", "MyPaletteEntryProvider.item1", group);
        createEntry("Entry 2", "MyPaletteEntryProvider.item2", group);
        return new IConfigurationElement[] { group };

    }

    private void createEntry(String name, String id, PaletteGroup group) {
        Map<String, String> attributes = new HashMap<>();
        String pceType = "entry";
        attributes.put(DISPLAY_NAME, name);
        attributes.put(CLASS, MyWrappActor.class.getName());
        attributes.put(TYPE, BoCategory.Actor.name());
        attributes.put("MyIdProperty", id);
        PaletteConfigurationElement pce = new PaletteConfigurationElement(pceType,
                "org.eclipse.triquetrum.workflow.editor", attributes);
        group.addChild(name, pce);
    }
}

I'm trying to add a custom attribute attributes.put("MyIdProperty", id); to distinguish between actors using the same class MyWrappActor.class, but I'm not sure if these are passed to the actor and how I can access this. Is this already supported/possible to pass attributes that way?

laeubi commented 4 years ago

I think i got it working :-) I'll prepare a PR with the changes necessary, just one thing, when I go to "edit properties" of an palette item there pops up a dialog where icon, wrapped type ... can be edited, is it possible to replace this dialog with a custom one that configures special properties of the actor instead?

erwindl0 commented 4 years ago

I'm trying to add a custom attribute attributes.put("MyIdProperty", id); to distinguish between actors using the same class MyWrappActor.class, but I'm not sure if these are passed to the actor and how I can access this. Is this already supported/possible to pass attributes that way?

I think that's feasible, but would need to investigate if it's really operational. There's a section in org.eclipse.triquetrum.workflow.editor.features.ModelElementCreateFeature.create(ICreateContext), lines 161-165 that is meant to pass the palette attributes on to the created model element.

erwindl0 commented 4 years ago

I think i got it working :-) I'll prepare a PR with the changes necessary, just one thing, when I go to "edit properties" of an palette item there pops up a dialog where icon, wrapped type ... can be edited, is it possible to replace this dialog with a custom one that configures special properties of the actor instead?

great stuff! I'll check the PR asap.

Replacing/customizing the actor configuration dialog per type of actor is not really feasible at this moment I'm afraid. The approach based on EMF Forms ties a form's view model to an EMF type. As we have just one base EMF Actor type, this is quite limited now. I would need to check if EMF Forms has features to inject custom view models or so, but that will probably not be easy if there's no corresponding structure within the ecore model.

cxbrooks commented 3 years ago

I'm sorry that I missed the PR before releasing 0.4. Should the PR be merged?

laeubi commented 3 years ago

Sure, better late than never :-) Let me know if I should adjust anything.