Skip to content
Snippets Groups Projects
Commit 3e230b16 authored by Paul Bartetzky's avatar Paul Bartetzky
Browse files

initial

parent f8c7533d
Branches
No related tags found
No related merge requests found
Showing
with 1801 additions and 0 deletions
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Action, Args, hasStringProp, Operation } from '@eclipse-glsp/client';
export interface EditSignalClauseOperation extends Operation {
kind: typeof EditSignalClauseOperation.KIND;
transitionId: string;
signalClause: string;
/**
* Custom arguments.
*/
args?: Args;
}
export namespace EditSignalClauseOperation {
export const KIND = 'EditSignalClauseOperation';
export function is(object: unknown): object is EditSignalClauseOperation {
return Action.hasKind(object, KIND) && hasStringProp(object, 'transitionId') && hasStringProp(object, 'signalClause');
}
export function create(transitionId: string, signalClause: string, options: { args?: Args } = {}): EditSignalClauseOperation {
return {
kind: KIND,
isOperation: true,
transitionId: transitionId,
signalClause: signalClause,
...options
};
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Action, Args, hasStringProp, Operation } from '@eclipse-glsp/client';
export interface FireTransitionOperation extends Operation {
kind: typeof FireTransitionOperation.KIND;
transitionId: string;
token?: Map<string, string[]>;
/**
* Custom arguments.
*/
args?: Args;
}
export namespace FireTransitionOperation {
export const KIND = 'FireTransitionOperation';
export function is(object: unknown): object is FireTransitionOperation {
return Action.hasKind(object, KIND) && hasStringProp(object, 'transitionId');
}
export function create(transitionId: string, token?: Map<string, string[]>, options: { args?: Args } = {}): FireTransitionOperation {
return {
kind: KIND,
isOperation: true,
transitionId: transitionId,
token: token,
...options
};
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Action, Args } from '@eclipse-glsp/client';
// Action that signifies that a model update was completed
export interface PostModelUpdateAction extends Action {
kind: typeof PostModelUpdateAction.KIND;
/**
* Custom arguments.
*/
args?: Args;
}
export namespace PostModelUpdateAction {
export const KIND = 'PostModelUpdateAction';
export function is(object: unknown): object is PostModelUpdateAction {
return Action.hasKind(object, KIND);
}
export function create(options: { args?: Args } = {}): PostModelUpdateAction {
return {
kind: KIND,
...options
};
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Action, Args, Operation } from '@eclipse-glsp/client';
export interface ResetMarkingsOperation extends Operation {
kind: typeof ResetMarkingsOperation.KIND;
/**
* Custom arguments.
*/
args?: Args;
}
export namespace ResetMarkingsOperation {
export const KIND = 'ResetMarkingsOperation';
export function is(object: unknown): object is ResetMarkingsOperation {
return Action.hasKind(object, KIND);
}
export function create(options: { args?: Args } = {}): ResetMarkingsOperation {
return {
kind: KIND,
isOperation: true,
...options
};
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Action, Args, hasStringProp, RequestAction } from '@eclipse-glsp/client';
import { TinaResponseAction } from './TinaResponseAction';
export interface RunTinaAction extends RequestAction<TinaResponseAction> {
kind: typeof RunTinaAction.KIND;
tinaArgs: string;
/**
* Custom arguments.
*/
args?: Args;
}
export namespace RunTinaAction {
export const KIND = 'RunTinaAction';
export function is(object: unknown): object is RunTinaAction {
return Action.hasKind(object, KIND) && hasStringProp(object, 'tinaArgs');
}
export function create(tinaArgs: string, options: { requestId?: string; args?: Args } = {}): RunTinaAction {
return {
kind: KIND,
tinaArgs,
requestId: '',
...options
};
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Action, Args, hasStringProp, Operation } from '@eclipse-glsp/client';
export interface SetPageVisibilityOperation extends Operation {
kind: typeof SetPageVisibilityOperation.KIND;
pageNodeId: string;
hidden?: boolean;
/**
* Custom arguments.
*/
args?: Args;
}
export namespace SetPageVisibilityOperation {
export const KIND = 'SetPageVisibility';
export function is(object: unknown): object is SetPageVisibilityOperation {
return Action.hasKind(object, KIND) && hasStringProp(object, 'pageNodeId');
}
export function create(pageNodeId: string, options: { hidden?: boolean; args?: Args } = {}): SetPageVisibilityOperation {
return {
kind: KIND,
isOperation: true,
pageNodeId,
...options
};
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Action, Args, hasStringProp, ResponseAction } from '@eclipse-glsp/client';
export interface TinaResponseAction extends ResponseAction {
kind: typeof TinaResponseAction.KIND;
tinaResponse: string;
/**
* Custom arguments.
*/
args?: Args;
}
export namespace TinaResponseAction {
export const KIND = 'TinaResponseAction';
export function is(object: unknown): object is TinaResponseAction {
return Action.hasKind(object, KIND) && hasStringProp(object, 'tinaResponse');
}
export function create(tinaResponse: string, options: { responseId?: string; args?: Args } = {}): TinaResponseAction {
return {
kind: KIND,
tinaResponse: tinaResponse,
responseId: '',
...options
};
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Action, EditorContextService, IActionDispatcher, IActionHandler, TYPES } from '@eclipse-glsp/client';
import { inject, injectable } from 'inversify';
import { CopyToClipboardAction } from '../Actions/CopyToClipboardAction';
@injectable()
export class CopyToClipboardHandler implements IActionHandler {
@inject(TYPES.IActionDispatcher)
protected dispatcher: IActionDispatcher;
@inject(EditorContextService)
protected editorContextService: EditorContextService;
handle(action: CopyToClipboardAction): void | Action {
try {
navigator.clipboard.writeText(action.text);
} catch (err) {
console.error('Failed to copy content: ', err);
}
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Emitter, GModelRoot, ISModelRootListener } from '@eclipse-glsp/client';
import { Event } from '@eclipse-glsp/sprotty';
import { injectable } from 'inversify';
// Listens for the completion of model updates
// separate from ISModelRootListener to prevent cyclic dependencies
@injectable()
export class ModelUpdateListener implements ISModelRootListener {
protected onModelUpdateCompleteEmitter = new Emitter<Readonly<GModelRoot>>();
get onModelUpdateComplete(): Event<Readonly<GModelRoot>> {
return this.onModelUpdateCompleteEmitter.event;
}
modelRootChanged(root: Readonly<GModelRoot>): void {
this.onModelUpdateCompleteEmitter.fire(root);
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { Action } from '@eclipse-glsp/client';
import { GLSPActionDispatcher } from '@eclipse-glsp/client/lib/base/action-dispatcher';
import { injectable } from 'inversify';
@injectable()
export class MyActionDispatcher extends GLSPActionDispatcher {
override async dispatch(action: Action): Promise<void> {
console.log(' ' + 'Dispatch: ' + action.kind);
return super.dispatch(action);
}
protected override handleAction(action: Action): Promise<void> {
console.log(' ' + 'Handle: ' + action.kind);
return super.handleAction(action);
}
}
/********************************************************************************
* Copyright (c) 2022 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied:
* -- GNU General Public License, version 2 with the GNU Classpath Exception
* which is available at https://www.gnu.org/software/classpath/license.html
* -- MIT License which is available at https://opensource.org/license/mit.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR MIT
********************************************************************************/
export * from './Actions/CopyToClipboardAction';
export * from './Actions/FireTransitionOperation';
export * from './Actions/ResetMarkingsOperation';
export * from './model';
export * from './tasklist-diagram-module';
export * from './ui-extensions/edit-input-signals';
export * from './ui-extensions/edit-tokens';
export * from './ui-extensions/signal-clause-menu';
export * from './ui-extensions/tina-menu';
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
export enum PNMLModelTypes {
PLACE = 'place',
TRANSITION = 'transition',
ARC = 'arc',
PAGE = 'page',
PAGE_NODE = 'pageNode',
REF_PLACE = 'referencePlace',
REF_TRANSITION = 'referenceTransition',
REFERENCE = 'reference',
INHIBITOR_ARC = 'inhibitorArc',
READ_ARC = 'readArc',
GRAPH = 'graph',
NAME_LABEL = 'nameLabel',
MARKING_LABEL = 'markingLabel',
ARC_LABEL = 'arcWeightLabel',
// DiNeROS types
TOPIC_TRANSITION = 'topicTransitionType',
TOPIC_LINK = 'topicLink',
SERVICE_TRANSITION = 'serviceTransitionType',
SERVICE_CHANNEL = 'serviceChannel',
SERVICE_CHANNEL_LINK = 'serviceChannelLink',
SERVER_PAGE = 'serverPrototype',
SERVICE_SERVER_LINK = 'serviceServerLink'
}
/********************************************************************************
* Copyright (c) 2020-2023 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import {
boundsFeature,
connectableFeature,
Containable,
containerFeature,
deletableFeature,
EditableLabel,
fadeFeature,
GChildElement,
GCompartment,
GGraph,
GModelElement,
GModelElementSchema,
GShapeElement,
hoverFeedbackFeature,
isEditableLabel,
isGModelElementSchema,
layoutableChildFeature,
layoutContainerFeature,
moveFeature,
Nameable,
nameFeature,
openFeature,
popupFeature,
RectangularNode,
resizeFeature,
selectFeature,
WithEditableLabel,
withEditLabelFeature
} from '@eclipse-glsp/client';
import { PNMLModelTypes } from './model-types';
export class TransitionNode extends RectangularNode implements Nameable, WithEditableLabel {
static override readonly DEFAULT_FEATURES = [
connectableFeature,
deletableFeature,
selectFeature,
boundsFeature,
moveFeature,
layoutContainerFeature,
fadeFeature,
hoverFeedbackFeature,
popupFeature,
nameFeature,
withEditLabelFeature,
resizeFeature
];
duration?: number;
taskType?: string;
reference?: string;
get editableLabel(): (GChildElement & EditableLabel) | undefined {
const label = this.children.find(element => element.type === 'label:heading');
if (label && isEditableLabel(label)) {
return label;
}
return undefined;
}
get name(): string {
const labelText = this.editableLabel?.text;
return labelText ? labelText : '<unknown>';
}
}
export class InsertableGCompartment extends GCompartment implements Containable {
static override readonly DEFAULT_FEATURES = [
boundsFeature,
layoutContainerFeature,
layoutableChildFeature,
fadeFeature,
containerFeature
];
isContainableElement(_input: string | GShapeElement | GModelElementSchema): boolean {
return true;
}
}
export class CategoryNode extends RectangularNode implements Nameable, WithEditableLabel, Containable {
static override readonly DEFAULT_FEATURES = [
deletableFeature,
selectFeature,
boundsFeature,
moveFeature,
layoutContainerFeature,
fadeFeature,
hoverFeedbackFeature,
popupFeature,
nameFeature,
withEditLabelFeature,
openFeature,
containerFeature
];
name = '';
isContainableElement(input: GModelElement | GModelElementSchema | string): boolean {
return true;
}
get editableLabel(): (GChildElement & EditableLabel) | undefined {
const label = this.children.find(element => element.type === 'label:heading');
if (label && isEditableLabel(label)) {
return label;
}
return undefined;
}
}
export function getTypeString(input: GModelElement | GModelElementSchema | string): string {
if (input instanceof GModelElement || isGModelElementSchema(input)) {
return input.type;
} else {
return input;
}
}
export class PageNode extends CategoryNode {
override isContainableElement(input: GModelElement | GModelElementSchema | string): boolean {
const type: string = getTypeString(input);
if (type === PNMLModelTypes.SERVICE_CHANNEL) {
return false;
}
return true;
}
}
export class ServerPageNode extends CategoryNode {
override isContainableElement(input: GModelElement | GModelElementSchema | string): boolean {
const type: string = getTypeString(input);
if (
type === PNMLModelTypes.PLACE ||
type === PNMLModelTypes.TRANSITION ||
type === PNMLModelTypes.REF_PLACE ||
type === PNMLModelTypes.REF_TRANSITION
) {
return true;
}
return false;
}
}
export class ServiceNode extends CategoryNode {
override isContainableElement(input: GModelElement | GModelElementSchema | string): boolean {
const type: string = getTypeString(input);
if (type === PNMLModelTypes.SERVICE_CHANNEL) {
return true;
}
return false;
}
}
export class PNMLGraph extends GGraph {
override isContainableElement(_input: string | GShapeElement | GModelElementSchema): boolean {
const type: string = getTypeString(_input);
if (type === PNMLModelTypes.PAGE_NODE) {
return true;
}
return false;
}
}
export function isTransition(element: GModelElement): boolean {
return element.type === PNMLModelTypes.TRANSITION;
}
export function isPlace(element: GModelElement): boolean {
return element.type === PNMLModelTypes.PLACE;
}
export interface HasArgs {
args: any;
}
/********************************************************************************
* Copyright (c) 2022 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied:
* -- GNU General Public License, version 2 with the GNU Classpath Exception
* which is available at https://www.gnu.org/software/classpath/license.html
* -- MIT License which is available at https://opensource.org/license/mit.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR MIT
********************************************************************************/
import {
// StructureCompartmentView,
CircularNode,
// moveFeature,
// resizeFeature,
// RectangularNode
// GCompartmentView
// GNode,
CircularNodeView,
configureActionHandler,
configureDefaultModelElements,
configureModelElement,
connectableFeature,
ConsoleLogger,
ContainerConfiguration,
DefaultTypes,
editLabelFeature,
GCompartment,
GCompartmentView,
GEdge,
GEdgeView,
// StructureCompartmentView,
GLabel,
GLabelView,
GLSPProjectionView,
GNode,
hoverFeedbackFeature,
initializeDiagramContainer,
LogLevel,
moveFeature,
RectangularNode,
RectangularNodeView,
resizeFeature,
RoundedCornerNodeView,
selectFeature,
TYPES
} from '@eclipse-glsp/client';
import { Container, ContainerModule } from 'inversify';
import '../css/diagram.css';
import { CopyToClipboardAction } from './Actions/CopyToClipboardAction';
import { CopyToClipboardHandler } from './Handlers/CopyToClipboardHandler';
import { ModelUpdateListener } from './Handlers/ModelUpdateListener';
import { PageNode, PNMLGraph, ServerPageNode, ServiceNode } from './model';
import { ActivePagesOverlay } from './ui-extensions/active-pages-overlay';
import { EditInputSignalMenu } from './ui-extensions/edit-input-signals';
import { EditTokensMenu } from './ui-extensions/edit-tokens';
import { SignalClauseMenu } from './ui-extensions/signal-clause-menu';
import { TinaMenu } from './ui-extensions/tina-menu';
import { DirectedEdgeView, InhibitorArcView, PageNodeView, ReadArcView, ReferenceEdgeView } from './views';
const taskListDiagramModule = new ContainerModule((bind, unbind, isBound, rebind) => {
rebind(TYPES.ILogger).to(ConsoleLogger).inSingletonScope();
rebind(TYPES.LogLevel).toConstantValue(LogLevel.warn);
bind(ActivePagesOverlay).toSelf().inSingletonScope();
bind(TYPES.IUIExtension).toService(ActivePagesOverlay);
bind(TYPES.IDiagramStartup).toService(ActivePagesOverlay);
const context = { bind, unbind, isBound, rebind };
// rebind(GLSPActionDispatcher).to(MyActionDispatcher).inSingletonScope();
configureActionHandler(context, CopyToClipboardAction.KIND, CopyToClipboardHandler);
bind(ModelUpdateListener).toSelf().inSingletonScope();
bind(TYPES.ISModelRootListener).toService(ModelUpdateListener);
bind(TinaMenu).toSelf().inSingletonScope();
bind(TYPES.IUIExtension).to(TinaMenu);
bind(SignalClauseMenu).toSelf().inSingletonScope();
bind(TYPES.IUIExtension).to(SignalClauseMenu);
bind(EditInputSignalMenu).toSelf().inSingletonScope();
bind(TYPES.IUIExtension).toService(EditInputSignalMenu);
bind(EditTokensMenu).toSelf().inSingletonScope();
bind(TYPES.IUIExtension).toService(EditTokensMenu);
configureDefaultModelElements(context);
configureModelElement(context, DefaultTypes.EDGE, GEdge, GEdgeView);
configureModelElement(context, 'place', CircularNode, CircularNodeView);
configureModelElement(context, 'transition', GNode, RectangularNodeView);
configureModelElement(context, 'arc', GEdge, DirectedEdgeView);
configureModelElement(context, 'comp:header', GCompartment, GCompartmentView);
configureModelElement(context, 'pageNode', PageNode, PageNodeView, { enable: [resizeFeature], disable: [hoverFeedbackFeature] });
configureModelElement(context, 'label', GLabel, GLabelView, { enable: [editLabelFeature, moveFeature] });
configureModelElement(context, 'markingLabel', GLabel, GLabelView);
configureModelElement(context, DefaultTypes.GRAPH, PNMLGraph, GLSPProjectionView);
configureModelElement(context, 'page', GCompartment, GCompartmentView);
configureModelElement(context, 'referencePlace', CircularNode, CircularNodeView);
configureModelElement(context, 'referenceTransition', GNode, RectangularNodeView);
configureModelElement(context, 'refLink', GEdge, ReferenceEdgeView);
configureModelElement(context, 'readArc', GEdge, ReadArcView);
configureModelElement(context, 'inhibitorArc', GEdge, InhibitorArcView);
configureModelElement(context, 'labelNode', RectangularNode, RectangularNodeView, {
disable: [moveFeature, hoverFeedbackFeature, selectFeature]
});
configureModelElement(context, 'labelComp', GCompartment, GCompartmentView);
configureModelElement(context, 'arcWeightLabel', GLabel, GLabelView, { enable: [editLabelFeature] });
configureModelElement(context, 'topicTransitionType', RectangularNode, RoundedCornerNodeView);
configureModelElement(context, 'topicLink', GEdge, GEdgeView);
configureModelElement(context, 'serviceTransitionType', ServiceNode, RoundedCornerNodeView, { enable: [connectableFeature] });
configureModelElement(context, 'serviceChannel', RectangularNode, RoundedCornerNodeView, { disable: [moveFeature] });
configureModelElement(context, 'serviceChannelLink', GEdge, GEdgeView);
configureModelElement(context, 'serviceServerLink', GEdge, GEdgeView);
configureModelElement(context, 'serverPrototype', ServerPageNode, PageNodeView, {
enable: [resizeFeature],
disable: [hoverFeedbackFeature]
});
configureModelElement(context, 'signalClauseLabel', GLabel, GLabelView);
configureModelElement(context, 'edgeTextLabel', GLabel, GLabelView);
configureModelElement(context, 'topicLinkLimitLabel', GLabel, GLabelView, { enable: [editLabelFeature] });
});
export function initializeTasklistDiagramContainer(container: Container, ...containerConfiguration: ContainerConfiguration): Container {
return initializeDiagramContainer(container, taskListDiagramModule, ...containerConfiguration);
}
/********************************************************************************
* Copyright (c) 2020-2023 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import {
AbstractUIExtension,
codiconCSSClasses,
EditorContextService,
GChildElement,
GLabel,
GModelRoot,
hasArgs,
IActionDispatcher,
IDiagramStartup,
MaybePromise,
TYPES
} from '@eclipse-glsp/client';
import { inject, injectable } from 'inversify';
import { SetPageVisibilityOperation } from '../Actions/SetPageVisibilityOperation';
import { ModelUpdateListener } from '../Handlers/ModelUpdateListener';
@injectable()
export class ActivePagesOverlay extends AbstractUIExtension implements IDiagramStartup {
@inject(TYPES.IActionDispatcher)
protected readonly actionDispatcher: IActionDispatcher;
@inject(EditorContextService)
protected editorContext: EditorContextService;
@inject(ModelUpdateListener)
protected modelUpdateListener: ModelUpdateListener;
static readonly ID = 'button-overlay';
id(): string {
return ActivePagesOverlay.ID;
}
containerClass(): string {
return ActivePagesOverlay.ID;
}
protected initializeContents(containerElement: HTMLElement): void {
this.modelUpdateListener.onModelUpdateComplete(change => {
this.modelUpdateReload();
});
containerElement.appendChild(this.createPageButtonDiv());
}
protected createPageButtonDiv(): HTMLElement {
const buttonContainer = document.createElement('div');
buttonContainer.id = 'page-button-container';
const pageNodeList: GChildElement[] = [];
this.editorContext.modelRoot.children.forEach(child => {
this.collectPages(pageNodeList, child);
});
pageNodeList.forEach(pageNode => {
let text = '';
if (pageNode.children[0] instanceof GLabel) {
text = pageNode.children[0].text;
}
buttonContainer.appendChild(this.createPageButton('btn_center_diagram', text, 'screen-normal', pageNode));
});
return buttonContainer;
}
protected collectPages(pageNodeList: GChildElement[], node: GChildElement): any[] {
if (node.type === 'pageNode') {
pageNodeList.push(node);
}
node.children.forEach(child => this.collectPages(pageNodeList, child));
return pageNodeList;
}
protected createPageButton(id: string, label: string, codiconId: string, pageNode: GChildElement): HTMLElement {
const baseDiv = document.getElementById(this.options.baseDiv);
if (baseDiv) {
const button = document.createElement('div');
const insertedDiv = baseDiv.insertBefore(button, baseDiv.firstChild);
button.id = id + label;
button.classList.add('overlay-button');
const icon = this.createIcon(codiconId);
insertedDiv.appendChild(icon);
insertedDiv.onclick = () => {
if (hasArgs(pageNode)) {
const isHidden = pageNode.args.hidden;
this.actionDispatcher.dispatch(
SetPageVisibilityOperation.create(pageNode.id, {
hidden: !isHidden
})
);
}
};
insertedDiv.insertAdjacentText('beforeend', label);
return button;
}
return document.createElement('div');
}
protected createIcon(codiconId: string): HTMLElement {
const icon = document.createElement('i');
icon.classList.add(...codiconCSSClasses(codiconId), 'overlay-icon');
return icon;
}
postModelInitialization(): MaybePromise<void> {
this.show(this.editorContext.modelRoot);
}
modelUpdateReload(): void {
document.getElementById('page-button-container')?.replaceWith(this.createPageButtonDiv());
}
override show(root: Readonly<GModelRoot>, ...contextElementIds: string[]): void {
this.activeElement = document.activeElement;
if (!this.containerElement) {
if (!this.initialize()) {
return;
}
}
this.onBeforeShow(this.containerElement, root, ...contextElementIds);
this.setContainerVisible(true);
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import {
AbstractUIExtension,
codiconCSSClasses,
Disposable,
DOMHelper,
EditorContextService,
GLSPActionDispatcher,
GLSPMouseTool,
GModelRoot,
hasArgs,
MousePositionTracker,
TYPES,
ViewerOptions
} from '@eclipse-glsp/client';
import { inject, injectable } from 'inversify';
import { AddInputSignalOperation } from '../Actions/AddInputSignalOperation';
import { DeleteInputSignalOperation } from '../Actions/DeleteInputSignalOperation';
import { ModelUpdateListener } from '../Handlers/ModelUpdateListener';
@injectable()
export class EditInputSignalMenu extends AbstractUIExtension {
@inject(TYPES.IActionDispatcher)
protected actionDispatcher: GLSPActionDispatcher;
@inject(EditorContextService)
protected editorContextService: EditorContextService;
@inject(MousePositionTracker)
protected mousePositionTracker: MousePositionTracker;
@inject(TYPES.ViewerOptions)
protected viewerOptions: ViewerOptions;
@inject(TYPES.DOMHelper)
protected domHelper: DOMHelper;
@inject(GLSPMouseTool) protected mouseTool: GLSPMouseTool;
@inject(ModelUpdateListener)
protected modelUpdateListener: ModelUpdateListener;
protected waitForUpdate: Disposable;
protected waitForUpdateIsDisposed = true;
static readonly ID = 'edit-signal-menu';
override id(): string {
return EditInputSignalMenu.ID;
}
override containerClass(): string {
return 'command-palette';
}
protected override initializeContents(containerElement: HTMLElement): void {
containerElement.appendChild(this.createWidget());
}
protected createWidget(): HTMLElement {
const editingElement = document.createElement('div');
editingElement.id = 'input-signal-editing-element';
editingElement.classList.add('edit-box');
const header = document.createElement('div');
header.appendChild(document.createTextNode('Edit Input Signals'));
const closeIcon = this.createIcon('chrome-close', 'Close');
closeIcon.style.margin = '0px 0px 0px 0px';
closeIcon.onclick = () => {
this.hide();
};
header.appendChild(closeIcon);
header.classList.add('edit-box-header');
editingElement.appendChild(header);
editingElement.appendChild(this.createInputSection());
const sepLine = document.createElement('hr');
sepLine.style.margin = '4px 0px 0px';
editingElement.appendChild(sepLine);
editingElement.appendChild(this.createDeletionSection());
return editingElement;
}
protected createInputSection(): HTMLElement {
const inputSection = document.createElement('div');
const titleDiv = document.createElement('div');
const title = document.createTextNode('Add Signal:');
titleDiv.appendChild(title);
titleDiv.classList.add('edit-box-text');
inputSection.appendChild(titleDiv);
const inputField = document.createElement('input');
inputField.id = 'add-signal-input-field';
inputField.style.width = '75%';
inputField.style.border = 'solid';
inputField.style.borderWidth = '1px';
inputField.style.borderColor = '#DDDDDD';
inputSection.appendChild(inputField);
const addButton = document.createElement('button');
addButton.appendChild(document.createTextNode('Add'));
addButton.style.color = '#333333';
addButton.onclick = async () => {
if (this.waitForUpdateIsDisposed) {
const signalId = inputField.value;
if (!signalId) {
return;
}
await this.actionDispatcher.dispatch(AddInputSignalOperation.create(signalId));
this.waitForUpdate = this.modelUpdateListener.onModelUpdateComplete(change => {
this.modelUpdateReload();
});
this.waitForUpdateIsDisposed = false;
}
};
inputSection.appendChild(addButton);
return inputSection;
}
protected createDeletionSection(): HTMLElement {
const deletionSection = document.createElement('div');
const titleDiv = document.createElement('div');
const title = document.createTextNode('Input Signals:');
titleDiv.appendChild(title);
titleDiv.classList.add('edit-box-text');
deletionSection.appendChild(titleDiv);
const root = this.editorContextService.modelRoot;
const graphArgs = hasArgs(root) ? root.args : {};
// eslint-disable-next-line guard-for-in
for (const signalId in graphArgs) {
deletionSection.appendChild(this.createDeletionElement(signalId));
}
return deletionSection;
}
protected createDeletionElement(signalId: string): HTMLElement {
const deletionElement = document.createElement('div');
deletionElement.classList.add('delete-field');
const icon = this.createIcon('chrome-close', 'Delete');
icon.onclick = async () => {
if (this.waitForUpdateIsDisposed) {
await this.actionDispatcher.dispatch(DeleteInputSignalOperation.create(signalId));
this.waitForUpdate = this.modelUpdateListener.onModelUpdateComplete(change => {
this.modelUpdateReload();
});
this.waitForUpdateIsDisposed = false;
}
};
deletionElement.appendChild(icon);
deletionElement.insertAdjacentText('beforeend', signalId);
return deletionElement;
}
protected createIcon(codiconId: string, hoverText: string): HTMLElement {
const icon = document.createElement('i');
icon.classList.add(...codiconCSSClasses(codiconId), 'overlay-icon', 'delete-icon');
icon.setAttribute('title', hoverText);
return icon;
}
override show(root: Readonly<GModelRoot>, ...contextElementIds: string[]): void {
super.show(root, ...contextElementIds);
}
protected override onBeforeShow(containerElement: HTMLElement, root: Readonly<GModelRoot>, ...contextElementIds: string[]): void {
this.setPosition(containerElement);
}
protected setPosition(containerElement: HTMLElement): void {
this.containerElement.style.position = 'absolute';
const x = 25;
const y = 100;
containerElement.style.left = `${x}px`;
containerElement.style.top = `${y}px`;
containerElement.style.width = '200px';
}
override hide(): void {
super.hide();
}
modelUpdateReload(): void {
document.getElementById('input-signal-editing-element')?.replaceWith(this.createWidget());
this.waitForUpdate?.dispose();
this.waitForUpdateIsDisposed = true;
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import {
AbstractUIExtension,
codiconCSSClasses,
Disposable,
DOMHelper,
EditorContextService,
GLSPActionDispatcher,
GLSPMouseTool,
GModelRoot,
GNode,
hasArgs,
ModelIndexImpl,
MousePositionTracker,
TYPES,
ViewerOptions
} from '@eclipse-glsp/client';
import { inject, injectable } from 'inversify';
import { AddDiNeROSTokenOperation } from '../Actions/AddDiNeROSTokenOperation';
import { DeleteDiNeROSTokenOperation } from '../Actions/DeleteDiNeROSTokenOperation';
import { ModelUpdateListener } from '../Handlers/ModelUpdateListener';
import { isPlace } from '../model';
@injectable()
export class EditTokensMenu extends AbstractUIExtension {
@inject(TYPES.IActionDispatcher)
protected actionDispatcher: GLSPActionDispatcher;
@inject(EditorContextService)
protected editorContextService: EditorContextService;
@inject(MousePositionTracker)
protected mousePositionTracker: MousePositionTracker;
@inject(TYPES.ViewerOptions)
protected viewerOptions: ViewerOptions;
@inject(TYPES.DOMHelper)
protected domHelper: DOMHelper;
@inject(GLSPMouseTool) protected mouseTool: GLSPMouseTool;
@inject(ModelUpdateListener)
protected modelUpdateListener: ModelUpdateListener;
protected waitForUpdate: Disposable;
protected noUpdateInProgress = true;
static readonly ID = 'edit-tokens-menu';
protected place: GNode;
override id(): string {
return EditTokensMenu.ID;
}
override containerClass(): string {
return 'command-palette';
}
protected override initializeContents(containerElement: HTMLElement): void {
containerElement.appendChild(this.createWidget());
}
protected createWidget(): HTMLElement {
const editingElement = document.createElement('div');
editingElement.id = 'token-editing-element';
editingElement.classList.add('edit-box');
const header = document.createElement('div');
header.appendChild(document.createTextNode('Edit Tokens'));
const closeIcon = this.createIcon('chrome-close', 'Close');
closeIcon.style.margin = '0px 0px 0px 0px';
closeIcon.onclick = () => {
this.hide();
};
header.appendChild(closeIcon);
header.classList.add('edit-box-header');
editingElement.appendChild(header);
const placeIdDiv = document.createElement('div');
placeIdDiv.appendChild(document.createTextNode('Place ID: ' + this.place.id));
placeIdDiv.style.padding = '0.4em';
editingElement.appendChild(placeIdDiv);
editingElement.appendChild(this.createInputSection());
const sepLine = document.createElement('hr');
sepLine.style.margin = '4px 0px 0px';
editingElement.appendChild(sepLine);
editingElement.appendChild(this.createDeletionSection());
return editingElement;
}
protected createInputSection(): HTMLElement {
const inputSection = document.createElement('div');
const titleDiv = document.createElement('div');
const title = document.createTextNode('Add Token:');
titleDiv.appendChild(title);
titleDiv.classList.add('edit-box-text');
inputSection.appendChild(titleDiv);
const inputField = document.createElement('textarea');
inputField.id = 'add-token-input-field';
inputField.style.width = '90%';
inputField.style.border = 'solid';
inputField.style.borderWidth = '1px';
inputField.style.borderColor = '#DDDDDD';
inputSection.appendChild(inputField);
const addButton = document.createElement('button');
addButton.appendChild(document.createTextNode('Add'));
addButton.style.color = '#333333';
addButton.onclick = async () => {
if (this.noUpdateInProgress) {
const token = inputField.value;
if (!token) {
return;
}
await this.actionDispatcher.dispatch(AddDiNeROSTokenOperation.create(this.place.id, token));
this.noUpdateInProgress = false;
}
};
inputSection.appendChild(addButton);
return inputSection;
}
protected createDeletionSection(): HTMLElement {
const deletionSection = document.createElement('div');
const titleDiv = document.createElement('div');
const title = document.createTextNode('Tokens:');
titleDiv.appendChild(title);
titleDiv.classList.add('edit-box-text');
deletionSection.appendChild(titleDiv);
const placeArgs = hasArgs(this.place) ? this.place.args : {};
const tokenListString = placeArgs.BalloonTokens;
const tokens: string[] = JSON.parse(tokenListString.toString());
tokens.forEach(token => {
deletionSection.appendChild(this.createDeletionElement(token));
});
return deletionSection;
}
protected createDeletionElement(token: string): HTMLElement {
const deletionElement = document.createElement('div');
deletionElement.classList.add('delete-field');
deletionElement.style.paddingBottom = '5px';
const icon = this.createIcon('chrome-close', 'Delete');
icon.onclick = async () => {
if (this.noUpdateInProgress) {
await this.actionDispatcher.dispatch(DeleteDiNeROSTokenOperation.create(this.place.id, token));
this.noUpdateInProgress = false;
}
};
deletionElement.appendChild(icon);
deletionElement.insertAdjacentText('beforeend', token);
return deletionElement;
}
protected createIcon(codiconId: string, hoverText: string): HTMLElement {
const icon = document.createElement('i');
icon.classList.add(...codiconCSSClasses(codiconId), 'overlay-icon', 'delete-icon');
icon.setAttribute('title', hoverText);
return icon;
}
override show(root: Readonly<GModelRoot>, ...contextElementIds: string[]): void {
this.place = getPlace(contextElementIds, root.index)[0];
super.show(root, ...contextElementIds);
document.getElementById('token-editing-element')?.replaceWith(this.createWidget());
this.waitForUpdate = this.modelUpdateListener.onModelUpdateComplete(change => {
this.modelUpdateReload();
});
}
protected override onBeforeShow(containerElement: HTMLElement, root: Readonly<GModelRoot>, ...contextElementIds: string[]): void {
this.setPosition(containerElement);
}
protected setPosition(containerElement: HTMLElement): void {
this.containerElement.style.position = 'absolute';
const x = 250;
const y = 100;
containerElement.style.left = `${x}px`;
containerElement.style.top = `${y}px`;
containerElement.style.width = '520px';
}
override hide(): void {
this.waitForUpdate?.dispose();
super.hide();
}
modelUpdateReload(): void {
this.place = getPlace([this.place.id], this.editorContextService.modelRoot.index)[0];
document.getElementById('token-editing-element')?.replaceWith(this.createWidget());
this.noUpdateInProgress = true;
}
}
function getPlace(ids: string[], index: ModelIndexImpl): GNode[] {
return ids.map(id => index.getById(id)).filter(element => element && isPlace(element)) as GNode[];
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import {
AbstractUIExtension,
AutoCompleteWidget,
DOMHelper,
EditorContextService,
getAbsoluteClientBounds,
GLSPActionDispatcher,
GModelRoot,
GNode,
LabeledAction,
ModelIndexImpl,
MousePositionTracker,
RequestEditValidationAction,
SetEditValidationResultAction,
TYPES,
ValidationDecorator,
ValidationStatus,
ViewerOptions
} from '@eclipse-glsp/client';
import { inject, injectable } from 'inversify';
import { EditSignalClauseOperation } from '../Actions/EditSignalClauseOperation';
import { isTransition } from '../model';
@injectable()
export class SignalClauseMenu extends AbstractUIExtension {
@inject(TYPES.IActionDispatcher)
protected actionDispatcher: GLSPActionDispatcher;
@inject(EditorContextService)
protected editorContextService: EditorContextService;
@inject(MousePositionTracker)
protected mousePositionTracker: MousePositionTracker;
@inject(TYPES.ViewerOptions)
protected viewerOptions: ViewerOptions;
@inject(TYPES.DOMHelper)
protected domHelper: DOMHelper;
static readonly ID = 'signal-clause-menu';
protected transition: GNode;
protected autoSuggestion: AutoCompleteWidget;
readonly autoSuggestionSettings = {
noSuggestionsMessage: '',
suggestionsClass: 'command-palette-suggestions',
debounceWaitMs: 50,
showOnFocus: true
};
override id(): string {
return SignalClauseMenu.ID;
}
override containerClass(): string {
return 'command-palette';
}
protected override initializeContents(containerElement: HTMLElement): void {
this.autoSuggestion = new AutoCompleteWidget(
this.autoSuggestionSettings,
{ provideSuggestions: input => this.retrieveSuggestions(input) },
{ executeFromSuggestion: input => {} },
() => this.hide(),
this.logger
);
this.autoSuggestion.configureValidation(
{ validate: input => this.validateInput(input) },
new ValidationDecorator(containerElement)
);
this.autoSuggestion.configureTextSubmitHandler({
executeFromTextOnlyInput: (input: string) => this.executeFromTextOnlyInput(input)
});
this.autoSuggestion.initialize(containerElement);
}
protected async validateInput(input: string): Promise<ValidationStatus> {
const response = await this.actionDispatcher.request(
RequestEditValidationAction.create({ contextId: SignalClauseMenu.ID, modelElementId: this.transition.id, text: input })
);
if (SetEditValidationResultAction.is(response)) {
return response.status;
}
return Promise.reject();
}
override show(root: Readonly<GModelRoot>, ...contextElementIds: string[]): void {
super.show(root, ...contextElementIds);
this.autoSuggestion.open(root);
}
protected override onBeforeShow(containerElement: HTMLElement, root: Readonly<GModelRoot>, ...contextElementIds: string[]): void {
this.transition = getTransition(contextElementIds, root.index)[0];
this.autoSuggestion.inputField.value = '';
this.setPosition(containerElement);
}
protected setPosition(containerElement: HTMLElement): void {
let x = 0;
let y = 0;
if (this.transition) {
const bounds = getAbsoluteClientBounds(this.transition, this.domHelper, this.viewerOptions);
x = bounds.x + 5;
y = bounds.y + 5;
}
containerElement.style.left = `${x}px`;
containerElement.style.top = `${y}px`;
containerElement.style.width = '200px';
}
executeFromTextOnlyInput(input: string): void {
this.actionDispatcher.dispatch(EditSignalClauseOperation.create(this.transition.id, input));
}
protected async retrieveSuggestions(input: string): Promise<LabeledAction[]> {
return [];
}
override hide(): void {
this.autoSuggestion.dispose();
super.hide();
}
}
function getTransition(ids: string[], index: ModelIndexImpl): GNode[] {
return ids.map(id => index.getById(id)).filter(element => element && isTransition(element)) as GNode[];
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import {
AbstractUIExtension,
codiconCSSClasses,
Disposable,
DOMHelper,
EditorContextService,
GLSPActionDispatcher,
GLSPMouseTool,
GModelRoot,
MousePositionTracker,
TYPES,
ViewerOptions
} from '@eclipse-glsp/client';
import { inject, injectable } from 'inversify';
import { RunTinaAction } from '../Actions/RunTinaAction';
import { TinaResponseAction } from '../Actions/TinaResponseAction';
import { ModelUpdateListener } from '../Handlers/ModelUpdateListener';
@injectable()
export class TinaMenu extends AbstractUIExtension {
@inject(TYPES.IActionDispatcher)
protected actionDispatcher: GLSPActionDispatcher;
@inject(EditorContextService)
protected editorContextService: EditorContextService;
@inject(MousePositionTracker)
protected mousePositionTracker: MousePositionTracker;
@inject(TYPES.ViewerOptions)
protected viewerOptions: ViewerOptions;
@inject(TYPES.DOMHelper)
protected domHelper: DOMHelper;
@inject(GLSPMouseTool) protected mouseTool: GLSPMouseTool;
@inject(ModelUpdateListener)
protected modelUpdateListener: ModelUpdateListener;
protected waitForUpdate: Disposable;
protected waitForUpdateIsDisposed = true;
static readonly ID = 'tina-menu';
override id(): string {
return TinaMenu.ID;
}
override containerClass(): string {
return 'command-palette';
}
protected override initializeContents(containerElement: HTMLElement): void {
containerElement.appendChild(this.createWidget());
}
protected createWidget(): HTMLElement {
const editingElement = document.createElement('div');
editingElement.id = 'tina-element';
editingElement.classList.add('edit-box');
const header = document.createElement('div');
header.appendChild(document.createTextNode('Run Tina'));
const closeIcon = this.createIcon('chrome-close', 'Close');
closeIcon.style.margin = '0px 0px 0px 0px';
closeIcon.onclick = () => {
this.hide();
};
header.appendChild(closeIcon);
header.classList.add('edit-box-header');
editingElement.appendChild(header);
editingElement.appendChild(this.createInputSection());
const sepLine = document.createElement('hr');
sepLine.style.margin = '4px 0px 0px';
editingElement.appendChild(sepLine);
editingElement.appendChild(this.createResponseSection(''));
return editingElement;
}
protected createInputSection(): HTMLElement {
const inputSection = document.createElement('div');
const inputField = document.createElement('input');
inputField.id = 'add-signal-input-field';
inputField.style.width = '85%';
inputField.style.border = 'solid';
inputField.style.borderWidth = '1px';
inputField.style.borderColor = '#DDDDDD';
inputSection.appendChild(inputField);
const addButton = document.createElement('button');
addButton.appendChild(document.createTextNode('Run'));
addButton.style.color = '#333333';
addButton.onclick = async () => {
const tinaCommand = inputField.value;
if (!tinaCommand) {
return;
}
const response = await this.actionDispatcher.request(RunTinaAction.create(tinaCommand));
inputField.value = '';
if (TinaResponseAction.is(response)) {
this.displayResponse(response.tinaResponse);
}
return Promise.reject();
};
inputSection.appendChild(addButton);
return inputSection;
}
protected createResponseSection(response: string): HTMLElement {
const responseSection = document.createElement('div');
responseSection.id = 'response-section-element';
if (response) {
responseSection.appendChild(document.createTextNode(response));
responseSection.style.padding = '0.4em';
}
return responseSection;
}
protected createIcon(codiconId: string, hoverText: string): HTMLElement {
const icon = document.createElement('i');
icon.classList.add(...codiconCSSClasses(codiconId), 'overlay-icon', 'delete-icon');
icon.setAttribute('title', hoverText);
return icon;
}
override show(root: Readonly<GModelRoot>, ...contextElementIds: string[]): void {
super.show(root, ...contextElementIds);
}
protected override onBeforeShow(containerElement: HTMLElement, root: Readonly<GModelRoot>, ...contextElementIds: string[]): void {
this.setPosition(containerElement);
}
protected setPosition(containerElement: HTMLElement): void {
this.containerElement.style.position = 'absolute';
const x = 250;
const y = 10;
containerElement.style.left = `${x}px`;
containerElement.style.top = `${y}px`;
containerElement.style.width = '400px';
}
override hide(): void {
document.getElementById('response-section-element')?.replaceWith(this.createResponseSection(''));
super.hide();
}
displayResponse(response: string): void {
document.getElementById('response-section-element')?.replaceWith(this.createResponseSection(response));
}
}
/********************************************************************************
* Copyright (c) 2024 EclipseSource and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import {
angleOfPoint,
GEdge,
GNode,
GShapeElement,
Hoverable,
isSelectable,
IViewArgs,
Point,
PolylineEdgeViewWithGapsOnIntersections,
RenderingContext,
RoundedCornerNodeView,
SEdgeImpl,
Selectable,
svg,
toDegrees
} from '@eclipse-glsp/client';
import { injectable } from 'inversify';
import { VNode } from 'snabbdom';
import { HasArgs } from './model';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const JSX = { createElement: svg };
@injectable()
export class DirectedEdgeView extends PolylineEdgeViewWithGapsOnIntersections {
protected arrowHead = 'M 1,0 L 10,-4 L 10,4 Z';
protected override renderAdditionals(edge: GEdge, segments: Point[], context: RenderingContext): VNode[] {
const additionals = super.renderAdditionals(edge, segments, context);
const p1 = segments[segments.length - 2];
const p2 = segments[segments.length - 1];
const arrow = (
<path
class-sprotty-edge={true}
class-arrow={true}
d={this.arrowHead}
transform={`rotate(${toDegrees(angleOfPoint({ x: p1.x - p2.x, y: p1.y - p2.y }))} ${p2.x} ${p2.y}) translate(${p2.x} ${
p2.y
})`}
/>
);
additionals.push(arrow);
return additionals;
}
}
@injectable()
export class ReadArcView extends DirectedEdgeView {
protected override arrowHead = 'M 1,0 L 10,-5 L 19,0 L 10,5 Z';
}
@injectable()
export class InhibitorArcView extends DirectedEdgeView {
protected override arrowHead = 'M 1,0 m 5,0 a 5,5 0 1,0 -10,0 a 5,5 0 1,0 10,0';
}
@injectable()
export class PageNodeView extends RoundedCornerNodeView {
override render(node: Readonly<GNode & Hoverable & Selectable & HasArgs>, context: RenderingContext): VNode | undefined {
if (node.type === 'pageNode' && node.args.hidden !== undefined && node.args.hidden === true) {
return undefined;
}
return super.render(node, context);
}
protected override renderWithoutRadius(
node: Readonly<GShapeElement & Hoverable & Selectable & HasArgs>,
context: RenderingContext
): VNode | undefined {
if (node.type === 'pageNode' && node.args.hidden !== undefined && node.args.hidden === true) {
return undefined;
}
return super.renderWithoutRadius(node, context);
}
}
@injectable()
export class ReferenceEdgeView extends PolylineEdgeViewWithGapsOnIntersections {
override render(edge: Readonly<SEdgeImpl>, context: RenderingContext, args?: IViewArgs): VNode | undefined {
const source = edge.source;
if (source && isSelectable(source) && source.selected) {
return super.render(edge, context, args);
}
return undefined;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment