blob: 756769dc714802d582792f4922bcdde2d97f9266 [file] [log] [blame]
Sean Condon0c577f62018-11-18 22:40:05 +00001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the 'License');
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an 'AS IS' BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16import {
Sean Condon50855cf2018-12-23 15:37:42 +000017 ChangeDetectionStrategy,
Sean Condon0c577f62018-11-18 22:40:05 +000018 ChangeDetectorRef,
19 Component,
Sean Condon50855cf2018-12-23 15:37:42 +000020 EventEmitter,
Sean Condon0c577f62018-11-18 22:40:05 +000021 Input,
22 OnChanges, Output,
23 SimpleChanges,
Sean Condon0c577f62018-11-18 22:40:05 +000024} from '@angular/core';
Sean Condon50855cf2018-12-23 15:37:42 +000025import {Device, LabelToggle, UiElement} from '../../models';
Sean Condon0c577f62018-11-18 22:40:05 +000026import {LogService} from 'gui2-fw-lib';
Sean Condon021f0fa2018-12-06 23:31:11 -080027import {NodeVisual} from '../nodevisual';
Sean Condon50855cf2018-12-23 15:37:42 +000028import {animate, state, style, transition, trigger} from '@angular/animations';
Sean Condon0c577f62018-11-18 22:40:05 +000029
30/**
31 * The Device node in the force graph
32 *
33 * Note: here the selector is given square brackets [] so that it can be
34 * inserted in SVG element like a directive
35 */
36@Component({
37 selector: '[onos-devicenodesvg]',
38 templateUrl: './devicenodesvg.component.html',
39 styleUrls: ['./devicenodesvg.component.css'],
Sean Condon50855cf2018-12-23 15:37:42 +000040 changeDetection: ChangeDetectionStrategy.Default,
41 animations: [
42 trigger('deviceLabelToggle', [
43 state('0', style({ // none
44 width: '36px',
45 })),
46 state('1, 2', // id
47 style({ width: '{{ txtWidth }}'}),
48 { params: {'txtWidth': '36px'}}
49 ), // default
50 transition('0 => 1', animate('250ms ease-in')),
51 transition('1 => 2', animate('250ms ease-in')),
52 transition('* => 0', animate('250ms ease-out'))
53 ]),
54 trigger('deviceLabelToggleTxt', [
55 state('0', style( {
56 opacity: 0,
57 })),
58 state( '1,2', style({
59 opacity: 1.0
60 })),
61 transition('0 => 1', animate('250ms ease-in')),
62 transition('* => 0', animate('250ms ease-out'))
63 ])
64 ]
Sean Condon0c577f62018-11-18 22:40:05 +000065})
Sean Condon021f0fa2018-12-06 23:31:11 -080066export class DeviceNodeSvgComponent extends NodeVisual implements OnChanges {
Sean Condon0c577f62018-11-18 22:40:05 +000067 @Input() device: Device;
68 @Input() scale: number = 1.0;
69 @Input() labelToggle: LabelToggle = LabelToggle.NONE;
Sean Condon50855cf2018-12-23 15:37:42 +000070 @Output() selectedEvent = new EventEmitter<UiElement>();
Sean Condon0c577f62018-11-18 22:40:05 +000071 textWidth: number = 36;
Sean Condon0c577f62018-11-18 22:40:05 +000072 constructor(
73 protected log: LogService,
74 private ref: ChangeDetectorRef
75 ) {
Sean Condon021f0fa2018-12-06 23:31:11 -080076 super();
Sean Condon0c577f62018-11-18 22:40:05 +000077 }
78
79 /**
80 * Called by parent (forcesvg) when a change happens
81 *
82 * There is a difficulty in passing the SVG text object to the animation
83 * directly, to get its width, so we capture it here and update textWidth
84 * local variable here and use it in the animation
85 */
86 ngOnChanges(changes: SimpleChanges) {
87 if (changes['device']) {
88 if (!this.device.x) {
89 this.device.x = 0;
90 this.device.y = 0;
91 }
92 }
93 if (changes['labelToggle']) {
94 this.labelToggle = changes['labelToggle'].currentValue;
95 }
96 this.ref.markForCheck();
97 }
Sean Condon50855cf2018-12-23 15:37:42 +000098
99 /**
100 * Calculate the text length in advance as well as possible
101 *
102 * The length of SVG text cannot be exactly estimated, because depending on
103 * the letters kerning might mean that it is shorter or longer than expected
104 *
105 * This takes the approach of 8px width per letter of this size, that on average
106 * evens out over words. A word like 'ilj' will be much shorter than 'wm0'
107 * because of kerning
108 *
109 *
110 * In addition in the template, the <svg:text> properties
111 * textLength and lengthAdjust ensure that the text becomes long with extra
112 * wide spacing created as necessary.
113 *
114 * Other approaches like getBBox() of the text
115 */
116 labelTextLen() {
117 if (this.labelToggle === 1) {
118 return this.device.id.length * 8 * this.scale;
119 } else if (this.labelToggle === 2 && this.device && this.device.props.name && this.device.props.name.trim().length > 0) {
120 return this.device.props.name.length * 8 * this.scale;
121 } else {
122 return 0;
123 }
124 }
Sean Condon0c577f62018-11-18 22:40:05 +0000125}