From 41b9f0fce6bf2499ecd52a4f445a7d8733e31935 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Tue, 19 Nov 2019 21:38:33 -0500 Subject: [PATCH] Palette renderer --- src/lib/editor/editor.component.html | 1 + src/lib/editor/editor.component.ts | 6 ++ src/lib/palette/palette.component.ts | 124 +++++++++++++++++++-------- src/lib/shared/flo-common.ts | 7 ++ 4 files changed, 103 insertions(+), 35 deletions(-) diff --git a/src/lib/editor/editor.component.html b/src/lib/editor/editor.component.html index 63e4183..3317d55 100644 --- a/src/lib/editor/editor.component.html +++ b/src/lib/editor/editor.component.html @@ -3,6 +3,7 @@
diff --git a/src/lib/editor/editor.component.ts b/src/lib/editor/editor.component.ts index f662e3b..bae0665 100644 --- a/src/lib/editor/editor.component.ts +++ b/src/lib/editor/editor.component.ts @@ -102,6 +102,12 @@ export class EditorComponent implements OnInit, OnDestroy { @Input() paletteSize: number; + /** + * Palette entry padding + */ + @Input() + paletteEntryPadding: dia.Size; + /** * Min zoom percent value */ diff --git a/src/lib/palette/palette.component.ts b/src/lib/palette/palette.component.ts index 180010e..c250bbe 100644 --- a/src/lib/palette/palette.component.ts +++ b/src/lib/palette/palette.component.ts @@ -153,11 +153,11 @@ export class Palette implements OnInit, OnDestroy, OnChanges { const cell: dia.Cell = cellview.model; if (cell.attributes.header) { // Toggle the header open/closed - if (cell.get('isOpen')) { - this.rotateClosed(cell); - } else { - this.rotateOpen(cell); - } + // if (cell.get('isOpen')) { + // this.rotateClosed(cell); + // } else { + // this.rotateOpen(cell); + // } } // TODO [palette] ensure other mouse handling events do nothing for headers // TODO [palette] move 'metadata' field to the right place (not inside attrs I think) @@ -204,13 +204,55 @@ export class Palette implements OnInit, OnDestroy, OnChanges { } private createPaletteGroup(title: string, isOpen: boolean): dia.Element { - let newGroupHeader = new joint.shapes.flo.PaletteGroupHeader({attrs: {text: {text: title}}}); - newGroupHeader.set('header', title); + const paletteRenderer: Flo.PaletteRenderer = this.renderer.getPaletteRenderer ? this.renderer.getPaletteRenderer() : { + createGroupHeader: (title: string, isOpen: boolean) => { + const newGroupHeader = new joint.shapes.flo.PaletteGroupHeader({attrs: {text: {text: title}}}); + if (!isOpen) { + newGroupHeader.attr({'path': {'transform': 'rotate(-90,15,13)'}}); + } + return newGroupHeader; + }, + onClose: (groupView: dia.CellView) => this.rotateClosed(groupView.model), + onOpen: (groupView: dia.CellView) => this.rotateOpen(groupView.model) + }; + let newGroupHeader = paletteRenderer.createGroupHeader(title, isOpen); if (!isOpen) { - newGroupHeader.attr({'path': {'transform': 'rotate(-90,15,13)'}}); newGroupHeader.set('isOpen', false); } + newGroupHeader.set('header', title); + this.paletteGraph.addCell(newGroupHeader); + + const view = this.palette.findViewByModel(newGroupHeader); + + view.on('cell:pointerclick', () => { + if (newGroupHeader.get('isOpen')) { + if (typeof paletteRenderer.onClose === 'function') { + paletteRenderer.onClose(view).then(() => { + newGroupHeader.set('isOpen', false); + this.closedGroups.add(newGroupHeader.get('header')); + this.rebuildPalette(); + }); + } else { + newGroupHeader.set('isOpen', false); + this.closedGroups.add(newGroupHeader.get('header')); + this.rebuildPalette(); + } + } else { + if (typeof paletteRenderer.onOpen === 'function') { + paletteRenderer.onOpen(view).then(() => { + newGroupHeader.set('isOpen', true); + this.closedGroups.delete(newGroupHeader.get('header')); + this.rebuildPalette(); + }); + } else { + newGroupHeader.set('isOpen', true); + this.closedGroups.delete(newGroupHeader.get('header')); + this.rebuildPalette(); + } + } + }); + return newGroupHeader; } @@ -270,7 +312,8 @@ export class Palette implements OnInit, OnDestroy, OnChanges { if (nodeActive) { if (!groupAdded.has(group)) { let header: dia.Element = this.createPaletteGroup(group, !this.closedGroups.has(group)); - header.set('size', {width: parentWidth, height: 30}); + header.set('size', {width: parentWidth, height: header.size().height || 30}); + console.log('Group size set to: ' + JSON.stringify(header.size())); paletteNodes.push(header); groupAdded.add(group); } @@ -287,9 +330,10 @@ export class Palette implements OnInit, OnDestroy, OnChanges { // Determine the size of the palette entry cell (width and height) paletteNodes.forEach(pnode => { if (pnode.attr('metadata/name')) { + const elementSize = this.palette.findViewByModel(pnode).getBBox(); let dimension: dia.Size = { - width: pnode.get('size').width, - height: pnode.get('size').height + width: elementSize.width, + height: elementSize.height }; if (cellWidth < dimension.width) { cellWidth = dimension.width; @@ -531,32 +575,36 @@ export class Palette implements OnInit, OnDestroy, OnChanges { /* * Modify the rotation of the arrow in the header from horizontal(closed) to vertical(open) */ - private rotateOpen(element: dia.Cell) { - setTimeout(() => this.doRotateOpen(element, 90)); + private rotateOpen(element: dia.Cell): Promise { + return new Promise(resolve => { + setTimeout(() => this.doRotateOpen(element, 90).then(() => { + resolve(); + })); + }); } - private doRotateOpen(element: dia.Cell, angle: number) { - angle -= 10; - element.attr({'path': {'transform': 'rotate(-' + angle + ',15,13)'}}); - if (angle <= 0) { - element.set('isOpen', true); - this.closedGroups.delete(element.get('header')); - this.rebuildPalette(); - } else { - setTimeout(() => this.doRotateOpen(element, angle), 10); - } + private doRotateOpen(element: dia.Cell, angle: number): Promise { + return new Promise(resolve => { + angle -= 10; + element.attr({'path': {'transform': 'rotate(-' + angle + ',15,13)'}}); + if (angle <= 0) { + resolve(); + } else { + setTimeout(() => this.doRotateOpen(element, angle).then(() => resolve()), 10); + } + }); } - private doRotateClose(element: dia.Cell, angle: number) { - angle += 10; - element.attr({'path': {'transform': 'rotate(-' + angle + ',15,13)'}}); - if (angle >= 90) { - element.set('isOpen', false); - this.closedGroups.add(element.get('header')); - this.rebuildPalette(); - } else { - setTimeout(() => this.doRotateClose(element, angle), 10); - } + private doRotateClose(element: dia.Cell, angle: number): Promise { + return new Promise(resolve => { + angle += 10; + element.attr({'path': {'transform': 'rotate(-' + angle + ',15,13)'}}); + if (angle >= 90) { + resolve(); + } else { + setTimeout(() => this.doRotateClose(element, angle).then(() => resolve()), 10); + } + }); } // TODO better name for this function as this does the animation *and* updates the palette @@ -564,8 +612,14 @@ export class Palette implements OnInit, OnDestroy, OnChanges { /* * Modify the rotation of the arrow in the header from vertical(open) to horizontal(closed) */ - private rotateClosed(element: dia.Cell) { - setTimeout(() => this.doRotateClose(element, 0)); + private rotateClosed(element: dia.Cell): Promise { + return new Promise(resolve => { + setTimeout(() => { + this.doRotateClose(element, 0).then(() => { + resolve(); + }); + }); + }); } } diff --git a/src/lib/shared/flo-common.ts b/src/lib/shared/flo-common.ts index da28b99..7383add 100644 --- a/src/lib/shared/flo-common.ts +++ b/src/lib/shared/flo-common.ts @@ -100,11 +100,18 @@ export namespace Flo { kind: string; } + export interface PaletteRenderer { + createGroupHeader(title: string, isOpen: boolean): dia.Element; + onOpen?(groupView: dia.CellView): Promise; + onClose?(groupView: dia.CellView): Promise; + } + export interface Renderer { createNode?(viewerDescriptor: ViewerDescriptor, metadata: ElementMetadata, props?: Map): dia.Element; createLink?(source: LinkEnd, target: LinkEnd, metadata?: ElementMetadata, props?: Map): dia.Link; createHandle?(kind: string, parent: dia.Cell): dia.Element; createDecoration?(kind: string, parent: dia.Cell): dia.Element; + getPaletteRenderer?(): PaletteRenderer; initializeNewNode?(node: dia.Element, viewerDescriptor: ViewerDescriptor): void; initializeNewLink?(link: dia.Link, viewerDescriptor: ViewerDescriptor): void; initializeNewHandle?(handle: dia.Element, viewerDescriptor: ViewerDescriptor): void;