Skip to content
This repository has been archived by the owner on Nov 22, 2019. It is now read-only.

Commit

Permalink
TEIIDTOOLS-467: begin hooking up the canvas to the view editor
Browse files Browse the repository at this point in the history
* Use the subscriptions and events to hook in the actions of the canvas to
  the models in the view editor and let the latter drive the creation of
  objects with the canvas responding accordingly.
  • Loading branch information
phantomjinx committed Jul 3, 2018
1 parent 0a123d9 commit a65dfb8
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 63 deletions.
6 changes: 5 additions & 1 deletion ngapp/src/app/dataservices/shared/deployment-state.enum.ts
Expand Up @@ -43,6 +43,10 @@ export enum DeploymentState {
/**
* not deployed
*/
NOT_DEPLOYED
NOT_DEPLOYED,

/**
* Indicates that the view compositions have changed.
*/
COMPOSITIONS_CHANGED = "COMPOSITIONS_CHANGED",
}
Expand Up @@ -31,6 +31,16 @@ export enum ViewEditorEventType {
*/
CANVAS_SELECTION_CHANGED = "CANVAS_SELECTION_CHANGED",

/**
* An event indicating a source should be created
*/
CREATE_SOURCE = "CREATE_SOURCE",

/**
* An event indicating a composition should be created
*/
CREATE_COMPOSITION = "CREATE_COMPOSITION",

/**
* An event indicating the view being edited has been set. This will only be fired one time one the view editor is
* opened. The one event argument is the {@link View} being set.
Expand Down
Expand Up @@ -211,4 +211,17 @@ export class ViewEditorEvent {
return this.type === ViewEditorEventType.VIEW_STATE_CHANGED;
}

/**
* @returns {boolean} `true` if the type is `ViewEditorEventType.CREATE_SOURCE`
*/
public typeIsCreateSource(): boolean {
return this.type === ViewEditorEventType.CREATE_SOURCE;
}

/**
* @returns {boolean} `true` if the type is `ViewEditorEventType.CREATE_COMPOSITION`
*/
public typeIsCreateComposition(): boolean {
return this.type === ViewEditorEventType.CREATE_COMPOSITION;
}
}
Expand Up @@ -14,26 +14,59 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Injectable, EventEmitter, ChangeDetectorRef } from '@angular/core';
import { Injectable, EventEmitter, ChangeDetectorRef, Output } from '@angular/core';
import { CanvasConstants } from '@dataservices/virtualization/view-editor/view-canvas/canvas-constants';
import { CanvasNode, CanvasLink, CanvasGraph } from '@dataservices/virtualization/view-editor/view-canvas/models';
import { ViewCanvasEvent } from "@dataservices/virtualization/view-editor/view-canvas/event/view-canvas-event";
import { ViewCanvasEventType } from "@dataservices/virtualization/view-editor/view-canvas/event/view-canvas-event-type.enum";
import * as d3 from 'd3';
import * as _ from "lodash";

