blob: 1cfe7cfe502c7f134fa3eee7ec5515699f4496c5 [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 Condon59d31372019-02-02 20:07:00 +000026import {IconService, 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,
Sean Condon59d31372019-02-02 20:07:00 +000074 private is: IconService,
Sean Condon0c577f62018-11-18 22:40:05 +000075 private ref: ChangeDetectorRef
76 ) {
Sean Condon021f0fa2018-12-06 23:31:11 -080077 super();
Sean Condon0c577f62018-11-18 22:40:05 +000078 }
79
80 /**
81 * Called by parent (forcesvg) when a change happens
82 *
83 * There is a difficulty in passing the SVG text object to the animation
84 * directly, to get its width, so we capture it here and update textWidth
85 * local variable here and use it in the animation
86 */
87 ngOnChanges(changes: SimpleChanges) {
88 if (changes['device']) {
89 if (!this.device.x) {
90 this.device.x = 0;
91 this.device.y = 0;
92 }
93 }
Sean Condon0c577f62018-11-18 22:40:05 +000094 this.ref.markForCheck();
95 }
Sean Condon50855cf2018-12-23 15:37:42 +000096
97 /**
98 * Calculate the text length in advance as well as possible
99 *
100 * The length of SVG text cannot be exactly estimated, because depending on
101 * the letters kerning might mean that it is shorter or longer than expected
102 *
103 * This takes the approach of 8px width per letter of this size, that on average
104 * evens out over words. A word like 'ilj' will be much shorter than 'wm0'
105 * because of kerning
106 *
107 *
108 * In addition in the template, the <svg:text> properties
109 * textLength and lengthAdjust ensure that the text becomes long with extra
110 * wide spacing created as necessary.
111 *
112 * Other approaches like getBBox() of the text
113 */
114 labelTextLen() {
115 if (this.labelToggle === 1) {
116 return this.device.id.length * 8 * this.scale;
117 } else if (this.labelToggle === 2 && this.device && this.device.props.name && this.device.props.name.trim().length > 0) {
118 return this.device.props.name.length * 8 * this.scale;
119 } else {
120 return 0;
121 }
122 }
Sean Condon59d31372019-02-02 20:07:00 +0000123
124 deviceIcon(): string {
125 if (this.device.props && this.device.props.uiType) {
126 this.is.loadIconDef(this.device.props.uiType);
127 return this.device.props.uiType;
128 } else {
129 return 'm_' + this.device.type;
130 }
131 }
Sean Condon0c577f62018-11-18 22:40:05 +0000132}