diff --git a/SBOLCanvasFrontend/src/app/canvas/canvas.component.html b/SBOLCanvasFrontend/src/app/canvas/canvas.component.html index b977f112..25cb4529 100644 --- a/SBOLCanvasFrontend/src/app/canvas/canvas.component.html +++ b/SBOLCanvasFrontend/src/app/canvas/canvas.component.html @@ -1 +1,3 @@ -
+
+ +
diff --git a/SBOLCanvasFrontend/src/app/canvas/canvas.component.ts b/SBOLCanvasFrontend/src/app/canvas/canvas.component.ts index 5a354f9b..ea4b8ee3 100644 --- a/SBOLCanvasFrontend/src/app/canvas/canvas.component.ts +++ b/SBOLCanvasFrontend/src/app/canvas/canvas.component.ts @@ -1,4 +1,4 @@ -import { Component, ElementRef, OnInit, ViewChild, HostListener } from '@angular/core'; +import { Component, ElementRef, OnInit, ViewChild, HostListener, Input, OnChanges, SimpleChanges } from '@angular/core'; import { GraphService } from '../graph.service'; @Component({ @@ -6,12 +6,12 @@ import { GraphService } from '../graph.service'; templateUrl: './canvas.component.html', styleUrls: ['./canvas.component.css'] }) -export class CanvasComponent implements OnInit { +export class CanvasComponent implements OnInit, OnChanges { constructor( private graphService: GraphService ) { } - + @ViewChild('canvasContainer', {static: true}) canvasContainer: ElementRef; ngOnInit() { @@ -19,6 +19,9 @@ export class CanvasComponent implements OnInit { const svg = this.graphService.getGraphDOM(); canvasContainer.appendChild(svg); } + ngOnChanges(): void { + + } @HostListener('wheel', ['$event']) onMouseWheel(event: WheelEvent) { const zoomCoef = -1 / 1000, @@ -35,4 +38,5 @@ export class CanvasComponent implements OnInit { // set the zoom this.graphService.setZoom(newZoom); } + } diff --git a/SBOLCanvasFrontend/src/app/graph-base.ts b/SBOLCanvasFrontend/src/app/graph-base.ts index c7547909..fafb90fe 100644 --- a/SBOLCanvasFrontend/src/app/graph-base.ts +++ b/SBOLCanvasFrontend/src/app/graph-base.ts @@ -90,6 +90,12 @@ export class GraphBase { // This object handles the hotkeys for the graph. keyHandler: any; + + selectedGlyphInfoName : string; + selectionGlyphInfoStack: string[] = []; + sequenceFeatureDict = {}; + selectedHTMLStack = []; + isGen :boolean = false; // when decoding we add any unformatted view cells to this set static unFormatedCells = new Set(); diff --git a/SBOLCanvasFrontend/src/app/graph-edits.ts b/SBOLCanvasFrontend/src/app/graph-edits.ts index efc67db4..b7d2138e 100644 --- a/SBOLCanvasFrontend/src/app/graph-edits.ts +++ b/SBOLCanvasFrontend/src/app/graph-edits.ts @@ -126,6 +126,7 @@ export class GraphEdits { // Zoom into the glyph // get the view cell for the selected cell let childViewCell; + console.log("glyphCell.value", this.glyphCell.value); if (!this.glyphCell.value) { childViewCell = this.glyphCell; } else { diff --git a/SBOLCanvasFrontend/src/app/graph-helpers.ts b/SBOLCanvasFrontend/src/app/graph-helpers.ts index ae757908..cc571e6c 100644 --- a/SBOLCanvasFrontend/src/app/graph-helpers.ts +++ b/SBOLCanvasFrontend/src/app/graph-helpers.ts @@ -21,6 +21,7 @@ import { CombinatorialInfo } from './combinatorialInfo'; import { VariableComponentInfo } from './variableComponentInfo'; import { IdentifiedInfo } from './identifiedInfo'; import { InteractionInfo } from './interactionInfo'; +import { ignoreElements } from 'rxjs'; // import { SystemJsNgModuleLoader } from '@angular/core'; /** @@ -1091,9 +1092,9 @@ export class GraphHelpers extends GraphBase { var cellsRemoved = evt.getProperty('added'); var cellsAdded = evt.getProperty('removed'); - console.debug("----handleSelectionChange-----"); + // console.debug("----handleSelectionChange-----"); - console.debug("cells removed: "); + // console.debug("cells removed: "); if (cellsRemoved) { for (var i = 0; i < cellsRemoved.length; i++) { console.debug(cellsRemoved[i]); @@ -1107,16 +1108,17 @@ export class GraphHelpers extends GraphBase { } } - console.debug("Current root: "); - console.debug(this.graph.getCurrentRoot()); + // console.debug("Current root: "); + // console.debug(this.graph.getCurrentRoot()); - console.debug("Undo manager: "); - console.debug(this.editor.undoManager); + // console.debug("Undo manager: "); + // console.debug(this.editor.undoManager); - console.debug("Graph Model: "); - console.debug(this.graph.getModel()); + // console.debug("Graph Model: "); + // console.debug(this.graph.getModel()); // Don't just use the new cells though, use all currently selected ones. + this.updateAngularMetadata(this.graph.getSelectionCells()); } @@ -1161,8 +1163,14 @@ export class GraphHelpers extends GraphBase { let glyphInfo; if (!cell) glyphInfo = this.getFromInfoDict(this.graph.getCurrentRoot().getId()); - else + else{ glyphInfo = this.getFromInfoDict(cell.value); + + if(cell.isCircuitContainer()){ + glyphInfo.partRole = 'Gen (Engineered Region)'; + } + + } if (glyphInfo) { this.metadataService.setSelectedGlyphInfo(glyphInfo.makeCopy()); } diff --git a/SBOLCanvasFrontend/src/app/graph.service.ts b/SBOLCanvasFrontend/src/app/graph.service.ts index 50e6c7d1..6e1dfbd6 100644 --- a/SBOLCanvasFrontend/src/app/graph.service.ts +++ b/SBOLCanvasFrontend/src/app/graph.service.ts @@ -25,15 +25,16 @@ import { EmbeddedService } from './embedded.service'; import { FilesService } from './files.service'; import { Observable } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; - +import { DomSanitizer } from '@angular/platform-browser'; @Injectable({ providedIn: 'root' }) export class GraphService extends GraphHelpers { - constructor(dialog: MatDialog, metadataService: MetadataService, glyphService: GlyphService, embeddedService: EmbeddedService, fileService: FilesService) { + constructor(dialog: MatDialog, metadataService: MetadataService, glyphService: GlyphService, embeddedService: EmbeddedService, fileService: FilesService, + private sanitizer: DomSanitizer) { super(dialog, metadataService, glyphService); - + // handle selection changes this.graph.getSelectionModel().addListener(mx.mxEvent.CHANGE, mx.mxUtils.bind(this, this.handleSelectionChange)); @@ -321,23 +322,51 @@ export class GraphService extends GraphHelpers { /** * "Drills in" to replace the canvas with the selected glyph's component/module view */ + + getSelectedGlyphName(){ + return this.selectedGlyphInfoName; + } + + getSelectedGlyphNameSet(){ + return this.selectionGlyphInfoStack; + } + getSelectedHTMLSet(){ + return this.selectedHTMLStack; + } + + enterGlyph() { + let selection = this.graph.getSelectionCells(); + console.log(selection[0].isCircuitContainer()); + console.log("isSequenceFeatureGlyph? " , selection[0].isSequenceFeatureGlyph()); if (selection.length != 1) { return; } - - if (!selection[0].isSequenceFeatureGlyph() && !selection[0].isModule()) { - return; - } - + + // if (!selection[0].isSequenceFeatureGlyph() && !selection[0].isModule()) { + // return; + // } + this.graph.getModel().beginUpdate(); try { let viewCell = this.graph.getModel().getCell(selection[0].getValue()); + console.log("ViewCell", viewCell); // doing this in the graph edit breaks things in the undo, so we put it here viewCell.refreshViewCell(this.graph); let zoomEdit = new GraphEdits.zoomEdit(this.graph.getView(), selection[0], this); + let glyphInfo = (this.getFromInfoDict(selection[0].getValue())); + this.selectedGlyphInfoName = glyphInfo.partRole; + + this.selectionGlyphInfoStack.push(this.selectedGlyphInfoName); this.graph.getModel().execute(zoomEdit); + + const sequenceFeatureElts = this.glyphService.getSequenceFeatureElements(); + let svg = sequenceFeatureElts[this.selectedGlyphInfoName]; + this.sequenceFeatureDict[this.selectedGlyphInfoName] = this.sanitizer.bypassSecurityTrustHtml(svg.innerHTML); + this.selectedHTMLStack.push(this.sequenceFeatureDict[this.selectedGlyphInfoName]); + + } finally { this.graph.getModel().endUpdate(); } @@ -350,9 +379,17 @@ export class GraphService extends GraphHelpers { */ exitGlyph() { // the root view should always be left on the viewStack + if (this.viewStack.length > 1) { let zoomEdit = new GraphEdits.zoomEdit(this.graph.getView(), null, this); this.graph.getModel().execute(zoomEdit); + + this.selectionGlyphInfoStack.pop(); + this.selectedHTMLStack.pop(); + + } + else{ + this.selectedHTMLStack = []; } } @@ -416,6 +453,7 @@ export class GraphService extends GraphHelpers { */ async delete() { const selectedCells = this.graph.getSelectionCells(); + if (selectedCells == null) { return; } @@ -770,17 +808,15 @@ export class GraphService extends GraphHelpers { // let the graph choose an arbitrary cell from the selection, // we'll pretend it's the only one selected const selection = this.graph.getSelectionCell(); - // if selection is nonexistent, or is not part of a strand, there is no suitable place. if (!selection || !(selection.isSequenceFeatureGlyph() || selection.isCircuitContainer())) { return; } const circuitContainer = selection.isCircuitContainer() ? selection : selection.getParent(); - // use y coord of the strand let y = circuitContainer.getGeometry().y; - + // x depends on the exact selection let x; if (selection.isCircuitContainer()) { @@ -791,11 +827,13 @@ export class GraphService extends GraphHelpers { // Add it this.addSequenceFeatureAt(name, x, y, circuitContainer); + } finally { this.graph.getModel().endUpdate(); } } + /** * Adds a sequenceFeatureGlyph. * @@ -843,13 +881,11 @@ export class GraphService extends GraphHelpers { // transform coords to be relative to parent x = x - circuitContainer.getGeometry().x; y = y - circuitContainer.getGeometry().y; - // create the glyph info and add it to the dictionary const glyphInfo = new GlyphInfo({ partRole: name }); this.addToInfoDict(glyphInfo); - // Insert new glyph and its components const sequenceFeatureCell = this.graph.insertVertex(circuitContainer, null, glyphInfo.getFullURI(), x, y, GraphBase.sequenceFeatureGlyphWidth, GraphBase.sequenceFeatureGlyphHeight, GraphBase.STYLE_SEQUENCE_FEATURE + name); @@ -884,7 +920,7 @@ export class GraphService extends GraphHelpers { this.graph.getModel().endUpdate(); } } - + /** * Turns the given element into a dragsource for creating molecular species glyphs */ @@ -1175,7 +1211,6 @@ export class GraphService extends GraphHelpers { */ async setSelectedCellInfo(info: Info) { const selectedCell = this.graph.getSelectionCell(); - this.graph.getModel().beginUpdate(); try { // figure out which type of info object it is diff --git a/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.css b/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.css index 3640918c..4d9fa24d 100644 --- a/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.css +++ b/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.css @@ -10,8 +10,8 @@ } .hierarchy-controls .level { - width: 4em; - height: 3em; + width: 6em; + height: 4em; margin: 8px; font-family: 'Roboto'; cursor: pointer; diff --git a/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.html b/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.html index a38b2eb9..93c95464 100644 --- a/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.html +++ b/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.html @@ -1,8 +1,8 @@ -
+
+
- {{i == 0 && "Top" || i}} - +
\ No newline at end of file diff --git a/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.ts b/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.ts index f9eef3aa..098e259e 100644 --- a/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.ts +++ b/SBOLCanvasFrontend/src/app/hierarchy-preview/hierarchy-preview.component.ts @@ -1,26 +1,35 @@ -import { Component } from '@angular/core' +import { Component, Input, OnInit } from '@angular/core' import { GraphService } from '../graph.service' - - +import { GlyphService } from '../glyph.service'; +import { DomSanitizer } from '@angular/platform-browser'; @Component({ selector: 'app-hierarchy-preview', templateUrl: './hierarchy-preview.component.html', styleUrls: ['./hierarchy-preview.component.css'] }) -export class HierarchyPreviewComponent { +export class HierarchyPreviewComponent { + + + constructor(private graphService: GraphService, private glyphService: GlyphService, private sanitizer : DomSanitizer) { } - constructor(private graphService: GraphService) { } + glyphName: string; + selectedStack = []; + selectedHTMLStack = []; + + getViewStack() { + this.glyphName = this.graphService.getSelectedGlyphName(); + this.selectedStack = this.graphService.getSelectedGlyphNameSet(); + this.selectedHTMLStack = this.graphService.getSelectedHTMLSet(); - getViewStack() { - // console.log(this.glyphMenu.sequenceFeatureDict) return this.graphService.viewStack } switchView(depth) { let levels = this.graphService.viewStack.length - depth - 1 - - for (let i = 0; i < levels; i++) + + for (let i = 0; i < levels; i++){ this.graphService.exitGlyph() + } } } diff --git a/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.css b/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.css index 4743a67d..fca409f2 100644 --- a/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.css +++ b/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.css @@ -28,4 +28,5 @@ .toolbar-row-section.grow { flex-grow: 1; -} \ No newline at end of file +} + diff --git a/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.html b/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.html index d33ee609..4edb46ab 100644 --- a/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.html +++ b/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.html @@ -107,9 +107,10 @@ - + +
- \ No newline at end of file + diff --git a/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.ts b/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.ts index f596c5c5..64c8cf24 100644 --- a/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.ts +++ b/SBOLCanvasFrontend/src/app/toolbar/toolbar.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, ElementRef, OnInit, QueryList, ViewChild } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, OnInit, QueryList, Sanitizer, ViewChild } from '@angular/core'; import { GraphService } from '../graph.service'; import { FilesService } from '../files.service'; import { MatDialog } from '@angular/material/dialog'; @@ -9,6 +9,8 @@ import { ExportDesignComponent } from '../export-design/export-design.component' import { ConfirmComponent } from '../confirm/confirm.component'; import { LoadGraphComponent } from '../load-graph/load-graph.component'; import { EmbeddedService } from '../embedded.service'; +import { GlyphService } from '../glyph.service'; + export interface SaveDialogData { filename: string; @@ -25,16 +27,21 @@ export interface LoadDialogData { export class ToolbarComponent implements OnInit, AfterViewInit { @ViewChild('backbone') backbone: ElementRef; + filename: string; popupOpen: boolean; users: {}; - + newGlyphName: string; + newHTML: string; + sequenceFeatureDict = {}; + constructor(public graphService: GraphService, private filesService: FilesService, - public dialog: MatDialog, public embeddedService: EmbeddedService) { + public dialog: MatDialog, public embeddedService: EmbeddedService, private glyphService: GlyphService) { } ngOnInit() { + } ngAfterViewInit() { @@ -129,4 +136,7 @@ export class ToolbarComponent implements OnInit, AfterViewInit { this.graphService.addMolecularSpecies("replacement-glyph"); this.graphService.addInteractionNode("replacement-glyph"); } + + + }