@Injectable()
export class CanvasService {

/**
* An event fired when the state of the canvas has changed.
*
* @type {EventEmitter<ViewCanvasEvent>}
*/
@Output() public canvasEvent: EventEmitter< ViewCanvasEvent > = new EventEmitter();

private canvasGraph: CanvasGraph;
private viewReference: ChangeDetectorRef;

public canvasNodesSelected: EventEmitter<CanvasNode[]> = new EventEmitter();

/**
* This service will provide methods to enable user interaction with elements
* while maintaining the d3 simulations physics
*/
constructor() {}

/**
* The interactable graph.
* This method does not interact with the document, purely physical calculations with d3
*/
public newCanvasGraph(options: { width, height }, changeDetectorRef: ChangeDetectorRef): CanvasGraph {
this.viewReference = changeDetectorRef;

this.canvasGraph = new CanvasGraph(this, options);
this.canvasGraph.nodesSelected.subscribe((nodes) => {
const event = ViewCanvasEvent.create(ViewCanvasEventType.CANVAS_SELECTION_CHANGED, nodes);
this.canvasEvent.emit(event);
});

/**
* Binding change detection check on each tick
* This along with an onPush change detection strategy should enforce checking only when relevant!
* This improves scripting computation duration, consistently.
* Also, it makes sense to avoid unnecessary checks when we are dealing only with simulations data binding.
*/
this.canvasGraph.ticker.subscribe((d) => {
this.viewReference.markForCheck();
});

return this.canvasGraph;
}

private stopPropagation(): void {
// Stop propagration of click event to parent svg
d3.event.stopPropagation();
Expand All @@ -53,31 +86,39 @@ export class CanvasService {
}

private addNodeCallback(source: CanvasNode): void {
let eventType = null;
if (source.type === CanvasConstants.SOURCE_TYPE)
eventType = ViewCanvasEventType.CREATE_COMPOSITION;
else if (source.type === CanvasConstants.COMPONENT_TYPE)
eventType = ViewCanvasEventType.CREATE_SOURCE;

const event = ViewCanvasEvent.create(eventType, []);
this.canvasEvent.emit(event);
//
// Ensure all nodes have been unfixed
// to allow the graph to properly relayout
// //
// // Ensure all nodes have been unfixed
// // to allow the graph to properly relayout
// //
// this.canvasGraph.unfixNodes();
//
this.canvasGraph.unfixNodes();

// //
// // Fix the source node
// //
// source.setFixed(true);
//
// Fix the source node
// let type = null;
// if (source.type === CanvasConstants.SOURCE_TYPE)
// type = CanvasConstants.COMPONENT_TYPE;
// else
// type = CanvasConstants.SOURCE_TYPE;
//
source.setFixed(true);

let type = null;
if (source.type === CanvasConstants.SOURCE_TYPE)
type = CanvasConstants.COMPONENT_TYPE;
else
type = CanvasConstants.SOURCE_TYPE;

const tgtId = this.createNode(type, '<<ToBeImplemented>>');
const srcId = source.id;

//
// Create the link and update the graph
// const tgtId = this.createNode(type, '<<ToBeImplemented>>');
// const srcId = source.id;
//
this.createLink(srcId, tgtId, true);
// //
// // Create the link and update the graph
// //
// this.createLink(srcId, tgtId, true);
this.stopPropagation();
}

Expand All @@ -86,31 +127,6 @@ export class CanvasService {
this.stopPropagation();
}

/**
* The interactable graph.
* This method does not interact with the document, purely physical calculations with d3
*/
public newCanvasGraph(options: { width, height }, changeDetectorRef: ChangeDetectorRef): CanvasGraph {
this.viewReference = changeDetectorRef;

this.canvasGraph = new CanvasGraph(this, options);
this.canvasGraph.nodesSelected.subscribe((nodes) => {
this.canvasNodesSelected.emit(nodes);
});

/**
* Binding change detection check on each tick
* This along with an onPush change detection strategy should enforce checking only when relevant!
* This improves scripting computation duration, consistently.
* Also, it makes sense to avoid unnecessary checks when we are dealing only with simulations data binding.
*/
this.canvasGraph.ticker.subscribe((d) => {
this.viewReference.markForCheck();
});

return this.canvasGraph;
}

public nodes(): CanvasNode[] {
if (!this.canvasGraph)
return new Array<CanvasNode>();
Expand Down Expand Up @@ -227,6 +243,9 @@ export class CanvasService {
return canvasNode.id;
}

/**
* Delete the node with the given id
*/
public deleteNode(nodeId: string, refresh?: boolean) {
if (! this.canvasGraph)
throw new Error("A canvas graph is required before removing a node");
Expand Down
@@ -0,0 +1,40 @@
/**
* @license
* Copyright 2017 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export enum ViewCanvasEventType {

/**
* An event indicating the selection of objects in the canvas has changed.
*/
CANVAS_SELECTION_CHANGED = "CANVAS_SELECTION_CHANGED",

/**
* An event indicating a source node should be created
*/
CREATE_SOURCE = "CREATE_SOURCE",

/**
* An event indicating a composition node should be created
*/
CREATE_COMPOSITION = "CREATE_COMPOSITION",

/**
* An event indicating a node should be deleted
*/
DELETE_NODE = "DELETE_NODE",

}
@@ -0,0 +1,88 @@
/**
* @license
* Copyright 2017 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { ViewCanvasEventType } from "@dataservices/virtualization/view-editor/view-canvas/event/view-canvas-event-type.enum";

export class ViewCanvasEvent {

private readonly _args: any[] = [];
private readonly _type: ViewCanvasEventType;

/**
* Factory method to create an event.
*
* @param {ViewCanvasEventType} type the type of event
* @param {object[]} args the optional args
* @returns {ViewCanvasEvent} the created event
*/
public static create( type: ViewCanvasEventType,
args?: any[] ): ViewCanvasEvent {
return new ViewCanvasEvent( type, args );
}

private constructor( type: ViewCanvasEventType,
args?: any[] ) {
this._type = type;

if ( args ) {
this._args = args;
}
}

/**
* @returns {any[]} the optional args to the event (never `null` but can be empty)
*/
public get args(): any[] {
return this._args;
}

/**
* @returns {string} a string representation of the event
*/
public toString(): string {
let text = `event type: ${this.type}, args: `;
let firstTime = true;

if ( this.args && this.args.length !== 0 ) {
for ( const arg of this.args ) {
if ( firstTime ) {
firstTime = false;
} else {
text += ", ";
}

text += arg;
}
}

return text;
}

/**
* @returns {ViewCanvasEventType} the event type
*/
public get type(): ViewCanvasEventType {
return this._type;
}

/**
* @returns {boolean} `true` if the type is `ViewCanvasEventType.CANVAS_SELECTION_CHANGED`
*/
public typeIsCanvasSelectionChanged(): boolean {
return this.type === ViewCanvasEventType.CANVAS_SELECTION_CHANGED;
}
}

0 comments on commit a65dfb8

Please sign in to comment.