diff --git a/src/demo/app/app.component.html b/src/demo/app/app.component.html
index 500c60d..239c2fc 100644
--- a/src/demo/app/app.component.html
+++ b/src/demo/app/app.component.html
@@ -7,7 +7,9 @@
Spring Flo Sample
-
+
diff --git a/src/lib/editor/editor.component.html b/src/lib/editor/editor.component.html
index a5e926e..85d011e 100644
--- a/src/lib/editor/editor.component.html
+++ b/src/lib/editor/editor.component.html
@@ -6,7 +6,9 @@
[paletteEntryPadding]="paletteEntryPadding || {width: 12, height: 12}"
(onPaletteEntryDrop)="handleDnDFromPalette($event)"
(paletteReady)="updatePaletteReadyState($event)"
- (paletteFocus)="graphToTextSync=true">
+ (paletteFocus)="graphToTextSync=true"
+ [searchFilterPlaceHolder]="searchFilterPlaceHolder">
+
diff --git a/src/lib/palette/palette.component.ts b/src/lib/palette/palette.component.ts
index 41bdd67..cf6a593 100644
--- a/src/lib/palette/palette.component.ts
+++ b/src/lib/palette/palette.component.ts
@@ -35,6 +35,39 @@ joint.shapes.flo.PaletteGroupHeader = joint.shapes.basic.Generic.extend({
}, joint.shapes.basic.Generic.prototype.defaults)
});
+joint.shapes.flo.NoMatchesFound = joint.shapes.basic.Generic.extend({
+ // The path is the open/close arrow, defaults to vertical (open)
+ markup: '',
+ defaults: joint.util.deepSupplement({
+ size: {width: 170, height: 30},
+ position: {x: 0, y: 0},
+ attrs: {
+ '.no-matches-label-border': {
+ refWidth: 1,
+ refHeight: 1,
+ refX: 0,
+ refY: 0,
+ },
+ '.no-macthes-label-bg': {
+ ref: '.no-matches-label',
+ refWidth: 10,
+ refHeight: 2,
+ 'follow-scale': true
+ },
+ '.no-matches-label': {
+ text: 'No Matches Found...',
+ ref: '.no-matches-label-border',
+ refX: 0.5,
+ refY: 0.5,
+ xAlignment: 'middle',
+ yAlignment: 'middle',
+ 'fill': '#777777',
+ 'font-style': 'italic'
+ },
+ },
+ }, joint.shapes.basic.Generic.prototype.defaults)
+});
+
@Component({
selector: 'flo-palette',
templateUrl: './palette.component.html',
@@ -79,6 +112,8 @@ export class Palette implements OnInit, OnDestroy, OnChanges {
private filterTextModel = new Subject();
+ private noMacthesFoundNode: dia.Cell;
+
@Input()
metamodel: Flo.Metamodel;
@@ -88,6 +123,9 @@ export class Palette implements OnInit, OnDestroy, OnChanges {
@Input()
paletteEntryPadding: dia.Size = {width: 12, height: 12};
+ @Input()
+ searchFilterPlaceHolder = 'Search...';
+
@Output()
onPaletteEntryDrop = new EventEmitter();
@@ -292,7 +330,7 @@ export class Palette implements OnInit, OnDestroy, OnChanges {
this.createPaletteGroup(group, !this.closedGroups.has(group));
groupAdded.add(group);
}
- if (!this.closedGroups.has(group)) {
+ if (!(node.metadata && node.metadata.noPaletteEntry)) {
this.createPaletteEntry(name, node);
}
}
@@ -300,6 +338,9 @@ export class Palette implements OnInit, OnDestroy, OnChanges {
}
});
+ this.noMacthesFoundNode = new joint.shapes.flo.NoMatchesFound();
+ this.palette.model.addCell(this.noMacthesFoundNode);
+
this.layout();
this.paletteReady.emit(true);
@@ -321,16 +362,36 @@ export class Palette implements OnInit, OnDestroy, OnChanges {
this.palette.model.getCells().forEach((cell: dia.Cell) => {
const metadata: Flo.ElementMetadata = cell.attr('metadata');
- if (cell.get('header') || metadata && metadata.group && metadata.name && !this.closedGroups.has(metadata.group)
- && (!filterText || metadata.group.indexOf(filterText) >= 0 || metadata.group.indexOf(filterText) >= 0)) {
+ if (cell.get('header')) {
+ const previous = paletteNodes.length > 0 ? paletteNodes[paletteNodes.length - 1] : undefined;
+ // If previous is a paletter header node as well then the previous header had no nodes under it and we can hide it and remove from paletteNodes aeeay
+ if (previous && previous.get('header') && !this.closedGroups.has(previous.get('header'))) {
+ paletteNodes.pop().attr('./display', 'none');
+ }
+ cell.attr('./display', 'block');
+ cell.removeAttr('./display');
+ paletteNodes.push(cell);
+ } else if (metadata && metadata.group && metadata.name && !this.closedGroups.has(metadata.group)
+ && (!filterText || metadata.group.indexOf(filterText) >= 0 || metadata.name.indexOf(filterText) >= 0)) {
cell.attr('./display', 'block');
cell.removeAttr('./display');
paletteNodes.push(cell);
} else {
- cell.attr('./display', 'none');
+ if (cell === this.noMacthesFoundNode) {
+
+ } else {
+ cell.attr('./display', 'none');
+ }
}
});
+ // Check if last group is empty
+ const previous = paletteNodes.length > 0 ? paletteNodes[paletteNodes.length - 1] : undefined;
+ // If previous is a paletter header node as well then the previous header had no nodes under it and we can hide it and remove from paletteNodes aeeay
+ if (previous && previous.get('header') && !this.closedGroups.has(previous.get('header'))) {
+ paletteNodes.pop().attr('./display', 'none');
+ }
+
let cellWidth = 0, cellHeight = 0;
// Determine the size of the palette entry cell (width and height)
paletteNodes.forEach(pnode => {
@@ -394,6 +455,20 @@ export class Palette implements OnInit, OnDestroy, OnChanges {
}
prevNode = pnode;
});
+
+ this.noMacthesFoundNode.set('size', {width: parentWidth, height: this.noMacthesFoundNode.get('size').height || 30});
+ this.noMacthesFoundNode.set('position', {x: 0, y: 0});
+ if (paletteNodes.length === 0 && filterText) {
+ // There is a filter present but everything is filtered out
+ // Show no matches found node
+ this.noMacthesFoundNode.attr('./display', 'block');
+ this.noMacthesFoundNode.removeAttr('./display');
+ ypos = this.noMacthesFoundNode.get('size').height;
+ } else {
+ // Hide no matches node in all other cases
+ this.noMacthesFoundNode.attr('./display', 'none');
+ }
+
this.palette.setDimensions(parentWidth, ypos);
console.debug('buildPalette layout ' + (new Date().getTime() - startTime) + 'ms');