Palette renderer

This commit is contained in:
BoykoAlex
2019-11-19 21:38:33 -05:00
parent 3b58c89d90
commit 41b9f0fce6
4 changed files with 103 additions and 35 deletions

View File

@@ -3,6 +3,7 @@
<div id="canvas" class="canvas" style="position:relative; display: block; width: 100%; height: 100%;">
<div *ngIf="!noPalette" id="palette-container" class="palette-container" style="overflow:hidden;">
<flo-palette [metamodel]="metamodel" [renderer]="renderer" [paletteSize]="paletteSize"
[paletteEntryPadding]="paletteEntryPadding || {width: 12, height: 12}"
(onPaletteEntryDrop)="handleDnDFromPalette($event)"
(paletteReady)="updatePaletteReadyState($event)"
(paletteFocus)="graphToTextSync=true"></flo-palette>

View File

@@ -102,6 +102,12 @@ export class EditorComponent implements OnInit, OnDestroy {
@Input()
paletteSize: number;
/**
* Palette entry padding
*/
@Input()
paletteEntryPadding: dia.Size;
/**
* Min zoom percent value
*/

View File

@@ -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<void> {
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<void> {
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<void> {
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<void> {
return new Promise(resolve => {
setTimeout(() => {
this.doRotateClose(element, 0).then(() => {
resolve();
});
});
});
}
}

View File

@@ -100,11 +100,18 @@ export namespace Flo {
kind: string;
}
export interface PaletteRenderer {
createGroupHeader(title: string, isOpen: boolean): dia.Element;
onOpen?(groupView: dia.CellView): Promise<any>;
onClose?(groupView: dia.CellView): Promise<any>;
}
export interface Renderer {
createNode?(viewerDescriptor: ViewerDescriptor, metadata: ElementMetadata, props?: Map<string, any>): dia.Element;
createLink?(source: LinkEnd, target: LinkEnd, metadata?: ElementMetadata, props?: Map<string, any>): 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;