Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data Elements #391

Open
Rtulpe opened this issue Oct 23, 2023 · 3 comments
Open

Data Elements #391

Rtulpe opened this issue Oct 23, 2023 · 3 comments
Labels
question Further information is requested

Comments

@Rtulpe
Copy link

Rtulpe commented Oct 23, 2023

I do not see a clear way of holding additional non-rendered data in both Model Source and Graph models. Would it be possible to have some kind of Data SModel elements, that would not require view configurations? Here are some examples where this would be useful:

Example 1:

Let's say for each node I want to have a different description. These would appear as a pop-up model elements. The way I have done this is by using SLabel child in the node with the description text. In PopupModelProvider I extracted the text string from the SLabel child and generate PreRenderedElement, so configureView() is not needed, yet I still have do register a view that returns "undefined".

If there was a string data element, which just stays as a child, but is not rendered, this would be a bit simplified.

Example 2:

I want to have edges with multiplicity, based on Crow's Foot Notation. If there were boolean data elements, I could just have 2 such values and a single view could render additionals a bit differently, depending on the boolean value of the data element children.

Instead, I would need to do one of the following:

  • Multiple edge types depending on multiplicity.
  • Borrow into CSS classes.
  • Send a request action to retrieve such data.
  • Some other non-straight forward ways (like BigUML relations).

Could this be a useful feature? This could also be implemented as a field for SModelElement (like data?: { [key: string]: any }), it would open up some new ways for diagram generation.

@spoenemann
Copy link
Contributor

Hi, thanks for the proposal!

Can't you use a custom property to hold the data? If you avoid putting it into children, the framework will simply ignore it, but you can still access it in your app-specific code.

@Rtulpe
Copy link
Author

Rtulpe commented Oct 30, 2023

The question would be how can I transfer this data, from the Sprotty-protocol Model to the Graph SModelImpl? Let's say, I generate a graph and add some data into the SNode. How could I access this data later in, let's say, RectangularNodeView?
There is some passing going on for the cssClasses, so what you assign initially, you can access them everywhere, even in the View.

Why not have something like:

export interface SModelElement {
    type: string
    id: string
    children?: SModelElement[]
    cssClasses?: string[]
    data?: { [key: string]: number | string | boolean }
}

and

export class SModelElementImpl {
    type: string;
    id: string;
    features?: FeatureSet;
    cssClasses?: string[];
    data?: { [key: string]: number | string | boolean };
...

Then you could add data into elements like:

<SNode>{
            id: 'node1',
            type: 'node:class',
            expanded: false,
            position: {
                x: 100,
                y: 100
            },
            layout: 'vbox',
            data: {
                header: 'Attributes',
                expanded: true,
                superfluous: false
            },
...

People wouldn't need to expand the protocol to send data. This could also be accessed anywhere. Just thought it would be a cool idea for Sprotty to have such feature.

@spoenemann
Copy link
Contributor

The problem is that data?: { [key: string]: number | string | boolean } means working with untyped JSON-like data. It's better to use an explicit type:

export interface MyModelElement extends SNode {
    data: {
        header: string
        expanded: boolean
        superfluous: boolean
    }
}

@injectable()
export class MyView extends ShapeView {
    render(node: Readonly<SNodeImpl & MyModelElement>, context: RenderingContext): VNode | undefined {
        const header = node.data.header;
        // ...
    }
}

@spoenemann spoenemann added the question Further information is requested label Nov 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants