mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-06-17 06:18:09 +00:00
Code optimization
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
import { TestHelper } from "./common.po"
|
import { TestHelper } from './common.po';
|
||||||
import { browser, by } from "protractor";
|
import { browser, by } from 'protractor';
|
||||||
|
|
||||||
export class ProjectMapPage {
|
export class ProjectMapPage {
|
||||||
helper = new TestHelper();
|
helper = new TestHelper();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { TestHelper } from "./common.po"
|
import { TestHelper } from './common.po';
|
||||||
import { browser, by } from "protractor";
|
import { browser, by } from 'protractor';
|
||||||
|
|
||||||
export class ProjectsPage {
|
export class ProjectsPage {
|
||||||
helper = new TestHelper();
|
helper = new TestHelper();
|
||||||
|
@ -2,7 +2,7 @@ import { browser, by, element } from 'protractor';
|
|||||||
import { TestHelper } from './common.po';
|
import { TestHelper } from './common.po';
|
||||||
|
|
||||||
export class ServersPage {
|
export class ServersPage {
|
||||||
helper = new TestHelper;
|
helper = new TestHelper();
|
||||||
|
|
||||||
maximizeWindow() {
|
maximizeWindow() {
|
||||||
browser.driver.manage().window().maximize();
|
browser.driver.manage().window().maximize();
|
||||||
@ -32,7 +32,7 @@ export class ServersPage {
|
|||||||
this.helper.sleep(2000);
|
this.helper.sleep(2000);
|
||||||
let hyperlinks = await browser.driver.findElements(by.css('a.table-link'));
|
let hyperlinks = await browser.driver.findElements(by.css('a.table-link'));
|
||||||
let serverLink;
|
let serverLink;
|
||||||
await this.helper.asyncForEach(hyperlinks, async element => {
|
await this.helper.asyncForEach(hyperlinks, async (element) => {
|
||||||
let text = await element.getText();
|
let text = await element.getText();
|
||||||
if (text === '127.0.0.1') serverLink = element;
|
if (text === '127.0.0.1') serverLink = element;
|
||||||
});
|
});
|
||||||
|
@ -33,7 +33,7 @@ describe('Servers page', () => {
|
|||||||
// act
|
// act
|
||||||
let firstRowOfServersTable = await page.checkServersTable();
|
let firstRowOfServersTable = await page.checkServersTable();
|
||||||
let serverData = [];
|
let serverData = [];
|
||||||
await helper.asyncForEach(firstRowOfServersTable, async element => {
|
await helper.asyncForEach(firstRowOfServersTable, async (element) => {
|
||||||
serverData.push(await element.getText());
|
serverData.push(await element.getText());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ const routes: Routes = [
|
|||||||
{
|
{
|
||||||
path: 'server/:server_id/projects',
|
path: 'server/:server_id/projects',
|
||||||
component: ProjectsComponent,
|
component: ProjectsComponent,
|
||||||
resolve: { server : ServerResolve }
|
resolve: { server: ServerResolve },
|
||||||
},
|
},
|
||||||
{ path: 'help', component: HelpComponent },
|
{ path: 'help', component: HelpComponent },
|
||||||
{ path: 'help/reportissue', component: ReportIssueComponent },
|
{ path: 'help/reportissue', component: ReportIssueComponent },
|
||||||
@ -90,7 +90,7 @@ const routes: Routes = [
|
|||||||
{
|
{
|
||||||
path: 'server/:server_id/project/:project_id/snapshots',
|
path: 'server/:server_id/project/:project_id/snapshots',
|
||||||
component: ListOfSnapshotsComponent,
|
component: ListOfSnapshotsComponent,
|
||||||
resolve: { server : ServerResolve }
|
resolve: { server: ServerResolve },
|
||||||
},
|
},
|
||||||
{ path: 'server/:server_id/preferences', component: PreferencesComponent },
|
{ path: 'server/:server_id/preferences', component: PreferencesComponent },
|
||||||
{ path: 'server/:server_id/preferences/gns3vm', component: Gns3vmComponent },
|
{ path: 'server/:server_id/preferences/gns3vm', component: Gns3vmComponent },
|
||||||
@ -98,26 +98,53 @@ const routes: Routes = [
|
|||||||
{ path: 'server/:server_id/preferences/builtin', component: BuiltInPreferencesComponent },
|
{ path: 'server/:server_id/preferences/builtin', component: BuiltInPreferencesComponent },
|
||||||
|
|
||||||
{ path: 'server/:server_id/preferences/builtin/ethernet-hubs', component: EthernetHubsTemplatesComponent },
|
{ path: 'server/:server_id/preferences/builtin/ethernet-hubs', component: EthernetHubsTemplatesComponent },
|
||||||
{ path: 'server/:server_id/preferences/builtin/ethernet-hubs/addtemplate', component: EthernetHubsAddTemplateComponent },
|
{
|
||||||
{ path: 'server/:server_id/preferences/builtin/ethernet-hubs/:template_id', component: EthernetHubsTemplateDetailsComponent },
|
path: 'server/:server_id/preferences/builtin/ethernet-hubs/addtemplate',
|
||||||
|
component: EthernetHubsAddTemplateComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'server/:server_id/preferences/builtin/ethernet-hubs/:template_id',
|
||||||
|
component: EthernetHubsTemplateDetailsComponent,
|
||||||
|
},
|
||||||
|
|
||||||
{ path: 'server/:server_id/preferences/builtin/ethernet-switches', component: EthernetSwitchesTemplatesComponent },
|
{
|
||||||
{ path: 'server/:server_id/preferences/builtin/ethernet-switches/addtemplate', component: EthernetSwitchesAddTemplateComponent },
|
path: 'server/:server_id/preferences/builtin/ethernet-switches',
|
||||||
{ path: 'server/:server_id/preferences/builtin/ethernet-switches/:template_id', component: EthernetSwitchesTemplateDetailsComponent },
|
component: EthernetSwitchesTemplatesComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'server/:server_id/preferences/builtin/ethernet-switches/addtemplate',
|
||||||
|
component: EthernetSwitchesAddTemplateComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'server/:server_id/preferences/builtin/ethernet-switches/:template_id',
|
||||||
|
component: EthernetSwitchesTemplateDetailsComponent,
|
||||||
|
},
|
||||||
|
|
||||||
{ path: 'server/:server_id/preferences/builtin/cloud-nodes', component: CloudNodesTemplatesComponent },
|
{ path: 'server/:server_id/preferences/builtin/cloud-nodes', component: CloudNodesTemplatesComponent },
|
||||||
{ path: 'server/:server_id/preferences/builtin/cloud-nodes/addtemplate', component: CloudNodesAddTemplateComponent },
|
{
|
||||||
{ path: 'server/:server_id/preferences/builtin/cloud-nodes/:template_id', component: CloudNodesTemplateDetailsComponent },
|
path: 'server/:server_id/preferences/builtin/cloud-nodes/addtemplate',
|
||||||
|
component: CloudNodesAddTemplateComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'server/:server_id/preferences/builtin/cloud-nodes/:template_id',
|
||||||
|
component: CloudNodesTemplateDetailsComponent,
|
||||||
|
},
|
||||||
|
|
||||||
//{ path: 'server/:server_id/preferences/dynamips', component: DynamipsPreferencesComponent },
|
//{ path: 'server/:server_id/preferences/dynamips', component: DynamipsPreferencesComponent },
|
||||||
{ path: 'server/:server_id/preferences/dynamips/templates', component: IosTemplatesComponent },
|
{ path: 'server/:server_id/preferences/dynamips/templates', component: IosTemplatesComponent },
|
||||||
{ path: 'server/:server_id/preferences/dynamips/templates/addtemplate', component: AddIosTemplateComponent },
|
{ path: 'server/:server_id/preferences/dynamips/templates/addtemplate', component: AddIosTemplateComponent },
|
||||||
{ path: 'server/:server_id/preferences/dynamips/templates/:template_id', component: IosTemplateDetailsComponent },
|
{ path: 'server/:server_id/preferences/dynamips/templates/:template_id', component: IosTemplateDetailsComponent },
|
||||||
{ path: 'server/:server_id/preferences/dynamips/templates/:template_id/copy', component: CopyIosTemplateComponent },
|
{
|
||||||
|
path: 'server/:server_id/preferences/dynamips/templates/:template_id/copy',
|
||||||
|
component: CopyIosTemplateComponent,
|
||||||
|
},
|
||||||
|
|
||||||
// { path: 'server/:server_id/preferences/qemu', component: QemuPreferencesComponent },
|
// { path: 'server/:server_id/preferences/qemu', component: QemuPreferencesComponent },
|
||||||
{ path: 'server/:server_id/preferences/qemu/templates', component: QemuVmTemplatesComponent },
|
{ path: 'server/:server_id/preferences/qemu/templates', component: QemuVmTemplatesComponent },
|
||||||
{ path: 'server/:server_id/preferences/qemu/templates/:template_id/copy', component: CopyQemuVmTemplateComponent },
|
{
|
||||||
|
path: 'server/:server_id/preferences/qemu/templates/:template_id/copy',
|
||||||
|
component: CopyQemuVmTemplateComponent,
|
||||||
|
},
|
||||||
{ path: 'server/:server_id/preferences/qemu/templates/:template_id', component: QemuVmTemplateDetailsComponent },
|
{ path: 'server/:server_id/preferences/qemu/templates/:template_id', component: QemuVmTemplateDetailsComponent },
|
||||||
{ path: 'server/:server_id/preferences/qemu/addtemplate', component: AddQemuVmTemplateComponent },
|
{ path: 'server/:server_id/preferences/qemu/addtemplate', component: AddQemuVmTemplateComponent },
|
||||||
|
|
||||||
@ -128,12 +155,18 @@ const routes: Routes = [
|
|||||||
|
|
||||||
// { path: 'server/:server_id/preferences/virtualbox', component: VirtualBoxPreferencesComponent },
|
// { path: 'server/:server_id/preferences/virtualbox', component: VirtualBoxPreferencesComponent },
|
||||||
{ path: 'server/:server_id/preferences/virtualbox/templates', component: VirtualBoxTemplatesComponent },
|
{ path: 'server/:server_id/preferences/virtualbox/templates', component: VirtualBoxTemplatesComponent },
|
||||||
{ path: 'server/:server_id/preferences/virtualbox/templates/:template_id', component: VirtualBoxTemplateDetailsComponent },
|
{
|
||||||
|
path: 'server/:server_id/preferences/virtualbox/templates/:template_id',
|
||||||
|
component: VirtualBoxTemplateDetailsComponent,
|
||||||
|
},
|
||||||
{ path: 'server/:server_id/preferences/virtualbox/addtemplate', component: AddVirtualBoxTemplateComponent },
|
{ path: 'server/:server_id/preferences/virtualbox/addtemplate', component: AddVirtualBoxTemplateComponent },
|
||||||
|
|
||||||
// { path: 'server/:server_id/preferences/vmware', component: VmwarePreferencesComponent },
|
// { path: 'server/:server_id/preferences/vmware', component: VmwarePreferencesComponent },
|
||||||
{ path: 'server/:server_id/preferences/vmware/templates', component: VmwareTemplatesComponent },
|
{ path: 'server/:server_id/preferences/vmware/templates', component: VmwareTemplatesComponent },
|
||||||
{ path: 'server/:server_id/preferences/vmware/templates/:template_id', component: VmwareTemplateDetailsComponent },
|
{
|
||||||
|
path: 'server/:server_id/preferences/vmware/templates/:template_id',
|
||||||
|
component: VmwareTemplateDetailsComponent,
|
||||||
|
},
|
||||||
{ path: 'server/:server_id/preferences/vmware/addtemplate', component: AddVmwareTemplateComponent },
|
{ path: 'server/:server_id/preferences/vmware/addtemplate', component: AddVmwareTemplateComponent },
|
||||||
|
|
||||||
// { path: 'server/:server_id/preferences/traceng', component: TracengPreferencesComponent },
|
// { path: 'server/:server_id/preferences/traceng', component: TracengPreferencesComponent },
|
||||||
@ -142,37 +175,49 @@ const routes: Routes = [
|
|||||||
// { path: 'server/:server_id/preferences/traceng/addtemplate', component: AddTracengTemplateComponent },
|
// { path: 'server/:server_id/preferences/traceng/addtemplate', component: AddTracengTemplateComponent },
|
||||||
|
|
||||||
{ path: 'server/:server_id/preferences/docker/templates', component: DockerTemplatesComponent },
|
{ path: 'server/:server_id/preferences/docker/templates', component: DockerTemplatesComponent },
|
||||||
{ path: 'server/:server_id/preferences/docker/templates/:template_id', component: DockerTemplateDetailsComponent },
|
{
|
||||||
{ path: 'server/:server_id/preferences/docker/templates/:template_id/copy', component: CopyDockerTemplateComponent },
|
path: 'server/:server_id/preferences/docker/templates/:template_id',
|
||||||
|
component: DockerTemplateDetailsComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'server/:server_id/preferences/docker/templates/:template_id/copy',
|
||||||
|
component: CopyDockerTemplateComponent,
|
||||||
|
},
|
||||||
{ path: 'server/:server_id/preferences/docker/addtemplate', component: AddDockerTemplateComponent },
|
{ path: 'server/:server_id/preferences/docker/addtemplate', component: AddDockerTemplateComponent },
|
||||||
|
|
||||||
{ path: 'server/:server_id/preferences/iou/templates', component: IouTemplatesComponent },
|
{ path: 'server/:server_id/preferences/iou/templates', component: IouTemplatesComponent },
|
||||||
{ path: 'server/:server_id/preferences/iou/templates/:template_id', component: IouTemplateDetailsComponent },
|
{ path: 'server/:server_id/preferences/iou/templates/:template_id', component: IouTemplateDetailsComponent },
|
||||||
{ path: 'server/:server_id/preferences/iou/templates/:template_id/copy', component: CopyIouTemplateComponent },
|
{ path: 'server/:server_id/preferences/iou/templates/:template_id/copy', component: CopyIouTemplateComponent },
|
||||||
{ path: 'server/:server_id/preferences/iou/addtemplate', component: AddIouTemplateComponent }
|
{ path: 'server/:server_id/preferences/iou/addtemplate', component: AddIouTemplateComponent },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'server/:server_id/project/:project_id',
|
path: 'server/:server_id/project/:project_id',
|
||||||
component: ProjectMapComponent,
|
component: ProjectMapComponent,
|
||||||
canDeactivate: [ConsoleGuard]
|
canDeactivate: [ConsoleGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'server/:server_id/project/:project_id/nodes/:node_id',
|
path: 'server/:server_id/project/:project_id/nodes/:node_id',
|
||||||
component: WebConsoleFullWindowComponent
|
component: WebConsoleFullWindowComponent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'static/web-ui/server/:server_id/project/:project_id/nodes/:node_id',
|
path: 'static/web-ui/server/:server_id/project/:project_id/nodes/:node_id',
|
||||||
component: WebConsoleFullWindowComponent
|
component: WebConsoleFullWindowComponent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
component: PageNotFoundComponent
|
component: PageNotFoundComponent,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forRoot(routes, { anchorScrolling: 'enabled', enableTracing: false, scrollPositionRestoration: 'enabled'})],
|
imports: [
|
||||||
exports: [RouterModule]
|
RouterModule.forRoot(routes, {
|
||||||
|
anchorScrolling: 'enabled',
|
||||||
|
enableTracing: false,
|
||||||
|
scrollPositionRestoration: 'enabled',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
exports: [RouterModule],
|
||||||
})
|
})
|
||||||
export class AppRoutingModule {}
|
export class AppRoutingModule {}
|
||||||
|
@ -22,7 +22,7 @@ describe('AppComponent', () => {
|
|||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
imports: [RouterTestingModule, MatIconModule, NgxElectronModule],
|
imports: [RouterTestingModule, MatIconModule, NgxElectronModule],
|
||||||
providers: [SettingsService, PersistenceService, ProgressService],
|
providers: [SettingsService, PersistenceService, ProgressService],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
electronService = TestBed.get(ElectronService);
|
electronService = TestBed.get(ElectronService);
|
||||||
|
@ -11,7 +11,7 @@ import { OverlayContainer} from '@angular/cdk/overlay';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: ['./app.component.scss']
|
styleUrls: ['./app.component.scss'],
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
public darkThemeEnabled: boolean = false;
|
public darkThemeEnabled: boolean = false;
|
||||||
@ -38,7 +38,7 @@ export class AppComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
if (this.electronService.isElectronApp) {
|
if (this.electronService.isElectronApp) {
|
||||||
this.settingsService.subscribe(settings => {
|
this.settingsService.subscribe((settings) => {
|
||||||
this.electronService.ipcRenderer.send('settings.changed', settings);
|
this.electronService.ipcRenderer.send('settings.changed', settings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -62,11 +62,11 @@ export class AppComponent implements OnInit {
|
|||||||
checkEvent(routerEvent): void {
|
checkEvent(routerEvent): void {
|
||||||
if (routerEvent instanceof NavigationStart) {
|
if (routerEvent instanceof NavigationStart) {
|
||||||
this.progressService.activate();
|
this.progressService.activate();
|
||||||
}
|
} else if (
|
||||||
|
routerEvent instanceof NavigationEnd ||
|
||||||
else if (routerEvent instanceof NavigationEnd ||
|
|
||||||
routerEvent instanceof NavigationCancel ||
|
routerEvent instanceof NavigationCancel ||
|
||||||
routerEvent instanceof NavigationError) {
|
routerEvent instanceof NavigationError
|
||||||
|
) {
|
||||||
this.progressService.deactivate();
|
this.progressService.deactivate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,7 +470,7 @@ import { OverlayContainer, OverlayModule } from '@angular/cdk/overlay';
|
|||||||
TemplateNameDialogComponent,
|
TemplateNameDialogComponent,
|
||||||
ConfigureCustomAdaptersDialogComponent,
|
ConfigureCustomAdaptersDialogComponent,
|
||||||
EditNetworkConfigurationDialogComponent,
|
EditNetworkConfigurationDialogComponent,
|
||||||
ReportIssueComponent
|
ReportIssueComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
AngularReactBrowserModule,
|
AngularReactBrowserModule,
|
||||||
@ -492,7 +492,7 @@ import { OverlayContainer, OverlayModule } from '@angular/cdk/overlay';
|
|||||||
NgxChildProcessModule,
|
NgxChildProcessModule,
|
||||||
MATERIAL_IMPORTS,
|
MATERIAL_IMPORTS,
|
||||||
NgCircleProgressModule.forRoot(),
|
NgCircleProgressModule.forRoot(),
|
||||||
OverlayModule
|
OverlayModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
SettingsService,
|
SettingsService,
|
||||||
@ -567,7 +567,7 @@ import { OverlayContainer, OverlayModule } from '@angular/cdk/overlay';
|
|||||||
ConsoleGuard,
|
ConsoleGuard,
|
||||||
Title,
|
Title,
|
||||||
ApplianceService,
|
ApplianceService,
|
||||||
UpdatesService
|
UpdatesService,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
AddServerDialogComponent,
|
AddServerDialogComponent,
|
||||||
@ -615,9 +615,9 @@ import { OverlayContainer, OverlayModule } from '@angular/cdk/overlay';
|
|||||||
ChangeHostnameDialogComponent,
|
ChangeHostnameDialogComponent,
|
||||||
ApplianceInfoDialogComponent,
|
ApplianceInfoDialogComponent,
|
||||||
ConfigureCustomAdaptersDialogComponent,
|
ConfigureCustomAdaptersDialogComponent,
|
||||||
EditNetworkConfigurationDialogComponent
|
EditNetworkConfigurationDialogComponent,
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent],
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
constructor(protected _googleAnalyticsService: GoogleAnalyticsService) {}
|
constructor(protected _googleAnalyticsService: GoogleAnalyticsService) {}
|
||||||
|
@ -23,5 +23,5 @@ export const ANGULAR_MAP_DECLARATIONS = [
|
|||||||
TextComponent,
|
TextComponent,
|
||||||
DraggableComponent,
|
DraggableComponent,
|
||||||
SelectionComponent,
|
SelectionComponent,
|
||||||
InterfaceLabelComponent
|
InterfaceLabelComponent,
|
||||||
];
|
];
|
||||||
|
@ -37,7 +37,7 @@ import {
|
|||||||
MapNodesDataSource,
|
MapNodesDataSource,
|
||||||
MapLinksDataSource,
|
MapLinksDataSource,
|
||||||
MapDrawingsDataSource,
|
MapDrawingsDataSource,
|
||||||
MapSymbolsDataSource
|
MapSymbolsDataSource,
|
||||||
} from './datasources/map-datasource';
|
} from './datasources/map-datasource';
|
||||||
import { LinksEventSource } from './events/links-event-source';
|
import { LinksEventSource } from './events/links-event-source';
|
||||||
import { D3MapComponent } from './components/d3-map/d3-map.component';
|
import { D3MapComponent } from './components/d3-map/d3-map.component';
|
||||||
@ -75,7 +75,7 @@ import { SerialLinkWidget } from './widgets/links/serial-link';
|
|||||||
SelectionSelectComponent,
|
SelectionSelectComponent,
|
||||||
DraggableSelectionComponent,
|
DraggableSelectionComponent,
|
||||||
MovingCanvasDirective,
|
MovingCanvasDirective,
|
||||||
ZoomingCanvasDirective
|
ZoomingCanvasDirective,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
CssFixer,
|
CssFixer,
|
||||||
@ -122,8 +122,8 @@ import { SerialLinkWidget } from './widgets/links/serial-link';
|
|||||||
StylesToFontConverter,
|
StylesToFontConverter,
|
||||||
EthernetLinkWidget,
|
EthernetLinkWidget,
|
||||||
SerialLinkWidget,
|
SerialLinkWidget,
|
||||||
...D3_MAP_IMPORTS
|
...D3_MAP_IMPORTS,
|
||||||
],
|
],
|
||||||
exports: [D3MapComponent, ExperimentalMapComponent]
|
exports: [D3MapComponent, ExperimentalMapComponent],
|
||||||
})
|
})
|
||||||
export class CartographyModule {}
|
export class CartographyModule {}
|
||||||
|
@ -1,14 +1,38 @@
|
|||||||
<svg id="map" #svg class="map" preserveAspectRatio="none" movingCanvas zoomingCanvas>
|
<svg id="map" #svg class="map" preserveAspectRatio="none" movingCanvas zoomingCanvas>
|
||||||
<filter id="grayscale"><feColorMatrix id="feGrayscale" type="saturate" values="0" /></filter>
|
<filter id="grayscale"><feColorMatrix id="feGrayscale" type="saturate" values="0" /></filter>
|
||||||
<defs>
|
<defs>
|
||||||
<pattern attr.x="{{drawingGridX}}" attr.y="{{drawingGridY}}" id="gridDrawing" attr.width="{{project.drawing_grid_size}}" attr.height="{{project.drawing_grid_size}}" patternUnits="userSpaceOnUse">
|
<pattern
|
||||||
<path attr.d="M {{project.drawing_grid_size}} 0 L 0 0 0 {{project.drawing_grid_size}}" fill="none" stroke="silver" attr.stroke-width="{{gridVisibility}}"/>
|
attr.x="{{ drawingGridX }}"
|
||||||
|
attr.y="{{ drawingGridY }}"
|
||||||
|
id="gridDrawing"
|
||||||
|
attr.width="{{ project.drawing_grid_size }}"
|
||||||
|
attr.height="{{ project.drawing_grid_size }}"
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
attr.d="M {{ project.drawing_grid_size }} 0 L 0 0 0 {{ project.drawing_grid_size }}"
|
||||||
|
fill="none"
|
||||||
|
stroke="silver"
|
||||||
|
attr.stroke-width="{{ gridVisibility }}"
|
||||||
|
/>
|
||||||
</pattern>
|
</pattern>
|
||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
<defs>
|
<defs>
|
||||||
<pattern attr.x="{{nodeGridX}}" attr.y="{{nodeGridY}}" id="gridNode" attr.width="{{project.grid_size}}" attr.height="{{project.grid_size}}" patternUnits="userSpaceOnUse">
|
<pattern
|
||||||
<path attr.d="M {{project.grid_size}} 0 L 0 0 0 {{project.grid_size}}" fill="none" stroke="DarkSlateGray" attr.stroke-width="{{gridVisibility}}"/>
|
attr.x="{{ nodeGridX }}"
|
||||||
|
attr.y="{{ nodeGridY }}"
|
||||||
|
id="gridNode"
|
||||||
|
attr.width="{{ project.grid_size }}"
|
||||||
|
attr.height="{{ project.grid_size }}"
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
attr.d="M {{ project.grid_size }} 0 L 0 0 0 {{ project.grid_size }}"
|
||||||
|
fill="none"
|
||||||
|
stroke="DarkSlateGray"
|
||||||
|
attr.stroke-width="{{ gridVisibility }}"
|
||||||
|
/>
|
||||||
</pattern>
|
</pattern>
|
||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.6 KiB |
@ -8,7 +8,7 @@ describe('D3MapComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [D3MapComponent]
|
declarations: [D3MapComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
SimpleChange,
|
SimpleChange,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
Output,
|
Output,
|
||||||
ViewChild
|
ViewChild,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { Selection, select } from 'd3-selection';
|
import { Selection, select } from 'd3-selection';
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ import { MapSettingsService } from '../../../services/mapsettings.service';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-d3-map',
|
selector: 'app-d3-map',
|
||||||
templateUrl: './d3-map.component.html',
|
templateUrl: './d3-map.component.html',
|
||||||
styleUrls: ['./d3-map.component.scss']
|
styleUrls: ['./d3-map.component.scss'],
|
||||||
})
|
})
|
||||||
export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
|
export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
@Input() nodes: Node[] = [];
|
@Input() nodes: Node[] = [];
|
||||||
@ -60,7 +60,7 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
private subscriptions: Subscription[] = [];
|
private subscriptions: Subscription[] = [];
|
||||||
private drawLinkTool: boolean;
|
private drawLinkTool: boolean;
|
||||||
protected settings = {
|
protected settings = {
|
||||||
show_interface_labels: true
|
show_interface_labels: true,
|
||||||
};
|
};
|
||||||
public gridVisibility: number = 0;
|
public gridVisibility: number = 0;
|
||||||
|
|
||||||
@ -148,9 +148,7 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.subscriptions.push(
|
this.subscriptions.push(this.mapScaleService.scaleChangeEmitter.subscribe((value: number) => this.redraw()));
|
||||||
this.mapScaleService.scaleChangeEmitter.subscribe((value: number) => this.redraw())
|
|
||||||
);
|
|
||||||
|
|
||||||
this.subscriptions.push(
|
this.subscriptions.push(
|
||||||
this.toolsService.isMovingToolActivated.subscribe((value: boolean) => {
|
this.toolsService.isMovingToolActivated.subscribe((value: boolean) => {
|
||||||
@ -172,7 +170,7 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.gridVisibility = localStorage.getItem('gridVisibility') === 'true' ? 1 : 0;
|
this.gridVisibility = localStorage.getItem('gridVisibility') === 'true' ? 1 : 0;
|
||||||
this.mapSettingsService.isScrollDisabled.subscribe(val => this.resize(val));
|
this.mapSettingsService.isScrollDisabled.subscribe((val) => this.resize(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
@ -190,10 +188,7 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
public createGraph(domElement: HTMLElement) {
|
public createGraph(domElement: HTMLElement) {
|
||||||
const rootElement = select(domElement);
|
const rootElement = select(domElement);
|
||||||
this.svg = rootElement.select<SVGSVGElement>('svg');
|
this.svg = rootElement.select<SVGSVGElement>('svg');
|
||||||
this.graphLayout.connect(
|
this.graphLayout.connect(this.svg, this.context);
|
||||||
this.svg,
|
|
||||||
this.context
|
|
||||||
);
|
|
||||||
this.graphLayout.draw(this.svg, this.context);
|
this.graphLayout.draw(this.svg, this.context);
|
||||||
this.mapChangeDetectorRef.hasBeenDrawn = true;
|
this.mapChangeDetectorRef.hasBeenDrawn = true;
|
||||||
}
|
}
|
||||||
@ -227,11 +222,23 @@ export class D3MapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateGrid() {
|
updateGrid() {
|
||||||
if (this.project.grid_size && this.project.grid_size > 0) this.nodeGridX = (this.project.scene_width/2 - (Math.floor(this.project.scene_width/2 / this.project.grid_size) * this.project.grid_size));
|
if (this.project.grid_size && this.project.grid_size > 0)
|
||||||
if (this.project.grid_size && this.project.grid_size > 0) this.nodeGridY = (this.project.scene_height/2 - (Math.floor(this.project.scene_height/2 / this.project.grid_size) * this.project.grid_size));
|
this.nodeGridX =
|
||||||
|
this.project.scene_width / 2 -
|
||||||
|
Math.floor(this.project.scene_width / 2 / this.project.grid_size) * this.project.grid_size;
|
||||||
|
if (this.project.grid_size && this.project.grid_size > 0)
|
||||||
|
this.nodeGridY =
|
||||||
|
this.project.scene_height / 2 -
|
||||||
|
Math.floor(this.project.scene_height / 2 / this.project.grid_size) * this.project.grid_size;
|
||||||
|
|
||||||
if (this.project.drawing_grid_size && this.project.drawing_grid_size > 0) this.drawingGridX = (this.project.scene_width/2 - (Math.floor(this.project.scene_width/2 / this.project.drawing_grid_size) * this.project.drawing_grid_size));
|
if (this.project.drawing_grid_size && this.project.drawing_grid_size > 0)
|
||||||
if (this.project.drawing_grid_size && this.project.drawing_grid_size > 0) this.drawingGridY = (this.project.scene_height/2 - (Math.floor(this.project.scene_height/2 / this.project.drawing_grid_size) * this.project.drawing_grid_size));
|
this.drawingGridX =
|
||||||
|
this.project.scene_width / 2 -
|
||||||
|
Math.floor(this.project.scene_width / 2 / this.project.drawing_grid_size) * this.project.drawing_grid_size;
|
||||||
|
if (this.project.drawing_grid_size && this.project.drawing_grid_size > 0)
|
||||||
|
this.drawingGridY =
|
||||||
|
this.project.scene_height / 2 -
|
||||||
|
Math.floor(this.project.scene_height / 2 / this.project.drawing_grid_size) * this.project.drawing_grid_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('window:resize', ['$event'])
|
@HostListener('window:resize', ['$event'])
|
||||||
|
@ -67,8 +67,8 @@ describe('DraggableSelectionComponent', () => {
|
|||||||
draggable: {
|
draggable: {
|
||||||
start: nodesStartEventEmitter,
|
start: nodesStartEventEmitter,
|
||||||
drag: nodesDragEventEmitter,
|
drag: nodesDragEventEmitter,
|
||||||
end: nodesEndEventEmitter
|
end: nodesEndEventEmitter,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const drawingsWidgetStub = {
|
const drawingsWidgetStub = {
|
||||||
@ -76,11 +76,11 @@ describe('DraggableSelectionComponent', () => {
|
|||||||
draggable: {
|
draggable: {
|
||||||
start: drawingsStartEventEmitter,
|
start: drawingsStartEventEmitter,
|
||||||
drag: drawingsDragEventEmitter,
|
drag: drawingsDragEventEmitter,
|
||||||
end: drawingsEndEventEmitter
|
end: drawingsEndEventEmitter,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
const linksWidgetStub = {
|
const linksWidgetStub = {
|
||||||
redrawLink: () => {}
|
redrawLink: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const labelWidgetStub = {
|
const labelWidgetStub = {
|
||||||
@ -88,27 +88,27 @@ describe('DraggableSelectionComponent', () => {
|
|||||||
draggable: {
|
draggable: {
|
||||||
start: labelStartEventEmitter,
|
start: labelStartEventEmitter,
|
||||||
drag: labelDragEventEmitter,
|
drag: labelDragEventEmitter,
|
||||||
end: labelEndEventEmitter
|
end: labelEndEventEmitter,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const interfaceLabelWidgetStub = {
|
const interfaceLabelWidgetStub = {
|
||||||
draggable: {
|
draggable: {
|
||||||
start: interfaceLabelStartEventEmitter,
|
start: interfaceLabelStartEventEmitter,
|
||||||
drag: interfaceLabelDragEventEmitter,
|
drag: interfaceLabelDragEventEmitter,
|
||||||
end: interfaceLabelEndEventEmitter
|
end: interfaceLabelEndEventEmitter,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const nodesEventSourceStub = {
|
const nodesEventSourceStub = {
|
||||||
dragged: { emit: () => {} },
|
dragged: { emit: () => {} },
|
||||||
labelDragged: { emit: () => {} }
|
labelDragged: { emit: () => {} },
|
||||||
};
|
};
|
||||||
const drawingsEventSourceStub = {
|
const drawingsEventSourceStub = {
|
||||||
dragged: { emit: () => {} }
|
dragged: { emit: () => {} },
|
||||||
};
|
};
|
||||||
const linksEventSourceStub = {
|
const linksEventSourceStub = {
|
||||||
interfaceDragged: { emit: () => {} }
|
interfaceDragged: { emit: () => {} },
|
||||||
};
|
};
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@ -123,9 +123,9 @@ describe('DraggableSelectionComponent', () => {
|
|||||||
{ provide: DrawingsEventSource, useValue: drawingsEventSourceStub },
|
{ provide: DrawingsEventSource, useValue: drawingsEventSourceStub },
|
||||||
{ provide: GraphDataManager, useValue: mockedGraphDataManager },
|
{ provide: GraphDataManager, useValue: mockedGraphDataManager },
|
||||||
{ provide: LinksEventSource, useValue: linksEventSourceStub },
|
{ provide: LinksEventSource, useValue: linksEventSourceStub },
|
||||||
{ provide: MapSettingsService, useClass: MapSettingsService }
|
{ provide: MapSettingsService, useClass: MapSettingsService },
|
||||||
],
|
],
|
||||||
declarations: [DraggableSelectionComponent]
|
declarations: [DraggableSelectionComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import { MapSettingsService } from '../../../services/mapsettings.service';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-draggable-selection',
|
selector: 'app-draggable-selection',
|
||||||
templateUrl: './draggable-selection.component.html',
|
templateUrl: './draggable-selection.component.html',
|
||||||
styleUrls: ['./draggable-selection.component.scss']
|
styleUrls: ['./draggable-selection.component.scss'],
|
||||||
})
|
})
|
||||||
export class DraggableSelectionComponent implements OnInit, OnDestroy {
|
export class DraggableSelectionComponent implements OnInit, OnDestroy {
|
||||||
private start: Subscription;
|
private start: Subscription;
|
||||||
@ -62,25 +62,25 @@ export class DraggableSelectionComponent implements OnInit, OnDestroy {
|
|||||||
).subscribe((evt: DraggableStart<any>) => {
|
).subscribe((evt: DraggableStart<any>) => {
|
||||||
const selected = this.selectionManager.getSelected();
|
const selected = this.selectionManager.getSelected();
|
||||||
if (evt.datum instanceof MapNode) {
|
if (evt.datum instanceof MapNode) {
|
||||||
if (selected.filter(item => item instanceof MapNode && item.id === evt.datum.id).length === 0) {
|
if (selected.filter((item) => item instanceof MapNode && item.id === evt.datum.id).length === 0) {
|
||||||
this.selectionManager.setSelected([evt.datum]);
|
this.selectionManager.setSelected([evt.datum]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evt.datum instanceof MapDrawing) {
|
if (evt.datum instanceof MapDrawing) {
|
||||||
if (selected.filter(item => item instanceof MapDrawing && item.id === evt.datum.id).length === 0) {
|
if (selected.filter((item) => item instanceof MapDrawing && item.id === evt.datum.id).length === 0) {
|
||||||
this.selectionManager.setSelected([evt.datum]);
|
this.selectionManager.setSelected([evt.datum]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evt.datum instanceof MapLabel) {
|
if (evt.datum instanceof MapLabel) {
|
||||||
if (selected.filter(item => item instanceof MapLabel && item.id === evt.datum.id).length === 0) {
|
if (selected.filter((item) => item instanceof MapLabel && item.id === evt.datum.id).length === 0) {
|
||||||
this.selectionManager.setSelected([evt.datum]);
|
this.selectionManager.setSelected([evt.datum]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evt.datum instanceof MapLinkNode) {
|
if (evt.datum instanceof MapLinkNode) {
|
||||||
if (selected.filter(item => item instanceof MapLinkNode && item.id === evt.datum.id).length === 0) {
|
if (selected.filter((item) => item instanceof MapLinkNode && item.id === evt.datum.id).length === 0) {
|
||||||
this.selectionManager.setSelected([evt.datum]);
|
this.selectionManager.setSelected([evt.datum]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ export class DraggableSelectionComponent implements OnInit, OnDestroy {
|
|||||||
if (!this.isMapLocked) {
|
if (!this.isMapLocked) {
|
||||||
const selected = this.selectionManager.getSelected();
|
const selected = this.selectionManager.getSelected();
|
||||||
// update nodes
|
// update nodes
|
||||||
let mapNodes = selected.filter(item => item instanceof MapNode);
|
let mapNodes = selected.filter((item) => item instanceof MapNode);
|
||||||
const lockedNodes = mapNodes.filter((item: MapNode) => item.locked);
|
const lockedNodes = mapNodes.filter((item: MapNode) => item.locked);
|
||||||
const selectedNodes = mapNodes.filter((item: MapNode) => !item.locked);
|
const selectedNodes = mapNodes.filter((item: MapNode) => !item.locked);
|
||||||
selectedNodes.forEach((node: MapNode) => {
|
selectedNodes.forEach((node: MapNode) => {
|
||||||
@ -107,18 +107,18 @@ export class DraggableSelectionComponent implements OnInit, OnDestroy {
|
|||||||
const links = this.graphDataManager
|
const links = this.graphDataManager
|
||||||
.getLinks()
|
.getLinks()
|
||||||
.filter(
|
.filter(
|
||||||
link =>
|
(link) =>
|
||||||
(link.target !== undefined && link.target.id === node.id) ||
|
(link.target !== undefined && link.target.id === node.id) ||
|
||||||
(link.source !== undefined && link.source.id === node.id)
|
(link.source !== undefined && link.source.id === node.id)
|
||||||
);
|
);
|
||||||
|
|
||||||
links.forEach(link => {
|
links.forEach((link) => {
|
||||||
this.linksWidget.redrawLink(svg, link);
|
this.linksWidget.redrawLink(svg, link);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// update drawings
|
// update drawings
|
||||||
let mapDrawings = selected.filter(item => item instanceof MapDrawing);
|
let mapDrawings = selected.filter((item) => item instanceof MapDrawing);
|
||||||
const selectedDrawings = mapDrawings.filter((item: MapDrawing) => !item.locked);
|
const selectedDrawings = mapDrawings.filter((item: MapDrawing) => !item.locked);
|
||||||
selectedDrawings.forEach((drawing: MapDrawing) => {
|
selectedDrawings.forEach((drawing: MapDrawing) => {
|
||||||
drawing.x += evt.dx;
|
drawing.x += evt.dx;
|
||||||
@ -127,32 +127,36 @@ export class DraggableSelectionComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// update labels
|
// update labels
|
||||||
let mapLabels = selected.filter(item => item instanceof MapLabel);
|
let mapLabels = selected.filter((item) => item instanceof MapLabel);
|
||||||
const selectedLabels = mapLabels.filter((item: MapLabel) => lockedNodes.filter((node) => node.id === item.nodeId).length === 0);
|
const selectedLabels = mapLabels.filter(
|
||||||
|
(item: MapLabel) => lockedNodes.filter((node) => node.id === item.nodeId).length === 0
|
||||||
|
);
|
||||||
selectedLabels.forEach((label: MapLabel) => {
|
selectedLabels.forEach((label: MapLabel) => {
|
||||||
const isParentNodeSelected = selectedNodes.filter(node => node.id === label.nodeId).length > 0;
|
const isParentNodeSelected = selectedNodes.filter((node) => node.id === label.nodeId).length > 0;
|
||||||
if (isParentNodeSelected) {
|
if (isParentNodeSelected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const node = this.graphDataManager.getNodes().filter(node => node.id === label.nodeId)[0];
|
const node = this.graphDataManager.getNodes().filter((node) => node.id === label.nodeId)[0];
|
||||||
node.label.x += evt.dx;
|
node.label.x += evt.dx;
|
||||||
node.label.y += evt.dy;
|
node.label.y += evt.dy;
|
||||||
this.labelWidget.redrawLabel(svg, label);
|
this.labelWidget.redrawLabel(svg, label);
|
||||||
});
|
});
|
||||||
|
|
||||||
// update interface labels
|
// update interface labels
|
||||||
let mapLinkNodes = selected.filter(item => item instanceof MapLinkNode);
|
let mapLinkNodes = selected.filter((item) => item instanceof MapLinkNode);
|
||||||
const selectedLinkNodes = mapLinkNodes.filter((item: MapLinkNode) => lockedNodes.filter((node) => node.id === item.nodeId).length === 0);
|
const selectedLinkNodes = mapLinkNodes.filter(
|
||||||
|
(item: MapLinkNode) => lockedNodes.filter((node) => node.id === item.nodeId).length === 0
|
||||||
|
);
|
||||||
selectedLinkNodes.forEach((interfaceLabel: MapLinkNode) => {
|
selectedLinkNodes.forEach((interfaceLabel: MapLinkNode) => {
|
||||||
const isParentNodeSelected = selectedNodes.filter(node => node.id === interfaceLabel.nodeId).length > 0;
|
const isParentNodeSelected = selectedNodes.filter((node) => node.id === interfaceLabel.nodeId).length > 0;
|
||||||
if (isParentNodeSelected) {
|
if (isParentNodeSelected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const link = this.graphDataManager
|
const link = this.graphDataManager
|
||||||
.getLinks()
|
.getLinks()
|
||||||
.filter(link => link.nodes[0].id === interfaceLabel.id || link.nodes[1].id === interfaceLabel.id)[0];
|
.filter((link) => link.nodes[0].id === interfaceLabel.id || link.nodes[1].id === interfaceLabel.id)[0];
|
||||||
if (link.nodes[0].id === interfaceLabel.id) {
|
if (link.nodes[0].id === interfaceLabel.id) {
|
||||||
link.nodes[0].label.x += evt.dx;
|
link.nodes[0].label.x += evt.dx;
|
||||||
link.nodes[0].label.y += evt.dy;
|
link.nodes[0].label.y += evt.dy;
|
||||||
@ -176,23 +180,25 @@ export class DraggableSelectionComponent implements OnInit, OnDestroy {
|
|||||||
if (!this.isMapLocked) {
|
if (!this.isMapLocked) {
|
||||||
const selected = this.selectionManager.getSelected();
|
const selected = this.selectionManager.getSelected();
|
||||||
|
|
||||||
let mapNodes = selected.filter(item => item instanceof MapNode);
|
let mapNodes = selected.filter((item) => item instanceof MapNode);
|
||||||
const lockedNodes = mapNodes.filter((item: MapNode) => item.locked);
|
const lockedNodes = mapNodes.filter((item: MapNode) => item.locked);
|
||||||
const selectedNodes = mapNodes.filter((item: MapNode) => !item.locked);
|
const selectedNodes = mapNodes.filter((item: MapNode) => !item.locked);
|
||||||
selectedNodes.forEach((item: MapNode) => {
|
selectedNodes.forEach((item: MapNode) => {
|
||||||
this.nodesEventSource.dragged.emit(new DraggedDataEvent<MapNode>(item, evt.dx, evt.dy));
|
this.nodesEventSource.dragged.emit(new DraggedDataEvent<MapNode>(item, evt.dx, evt.dy));
|
||||||
});
|
});
|
||||||
|
|
||||||
let mapDrawings = selected.filter(item => item instanceof MapDrawing);
|
let mapDrawings = selected.filter((item) => item instanceof MapDrawing);
|
||||||
const selectedDrawings = mapDrawings.filter((item: MapDrawing) => !item.locked);
|
const selectedDrawings = mapDrawings.filter((item: MapDrawing) => !item.locked);
|
||||||
selectedDrawings.forEach((item: MapDrawing) => {
|
selectedDrawings.forEach((item: MapDrawing) => {
|
||||||
this.drawingsEventSource.dragged.emit(new DraggedDataEvent<MapDrawing>(item, evt.dx, evt.dy));
|
this.drawingsEventSource.dragged.emit(new DraggedDataEvent<MapDrawing>(item, evt.dx, evt.dy));
|
||||||
});
|
});
|
||||||
|
|
||||||
let mapLabels = selected.filter(item => item instanceof MapLabel);
|
let mapLabels = selected.filter((item) => item instanceof MapLabel);
|
||||||
const selectedLabels = mapLabels.filter((item: MapLabel) => lockedNodes.filter((node) => node.id === item.nodeId).length === 0);
|
const selectedLabels = mapLabels.filter(
|
||||||
|
(item: MapLabel) => lockedNodes.filter((node) => node.id === item.nodeId).length === 0
|
||||||
|
);
|
||||||
selectedLabels.forEach((label: MapLabel) => {
|
selectedLabels.forEach((label: MapLabel) => {
|
||||||
const isParentNodeSelected = selectedNodes.filter(node => node.id === label.nodeId).length > 0;
|
const isParentNodeSelected = selectedNodes.filter((node) => node.id === label.nodeId).length > 0;
|
||||||
if (isParentNodeSelected) {
|
if (isParentNodeSelected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -200,10 +206,12 @@ export class DraggableSelectionComponent implements OnInit, OnDestroy {
|
|||||||
this.nodesEventSource.labelDragged.emit(new DraggedDataEvent<MapLabel>(label, evt.dx, evt.dy));
|
this.nodesEventSource.labelDragged.emit(new DraggedDataEvent<MapLabel>(label, evt.dx, evt.dy));
|
||||||
});
|
});
|
||||||
|
|
||||||
let mapLinkNodes = selected.filter(item => item instanceof MapLinkNode);
|
let mapLinkNodes = selected.filter((item) => item instanceof MapLinkNode);
|
||||||
const selectedLinkNodes = mapLinkNodes.filter((item: MapLinkNode) => lockedNodes.filter((node) => node.id === item.nodeId).length === 0)
|
const selectedLinkNodes = mapLinkNodes.filter(
|
||||||
|
(item: MapLinkNode) => lockedNodes.filter((node) => node.id === item.nodeId).length === 0
|
||||||
|
);
|
||||||
selectedLinkNodes.forEach((label: MapLinkNode) => {
|
selectedLinkNodes.forEach((label: MapLinkNode) => {
|
||||||
const isParentNodeSelected = selectedNodes.filter(node => node.id === label.nodeId).length > 0;
|
const isParentNodeSelected = selectedNodes.filter((node) => node.id === label.nodeId).length > 0;
|
||||||
if (isParentNodeSelected) {
|
if (isParentNodeSelected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ describe('DrawingAddingComponent', () => {
|
|||||||
imports: [NoopAnimationsModule],
|
imports: [NoopAnimationsModule],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: DrawingsEventSource, useValue: drawingsEventSource },
|
{ provide: DrawingsEventSource, useValue: drawingsEventSource },
|
||||||
{ provide: Context, useClass: Context }
|
{ provide: Context, useClass: Context },
|
||||||
],
|
],
|
||||||
declarations: [DrawingAddingComponent]
|
declarations: [DrawingAddingComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import { Subscription } from 'rxjs';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-drawing-adding',
|
selector: 'app-drawing-adding',
|
||||||
templateUrl: './drawing-adding.component.html',
|
templateUrl: './drawing-adding.component.html',
|
||||||
styleUrls: ['./drawing-adding.component.scss']
|
styleUrls: ['./drawing-adding.component.scss'],
|
||||||
})
|
})
|
||||||
export class DrawingAddingComponent implements OnInit, OnDestroy {
|
export class DrawingAddingComponent implements OnInit, OnDestroy {
|
||||||
@Input('svg') svg: SVGSVGElement;
|
@Input('svg') svg: SVGSVGElement;
|
||||||
@ -18,15 +18,19 @@ export class DrawingAddingComponent implements OnInit, OnDestroy {
|
|||||||
constructor(private drawingsEventSource: DrawingsEventSource, private context: Context) {}
|
constructor(private drawingsEventSource: DrawingsEventSource, private context: Context) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.drawingSelected = this.drawingsEventSource.selected.subscribe(evt => {
|
this.drawingSelected = this.drawingsEventSource.selected.subscribe((evt) => {
|
||||||
evt === '' ? this.deactivate() : this.activate();
|
evt === '' ? this.deactivate() : this.activate();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
activate() {
|
activate() {
|
||||||
let listener = (event: MouseEvent) => {
|
let listener = (event: MouseEvent) => {
|
||||||
let x = (event.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x))/this.context.transformation.k;
|
let x =
|
||||||
let y = (event.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y))/this.context.transformation.k;
|
(event.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x)) /
|
||||||
|
this.context.transformation.k;
|
||||||
|
let y =
|
||||||
|
(event.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y)) /
|
||||||
|
this.context.transformation.k;
|
||||||
|
|
||||||
this.drawingsEventSource.pointToAddSelected.emit(new AddedDataEvent(x, y));
|
this.drawingsEventSource.pointToAddSelected.emit(new AddedDataEvent(x, y));
|
||||||
this.deactivate();
|
this.deactivate();
|
||||||
|
@ -36,9 +36,9 @@ describe('DrawingResizingComponent', () => {
|
|||||||
imports: [NoopAnimationsModule],
|
imports: [NoopAnimationsModule],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: DrawingsWidget, useValue: drawingsWidgetMock },
|
{ provide: DrawingsWidget, useValue: drawingsWidgetMock },
|
||||||
{ provide: DrawingsEventSource, useValue: drawingsEventSource }
|
{ provide: DrawingsEventSource, useValue: drawingsEventSource },
|
||||||
],
|
],
|
||||||
declarations: [DrawingResizingComponent]
|
declarations: [DrawingResizingComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -8,10 +8,8 @@ import { ResizingEnd } from '../../events/resizing';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-drawing-resizing',
|
selector: 'app-drawing-resizing',
|
||||||
template: `
|
template: ` <ng-content></ng-content> `,
|
||||||
<ng-content></ng-content>
|
styleUrls: ['./drawing-resizing.component.scss'],
|
||||||
`,
|
|
||||||
styleUrls: ['./drawing-resizing.component.scss']
|
|
||||||
})
|
})
|
||||||
export class DrawingResizingComponent implements OnInit, OnDestroy {
|
export class DrawingResizingComponent implements OnInit, OnDestroy {
|
||||||
resizingFinished: Subscription;
|
resizingFinished: Subscription;
|
||||||
|
@ -8,7 +8,7 @@ describe('DraggableComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [DraggableComponent]
|
declarations: [DraggableComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -8,10 +8,8 @@ export class DraggableDraggedEvent {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: '[app-draggable]',
|
selector: '[app-draggable]',
|
||||||
template: `
|
template: ` <ng-content></ng-content> `,
|
||||||
<ng-content></ng-content>
|
styleUrls: ['./draggable.component.scss'],
|
||||||
`,
|
|
||||||
styleUrls: ['./draggable.component.scss']
|
|
||||||
})
|
})
|
||||||
export class DraggableComponent implements OnInit, AfterViewInit, OnDestroy {
|
export class DraggableComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||||
@Input('app-draggable') item: Point;
|
@Input('app-draggable') item: Point;
|
||||||
|
@ -8,7 +8,7 @@ describe('DrawingComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [DrawingComponent]
|
declarations: [DrawingComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import { DrawingsEventSource } from '../../../events/drawings-event-source';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: '[app-drawing]',
|
selector: '[app-drawing]',
|
||||||
templateUrl: './drawing.component.html',
|
templateUrl: './drawing.component.html',
|
||||||
styleUrls: ['./drawing.component.scss']
|
styleUrls: ['./drawing.component.scss'],
|
||||||
})
|
})
|
||||||
export class DrawingComponent implements OnInit {
|
export class DrawingComponent implements OnInit {
|
||||||
@Input('app-drawing') drawing: MapDrawing;
|
@Input('app-drawing') drawing: MapDrawing;
|
||||||
|
@ -8,7 +8,7 @@ describe('EllipseComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [EllipseComponent]
|
declarations: [EllipseComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { QtDasharrayFixer } from '../../../../../helpers/qt-dasharray-fixer';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: '[app-ellipse]',
|
selector: '[app-ellipse]',
|
||||||
templateUrl: './ellipse.component.html',
|
templateUrl: './ellipse.component.html',
|
||||||
styleUrls: ['./ellipse.component.scss']
|
styleUrls: ['./ellipse.component.scss'],
|
||||||
})
|
})
|
||||||
export class EllipseComponent implements OnInit {
|
export class EllipseComponent implements OnInit {
|
||||||
@Input('app-ellipse') ellipse: EllipseElement;
|
@Input('app-ellipse') ellipse: EllipseElement;
|
||||||
|
@ -8,7 +8,7 @@ describe('ImageComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [ImageComponent]
|
declarations: [ImageComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { ImageElement } from '../../../../../models/drawings/image-element';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: '[app-image]',
|
selector: '[app-image]',
|
||||||
templateUrl: './image.component.html',
|
templateUrl: './image.component.html',
|
||||||
styleUrls: ['./image.component.scss']
|
styleUrls: ['./image.component.scss'],
|
||||||
})
|
})
|
||||||
export class ImageComponent implements OnInit {
|
export class ImageComponent implements OnInit {
|
||||||
@Input('app-image') image: ImageElement;
|
@Input('app-image') image: ImageElement;
|
||||||
|
@ -8,7 +8,7 @@ describe('LineComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [LineComponent]
|
declarations: [LineComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { LineElement } from '../../../../../models/drawings/line-element';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: '[app-line]',
|
selector: '[app-line]',
|
||||||
templateUrl: './line.component.html',
|
templateUrl: './line.component.html',
|
||||||
styleUrls: ['./line.component.scss']
|
styleUrls: ['./line.component.scss'],
|
||||||
})
|
})
|
||||||
export class LineComponent implements OnInit {
|
export class LineComponent implements OnInit {
|
||||||
@Input('app-line') line: LineElement;
|
@Input('app-line') line: LineElement;
|
||||||
|
@ -8,7 +8,7 @@ describe('RectComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [RectComponent]
|
declarations: [RectComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { QtDasharrayFixer } from '../../../../../helpers/qt-dasharray-fixer';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: '[app-rect]',
|
selector: '[app-rect]',
|
||||||
templateUrl: './rect.component.html',
|
templateUrl: './rect.component.html',
|
||||||
styleUrls: ['./rect.component.scss']
|
styleUrls: ['./rect.component.scss'],
|
||||||
})
|
})
|
||||||
export class RectComponent implements OnInit {
|
export class RectComponent implements OnInit {
|
||||||
@Input('app-rect') rect: RectElement;
|
@Input('app-rect') rect: RectElement;
|
||||||
|
@ -8,7 +8,7 @@ describe('TextComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [TextComponent]
|
declarations: [TextComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import { FontFixer } from '../../../../../helpers/font-fixer';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: '[app-text]',
|
selector: '[app-text]',
|
||||||
templateUrl: './text.component.html',
|
templateUrl: './text.component.html',
|
||||||
styleUrls: ['./text.component.scss']
|
styleUrls: ['./text.component.scss'],
|
||||||
})
|
})
|
||||||
export class TextComponent implements OnInit, DoCheck {
|
export class TextComponent implements OnInit, DoCheck {
|
||||||
static MARGIN = 4;
|
static MARGIN = 4;
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
SimpleChange,
|
SimpleChange,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
ViewChild
|
ViewChild,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import { GraphLayout } from '../../widgets/graph-layout';
|
import { GraphLayout } from '../../widgets/graph-layout';
|
||||||
@ -29,7 +29,7 @@ import { LayersManager } from '../../managers/layers-manager';
|
|||||||
selector: 'app-experimental-map',
|
selector: 'app-experimental-map',
|
||||||
templateUrl: './experimental-map.component.html',
|
templateUrl: './experimental-map.component.html',
|
||||||
styleUrls: ['./experimental-map.component.scss'],
|
styleUrls: ['./experimental-map.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class ExperimentalMapComponent implements OnInit, OnChanges, OnDestroy {
|
export class ExperimentalMapComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
@Input() nodes: Node[] = [];
|
@Input() nodes: Node[] = [];
|
||||||
@ -48,7 +48,7 @@ export class ExperimentalMapComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
private changesDetected: Subscription;
|
private changesDetected: Subscription;
|
||||||
|
|
||||||
protected settings = {
|
protected settings = {
|
||||||
show_interface_labels: true
|
show_interface_labels: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -8,7 +8,7 @@ describe('InterfaceLabelComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [InterfaceLabelComponent]
|
declarations: [InterfaceLabelComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { CssFixer } from '../../../helpers/css-fixer';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: '[app-interface-label]',
|
selector: '[app-interface-label]',
|
||||||
templateUrl: './interface-label.component.html',
|
templateUrl: './interface-label.component.html',
|
||||||
styleUrls: ['./interface-label.component.scss']
|
styleUrls: ['./interface-label.component.scss'],
|
||||||
})
|
})
|
||||||
export class InterfaceLabelComponent implements OnInit {
|
export class InterfaceLabelComponent implements OnInit {
|
||||||
@Input('app-interface-label') ignore: any;
|
@Input('app-interface-label') ignore: any;
|
||||||
@ -17,7 +17,7 @@ export class InterfaceLabelComponent implements OnInit {
|
|||||||
y: 0,
|
y: 0,
|
||||||
text: '',
|
text: '',
|
||||||
style: '',
|
style: '',
|
||||||
rotation: 0
|
rotation: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
borderSize = 5;
|
borderSize = 5;
|
||||||
|
@ -8,7 +8,7 @@ describe('LinkComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [LinkComponent]
|
declarations: [LinkComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
ElementRef,
|
ElementRef,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
OnDestroy
|
OnDestroy,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { LinkStrategy } from './strategies/link-strategy';
|
import { LinkStrategy } from './strategies/link-strategy';
|
||||||
@ -19,7 +19,7 @@ import { MapLink } from '../../../models/map/map-link';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: '[app-link]',
|
selector: '[app-link]',
|
||||||
templateUrl: './link.component.html',
|
templateUrl: './link.component.html',
|
||||||
styleUrls: ['./link.component.scss']
|
styleUrls: ['./link.component.scss'],
|
||||||
})
|
})
|
||||||
export class LinkComponent implements OnInit, OnDestroy {
|
export class LinkComponent implements OnInit, OnDestroy {
|
||||||
@Input('app-link') link: MapLink;
|
@Input('app-link') link: MapLink;
|
||||||
|
@ -6,7 +6,7 @@ export class EthernetLinkStrategy implements LinkStrategy {
|
|||||||
public d(link: MapLink): string {
|
public d(link: MapLink): string {
|
||||||
const points = [
|
const points = [
|
||||||
[link.source.x + link.source.width / 2, link.source.y + link.source.height / 2],
|
[link.source.x + link.source.width / 2, link.source.y + link.source.height / 2],
|
||||||
[link.target.x + link.target.width / 2, link.target.y + link.target.height / 2]
|
[link.target.x + link.target.width / 2, link.target.y + link.target.height / 2],
|
||||||
];
|
];
|
||||||
|
|
||||||
const line_generator = path();
|
const line_generator = path();
|
||||||
|
@ -6,11 +6,11 @@ export class SerialLinkStrategy implements LinkStrategy {
|
|||||||
private linkToPoints(link: MapLink) {
|
private linkToPoints(link: MapLink) {
|
||||||
const source = {
|
const source = {
|
||||||
x: link.source.x + link.source.width / 2,
|
x: link.source.x + link.source.width / 2,
|
||||||
y: link.source.y + link.source.height / 2
|
y: link.source.y + link.source.height / 2,
|
||||||
};
|
};
|
||||||
const target = {
|
const target = {
|
||||||
x: link.target.x + link.target.width / 2,
|
x: link.target.x + link.target.width / 2,
|
||||||
y: link.target.y + link.target.height / 2
|
y: link.target.y + link.target.height / 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
const dx = target.x - source.x;
|
const dx = target.x - source.x;
|
||||||
@ -22,12 +22,12 @@ export class SerialLinkStrategy implements LinkStrategy {
|
|||||||
|
|
||||||
const angle_source: [number, number] = [
|
const angle_source: [number, number] = [
|
||||||
source.x + dx / 2.0 + 15 * vect_rot[0],
|
source.x + dx / 2.0 + 15 * vect_rot[0],
|
||||||
source.y + dy / 2.0 + 15 * vect_rot[1]
|
source.y + dy / 2.0 + 15 * vect_rot[1],
|
||||||
];
|
];
|
||||||
|
|
||||||
const angle_target: [number, number] = [
|
const angle_target: [number, number] = [
|
||||||
target.x - dx / 2.0 - 15 * vect_rot[0],
|
target.x - dx / 2.0 - 15 * vect_rot[0],
|
||||||
target.y - dy / 2.0 - 15 * vect_rot[1]
|
target.y - dy / 2.0 - 15 * vect_rot[1],
|
||||||
];
|
];
|
||||||
|
|
||||||
return [[source.x, source.y], angle_source, angle_target, [target.x, target.y]];
|
return [[source.x, source.y], angle_source, angle_target, [target.x, target.y]];
|
||||||
|
@ -8,7 +8,7 @@ describe('NodeComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [NodeComponent]
|
declarations: [NodeComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
EventEmitter,
|
EventEmitter,
|
||||||
OnDestroy,
|
OnDestroy,
|
||||||
OnChanges,
|
OnChanges,
|
||||||
AfterViewInit
|
AfterViewInit,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
@ -25,7 +25,7 @@ import { DraggedDataEvent } from '../../../events/event-source';
|
|||||||
selector: '[app-node]',
|
selector: '[app-node]',
|
||||||
templateUrl: './node.component.html',
|
templateUrl: './node.component.html',
|
||||||
styleUrls: ['./node.component.scss'],
|
styleUrls: ['./node.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class NodeComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
|
export class NodeComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
|
||||||
static NODE_LABEL_MARGIN = 3;
|
static NODE_LABEL_MARGIN = 3;
|
||||||
|
@ -8,7 +8,7 @@ describe('SelectionComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [SelectionComponent]
|
declarations: [SelectionComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { Rectangle } from '../../../models/rectangle';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: '[app-selection]',
|
selector: '[app-selection]',
|
||||||
templateUrl: './selection.component.html',
|
templateUrl: './selection.component.html',
|
||||||
styleUrls: ['./selection.component.scss']
|
styleUrls: ['./selection.component.scss'],
|
||||||
})
|
})
|
||||||
export class SelectionComponent implements OnInit, AfterViewInit {
|
export class SelectionComponent implements OnInit, AfterViewInit {
|
||||||
@Input('app-selection') svg: SVGSVGElement;
|
@Input('app-selection') svg: SVGSVGElement;
|
||||||
|
@ -8,7 +8,7 @@ describe('StatusComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [StatusComponent]
|
declarations: [StatusComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { Component, ElementRef, Input, ChangeDetectorRef } from '@angular/core';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: '[app-status]',
|
selector: '[app-status]',
|
||||||
templateUrl: './status.component.html',
|
templateUrl: './status.component.html',
|
||||||
styleUrls: ['./status.component.scss']
|
styleUrls: ['./status.component.scss'],
|
||||||
})
|
})
|
||||||
export class StatusComponent {
|
export class StatusComponent {
|
||||||
static STOPPED_STATUS_RECT_WIDTH = 10;
|
static STOPPED_STATUS_RECT_WIDTH = 10;
|
||||||
@ -12,7 +12,7 @@ export class StatusComponent {
|
|||||||
status: '',
|
status: '',
|
||||||
path: null,
|
path: null,
|
||||||
direction: null,
|
direction: null,
|
||||||
d: null
|
d: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(protected element: ElementRef, private ref: ChangeDetectorRef) {}
|
constructor(protected element: ElementRef, private ref: ChangeDetectorRef) {}
|
||||||
|
@ -9,7 +9,7 @@ import { Rectangle } from '../../models/rectangle';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-selection-control',
|
selector: 'app-selection-control',
|
||||||
templateUrl: './selection-control.component.html',
|
templateUrl: './selection-control.component.html',
|
||||||
styleUrls: ['./selection-control.component.scss']
|
styleUrls: ['./selection-control.component.scss'],
|
||||||
})
|
})
|
||||||
export class SelectionControlComponent implements OnInit, OnDestroy {
|
export class SelectionControlComponent implements OnInit, OnDestroy {
|
||||||
private onSelection: Subscription;
|
private onSelection: Subscription;
|
||||||
@ -23,21 +23,21 @@ export class SelectionControlComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.onSelection = this.selectionEventSource.selected.subscribe((rectangle: Rectangle) => {
|
this.onSelection = this.selectionEventSource.selected.subscribe((rectangle: Rectangle) => {
|
||||||
const selectedNodes = this.graphDataManager.getNodes().filter(node => {
|
const selectedNodes = this.graphDataManager.getNodes().filter((node) => {
|
||||||
return this.inRectangleHelper.inRectangle(rectangle, node.x, node.y);
|
return this.inRectangleHelper.inRectangle(rectangle, node.x, node.y);
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedLinks = this.graphDataManager.getLinks().filter(link => {
|
const selectedLinks = this.graphDataManager.getLinks().filter((link) => {
|
||||||
return this.inRectangleHelper.inRectangle(rectangle, link.x, link.y);
|
return this.inRectangleHelper.inRectangle(rectangle, link.x, link.y);
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedDrawings = this.graphDataManager.getDrawings().filter(drawing => {
|
const selectedDrawings = this.graphDataManager.getDrawings().filter((drawing) => {
|
||||||
return this.inRectangleHelper.inRectangle(rectangle, drawing.x, drawing.y);
|
return this.inRectangleHelper.inRectangle(rectangle, drawing.x, drawing.y);
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedLabels = this.graphDataManager
|
const selectedLabels = this.graphDataManager
|
||||||
.getNodes()
|
.getNodes()
|
||||||
.filter(node => {
|
.filter((node) => {
|
||||||
if (node.label === undefined) {
|
if (node.label === undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -45,11 +45,11 @@ export class SelectionControlComponent implements OnInit, OnDestroy {
|
|||||||
const labelY = node.y + node.label.y;
|
const labelY = node.y + node.label.y;
|
||||||
return this.inRectangleHelper.inRectangle(rectangle, labelX, labelY);
|
return this.inRectangleHelper.inRectangle(rectangle, labelX, labelY);
|
||||||
})
|
})
|
||||||
.map(node => node.label);
|
.map((node) => node.label);
|
||||||
|
|
||||||
const selectedInterfacesLabelsSources = this.graphDataManager
|
const selectedInterfacesLabelsSources = this.graphDataManager
|
||||||
.getLinks()
|
.getLinks()
|
||||||
.filter(link => {
|
.filter((link) => {
|
||||||
if (link.source === undefined || link.nodes.length != 2 || link.nodes[0].label === undefined) {
|
if (link.source === undefined || link.nodes.length != 2 || link.nodes[0].label === undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -57,11 +57,11 @@ export class SelectionControlComponent implements OnInit, OnDestroy {
|
|||||||
const interfaceLabelY = link.source.y + link.nodes[0].label.y;
|
const interfaceLabelY = link.source.y + link.nodes[0].label.y;
|
||||||
return this.inRectangleHelper.inRectangle(rectangle, interfaceLabelX, interfaceLabelY);
|
return this.inRectangleHelper.inRectangle(rectangle, interfaceLabelX, interfaceLabelY);
|
||||||
})
|
})
|
||||||
.map(link => link.nodes[0]);
|
.map((link) => link.nodes[0]);
|
||||||
|
|
||||||
const selectedInterfacesLabelsTargets = this.graphDataManager
|
const selectedInterfacesLabelsTargets = this.graphDataManager
|
||||||
.getLinks()
|
.getLinks()
|
||||||
.filter(link => {
|
.filter((link) => {
|
||||||
if (link.target === undefined || link.nodes.length != 2 || link.nodes[1].label === undefined) {
|
if (link.target === undefined || link.nodes.length != 2 || link.nodes[1].label === undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ export class SelectionControlComponent implements OnInit, OnDestroy {
|
|||||||
const interfaceLabelY = link.target.y + link.nodes[1].label.y;
|
const interfaceLabelY = link.target.y + link.nodes[1].label.y;
|
||||||
return this.inRectangleHelper.inRectangle(rectangle, interfaceLabelX, interfaceLabelY);
|
return this.inRectangleHelper.inRectangle(rectangle, interfaceLabelX, interfaceLabelY);
|
||||||
})
|
})
|
||||||
.map(link => link.nodes[1]);
|
.map((link) => link.nodes[1]);
|
||||||
|
|
||||||
const selectedInterfaces = [...selectedInterfacesLabelsSources, ...selectedInterfacesLabelsTargets];
|
const selectedInterfaces = [...selectedInterfacesLabelsSources, ...selectedInterfacesLabelsTargets];
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ export class SelectionControlComponent implements OnInit, OnDestroy {
|
|||||||
...selectedLinks,
|
...selectedLinks,
|
||||||
...selectedDrawings,
|
...selectedDrawings,
|
||||||
...selectedLabels,
|
...selectedLabels,
|
||||||
...selectedInterfaces
|
...selectedInterfaces,
|
||||||
];
|
];
|
||||||
|
|
||||||
this.selectionManager.setSelected(selected);
|
this.selectionManager.setSelected(selected);
|
||||||
|
@ -8,7 +8,7 @@ describe('SelectionSelectComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [SelectionSelectComponent]
|
declarations: [SelectionSelectComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -6,16 +6,13 @@ import { MapChangeDetectorRef } from '../../services/map-change-detector-ref';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-selection-select',
|
selector: 'app-selection-select',
|
||||||
templateUrl: './selection-select.component.html',
|
templateUrl: './selection-select.component.html',
|
||||||
styleUrls: ['./selection-select.component.scss']
|
styleUrls: ['./selection-select.component.scss'],
|
||||||
})
|
})
|
||||||
export class SelectionSelectComponent implements OnInit, OnDestroy {
|
export class SelectionSelectComponent implements OnInit, OnDestroy {
|
||||||
private onSelected: Subscription;
|
private onSelected: Subscription;
|
||||||
private onUnselected: Subscription;
|
private onUnselected: Subscription;
|
||||||
|
|
||||||
constructor(
|
constructor(private selectionManager: SelectionManager, private mapChangeDetectorRef: MapChangeDetectorRef) {}
|
||||||
private selectionManager: SelectionManager,
|
|
||||||
private mapChangeDetectorRef: MapChangeDetectorRef
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.onSelected = this.selectionManager.selected.subscribe(() => {
|
this.onSelected = this.selectionManager.selected.subscribe(() => {
|
||||||
|
@ -31,9 +31,9 @@ describe('TextEditorComponent', () => {
|
|||||||
{ provide: NodesDataSource, useClass: NodesDataSource },
|
{ provide: NodesDataSource, useClass: NodesDataSource },
|
||||||
{ provide: LinksDataSource, useClass: LinksDataSource },
|
{ provide: LinksDataSource, useClass: LinksDataSource },
|
||||||
{ provide: SelectionManager, useClass: SelectionManager },
|
{ provide: SelectionManager, useClass: SelectionManager },
|
||||||
{ provide: FontFixer, useClass: FontFixer }
|
{ provide: FontFixer, useClass: FontFixer },
|
||||||
],
|
],
|
||||||
declarations: [TextEditorComponent]
|
declarations: [TextEditorComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,4 +1,14 @@
|
|||||||
import { Component, ViewChild, ElementRef, OnInit, Input, EventEmitter, OnDestroy, Renderer2, NgZone } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
ViewChild,
|
||||||
|
ElementRef,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
EventEmitter,
|
||||||
|
OnDestroy,
|
||||||
|
Renderer2,
|
||||||
|
NgZone,
|
||||||
|
} from '@angular/core';
|
||||||
import { DrawingsEventSource } from '../../events/drawings-event-source';
|
import { DrawingsEventSource } from '../../events/drawings-event-source';
|
||||||
import { TextAddedDataEvent, TextEditedDataEvent } from '../../events/event-source';
|
import { TextAddedDataEvent, TextEditedDataEvent } from '../../events/event-source';
|
||||||
import { ToolsService } from '../../../services/tools.service';
|
import { ToolsService } from '../../../services/tools.service';
|
||||||
@ -24,7 +34,7 @@ import { Font } from '../../models/font';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-text-editor',
|
selector: 'app-text-editor',
|
||||||
templateUrl: './text-editor.component.html',
|
templateUrl: './text-editor.component.html',
|
||||||
styleUrls: ['./text-editor.component.scss']
|
styleUrls: ['./text-editor.component.scss'],
|
||||||
})
|
})
|
||||||
export class TextEditorComponent implements OnInit, OnDestroy {
|
export class TextEditorComponent implements OnInit, OnDestroy {
|
||||||
@ViewChild('temporaryTextElement') temporaryTextElement: ElementRef;
|
@ViewChild('temporaryTextElement') temporaryTextElement: ElementRef;
|
||||||
@ -73,7 +83,11 @@ export class TextEditorComponent implements OnInit, OnDestroy {
|
|||||||
this.leftPosition = event.pageX.toString() + 'px';
|
this.leftPosition = event.pageX.toString() + 'px';
|
||||||
this.topPosition = event.pageY.toString() + 'px';
|
this.topPosition = event.pageY.toString() + 'px';
|
||||||
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'display', 'initial');
|
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'display', 'initial');
|
||||||
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'transform', `scale(${this.mapScaleService.getScale()})`);
|
this.renderer.setStyle(
|
||||||
|
this.temporaryTextElement.nativeElement,
|
||||||
|
'transform',
|
||||||
|
`scale(${this.mapScaleService.getScale()})`
|
||||||
|
);
|
||||||
this.temporaryTextElement.nativeElement.focus();
|
this.temporaryTextElement.nativeElement.focus();
|
||||||
|
|
||||||
let textListener = () => {
|
let textListener = () => {
|
||||||
@ -113,7 +127,11 @@ export class TextEditorComponent implements OnInit, OnDestroy {
|
|||||||
this.selectionManager.setSelected([]);
|
this.selectionManager.setSelected([]);
|
||||||
|
|
||||||
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'display', 'initial');
|
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'display', 'initial');
|
||||||
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'transform', `scale(${this.mapScaleService.getScale()})`);
|
this.renderer.setStyle(
|
||||||
|
this.temporaryTextElement.nativeElement,
|
||||||
|
'transform',
|
||||||
|
`scale(${this.mapScaleService.getScale()})`
|
||||||
|
);
|
||||||
this.editedLink = elem;
|
this.editedLink = elem;
|
||||||
|
|
||||||
select(textElements[index]).attr('visibility', 'hidden');
|
select(textElements[index]).attr('visibility', 'hidden');
|
||||||
@ -121,26 +139,44 @@ export class TextEditorComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.editedNode = this.nodesDataSource.get(elem.nodeId);
|
this.editedNode = this.nodesDataSource.get(elem.nodeId);
|
||||||
this.editedLink = elem;
|
this.editedLink = elem;
|
||||||
let x = ((elem.label.originalX + this.editedNode.x - 1) * this.context.transformation.k) + this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x;
|
let x =
|
||||||
let y = ((elem.label.originalY + this.editedNode.y + 4) * this.context.transformation.k) + this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y;
|
(elem.label.originalX + this.editedNode.x - 1) * this.context.transformation.k +
|
||||||
|
this.context.getZeroZeroTransformationPoint().x +
|
||||||
|
this.context.transformation.x;
|
||||||
|
let y =
|
||||||
|
(elem.label.originalY + this.editedNode.y + 4) * this.context.transformation.k +
|
||||||
|
this.context.getZeroZeroTransformationPoint().y +
|
||||||
|
this.context.transformation.y;
|
||||||
this.leftPosition = x.toString() + 'px';
|
this.leftPosition = x.toString() + 'px';
|
||||||
this.topPosition = y.toString() + 'px';
|
this.topPosition = y.toString() + 'px';
|
||||||
this.temporaryTextElement.nativeElement.innerText = elem.label.text;
|
this.temporaryTextElement.nativeElement.innerText = elem.label.text;
|
||||||
|
|
||||||
let styleProperties: StyleProperty[] = [];
|
let styleProperties: StyleProperty[] = [];
|
||||||
for (let property of elem.label.style.split(";")){
|
for (let property of elem.label.style.split(';')) {
|
||||||
styleProperties.push({
|
styleProperties.push({
|
||||||
property: property.split(": ")[0],
|
property: property.split(': ')[0],
|
||||||
value: property.split(": ")[1]
|
value: property.split(': ')[1],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let font: Font = {
|
let font: Font = {
|
||||||
font_family: styleProperties.find(p => p.property === 'font-family') ? styleProperties.find(p => p.property === 'font-family').value : 'TypeWriter',
|
font_family: styleProperties.find((p) => p.property === 'font-family')
|
||||||
font_size: styleProperties.find(p => p.property === 'font-size') ? Number(styleProperties.find(p => p.property === 'font-size').value) : 10.0,
|
? styleProperties.find((p) => p.property === 'font-family').value
|
||||||
font_weight: styleProperties.find(p => p.property === 'font-weight') ? styleProperties.find(p => p.property === 'font-weight').value : 'normal'
|
: 'TypeWriter',
|
||||||
|
font_size: styleProperties.find((p) => p.property === 'font-size')
|
||||||
|
? Number(styleProperties.find((p) => p.property === 'font-size').value)
|
||||||
|
: 10.0,
|
||||||
|
font_weight: styleProperties.find((p) => p.property === 'font-weight')
|
||||||
|
? styleProperties.find((p) => p.property === 'font-weight').value
|
||||||
|
: 'normal',
|
||||||
};
|
};
|
||||||
font = this.fontFixer.fix(font);
|
font = this.fontFixer.fix(font);
|
||||||
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'color', styleProperties.find(p => p.property === 'fill') ? styleProperties.find(p => p.property === 'fill').value : '#000000');
|
this.renderer.setStyle(
|
||||||
|
this.temporaryTextElement.nativeElement,
|
||||||
|
'color',
|
||||||
|
styleProperties.find((p) => p.property === 'fill')
|
||||||
|
? styleProperties.find((p) => p.property === 'fill').value
|
||||||
|
: '#000000'
|
||||||
|
);
|
||||||
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'font-family', font.font_family);
|
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'font-family', font.font_family);
|
||||||
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'font-size', `${font.font_size}pt`);
|
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'font-size', `${font.font_size}pt`);
|
||||||
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'font-weight', font.font_weight);
|
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'font-weight', font.font_weight);
|
||||||
@ -148,7 +184,7 @@ export class TextEditorComponent implements OnInit, OnDestroy {
|
|||||||
let listener = () => {
|
let listener = () => {
|
||||||
let innerText = this.temporaryTextElement.nativeElement.innerText;
|
let innerText = this.temporaryTextElement.nativeElement.innerText;
|
||||||
let link: Link = this.linksDataSource.get(this.editedLink.linkId);
|
let link: Link = this.linksDataSource.get(this.editedLink.linkId);
|
||||||
link.nodes.find(n => n.node_id === this.editedNode.node_id).label.text = innerText;
|
link.nodes.find((n) => n.node_id === this.editedNode.node_id).label.text = innerText;
|
||||||
|
|
||||||
this.linkService.updateLink(this.server, link).subscribe((link: Link) => {
|
this.linkService.updateLink(this.server, link).subscribe((link: Link) => {
|
||||||
rootElement
|
rootElement
|
||||||
@ -177,7 +213,11 @@ export class TextEditorComponent implements OnInit, OnDestroy {
|
|||||||
.selectAll<SVGTextElement, TextElement>('text.text_element')
|
.selectAll<SVGTextElement, TextElement>('text.text_element')
|
||||||
.on('dblclick', (elem, index, textElements) => {
|
.on('dblclick', (elem, index, textElements) => {
|
||||||
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'display', 'initial');
|
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'display', 'initial');
|
||||||
this.renderer.setStyle(this.temporaryTextElement.nativeElement, 'transform', `scale(${this.mapScaleService.getScale()})`);
|
this.renderer.setStyle(
|
||||||
|
this.temporaryTextElement.nativeElement,
|
||||||
|
'transform',
|
||||||
|
`scale(${this.mapScaleService.getScale()})`
|
||||||
|
);
|
||||||
this.editedElement = elem;
|
this.editedElement = elem;
|
||||||
|
|
||||||
select(textElements[index]).attr('visibility', 'hidden');
|
select(textElements[index]).attr('visibility', 'hidden');
|
||||||
@ -185,8 +225,14 @@ export class TextEditorComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.editingDrawingId = textElements[index].parentElement.parentElement.getAttribute('drawing_id');
|
this.editingDrawingId = textElements[index].parentElement.parentElement.getAttribute('drawing_id');
|
||||||
var transformData = textElements[index].parentElement.getAttribute('transform').split(/\(|\)/);
|
var transformData = textElements[index].parentElement.getAttribute('transform').split(/\(|\)/);
|
||||||
var x = (Number(transformData[1].split(/,/)[0]) * this.context.transformation.k) + this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x;
|
var x =
|
||||||
var y = (Number(transformData[1].split(/,/)[1]) * this.context.transformation.k) + this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y;
|
Number(transformData[1].split(/,/)[0]) * this.context.transformation.k +
|
||||||
|
this.context.getZeroZeroTransformationPoint().x +
|
||||||
|
this.context.transformation.x;
|
||||||
|
var y =
|
||||||
|
Number(transformData[1].split(/,/)[1]) * this.context.transformation.k +
|
||||||
|
this.context.getZeroZeroTransformationPoint().y +
|
||||||
|
this.context.transformation.y;
|
||||||
this.leftPosition = x.toString() + 'px';
|
this.leftPosition = x.toString() + 'px';
|
||||||
this.topPosition = y.toString() + 'px';
|
this.topPosition = y.toString() + 'px';
|
||||||
this.temporaryTextElement.nativeElement.innerText = elem.text;
|
this.temporaryTextElement.nativeElement.innerText = elem.text;
|
||||||
|
@ -17,7 +17,9 @@ export class LinkToMapLinkConverter implements Converter<Link, MapLink> {
|
|||||||
mapLink.capturing = link.capturing;
|
mapLink.capturing = link.capturing;
|
||||||
mapLink.filters = link.filters;
|
mapLink.filters = link.filters;
|
||||||
mapLink.linkType = link.link_type;
|
mapLink.linkType = link.link_type;
|
||||||
mapLink.nodes = link.nodes.map(linkNode => this.linkNodeToMapLinkNode.convert(linkNode, { link_id: link.link_id }));
|
mapLink.nodes = link.nodes.map((linkNode) =>
|
||||||
|
this.linkNodeToMapLinkNode.convert(linkNode, { link_id: link.link_id })
|
||||||
|
);
|
||||||
mapLink.projectId = link.project_id;
|
mapLink.projectId = link.project_id;
|
||||||
mapLink.suspend = link.suspend;
|
mapLink.suspend = link.suspend;
|
||||||
return mapLink;
|
return mapLink;
|
||||||
|
@ -15,27 +15,13 @@ export class MapDrawingToSvgConverter implements Converter<MapDrawing, string> {
|
|||||||
let elem = ``;
|
let elem = ``;
|
||||||
|
|
||||||
if (mapDrawing.element instanceof RectElement) {
|
if (mapDrawing.element instanceof RectElement) {
|
||||||
elem = `<rect fill=\"${mapDrawing.element.fill}\" fill-opacity=\"${mapDrawing.element.fill_opacity}\" height=\"${
|
elem = `<rect fill=\"${mapDrawing.element.fill}\" fill-opacity=\"${mapDrawing.element.fill_opacity}\" height=\"${mapDrawing.element.height}\" width=\"${mapDrawing.element.width}\" stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${mapDrawing.element.stroke_width}\" />`;
|
||||||
mapDrawing.element.height
|
|
||||||
}\" width=\"${mapDrawing.element.width}\" stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${
|
|
||||||
mapDrawing.element.stroke_width
|
|
||||||
}\" />`;
|
|
||||||
} else if (mapDrawing.element instanceof EllipseElement) {
|
} else if (mapDrawing.element instanceof EllipseElement) {
|
||||||
elem = `<ellipse fill=\"${mapDrawing.element.fill}\" fill-opacity=\"${mapDrawing.element.fill_opacity}\" cx=\"${
|
elem = `<ellipse fill=\"${mapDrawing.element.fill}\" fill-opacity=\"${mapDrawing.element.fill_opacity}\" cx=\"${mapDrawing.element.cx}\" cy=\"${mapDrawing.element.cy}\" rx=\"${mapDrawing.element.rx}\" ry=\"${mapDrawing.element.ry}\" stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${mapDrawing.element.stroke_width}\" />`;
|
||||||
mapDrawing.element.cx
|
|
||||||
}\" cy=\"${mapDrawing.element.cy}\" rx=\"${mapDrawing.element.rx}\" ry=\"${mapDrawing.element.ry}\" stroke=\"${
|
|
||||||
mapDrawing.element.stroke
|
|
||||||
}\" stroke-width=\"${mapDrawing.element.stroke_width}\" />`;
|
|
||||||
} else if (mapDrawing.element instanceof LineElement) {
|
} else if (mapDrawing.element instanceof LineElement) {
|
||||||
elem = `<line stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${mapDrawing.element.stroke_width}\" x1=\"${
|
elem = `<line stroke=\"${mapDrawing.element.stroke}\" stroke-width=\"${mapDrawing.element.stroke_width}\" x1=\"${mapDrawing.element.x1}\" x2=\"${mapDrawing.element.x2}\" y1=\"${mapDrawing.element.y1}\" y2=\"${mapDrawing.element.y2}\" />`;
|
||||||
mapDrawing.element.x1
|
|
||||||
}\" x2=\"${mapDrawing.element.x2}\" y1=\"${mapDrawing.element.y1}\" y2=\"${mapDrawing.element.y2}\" />`;
|
|
||||||
} else if (mapDrawing.element instanceof TextElement) {
|
} else if (mapDrawing.element instanceof TextElement) {
|
||||||
elem = `<text fill=\"${mapDrawing.element.fill}\" fill-opacity=\"1.0\" font-family=\"${
|
elem = `<text fill=\"${mapDrawing.element.fill}\" fill-opacity=\"1.0\" font-family=\"${mapDrawing.element.font_family}\" font-size=\"${mapDrawing.element.font_size}\" font-weight=\"${mapDrawing.element.font_weight}\">${mapDrawing.element.text}</text>`;
|
||||||
mapDrawing.element.font_family
|
|
||||||
}\" font-size=\"${mapDrawing.element.font_size}\" font-weight=\"${mapDrawing.element.font_weight}\">${
|
|
||||||
mapDrawing.element.text
|
|
||||||
}</text>`;
|
|
||||||
} else return '';
|
} else return '';
|
||||||
|
|
||||||
return `<svg height=\"${mapDrawing.element.height}\" width=\"${mapDrawing.element.width}\">${elem}</svg>`;
|
return `<svg height=\"${mapDrawing.element.height}\" width=\"${mapDrawing.element.width}\">${elem}</svg>`;
|
||||||
|
@ -17,7 +17,7 @@ export class MapLinkToLinkConverter implements Converter<MapLink, Link> {
|
|||||||
link.capturing = mapLink.capturing;
|
link.capturing = mapLink.capturing;
|
||||||
link.filters = mapLink.filters;
|
link.filters = mapLink.filters;
|
||||||
link.link_type = mapLink.linkType;
|
link.link_type = mapLink.linkType;
|
||||||
link.nodes = mapLink.nodes.map(mapLinkNode => this.mapLinkNodeToMapLinkNode.convert(mapLinkNode));
|
link.nodes = mapLink.nodes.map((mapLinkNode) => this.mapLinkNodeToMapLinkNode.convert(mapLinkNode));
|
||||||
link.project_id = mapLink.projectId;
|
link.project_id = mapLink.projectId;
|
||||||
link.suspend = mapLink.suspend;
|
link.suspend = mapLink.suspend;
|
||||||
return link;
|
return link;
|
||||||
|
@ -27,7 +27,7 @@ export class MapNodeToNodeConverter implements Converter<MapNode, Node> {
|
|||||||
node.node_type = mapNode.nodeType;
|
node.node_type = mapNode.nodeType;
|
||||||
node.port_name_format = mapNode.portNameFormat;
|
node.port_name_format = mapNode.portNameFormat;
|
||||||
node.port_segment_size = mapNode.portSegmentSize;
|
node.port_segment_size = mapNode.portSegmentSize;
|
||||||
node.ports = mapNode.ports ? mapNode.ports.map(mapPort => this.mapPortToPort.convert(mapPort)) : [];
|
node.ports = mapNode.ports ? mapNode.ports.map((mapPort) => this.mapPortToPort.convert(mapPort)) : [];
|
||||||
node.project_id = mapNode.projectId;
|
node.project_id = mapNode.projectId;
|
||||||
node.status = mapNode.status;
|
node.status = mapNode.status;
|
||||||
node.symbol = mapNode.symbol;
|
node.symbol = mapNode.symbol;
|
||||||
|
@ -29,14 +29,16 @@ export class NodeToMapNodeConverter implements Converter<Node, MapNode> {
|
|||||||
mapNode.consoleType = node.console_type;
|
mapNode.consoleType = node.console_type;
|
||||||
mapNode.firstPortName = node.first_port_name;
|
mapNode.firstPortName = node.first_port_name;
|
||||||
mapNode.height = node.height;
|
mapNode.height = node.height;
|
||||||
mapNode.label = this.labelToMapLabel ? this.labelToMapLabel.convert(node.label, { node_id: node.node_id }) : undefined;
|
mapNode.label = this.labelToMapLabel
|
||||||
|
? this.labelToMapLabel.convert(node.label, { node_id: node.node_id })
|
||||||
|
: undefined;
|
||||||
mapNode.locked = node.locked;
|
mapNode.locked = node.locked;
|
||||||
mapNode.name = node.name;
|
mapNode.name = node.name;
|
||||||
mapNode.nodeDirectory = node.node_directory;
|
mapNode.nodeDirectory = node.node_directory;
|
||||||
mapNode.nodeType = node.node_type;
|
mapNode.nodeType = node.node_type;
|
||||||
mapNode.portNameFormat = node.port_name_format;
|
mapNode.portNameFormat = node.port_name_format;
|
||||||
mapNode.portSegmentSize = node.port_segment_size;
|
mapNode.portSegmentSize = node.port_segment_size;
|
||||||
mapNode.ports = node.ports ? node.ports.map(port => this.portToMapPort.convert(port)) : [];
|
mapNode.ports = node.ports ? node.ports.map((port) => this.portToMapPort.convert(port)) : [];
|
||||||
mapNode.projectId = node.project_id;
|
mapNode.projectId = node.project_id;
|
||||||
mapNode.status = node.status;
|
mapNode.status = node.status;
|
||||||
mapNode.symbol = node.symbol;
|
mapNode.symbol = node.symbol;
|
||||||
|
@ -14,7 +14,7 @@ describe('StylesToFontConverter', () => {
|
|||||||
const expectedFont: Font = {
|
const expectedFont: Font = {
|
||||||
font_family: 'TypeWriter',
|
font_family: 'TypeWriter',
|
||||||
font_size: 10,
|
font_size: 10,
|
||||||
font_weight: 'bold'
|
font_weight: 'bold',
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(converter.convert(styles)).toEqual(expectedFont);
|
expect(converter.convert(styles)).toEqual(expectedFont);
|
||||||
|
@ -10,30 +10,30 @@ export class StylesToFontConverter implements Converter<string, Font> {
|
|||||||
const font: Font = {
|
const font: Font = {
|
||||||
font_family: undefined,
|
font_family: undefined,
|
||||||
font_size: undefined,
|
font_size: undefined,
|
||||||
font_weight: undefined
|
font_weight: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ast = csstree.parse(styles, {
|
const ast = csstree.parse(styles, {
|
||||||
context: 'declarationList'
|
context: 'declarationList',
|
||||||
});
|
});
|
||||||
|
|
||||||
ast.children.forEach(child => {
|
ast.children.forEach((child) => {
|
||||||
if (child.property === 'font-size' && child.value && child.value.children) {
|
if (child.property === 'font-size' && child.value && child.value.children) {
|
||||||
child.value.children.forEach(value => {
|
child.value.children.forEach((value) => {
|
||||||
if (value.type === 'Dimension') {
|
if (value.type === 'Dimension') {
|
||||||
font.font_size = parseInt(value.value);
|
font.font_size = parseInt(value.value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (child.property === 'font-family' && child.value && child.value.children) {
|
if (child.property === 'font-family' && child.value && child.value.children) {
|
||||||
child.value.children.forEach(value => {
|
child.value.children.forEach((value) => {
|
||||||
if (value.type === 'Identifier') {
|
if (value.type === 'Identifier') {
|
||||||
font.font_family = value.name;
|
font.font_family = value.name;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (child.property === 'font-weight' && child.value && child.value.children) {
|
if (child.property === 'font-weight' && child.value && child.value.children) {
|
||||||
child.value.children.forEach(value => {
|
child.value.children.forEach((value) => {
|
||||||
if (value.type === 'Identifier') {
|
if (value.type === 'Identifier') {
|
||||||
font.font_weight = value.name;
|
font.font_weight = value.name;
|
||||||
}
|
}
|
||||||
|
@ -37,5 +37,5 @@ export const D3_MAP_IMPORTS = [
|
|||||||
LineDrawingWidget,
|
LineDrawingWidget,
|
||||||
RectDrawingWidget,
|
RectDrawingWidget,
|
||||||
TextDrawingWidget,
|
TextDrawingWidget,
|
||||||
DrawingWidget
|
DrawingWidget,
|
||||||
];
|
];
|
||||||
|
@ -20,7 +20,7 @@ export abstract class DataSource<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public set(data: T[]) {
|
public set(data: T[]) {
|
||||||
data.forEach(item => {
|
data.forEach((item) => {
|
||||||
const index = this.findIndex(item);
|
const index = this.findIndex(item);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
const updated = Object.assign(this.data[index], item);
|
const updated = Object.assign(this.data[index], item);
|
||||||
@ -31,9 +31,9 @@ export abstract class DataSource<T> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const toRemove = this.data.filter(
|
const toRemove = this.data.filter(
|
||||||
item => data.filter(i => this.getItemKey(i) === this.getItemKey(item)).length === 0
|
(item) => data.filter((i) => this.getItemKey(i) === this.getItemKey(item)).length === 0
|
||||||
);
|
);
|
||||||
toRemove.forEach(item => this.remove(item));
|
toRemove.forEach((item) => this.remove(item));
|
||||||
|
|
||||||
this.dataChange.next(this.data);
|
this.dataChange.next(this.data);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,9 @@ import { MovingCanvasDirective } from './moving-canvas.directive';
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `<svg #svg class="map" preserveAspectRatio="none" movingCanvas><g class="canvas" transform="translate(0, 0) scale(1)"></g></svg>`
|
template: `<svg #svg class="map" preserveAspectRatio="none" movingCanvas>
|
||||||
|
<g class="canvas" transform="translate(0, 0) scale(1)"></g>
|
||||||
|
</svg>`,
|
||||||
})
|
})
|
||||||
class DummyComponent {
|
class DummyComponent {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
@ -22,9 +24,9 @@ describe('MovingCanvasDirective', () => {
|
|||||||
imports: [NoopAnimationsModule],
|
imports: [NoopAnimationsModule],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: MovingEventSource, useValue: movingEventSource },
|
{ provide: MovingEventSource, useValue: movingEventSource },
|
||||||
{ provide: Context, useClass: Context }
|
{ provide: Context, useClass: Context },
|
||||||
],
|
],
|
||||||
declarations: [DummyComponent, MovingCanvasDirective]
|
declarations: [DummyComponent, MovingCanvasDirective],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -44,21 +46,25 @@ describe('MovingCanvasDirective', () => {
|
|||||||
let xMovement: number = 200;
|
let xMovement: number = 200;
|
||||||
let yMovement: number = 200;
|
let yMovement: number = 200;
|
||||||
|
|
||||||
canvas.dispatchEvent(new MouseEvent('mousedown', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mousedown', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
clientX: 0,
|
clientX: 0,
|
||||||
clientY: 0,
|
clientY: 0,
|
||||||
screenY: 0,
|
screenY: 0,
|
||||||
screenX: 0,
|
screenX: 0,
|
||||||
view: window
|
view: window,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
canvas.dispatchEvent(new MouseEvent('mousemove', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mousemove', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
movementX: xMovement,
|
movementX: xMovement,
|
||||||
movementY: yMovement
|
movementY: yMovement,
|
||||||
} as MouseEventInit));
|
} as MouseEventInit)
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual(`translate(${xMovement}, ${yMovement}) scale(1)`);
|
expect(canvas.getAttribute('transform')).toEqual(`translate(${xMovement}, ${yMovement}) scale(1)`);
|
||||||
@ -67,21 +73,25 @@ describe('MovingCanvasDirective', () => {
|
|||||||
it('should not move canvas if moving mode is not activated', fakeAsync(() => {
|
it('should not move canvas if moving mode is not activated', fakeAsync(() => {
|
||||||
const canvas: HTMLElement = fixture.debugElement.nativeElement.querySelector('.canvas');
|
const canvas: HTMLElement = fixture.debugElement.nativeElement.querySelector('.canvas');
|
||||||
|
|
||||||
canvas.dispatchEvent(new MouseEvent('mousedown', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mousedown', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
clientX: 0,
|
clientX: 0,
|
||||||
clientY: 0,
|
clientY: 0,
|
||||||
screenY: 0,
|
screenY: 0,
|
||||||
screenX: 0,
|
screenX: 0,
|
||||||
view: window
|
view: window,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
canvas.dispatchEvent(new MouseEvent('mousemove', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mousemove', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
movementX: 1000,
|
movementX: 1000,
|
||||||
movementY: 1000
|
movementY: 1000,
|
||||||
} as MouseEventInit));
|
} as MouseEventInit)
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual('translate(0, 0) scale(1)');
|
expect(canvas.getAttribute('transform')).toEqual('translate(0, 0) scale(1)');
|
||||||
@ -93,38 +103,46 @@ describe('MovingCanvasDirective', () => {
|
|||||||
let xMovement: number = 200;
|
let xMovement: number = 200;
|
||||||
let yMovement: number = 200;
|
let yMovement: number = 200;
|
||||||
|
|
||||||
canvas.dispatchEvent(new MouseEvent('mousedown', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mousedown', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
clientX: 0,
|
clientX: 0,
|
||||||
clientY: 0,
|
clientY: 0,
|
||||||
screenY: 0,
|
screenY: 0,
|
||||||
screenX: 0,
|
screenX: 0,
|
||||||
view: window
|
view: window,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
canvas.dispatchEvent(new MouseEvent('mousemove', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mousemove', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
movementX: xMovement,
|
movementX: xMovement,
|
||||||
movementY: yMovement
|
movementY: yMovement,
|
||||||
} as MouseEventInit));
|
} as MouseEventInit)
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual(`translate(${xMovement}, ${yMovement}) scale(1)`);
|
expect(canvas.getAttribute('transform')).toEqual(`translate(${xMovement}, ${yMovement}) scale(1)`);
|
||||||
|
|
||||||
canvas.dispatchEvent(new MouseEvent('mouseup', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mouseup', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
movementX: 1000,
|
movementX: 1000,
|
||||||
movementY: 1000
|
movementY: 1000,
|
||||||
} as MouseEventInit));
|
} as MouseEventInit)
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
canvas.dispatchEvent(new MouseEvent('mousemove', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mousemove', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
movementX: xMovement,
|
movementX: xMovement,
|
||||||
movementY: yMovement
|
movementY: yMovement,
|
||||||
} as MouseEventInit));
|
} as MouseEventInit)
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual(`translate(${xMovement}, ${yMovement}) scale(1)`);
|
expect(canvas.getAttribute('transform')).toEqual(`translate(${xMovement}, ${yMovement}) scale(1)`);
|
||||||
@ -136,32 +154,38 @@ describe('MovingCanvasDirective', () => {
|
|||||||
let xMovement: number = 200;
|
let xMovement: number = 200;
|
||||||
let yMovement: number = 200;
|
let yMovement: number = 200;
|
||||||
|
|
||||||
canvas.dispatchEvent(new MouseEvent('mousedown', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mousedown', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
clientX: 0,
|
clientX: 0,
|
||||||
clientY: 0,
|
clientY: 0,
|
||||||
screenY: 0,
|
screenY: 0,
|
||||||
screenX: 0,
|
screenX: 0,
|
||||||
view: window
|
view: window,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
canvas.dispatchEvent(new MouseEvent('mousemove', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mousemove', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
movementX: xMovement,
|
movementX: xMovement,
|
||||||
movementY: yMovement
|
movementY: yMovement,
|
||||||
} as MouseEventInit));
|
} as MouseEventInit)
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual(`translate(${xMovement}, ${yMovement}) scale(1)`);
|
expect(canvas.getAttribute('transform')).toEqual(`translate(${xMovement}, ${yMovement}) scale(1)`);
|
||||||
|
|
||||||
movingEventSource.movingModeState.emit(false);
|
movingEventSource.movingModeState.emit(false);
|
||||||
canvas.dispatchEvent(new MouseEvent('mousemove', {
|
canvas.dispatchEvent(
|
||||||
|
new MouseEvent('mousemove', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
movementX: 1000,
|
movementX: 1000,
|
||||||
movementY: 1000
|
movementY: 1000,
|
||||||
} as MouseEventInit));
|
} as MouseEventInit)
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual(`translate(${xMovement}, ${yMovement}) scale(1)`);
|
expect(canvas.getAttribute('transform')).toEqual(`translate(${xMovement}, ${yMovement}) scale(1)`);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { HostListener, ElementRef, Directive, Input, OnInit, OnDestroy, Renderer2 } from '@angular/core'
|
import { HostListener, ElementRef, Directive, Input, OnInit, OnDestroy, Renderer2 } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { MovingEventSource } from '../events/moving-event-source';
|
import { MovingEventSource } from '../events/moving-event-source';
|
||||||
import { Context } from '../models/context';
|
import { Context } from '../models/context';
|
||||||
@ -13,11 +13,7 @@ export class MovingCanvasDirective implements OnInit, OnDestroy {
|
|||||||
private movingModeState: Subscription;
|
private movingModeState: Subscription;
|
||||||
private activated: boolean = false;
|
private activated: boolean = false;
|
||||||
|
|
||||||
constructor(
|
constructor(private element: ElementRef, private movingEventSource: MovingEventSource, private context: Context) {}
|
||||||
private element: ElementRef,
|
|
||||||
private movingEventSource: MovingEventSource,
|
|
||||||
private context: Context
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.movingModeState = this.movingEventSource.movingModeState.subscribe((event: boolean) => {
|
this.movingModeState = this.movingEventSource.movingModeState.subscribe((event: boolean) => {
|
||||||
@ -53,13 +49,25 @@ export class MovingCanvasDirective implements OnInit, OnDestroy {
|
|||||||
this.removelisteners();
|
this.removelisteners();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.element.nativeElement.addEventListener('mouseup', this.mouseupListener as EventListenerOrEventListenerObject);
|
this.element.nativeElement.addEventListener(
|
||||||
this.element.nativeElement.addEventListener('mousemove', this.mousemoveListener as EventListenerOrEventListenerObject);
|
'mouseup',
|
||||||
|
this.mouseupListener as EventListenerOrEventListenerObject
|
||||||
|
);
|
||||||
|
this.element.nativeElement.addEventListener(
|
||||||
|
'mousemove',
|
||||||
|
this.mousemoveListener as EventListenerOrEventListenerObject
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removelisteners() {
|
removelisteners() {
|
||||||
this.element.nativeElement.removeEventListener('mouseup', this.mouseupListener as EventListenerOrEventListenerObject);
|
this.element.nativeElement.removeEventListener(
|
||||||
this.element.nativeElement.removeEventListener('mousemove', this.mousemoveListener as EventListenerOrEventListenerObject);
|
'mouseup',
|
||||||
|
this.mouseupListener as EventListenerOrEventListenerObject
|
||||||
|
);
|
||||||
|
this.element.nativeElement.removeEventListener(
|
||||||
|
'mousemove',
|
||||||
|
this.mousemoveListener as EventListenerOrEventListenerObject
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,9 @@ import { ZoomingCanvasDirective } from './zooming-canvas.directive';
|
|||||||
import { MapScaleService } from '../../services/mapScale.service';
|
import { MapScaleService } from '../../services/mapScale.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `<svg #svg class="map" preserveAspectRatio="none" zoomingCanvas><g class="canvas" transform="translate(0, 0) scale(1)"></g></svg>`
|
template: `<svg #svg class="map" preserveAspectRatio="none" zoomingCanvas>
|
||||||
|
<g class="canvas" transform="translate(0, 0) scale(1)"></g>
|
||||||
|
</svg>`,
|
||||||
})
|
})
|
||||||
class DummyComponent {
|
class DummyComponent {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
@ -24,9 +26,9 @@ describe('ZoomingCanvasDirective', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: MovingEventSource, useValue: movingEventSource },
|
{ provide: MovingEventSource, useValue: movingEventSource },
|
||||||
{ provide: Context, useClass: Context },
|
{ provide: Context, useClass: Context },
|
||||||
{ provide: MapScaleService, useClass: MapScaleService }
|
{ provide: MapScaleService, useClass: MapScaleService },
|
||||||
],
|
],
|
||||||
declarations: [DummyComponent, ZoomingCanvasDirective]
|
declarations: [DummyComponent, ZoomingCanvasDirective],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -46,12 +48,14 @@ describe('ZoomingCanvasDirective', () => {
|
|||||||
let deltaMode: number = 0;
|
let deltaMode: number = 0;
|
||||||
let zoom: number = -1000;
|
let zoom: number = -1000;
|
||||||
|
|
||||||
canvas.dispatchEvent(new WheelEvent('wheel', {
|
canvas.dispatchEvent(
|
||||||
|
new WheelEvent('wheel', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
deltaMode: deltaMode,
|
deltaMode: deltaMode,
|
||||||
deltaY: zoom
|
deltaY: zoom,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual(`translate(0, 0) scale(2)`);
|
expect(canvas.getAttribute('transform')).toEqual(`translate(0, 0) scale(2)`);
|
||||||
@ -63,12 +67,14 @@ describe('ZoomingCanvasDirective', () => {
|
|||||||
let deltaMode: number = 0;
|
let deltaMode: number = 0;
|
||||||
let zoom: number = 100;
|
let zoom: number = 100;
|
||||||
|
|
||||||
canvas.dispatchEvent(new WheelEvent('wheel', {
|
canvas.dispatchEvent(
|
||||||
|
new WheelEvent('wheel', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
deltaMode: deltaMode,
|
deltaMode: deltaMode,
|
||||||
deltaY: zoom
|
deltaY: zoom,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual(`translate(0, 0) scale(0.9)`);
|
expect(canvas.getAttribute('transform')).toEqual(`translate(0, 0) scale(0.9)`);
|
||||||
@ -80,23 +86,27 @@ describe('ZoomingCanvasDirective', () => {
|
|||||||
let deltaMode: number = 0;
|
let deltaMode: number = 0;
|
||||||
let zoom: number = -1000;
|
let zoom: number = -1000;
|
||||||
|
|
||||||
canvas.dispatchEvent(new WheelEvent('wheel', {
|
canvas.dispatchEvent(
|
||||||
|
new WheelEvent('wheel', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
deltaMode: deltaMode,
|
deltaMode: deltaMode,
|
||||||
deltaY: zoom
|
deltaY: zoom,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual(`translate(0, 0) scale(2)`);
|
expect(canvas.getAttribute('transform')).toEqual(`translate(0, 0) scale(2)`);
|
||||||
|
|
||||||
movingEventSource.movingModeState.emit(false);
|
movingEventSource.movingModeState.emit(false);
|
||||||
canvas.dispatchEvent(new WheelEvent('wheel', {
|
canvas.dispatchEvent(
|
||||||
|
new WheelEvent('wheel', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
deltaMode: deltaMode,
|
deltaMode: deltaMode,
|
||||||
deltaY: zoom
|
deltaY: zoom,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual(`translate(0, 0) scale(2)`);
|
expect(canvas.getAttribute('transform')).toEqual(`translate(0, 0) scale(2)`);
|
||||||
@ -107,12 +117,14 @@ describe('ZoomingCanvasDirective', () => {
|
|||||||
let deltaMode: number = 0;
|
let deltaMode: number = 0;
|
||||||
let zoom: number = -1000;
|
let zoom: number = -1000;
|
||||||
|
|
||||||
canvas.dispatchEvent(new WheelEvent('wheel', {
|
canvas.dispatchEvent(
|
||||||
|
new WheelEvent('wheel', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
deltaMode: deltaMode,
|
deltaMode: deltaMode,
|
||||||
deltaY: zoom
|
deltaY: zoom,
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(canvas.getAttribute('transform')).toEqual(`translate(0, 0) scale(1)`);
|
expect(canvas.getAttribute('transform')).toEqual(`translate(0, 0) scale(1)`);
|
||||||
@ -127,7 +139,7 @@ describe('ZoomingCanvasDirective', () => {
|
|||||||
bubbles: true,
|
bubbles: true,
|
||||||
relatedTarget: canvas,
|
relatedTarget: canvas,
|
||||||
deltaMode: deltaMode,
|
deltaMode: deltaMode,
|
||||||
deltaY: zoom
|
deltaY: zoom,
|
||||||
});
|
});
|
||||||
spyOn(event, 'preventDefault');
|
spyOn(event, 'preventDefault');
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ElementRef, Directive, OnInit, OnDestroy } from '@angular/core'
|
import { ElementRef, Directive, OnInit, OnDestroy } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { MovingEventSource } from '../events/moving-event-source';
|
import { MovingEventSource } from '../events/moving-event-source';
|
||||||
import { Context } from '../models/context';
|
import { Context } from '../models/context';
|
||||||
@ -52,7 +52,9 @@ export class ZoomingCanvasDirective implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.element.nativeElement.addEventListener('wheel', this.wheelListener as EventListenerOrEventListenerObject, {passive: false});
|
this.element.nativeElement.addEventListener('wheel', this.wheelListener as EventListenerOrEventListenerObject, {
|
||||||
|
passive: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeListener() {
|
removeListener() {
|
||||||
|
@ -4,7 +4,7 @@ import {
|
|||||||
ResizedDataEvent,
|
ResizedDataEvent,
|
||||||
TextAddedDataEvent,
|
TextAddedDataEvent,
|
||||||
TextEditedDataEvent,
|
TextEditedDataEvent,
|
||||||
AddedDataEvent
|
AddedDataEvent,
|
||||||
} from './event-source';
|
} from './event-source';
|
||||||
import { MapDrawing } from '../models/map/map-drawing';
|
import { MapDrawing } from '../models/map/map-drawing';
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Injectable, EventEmitter } from "@angular/core";
|
import { Injectable, EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MovingEventSource {
|
export class MovingEventSource {
|
||||||
|
@ -6,13 +6,13 @@ import { Injectable } from '@angular/core';
|
|||||||
export class CssFixer {
|
export class CssFixer {
|
||||||
public fix(styles: string): string {
|
public fix(styles: string): string {
|
||||||
const ast = csstree.parse(styles, {
|
const ast = csstree.parse(styles, {
|
||||||
context: 'declarationList'
|
context: 'declarationList',
|
||||||
});
|
});
|
||||||
|
|
||||||
// fixes font-size when unit (pt|px) is not defined
|
// fixes font-size when unit (pt|px) is not defined
|
||||||
ast.children.forEach(child => {
|
ast.children.forEach((child) => {
|
||||||
if (child.property === 'font-size' && child.value && child.value.children) {
|
if (child.property === 'font-size' && child.value && child.value.children) {
|
||||||
child.value.children.forEach(value => {
|
child.value.children.forEach((value) => {
|
||||||
if (value.type === 'Number') {
|
if (value.type === 'Number') {
|
||||||
const fontSize = value.value.toString();
|
const fontSize = value.value.toString();
|
||||||
if (!(fontSize.indexOf('pt') >= 0 || fontSize.indexOf('px') >= 0)) {
|
if (!(fontSize.indexOf('pt') >= 0 || fontSize.indexOf('px') >= 0)) {
|
||||||
|
@ -21,7 +21,7 @@ export class DefaultDrawingsFactory {
|
|||||||
text: this.textElementFactory,
|
text: this.textElementFactory,
|
||||||
ellipse: this.ellipseElementFactory,
|
ellipse: this.ellipseElementFactory,
|
||||||
rectangle: this.rectangleElementFactory,
|
rectangle: this.rectangleElementFactory,
|
||||||
line: this.lineElementFactory
|
line: this.lineElementFactory,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ export class FontBBoxCalculator {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
width: bbox.width,
|
width: bbox.width,
|
||||||
height: bbox.height
|
height: bbox.height,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,13 @@ describe('FontFixer', () => {
|
|||||||
const font: Font = {
|
const font: Font = {
|
||||||
font_family: 'TypeWriter',
|
font_family: 'TypeWriter',
|
||||||
font_size: 10,
|
font_size: 10,
|
||||||
font_weight: 'bold'
|
font_weight: 'bold',
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(fixer.fix(font)).toEqual({
|
expect(fixer.fix(font)).toEqual({
|
||||||
font_family: 'Noto Sans',
|
font_family: 'Noto Sans',
|
||||||
font_size: 11,
|
font_size: 11,
|
||||||
font_weight: 'bold'
|
font_weight: 'bold',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -26,13 +26,13 @@ describe('FontFixer', () => {
|
|||||||
const font: Font = {
|
const font: Font = {
|
||||||
font_family: 'OtherFont',
|
font_family: 'OtherFont',
|
||||||
font_size: 11,
|
font_size: 11,
|
||||||
font_weight: 'bold'
|
font_weight: 'bold',
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(fixer.fix(font)).toEqual({
|
expect(fixer.fix(font)).toEqual({
|
||||||
font_family: 'OtherFont',
|
font_family: 'OtherFont',
|
||||||
font_size: 11,
|
font_size: 11,
|
||||||
font_weight: 'bold'
|
font_weight: 'bold',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -22,16 +22,16 @@ export class FontFixer {
|
|||||||
|
|
||||||
public fixStyles(styles: string) {
|
public fixStyles(styles: string) {
|
||||||
const ast = csstree.parse(styles, {
|
const ast = csstree.parse(styles, {
|
||||||
context: 'declarationList'
|
context: 'declarationList',
|
||||||
});
|
});
|
||||||
|
|
||||||
let fontFamilyPointer = null;
|
let fontFamilyPointer = null;
|
||||||
let fontSizePointer = null;
|
let fontSizePointer = null;
|
||||||
let isByIdentifier = true;
|
let isByIdentifier = true;
|
||||||
|
|
||||||
ast.children.forEach(child => {
|
ast.children.forEach((child) => {
|
||||||
if (child.property === 'font-family' && child.value && child.value.children) {
|
if (child.property === 'font-family' && child.value && child.value.children) {
|
||||||
child.value.children.forEach(value => {
|
child.value.children.forEach((value) => {
|
||||||
if (value.type === 'Identifier') {
|
if (value.type === 'Identifier') {
|
||||||
fontFamilyPointer = value;
|
fontFamilyPointer = value;
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ export class FontFixer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (child.property === 'font-size' && child.value && child.value.children) {
|
if (child.property === 'font-size' && child.value && child.value.children) {
|
||||||
child.value.children.forEach(value => {
|
child.value.children.forEach((value) => {
|
||||||
if (value.type === 'Dimension') {
|
if (value.type === 'Dimension') {
|
||||||
fontSizePointer = value;
|
fontSizePointer = value;
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ export class FontFixer {
|
|||||||
|
|
||||||
const fixedFont = this.fix({
|
const fixedFont = this.fix({
|
||||||
font_family: fontFamilyValue.split('"').join(''),
|
font_family: fontFamilyValue.split('"').join(''),
|
||||||
font_size: parseInt(fontSizeValue, 10)
|
font_size: parseInt(fontSizeValue, 10),
|
||||||
} as Font);
|
} as Font);
|
||||||
|
|
||||||
if (isByIdentifier) {
|
if (isByIdentifier) {
|
||||||
|
@ -25,7 +25,7 @@ export class MultiLinkCalculatorHelper {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
dx: x2_x0,
|
dx: x2_x0,
|
||||||
dy: y2_y0
|
dy: y2_y0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ export class QtDasharrayFixer {
|
|||||||
'25, 25': '10, 2',
|
'25, 25': '10, 2',
|
||||||
'5, 25': '4, 2',
|
'5, 25': '4, 2',
|
||||||
'5, 25, 25': '5, 5, 1, 5',
|
'5, 25, 25': '5, 5, 1, 5',
|
||||||
'25, 25, 5, 25, 5': '5, 2, 5, 2, 5'
|
'25, 25, 5, 25, 5': '5, 2, 5, 2, 5',
|
||||||
};
|
};
|
||||||
|
|
||||||
public fix(dasharray: string): string {
|
public fix(dasharray: string): string {
|
||||||
|
@ -19,7 +19,7 @@ export class SvgToDrawingConverter {
|
|||||||
image: new ImageConverter(),
|
image: new ImageConverter(),
|
||||||
rect: new RectConverter(),
|
rect: new RectConverter(),
|
||||||
line: new LineConverter(),
|
line: new LineConverter(),
|
||||||
ellipse: new EllipseConverter()
|
ellipse: new EllipseConverter(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
MapNodesDataSource,
|
MapNodesDataSource,
|
||||||
MapLinksDataSource,
|
MapLinksDataSource,
|
||||||
MapDrawingsDataSource,
|
MapDrawingsDataSource,
|
||||||
MapSymbolsDataSource
|
MapSymbolsDataSource,
|
||||||
} from '../datasources/map-datasource';
|
} from '../datasources/map-datasource';
|
||||||
import { MultiLinkCalculatorHelper } from '../helpers/multi-link-calculator-helper';
|
import { MultiLinkCalculatorHelper } from '../helpers/multi-link-calculator-helper';
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ export class GraphDataManager {
|
|||||||
|
|
||||||
public setNodes(nodes: Node[]) {
|
public setNodes(nodes: Node[]) {
|
||||||
if (nodes) {
|
if (nodes) {
|
||||||
const mapNodes = nodes.map(n => this.nodeToMapNode.convert(n));
|
const mapNodes = nodes.map((n) => this.nodeToMapNode.convert(n));
|
||||||
this.mapNodesDataSource.set(mapNodes);
|
this.mapNodesDataSource.set(mapNodes);
|
||||||
|
|
||||||
this.assignDataToLinks();
|
this.assignDataToLinks();
|
||||||
@ -45,7 +45,7 @@ export class GraphDataManager {
|
|||||||
|
|
||||||
public setLinks(links: Link[]) {
|
public setLinks(links: Link[]) {
|
||||||
if (links) {
|
if (links) {
|
||||||
const mapLinks = links.map(l => this.linkToMapLink.convert(l));
|
const mapLinks = links.map((l) => this.linkToMapLink.convert(l));
|
||||||
this.mapLinksDataSource.set(mapLinks);
|
this.mapLinksDataSource.set(mapLinks);
|
||||||
|
|
||||||
this.assignDataToLinks();
|
this.assignDataToLinks();
|
||||||
@ -55,7 +55,7 @@ export class GraphDataManager {
|
|||||||
|
|
||||||
public setDrawings(drawings: Drawing[]) {
|
public setDrawings(drawings: Drawing[]) {
|
||||||
if (drawings) {
|
if (drawings) {
|
||||||
const mapDrawings = drawings.map(d => this.drawingToMapDrawing.convert(d));
|
const mapDrawings = drawings.map((d) => this.drawingToMapDrawing.convert(d));
|
||||||
this.mapDrawingsDataSource.set(mapDrawings);
|
this.mapDrawingsDataSource.set(mapDrawings);
|
||||||
|
|
||||||
this.onDataUpdate();
|
this.onDataUpdate();
|
||||||
@ -64,7 +64,7 @@ export class GraphDataManager {
|
|||||||
|
|
||||||
public setSymbols(symbols: Symbol[]) {
|
public setSymbols(symbols: Symbol[]) {
|
||||||
if (symbols) {
|
if (symbols) {
|
||||||
const mapSymbols = symbols.map(s => this.symbolToMapSymbol.convert(s));
|
const mapSymbols = symbols.map((s) => this.symbolToMapSymbol.convert(s));
|
||||||
this.mapSymbolsDataSource.set(mapSymbols);
|
this.mapSymbolsDataSource.set(mapSymbols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,16 +13,16 @@ export class SelectionManager {
|
|||||||
const dictItems = this.convertToKeyDict(items);
|
const dictItems = this.convertToKeyDict(items);
|
||||||
|
|
||||||
const selected = Object.keys(dictItems)
|
const selected = Object.keys(dictItems)
|
||||||
.filter(key => {
|
.filter((key) => {
|
||||||
return !this.isSelectedByKey(key);
|
return !this.isSelectedByKey(key);
|
||||||
})
|
})
|
||||||
.map(key => dictItems[key]);
|
.map((key) => dictItems[key]);
|
||||||
|
|
||||||
const unselected = Object.keys(this.selection)
|
const unselected = Object.keys(this.selection)
|
||||||
.filter(key => {
|
.filter((key) => {
|
||||||
return !(key in dictItems);
|
return !(key in dictItems);
|
||||||
})
|
})
|
||||||
.map(key => this.selection[key]);
|
.map((key) => this.selection[key]);
|
||||||
|
|
||||||
this.selection = dictItems;
|
this.selection = dictItems;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ export class SelectionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getSelected(): Indexed[] {
|
public getSelected(): Indexed[] {
|
||||||
return Object.keys(this.selection).map(key => this.selection[key]);
|
return Object.keys(this.selection).map((key) => this.selection[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public isSelected(item): boolean {
|
public isSelected(item): boolean {
|
||||||
@ -55,7 +55,7 @@ export class SelectionManager {
|
|||||||
|
|
||||||
private convertToKeyDict(items: Indexed[]) {
|
private convertToKeyDict(items: Indexed[]) {
|
||||||
const dict = {};
|
const dict = {};
|
||||||
items.forEach(item => {
|
items.forEach((item) => {
|
||||||
dict[this.getKey(item)] = item;
|
dict[this.getKey(item)] = item;
|
||||||
});
|
});
|
||||||
return dict;
|
return dict;
|
||||||
|
@ -9,17 +9,12 @@ export class TestSVGCanvas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public create() {
|
public create() {
|
||||||
this.svg = select('body')
|
this.svg = select('body').append<SVGSVGElement>('svg').attr('width', 1000).attr('height', 1000);
|
||||||
.append<SVGSVGElement>('svg')
|
|
||||||
.attr('width', 1000)
|
|
||||||
.attr('height', 1000);
|
|
||||||
|
|
||||||
this.canvas = this.svg.append<SVGGElement>('g').attr('class', 'canvas');
|
this.canvas = this.svg.append<SVGGElement>('g').attr('class', 'canvas');
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroy() {
|
public destroy() {
|
||||||
select('body')
|
select('body').selectAll('svg').remove();
|
||||||
.selectAll('svg')
|
|
||||||
.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,7 @@ describe('MovingTool', () => {
|
|||||||
tool = new MovingTool(context);
|
tool = new MovingTool(context);
|
||||||
svg = new TestSVGCanvas();
|
svg = new TestSVGCanvas();
|
||||||
|
|
||||||
node = svg.canvas
|
node = svg.canvas.append<SVGGElement>('g').attr('class', 'node').attr('x', 10).attr('y', 20);
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.attr('class', 'node')
|
|
||||||
.attr('x', 10)
|
|
||||||
.attr('y', 20);
|
|
||||||
|
|
||||||
tool.setEnabled(true);
|
tool.setEnabled(true);
|
||||||
tool.draw(svg.svg, context);
|
tool.draw(svg.svg, context);
|
||||||
@ -39,7 +35,7 @@ describe('MovingTool', () => {
|
|||||||
relatedTarget: svg.svg.node(),
|
relatedTarget: svg.svg.node(),
|
||||||
screenY: 1024,
|
screenY: 1024,
|
||||||
screenX: 1024,
|
screenX: 1024,
|
||||||
view: window
|
view: window,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -70,7 +66,7 @@ describe('MovingTool', () => {
|
|||||||
relatedTarget: svg.svg.node(),
|
relatedTarget: svg.svg.node(),
|
||||||
screenY: 1024,
|
screenY: 1024,
|
||||||
screenX: 1024,
|
screenX: 1024,
|
||||||
view: window
|
view: window,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -101,7 +97,7 @@ describe('MovingTool', () => {
|
|||||||
relatedTarget: svg.svg.node(),
|
relatedTarget: svg.svg.node(),
|
||||||
screenY: 1024,
|
screenY: 1024,
|
||||||
screenX: 1024,
|
screenX: 1024,
|
||||||
view: window
|
view: window,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -17,14 +17,9 @@ export class SelectionTool {
|
|||||||
private path;
|
private path;
|
||||||
private enabled = false;
|
private enabled = false;
|
||||||
|
|
||||||
public constructor(
|
public constructor(private context: Context, private selectionEventSource: SelectionEventSource) {}
|
||||||
private context: Context,
|
|
||||||
private selectionEventSource: SelectionEventSource
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public disableContextMenu(){
|
public disableContextMenu() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEnabled(enabled) {
|
public setEnabled(enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
@ -102,7 +97,10 @@ export class SelectionTool {
|
|||||||
private moveSelection(start, move) {
|
private moveSelection(start, move) {
|
||||||
let x = start[0] / this.context.transformation.k;
|
let x = start[0] / this.context.transformation.k;
|
||||||
let y = start[1] / this.context.transformation.k;
|
let y = start[1] / this.context.transformation.k;
|
||||||
this.path.attr('d', this.rect(x, y, move[0]/this.context.transformation.k - x, move[1]/this.context.transformation.k - y));
|
this.path.attr(
|
||||||
|
'd',
|
||||||
|
this.rect(x, y, move[0] / this.context.transformation.k - x, move[1] / this.context.transformation.k - y)
|
||||||
|
);
|
||||||
this.selectedEvent(start, move);
|
this.selectedEvent(start, move);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +125,7 @@ export class SelectionTool {
|
|||||||
const transformation_point = this.context.getZeroZeroTransformationPoint();
|
const transformation_point = this.context.getZeroZeroTransformationPoint();
|
||||||
return [
|
return [
|
||||||
point[0] - transformation_point.x - this.context.transformation.x,
|
point[0] - transformation_point.x - this.context.transformation.x,
|
||||||
point[1] - transformation_point.y - this.context.transformation.y
|
point[1] - transformation_point.y - this.context.transformation.y,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,10 @@ export class DrawingLineWidget {
|
|||||||
|
|
||||||
if (this.drawing) {
|
if (this.drawing) {
|
||||||
link_data = [
|
link_data = [
|
||||||
[[this.drawingLine.start.x, this.drawingLine.start.y], [this.drawingLine.end.x, this.drawingLine.end.y]]
|
[
|
||||||
|
[this.drawingLine.start.x, this.drawingLine.start.y],
|
||||||
|
[this.drawingLine.end.x, this.drawingLine.end.y],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,11 +75,7 @@ export class DrawingLineWidget {
|
|||||||
|
|
||||||
const enter = tool.enter().append<SVGPathElement>('path');
|
const enter = tool.enter().append<SVGPathElement>('path');
|
||||||
|
|
||||||
tool
|
tool.merge(enter).attr('d', value_line).attr('stroke', '#000').attr('stroke-width', '2');
|
||||||
.merge(enter)
|
|
||||||
.attr('d', value_line)
|
|
||||||
.attr('stroke', '#000')
|
|
||||||
.attr('stroke-width', '2');
|
|
||||||
|
|
||||||
tool.exit().remove();
|
tool.exit().remove();
|
||||||
}
|
}
|
||||||
|
@ -33,52 +33,49 @@ export class DrawingWidget implements Widget {
|
|||||||
this.imageDrawingWidget,
|
this.imageDrawingWidget,
|
||||||
this.rectDrawingWidget,
|
this.rectDrawingWidget,
|
||||||
this.lineDrawingWidget,
|
this.lineDrawingWidget,
|
||||||
this.ellipseDrawingWidget
|
this.ellipseDrawingWidget,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public draw(view: SVGSelection) {
|
public draw(view: SVGSelection) {
|
||||||
const drawing_body = view.selectAll<SVGGElement, MapDrawing>('g.drawing_body').data((l: MapDrawing) => [l]);
|
const drawing_body = view.selectAll<SVGGElement, MapDrawing>('g.drawing_body').data((l: MapDrawing) => [l]);
|
||||||
|
|
||||||
const drawing_body_enter = drawing_body
|
const drawing_body_enter = drawing_body.enter().append<SVGGElement>('g').attr('class', 'drawing_body');
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.attr('class', 'drawing_body');
|
|
||||||
|
|
||||||
const drawing_body_merge = drawing_body.merge(drawing_body_enter).attr('transform', (d: MapDrawing) => {
|
const drawing_body_merge = drawing_body.merge(drawing_body_enter).attr('transform', (d: MapDrawing) => {
|
||||||
return `translate(${d.x},${d.y}) rotate(${d.rotation})`;
|
return `translate(${d.x},${d.y}) rotate(${d.rotation})`;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.drawingWidgets.forEach(widget => {
|
this.drawingWidgets.forEach((widget) => {
|
||||||
widget.draw(drawing_body_merge);
|
widget.draw(drawing_body_merge);
|
||||||
});
|
});
|
||||||
|
|
||||||
drawing_body_merge.select('.layer_label_wrapper').remove();
|
drawing_body_merge.select('.layer_label_wrapper').remove();
|
||||||
if (this.mapSettingsService.isLayerNumberVisible) {
|
if (this.mapSettingsService.isLayerNumberVisible) {
|
||||||
drawing_body_merge
|
drawing_body_merge
|
||||||
.filter(n => ((n.element instanceof RectElement) || (n.element instanceof EllipseElement)))
|
.filter((n) => n.element instanceof RectElement || n.element instanceof EllipseElement)
|
||||||
.append<SVGRectElement>('rect')
|
.append<SVGRectElement>('rect')
|
||||||
.attr('class', 'layer_label_wrapper')
|
.attr('class', 'layer_label_wrapper')
|
||||||
.attr('width', '26')
|
.attr('width', '26')
|
||||||
.attr('height', '26')
|
.attr('height', '26')
|
||||||
.attr('x', n => n.element ? n.element.width/2 - 13 : 0)
|
.attr('x', (n) => (n.element ? n.element.width / 2 - 13 : 0))
|
||||||
.attr('y', n => n.element ? n.element.height/2 - 13 : 0)
|
.attr('y', (n) => (n.element ? n.element.height / 2 - 13 : 0))
|
||||||
.attr('fill', 'red');
|
.attr('fill', 'red');
|
||||||
}
|
}
|
||||||
|
|
||||||
drawing_body_merge.select('.layer_label').remove();
|
drawing_body_merge.select('.layer_label').remove();
|
||||||
if (this.mapSettingsService.isLayerNumberVisible) {
|
if (this.mapSettingsService.isLayerNumberVisible) {
|
||||||
drawing_body_merge
|
drawing_body_merge
|
||||||
.filter(n => ((n.element instanceof RectElement) || (n.element instanceof EllipseElement)))
|
.filter((n) => n.element instanceof RectElement || n.element instanceof EllipseElement)
|
||||||
.append<SVGTextElement>('text')
|
.append<SVGTextElement>('text')
|
||||||
.attr('class', 'layer_label')
|
.attr('class', 'layer_label')
|
||||||
.text((elem) => elem.z)
|
.text((elem) => elem.z)
|
||||||
.attr('x', function (n) {
|
.attr('x', function (n) {
|
||||||
if(n.z >= 100 ) return n.element ? n.element.width/2 - 13 : 0
|
if (n.z >= 100) return n.element ? n.element.width / 2 - 13 : 0;
|
||||||
else if(n.z >= 10 ) return n.element ? n.element.width/2 - 9 : 0
|
else if (n.z >= 10) return n.element ? n.element.width / 2 - 9 : 0;
|
||||||
else return n.element.width/2 - 5
|
else return n.element.width / 2 - 5;
|
||||||
})
|
})
|
||||||
.attr('y', n => n.element ? n.element.height/2 + 5 : 0)
|
.attr('y', (n) => (n.element ? n.element.height / 2 + 5 : 0))
|
||||||
.attr('style', () => {
|
.attr('style', () => {
|
||||||
const styles: string[] = [];
|
const styles: string[] = [];
|
||||||
styles.push(`font-family: "Noto Sans"`);
|
styles.push(`font-family: "Noto Sans"`);
|
||||||
@ -93,10 +90,10 @@ export class DrawingWidget implements Widget {
|
|||||||
.select<SVGAElement>('line.top')
|
.select<SVGAElement>('line.top')
|
||||||
.attr('stroke', 'transparent')
|
.attr('stroke', 'transparent')
|
||||||
.attr('stroke-width', '8px')
|
.attr('stroke-width', '8px')
|
||||||
.attr('x1', drawing =>
|
.attr('x1', (drawing) =>
|
||||||
drawing.element instanceof EllipseElement ? drawing.element.cx - drawing.element.width / 10 : '0'
|
drawing.element instanceof EllipseElement ? drawing.element.cx - drawing.element.width / 10 : '0'
|
||||||
)
|
)
|
||||||
.attr('x2', drawing =>
|
.attr('x2', (drawing) =>
|
||||||
drawing.element instanceof EllipseElement
|
drawing.element instanceof EllipseElement
|
||||||
? drawing.element.cx + drawing.element.width / 10
|
? drawing.element.cx + drawing.element.width / 10
|
||||||
: drawing.element.width
|
: drawing.element.width
|
||||||
@ -110,16 +107,16 @@ export class DrawingWidget implements Widget {
|
|||||||
.select<SVGAElement>('line.bottom')
|
.select<SVGAElement>('line.bottom')
|
||||||
.attr('stroke', 'transparent')
|
.attr('stroke', 'transparent')
|
||||||
.attr('stroke-width', '8px')
|
.attr('stroke-width', '8px')
|
||||||
.attr('x1', drawing =>
|
.attr('x1', (drawing) =>
|
||||||
drawing.element instanceof EllipseElement ? drawing.element.cx - drawing.element.width / 10 : '0'
|
drawing.element instanceof EllipseElement ? drawing.element.cx - drawing.element.width / 10 : '0'
|
||||||
)
|
)
|
||||||
.attr('x2', drawing =>
|
.attr('x2', (drawing) =>
|
||||||
drawing.element instanceof EllipseElement
|
drawing.element instanceof EllipseElement
|
||||||
? drawing.element.cx + drawing.element.width / 10
|
? drawing.element.cx + drawing.element.width / 10
|
||||||
: drawing.element.width
|
: drawing.element.width
|
||||||
)
|
)
|
||||||
.attr('y1', drawing => drawing.element.height)
|
.attr('y1', (drawing) => drawing.element.height)
|
||||||
.attr('y2', drawing => drawing.element.height)
|
.attr('y2', (drawing) => drawing.element.height)
|
||||||
.attr('draggable', 'true')
|
.attr('draggable', 'true')
|
||||||
.attr('cursor', 'ns-resize');
|
.attr('cursor', 'ns-resize');
|
||||||
|
|
||||||
@ -129,10 +126,10 @@ export class DrawingWidget implements Widget {
|
|||||||
.attr('stroke-width', '8px')
|
.attr('stroke-width', '8px')
|
||||||
.attr('x1', '0')
|
.attr('x1', '0')
|
||||||
.attr('x2', '0')
|
.attr('x2', '0')
|
||||||
.attr('y1', drawing =>
|
.attr('y1', (drawing) =>
|
||||||
drawing.element instanceof EllipseElement ? drawing.element.cy - drawing.element.height / 10 : '0'
|
drawing.element instanceof EllipseElement ? drawing.element.cy - drawing.element.height / 10 : '0'
|
||||||
)
|
)
|
||||||
.attr('y2', drawing =>
|
.attr('y2', (drawing) =>
|
||||||
drawing.element instanceof EllipseElement
|
drawing.element instanceof EllipseElement
|
||||||
? drawing.element.cy + drawing.element.height / 10
|
? drawing.element.cy + drawing.element.height / 10
|
||||||
: drawing.element.height
|
: drawing.element.height
|
||||||
@ -144,12 +141,12 @@ export class DrawingWidget implements Widget {
|
|||||||
.select<SVGAElement>('line.left')
|
.select<SVGAElement>('line.left')
|
||||||
.attr('stroke', 'transparent')
|
.attr('stroke', 'transparent')
|
||||||
.attr('stroke-width', '8px')
|
.attr('stroke-width', '8px')
|
||||||
.attr('x1', drawing => drawing.element.width)
|
.attr('x1', (drawing) => drawing.element.width)
|
||||||
.attr('x2', drawing => drawing.element.width)
|
.attr('x2', (drawing) => drawing.element.width)
|
||||||
.attr('y1', drawing =>
|
.attr('y1', (drawing) =>
|
||||||
drawing.element instanceof EllipseElement ? drawing.element.cy - drawing.element.height / 10 : '0'
|
drawing.element instanceof EllipseElement ? drawing.element.cy - drawing.element.height / 10 : '0'
|
||||||
)
|
)
|
||||||
.attr('y2', drawing =>
|
.attr('y2', (drawing) =>
|
||||||
drawing.element instanceof EllipseElement
|
drawing.element instanceof EllipseElement
|
||||||
? drawing.element.cy + drawing.element.height / 10
|
? drawing.element.cy + drawing.element.height / 10
|
||||||
: drawing.element.height
|
: drawing.element.height
|
||||||
@ -162,8 +159,8 @@ export class DrawingWidget implements Widget {
|
|||||||
.attr('draggable', 'true')
|
.attr('draggable', 'true')
|
||||||
.attr('fill', 'transparent')
|
.attr('fill', 'transparent')
|
||||||
.attr('stroke', 'transparent')
|
.attr('stroke', 'transparent')
|
||||||
.attr('cx', drawing => (drawing.element as LineElement).x1)
|
.attr('cx', (drawing) => (drawing.element as LineElement).x1)
|
||||||
.attr('cy', drawing => (drawing.element as LineElement).y1)
|
.attr('cy', (drawing) => (drawing.element as LineElement).y1)
|
||||||
.attr('r', 10)
|
.attr('r', 10)
|
||||||
.attr('cursor', 'move');
|
.attr('cursor', 'move');
|
||||||
|
|
||||||
@ -172,8 +169,8 @@ export class DrawingWidget implements Widget {
|
|||||||
.attr('draggable', 'true')
|
.attr('draggable', 'true')
|
||||||
.attr('fill', 'transparent')
|
.attr('fill', 'transparent')
|
||||||
.attr('stroke', 'transparent')
|
.attr('stroke', 'transparent')
|
||||||
.attr('cx', drawing => (drawing.element as LineElement).x2)
|
.attr('cx', (drawing) => (drawing.element as LineElement).x2)
|
||||||
.attr('cy', drawing => (drawing.element as LineElement).y2)
|
.attr('cy', (drawing) => (drawing.element as LineElement).y2)
|
||||||
.attr('r', 10)
|
.attr('r', 10)
|
||||||
.attr('cursor', 'move');
|
.attr('cursor', 'move');
|
||||||
|
|
||||||
|
@ -111,7 +111,9 @@ export class DrawingsWidget implements Widget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dy = y - (evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y));
|
dy =
|
||||||
|
y -
|
||||||
|
(evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y));
|
||||||
y = evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y);
|
y = evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y);
|
||||||
|
|
||||||
if (datum.element.height + dy < 0) {
|
if (datum.element.height + dy < 0) {
|
||||||
@ -119,7 +121,8 @@ export class DrawingsWidget implements Widget {
|
|||||||
y = topEdge;
|
y = topEdge;
|
||||||
datum.element.height = Math.abs(datum.element.height + evt.dy);
|
datum.element.height = Math.abs(datum.element.height + evt.dy);
|
||||||
} else {
|
} else {
|
||||||
datum.y = evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y);
|
datum.y =
|
||||||
|
evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y);
|
||||||
datum.element.height += dy;
|
datum.element.height += dy;
|
||||||
if (datum.element instanceof EllipseElement) {
|
if (datum.element instanceof EllipseElement) {
|
||||||
(datum.element as EllipseElement).cy =
|
(datum.element as EllipseElement).cy =
|
||||||
@ -151,7 +154,9 @@ export class DrawingsWidget implements Widget {
|
|||||||
const evt = event;
|
const evt = event;
|
||||||
|
|
||||||
if (!isReflectedVertical) {
|
if (!isReflectedVertical) {
|
||||||
dy = y - (evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y));
|
dy =
|
||||||
|
y -
|
||||||
|
(evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y));
|
||||||
y = evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y);
|
y = evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y);
|
||||||
|
|
||||||
if (datum.element.height + dy < 0) {
|
if (datum.element.height + dy < 0) {
|
||||||
@ -159,7 +164,8 @@ export class DrawingsWidget implements Widget {
|
|||||||
isReflectedVertical = true;
|
isReflectedVertical = true;
|
||||||
datum.element.height = Math.abs(datum.element.height + evt.dy);
|
datum.element.height = Math.abs(datum.element.height + evt.dy);
|
||||||
} else {
|
} else {
|
||||||
datum.y = evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y);
|
datum.y =
|
||||||
|
evt.sourceEvent.pageY - (this.context.getZeroZeroTransformationPoint().y + this.context.transformation.y);
|
||||||
datum.element.height += dy;
|
datum.element.height += dy;
|
||||||
if (datum.element instanceof EllipseElement) {
|
if (datum.element instanceof EllipseElement) {
|
||||||
(datum.element as EllipseElement).cy =
|
(datum.element as EllipseElement).cy =
|
||||||
@ -215,7 +221,9 @@ export class DrawingsWidget implements Widget {
|
|||||||
const evt = event;
|
const evt = event;
|
||||||
|
|
||||||
if (!isReflectedHorizontal) {
|
if (!isReflectedHorizontal) {
|
||||||
dx = x - (evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x));
|
dx =
|
||||||
|
x -
|
||||||
|
(evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x));
|
||||||
x = evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x);
|
x = evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x);
|
||||||
|
|
||||||
if (datum.element.width + dx < 0) {
|
if (datum.element.width + dx < 0) {
|
||||||
@ -223,7 +231,8 @@ export class DrawingsWidget implements Widget {
|
|||||||
isReflectedHorizontal = true;
|
isReflectedHorizontal = true;
|
||||||
datum.element.width = Math.abs(datum.element.width + evt.dx);
|
datum.element.width = Math.abs(datum.element.width + evt.dx);
|
||||||
} else {
|
} else {
|
||||||
datum.x = evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x);
|
datum.x =
|
||||||
|
evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x);
|
||||||
datum.element.width += dx;
|
datum.element.width += dx;
|
||||||
if (datum.element instanceof EllipseElement) {
|
if (datum.element instanceof EllipseElement) {
|
||||||
(datum.element as EllipseElement).cx =
|
(datum.element as EllipseElement).cx =
|
||||||
@ -290,7 +299,9 @@ export class DrawingsWidget implements Widget {
|
|||||||
datum.element.width = datum.element.width + evt.dx < 0 ? 1 : (datum.element.width += evt.dx);
|
datum.element.width = datum.element.width + evt.dx < 0 ? 1 : (datum.element.width += evt.dx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dx = x - (evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x));
|
dx =
|
||||||
|
x -
|
||||||
|
(evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x));
|
||||||
x = evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x);
|
x = evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x);
|
||||||
|
|
||||||
if (datum.element.width + dx < 0) {
|
if (datum.element.width + dx < 0) {
|
||||||
@ -298,7 +309,8 @@ export class DrawingsWidget implements Widget {
|
|||||||
isReflectedHorizontal = false;
|
isReflectedHorizontal = false;
|
||||||
datum.element.width = Math.abs(datum.element.width + evt.dx);
|
datum.element.width = Math.abs(datum.element.width + evt.dx);
|
||||||
} else {
|
} else {
|
||||||
datum.x = evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x);
|
datum.x =
|
||||||
|
evt.sourceEvent.pageX - (this.context.getZeroZeroTransformationPoint().x + this.context.transformation.x);
|
||||||
datum.element.width += dx;
|
datum.element.width += dx;
|
||||||
if (datum.element instanceof EllipseElement) {
|
if (datum.element instanceof EllipseElement) {
|
||||||
(datum.element as EllipseElement).cx =
|
(datum.element as EllipseElement).cx =
|
||||||
|
@ -33,10 +33,7 @@ describe('EllipseDrawingWidget', () => {
|
|||||||
drawing.element = ellipse;
|
drawing.element = ellipse;
|
||||||
|
|
||||||
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
||||||
const drawings_enter = drawings
|
const drawings_enter = drawings.enter().append<SVGGElement>('g').classed('drawing', true);
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.classed('drawing', true);
|
|
||||||
const drawings_merge = drawings.merge(drawings_enter);
|
const drawings_merge = drawings.merge(drawings_enter);
|
||||||
|
|
||||||
widget.draw(drawings_merge);
|
widget.draw(drawings_merge);
|
||||||
|
@ -17,25 +17,13 @@ export class EllipseDrawingWidget implements DrawingShapeWidget {
|
|||||||
return d.element && d.element instanceof EllipseElement ? [d.element] : [];
|
return d.element && d.element instanceof EllipseElement ? [d.element] : [];
|
||||||
});
|
});
|
||||||
|
|
||||||
drawing
|
drawing.enter().append<SVGAElement>('line').attr('class', 'top');
|
||||||
.enter()
|
|
||||||
.append<SVGAElement>('line')
|
|
||||||
.attr('class', 'top');
|
|
||||||
|
|
||||||
drawing
|
drawing.enter().append<SVGAElement>('line').attr('class', 'bottom');
|
||||||
.enter()
|
|
||||||
.append<SVGAElement>('line')
|
|
||||||
.attr('class', 'bottom');
|
|
||||||
|
|
||||||
drawing
|
drawing.enter().append<SVGAElement>('line').attr('class', 'right');
|
||||||
.enter()
|
|
||||||
.append<SVGAElement>('line')
|
|
||||||
.attr('class', 'right');
|
|
||||||
|
|
||||||
drawing
|
drawing.enter().append<SVGAElement>('line').attr('class', 'left');
|
||||||
.enter()
|
|
||||||
.append<SVGAElement>('line')
|
|
||||||
.attr('class', 'left');
|
|
||||||
|
|
||||||
const drawing_enter = drawing
|
const drawing_enter = drawing
|
||||||
.enter()
|
.enter()
|
||||||
@ -45,15 +33,15 @@ export class EllipseDrawingWidget implements DrawingShapeWidget {
|
|||||||
const merge = drawing.merge(drawing_enter);
|
const merge = drawing.merge(drawing_enter);
|
||||||
|
|
||||||
merge
|
merge
|
||||||
.attr('fill', ellipse => ellipse.fill)
|
.attr('fill', (ellipse) => ellipse.fill)
|
||||||
.attr('fill-opacity', ellipse => ellipse.fill_opacity)
|
.attr('fill-opacity', (ellipse) => ellipse.fill_opacity)
|
||||||
.attr('stroke', ellipse => ellipse.stroke)
|
.attr('stroke', (ellipse) => ellipse.stroke)
|
||||||
.attr('stroke-width', ellipse => ellipse.stroke_width)
|
.attr('stroke-width', (ellipse) => ellipse.stroke_width)
|
||||||
.attr('stroke-dasharray', ellipse => this.qtDasharrayFixer.fix(ellipse.stroke_dasharray))
|
.attr('stroke-dasharray', (ellipse) => this.qtDasharrayFixer.fix(ellipse.stroke_dasharray))
|
||||||
.attr('cx', ellipse => ellipse.cx)
|
.attr('cx', (ellipse) => ellipse.cx)
|
||||||
.attr('cy', ellipse => ellipse.cy)
|
.attr('cy', (ellipse) => ellipse.cy)
|
||||||
.attr('rx', ellipse => ellipse.rx)
|
.attr('rx', (ellipse) => ellipse.rx)
|
||||||
.attr('ry', ellipse => ellipse.ry);
|
.attr('ry', (ellipse) => ellipse.ry);
|
||||||
|
|
||||||
drawing.exit().remove();
|
drawing.exit().remove();
|
||||||
}
|
}
|
||||||
|
@ -26,10 +26,7 @@ describe('ImageDrawingWidget', () => {
|
|||||||
drawing.element = image;
|
drawing.element = image;
|
||||||
|
|
||||||
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
||||||
const drawings_enter = drawings
|
const drawings_enter = drawings.enter().append<SVGGElement>('g').classed('drawing', true);
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.classed('drawing', true);
|
|
||||||
const drawings_merge = drawings.merge(drawings_enter);
|
const drawings_merge = drawings.merge(drawings_enter);
|
||||||
|
|
||||||
widget.draw(drawings_merge);
|
widget.draw(drawings_merge);
|
||||||
|
@ -12,17 +12,14 @@ export class ImageDrawingWidget implements DrawingShapeWidget {
|
|||||||
return d.element && d.element instanceof ImageElement ? [d.element] : [];
|
return d.element && d.element instanceof ImageElement ? [d.element] : [];
|
||||||
});
|
});
|
||||||
|
|
||||||
const drawing_enter = drawing
|
const drawing_enter = drawing.enter().append<SVGImageElement>('image').attr('class', 'image_element noselect');
|
||||||
.enter()
|
|
||||||
.append<SVGImageElement>('image')
|
|
||||||
.attr('class', 'image_element noselect');
|
|
||||||
|
|
||||||
const merge = drawing.merge(drawing_enter);
|
const merge = drawing.merge(drawing_enter);
|
||||||
|
|
||||||
merge
|
merge
|
||||||
.attr('xlink:href', (image: ImageElement) => image.data)
|
.attr('xlink:href', (image: ImageElement) => image.data)
|
||||||
.attr('width', image => image.width)
|
.attr('width', (image) => image.width)
|
||||||
.attr('height', image => image.height);
|
.attr('height', (image) => image.height);
|
||||||
|
|
||||||
drawing.exit().remove();
|
drawing.exit().remove();
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,7 @@ describe('LineDrawingWidget', () => {
|
|||||||
drawing.element = line;
|
drawing.element = line;
|
||||||
|
|
||||||
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
||||||
const drawings_enter = drawings
|
const drawings_enter = drawings.enter().append<SVGGElement>('g').classed('drawing', true);
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.classed('drawing', true);
|
|
||||||
const drawings_merge = drawings.merge(drawings_enter);
|
const drawings_merge = drawings.merge(drawings_enter);
|
||||||
|
|
||||||
widget.draw(drawings_merge);
|
widget.draw(drawings_merge);
|
||||||
|
@ -15,31 +15,22 @@ export class LineDrawingWidget implements DrawingShapeWidget {
|
|||||||
return d.element && d.element instanceof LineElement ? [d.element] : [];
|
return d.element && d.element instanceof LineElement ? [d.element] : [];
|
||||||
});
|
});
|
||||||
|
|
||||||
drawing
|
drawing.enter().append<SVGCircleElement>('circle').attr('class', 'right');
|
||||||
.enter()
|
|
||||||
.append<SVGCircleElement>('circle')
|
|
||||||
.attr('class', 'right');
|
|
||||||
|
|
||||||
drawing
|
drawing.enter().append<SVGCircleElement>('circle').attr('class', 'left');
|
||||||
.enter()
|
|
||||||
.append<SVGCircleElement>('circle')
|
|
||||||
.attr('class', 'left');
|
|
||||||
|
|
||||||
const drawing_enter = drawing
|
const drawing_enter = drawing.enter().append<SVGLineElement>('line').attr('class', 'line_element noselect');
|
||||||
.enter()
|
|
||||||
.append<SVGLineElement>('line')
|
|
||||||
.attr('class', 'line_element noselect');
|
|
||||||
|
|
||||||
const merge = drawing.merge(drawing_enter);
|
const merge = drawing.merge(drawing_enter);
|
||||||
|
|
||||||
merge
|
merge
|
||||||
.attr('stroke', line => line.stroke)
|
.attr('stroke', (line) => line.stroke)
|
||||||
.attr('stroke-width', line => line.stroke_width)
|
.attr('stroke-width', (line) => line.stroke_width)
|
||||||
.attr('stroke-dasharray', line => this.qtDasharrayFixer.fix(line.stroke_dasharray))
|
.attr('stroke-dasharray', (line) => this.qtDasharrayFixer.fix(line.stroke_dasharray))
|
||||||
.attr('x1', line => line.x1)
|
.attr('x1', (line) => line.x1)
|
||||||
.attr('x2', line => line.x2)
|
.attr('x2', (line) => line.x2)
|
||||||
.attr('y1', line => line.y1)
|
.attr('y1', (line) => line.y1)
|
||||||
.attr('y2', line => line.y2);
|
.attr('y2', (line) => line.y2);
|
||||||
|
|
||||||
drawing.exit().remove();
|
drawing.exit().remove();
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,7 @@ describe('RectDrawingWidget', () => {
|
|||||||
drawing.element = rect;
|
drawing.element = rect;
|
||||||
|
|
||||||
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
||||||
const drawings_enter = drawings
|
const drawings_enter = drawings.enter().append<SVGGElement>('g').classed('drawing', true);
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.classed('drawing', true);
|
|
||||||
const drawings_merge = drawings.merge(drawings_enter);
|
const drawings_merge = drawings.merge(drawings_enter);
|
||||||
|
|
||||||
widget.draw(drawings_merge);
|
widget.draw(drawings_merge);
|
||||||
|
@ -15,41 +15,26 @@ export class RectDrawingWidget implements DrawingShapeWidget {
|
|||||||
return d.element && d.element instanceof RectElement ? [d.element] : [];
|
return d.element && d.element instanceof RectElement ? [d.element] : [];
|
||||||
});
|
});
|
||||||
|
|
||||||
drawing
|
drawing.enter().append<SVGAElement>('line').attr('class', 'top');
|
||||||
.enter()
|
|
||||||
.append<SVGAElement>('line')
|
|
||||||
.attr('class', 'top');
|
|
||||||
|
|
||||||
drawing
|
drawing.enter().append<SVGAElement>('line').attr('class', 'bottom');
|
||||||
.enter()
|
|
||||||
.append<SVGAElement>('line')
|
|
||||||
.attr('class', 'bottom');
|
|
||||||
|
|
||||||
drawing
|
drawing.enter().append<SVGAElement>('line').attr('class', 'right');
|
||||||
.enter()
|
|
||||||
.append<SVGAElement>('line')
|
|
||||||
.attr('class', 'right');
|
|
||||||
|
|
||||||
drawing
|
drawing.enter().append<SVGAElement>('line').attr('class', 'left');
|
||||||
.enter()
|
|
||||||
.append<SVGAElement>('line')
|
|
||||||
.attr('class', 'left');
|
|
||||||
|
|
||||||
const drawing_enter = drawing
|
const drawing_enter = drawing.enter().append<SVGRectElement>('rect').attr('class', 'rect_element noselect');
|
||||||
.enter()
|
|
||||||
.append<SVGRectElement>('rect')
|
|
||||||
.attr('class', 'rect_element noselect');
|
|
||||||
|
|
||||||
const merge = drawing.merge(drawing_enter);
|
const merge = drawing.merge(drawing_enter);
|
||||||
|
|
||||||
merge
|
merge
|
||||||
.attr('fill', rect => rect.fill)
|
.attr('fill', (rect) => rect.fill)
|
||||||
.attr('fill-opacity', rect => rect.fill_opacity)
|
.attr('fill-opacity', (rect) => rect.fill_opacity)
|
||||||
.attr('stroke', rect => rect.stroke)
|
.attr('stroke', (rect) => rect.stroke)
|
||||||
.attr('stroke-width', rect => rect.stroke_width)
|
.attr('stroke-width', (rect) => rect.stroke_width)
|
||||||
.attr('stroke-dasharray', rect => this.qtDasharrayFixer.fix(rect.stroke_dasharray))
|
.attr('stroke-dasharray', (rect) => this.qtDasharrayFixer.fix(rect.stroke_dasharray))
|
||||||
.attr('width', rect => rect.width)
|
.attr('width', (rect) => rect.width)
|
||||||
.attr('height', rect => rect.height);
|
.attr('height', (rect) => rect.height);
|
||||||
|
|
||||||
drawing.exit().remove();
|
drawing.exit().remove();
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,7 @@ describe('TextDrawingWidget', () => {
|
|||||||
drawing.element = text;
|
drawing.element = text;
|
||||||
|
|
||||||
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
||||||
const drawings_enter = drawings
|
const drawings_enter = drawings.enter().append<SVGGElement>('g').classed('drawing', true);
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.classed('drawing', true);
|
|
||||||
const drawings_merge = drawings.merge(drawings_enter);
|
const drawings_merge = drawings.merge(drawings_enter);
|
||||||
|
|
||||||
widget.draw(drawings_merge);
|
widget.draw(drawings_merge);
|
||||||
@ -55,10 +52,7 @@ describe('TextDrawingWidget', () => {
|
|||||||
drawing.element = text;
|
drawing.element = text;
|
||||||
|
|
||||||
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
||||||
const drawings_enter = drawings
|
const drawings_enter = drawings.enter().append<SVGGElement>('g').classed('drawing', true);
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.classed('drawing', true);
|
|
||||||
const drawings_merge = drawings.merge(drawings_enter);
|
const drawings_merge = drawings.merge(drawings_enter);
|
||||||
|
|
||||||
widget.draw(drawings_merge);
|
widget.draw(drawings_merge);
|
||||||
@ -81,10 +75,7 @@ describe('TextDrawingWidget', () => {
|
|||||||
drawing.element = text;
|
drawing.element = text;
|
||||||
|
|
||||||
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
const drawings = svg.canvas.selectAll<SVGGElement, MapDrawing>('g.drawing').data([drawing]);
|
||||||
const drawings_enter = drawings
|
const drawings_enter = drawings.enter().append<SVGGElement>('g').classed('drawing', true);
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.classed('drawing', true);
|
|
||||||
const drawings_merge = drawings.merge(drawings_enter);
|
const drawings_merge = drawings.merge(drawings_enter);
|
||||||
|
|
||||||
widget.draw(drawings_merge);
|
widget.draw(drawings_merge);
|
||||||
|
@ -18,10 +18,7 @@ export class TextDrawingWidget implements DrawingShapeWidget {
|
|||||||
return d.element && d.element instanceof TextElement ? [d.element] : [];
|
return d.element && d.element instanceof TextElement ? [d.element] : [];
|
||||||
});
|
});
|
||||||
|
|
||||||
const drawing_enter = drawing
|
const drawing_enter = drawing.enter().append<SVGTextElement>('text').attr('class', 'text_element noselect');
|
||||||
.enter()
|
|
||||||
.append<SVGTextElement>('text')
|
|
||||||
.attr('class', 'text_element noselect');
|
|
||||||
|
|
||||||
const merge = drawing.merge(drawing_enter);
|
const merge = drawing.merge(drawing_enter);
|
||||||
merge
|
merge
|
||||||
@ -40,8 +37,8 @@ export class TextDrawingWidget implements DrawingShapeWidget {
|
|||||||
}
|
}
|
||||||
return styles.join('; ');
|
return styles.join('; ');
|
||||||
})
|
})
|
||||||
.attr('fill', text => text.fill)
|
.attr('fill', (text) => text.fill)
|
||||||
.attr('text-decoration', text => text.text_decoration);
|
.attr('text-decoration', (text) => text.text_decoration);
|
||||||
|
|
||||||
const lines = merge.selectAll<SVGTSpanElement, string>('tspan').data((text: TextElement) => {
|
const lines = merge.selectAll<SVGTSpanElement, string>('tspan').data((text: TextElement) => {
|
||||||
return text.text.split(/\r?\n/);
|
return text.text.split(/\r?\n/);
|
||||||
@ -52,7 +49,7 @@ export class TextDrawingWidget implements DrawingShapeWidget {
|
|||||||
const lines_merge = lines.merge(lines_enter);
|
const lines_merge = lines.merge(lines_enter);
|
||||||
|
|
||||||
lines_merge
|
lines_merge
|
||||||
.text(line => line)
|
.text((line) => line)
|
||||||
.attr('xml:space', 'preserve')
|
.attr('xml:space', 'preserve')
|
||||||
.attr('x', 0)
|
.attr('x', 0)
|
||||||
.attr('dy', (line, i) => (i === 0 ? '0em' : '1.4em'));
|
.attr('dy', (line, i) => (i === 0 ? '0em' : '1.4em'));
|
||||||
|
@ -33,10 +33,7 @@ export class GraphLayout implements Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect(view: SVGSelection, context: Context) {
|
connect(view: SVGSelection, context: Context) {
|
||||||
this.drawingLineTool.connect(
|
this.drawingLineTool.connect(view, context);
|
||||||
view,
|
|
||||||
context
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(view: SVGSelection, context: Context) {
|
draw(view: SVGSelection, context: Context) {
|
||||||
@ -44,10 +41,7 @@ export class GraphLayout implements Widget {
|
|||||||
|
|
||||||
const canvas = view.selectAll<SVGGElement, Context>('g.canvas').data([context]);
|
const canvas = view.selectAll<SVGGElement, Context>('g.canvas').data([context]);
|
||||||
|
|
||||||
const canvasEnter = canvas
|
const canvasEnter = canvas.enter().append<SVGGElement>('g').attr('class', 'canvas');
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.attr('class', 'canvas');
|
|
||||||
|
|
||||||
canvas.merge(canvasEnter).attr('transform', (ctx: Context) => {
|
canvas.merge(canvasEnter).attr('transform', (ctx: Context) => {
|
||||||
const xTrans = ctx.getZeroZeroTransformationPoint().x + ctx.transformation.x;
|
const xTrans = ctx.getZeroZeroTransformationPoint().x + ctx.transformation.x;
|
||||||
|
@ -58,10 +58,7 @@ describe('InterfaceLabelsWidget', () => {
|
|||||||
|
|
||||||
const linksSelection = svg.canvas.selectAll<SVGGElement, MapLink>('g.link').data(links);
|
const linksSelection = svg.canvas.selectAll<SVGGElement, MapLink>('g.link').data(links);
|
||||||
|
|
||||||
linksEnter = linksSelection
|
linksEnter = linksSelection.enter().append<SVGGElement>('g').attr('class', 'link');
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.attr('class', 'link');
|
|
||||||
|
|
||||||
linksSelection.exit().remove();
|
linksSelection.exit().remove();
|
||||||
|
|
||||||
|
@ -36,7 +36,10 @@ export class InterfaceLabelWidget {
|
|||||||
|
|
||||||
const link_node_position = selection
|
const link_node_position = selection
|
||||||
.selectAll<SVGGElement, MapLinkNode>('g.link_node_position')
|
.selectAll<SVGGElement, MapLinkNode>('g.link_node_position')
|
||||||
.data((link: MapLink) => [[link.source, link.nodes[0]], [link.target, link.nodes[1]]]);
|
.data((link: MapLink) => [
|
||||||
|
[link.source, link.nodes[0]],
|
||||||
|
[link.target, link.nodes[1]],
|
||||||
|
]);
|
||||||
|
|
||||||
const enter_link_node_position = link_node_position
|
const enter_link_node_position = link_node_position
|
||||||
.enter()
|
.enter()
|
||||||
@ -58,10 +61,7 @@ export class InterfaceLabelWidget {
|
|||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
|
||||||
const enter = labels
|
const enter = labels.enter().append<SVGGElement>('g').classed('interface_label_container', true);
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.classed('interface_label_container', true);
|
|
||||||
|
|
||||||
// create surrounding rect
|
// create surrounding rect
|
||||||
enter.append<SVGRectElement>('rect').attr('class', 'interface_label_selection');
|
enter.append<SVGRectElement>('rect').attr('class', 'interface_label_selection');
|
||||||
@ -72,9 +72,7 @@ export class InterfaceLabelWidget {
|
|||||||
.attr('class', 'interface_label noselect')
|
.attr('class', 'interface_label noselect')
|
||||||
.attr('interface_label_id', (i: MapLinkNode) => `${i.id}`);
|
.attr('interface_label_id', (i: MapLinkNode) => `${i.id}`);
|
||||||
|
|
||||||
const merge = labels
|
const merge = labels.merge(enter).on('contextmenu', (n: MapLinkNode, i: number) => {
|
||||||
.merge(enter)
|
|
||||||
.on('contextmenu', (n: MapLinkNode, i: number) => {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
self.onContextMenu.emit(new InterfaceLabelContextMenu(event, n));
|
self.onContextMenu.emit(new InterfaceLabelContextMenu(event, n));
|
||||||
});
|
});
|
||||||
|
@ -10,11 +10,9 @@ import { MapSettingsService } from '../../services/mapsettings.service';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InterfaceStatusWidget implements Widget {
|
export class InterfaceStatusWidget implements Widget {
|
||||||
private mapSettingsService: MapSettingsService
|
private mapSettingsService: MapSettingsService;
|
||||||
|
|
||||||
constructor(
|
constructor(private _mapSettingsService: MapSettingsService) {
|
||||||
private _mapSettingsService: MapSettingsService
|
|
||||||
) {
|
|
||||||
this.mapSettingsService = _mapSettingsService;
|
this.mapSettingsService = _mapSettingsService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,12 +23,14 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
view.each(function (this: SVGGElement, l: MapLink) {
|
view.each(function (this: SVGGElement, l: MapLink) {
|
||||||
mapLinks.push(l);
|
mapLinks.push(l);
|
||||||
});
|
});
|
||||||
mapLinks.forEach(mapLink => {
|
mapLinks.forEach((mapLink) => {
|
||||||
mapLinks.forEach(n => {
|
mapLinks.forEach((n) => {
|
||||||
if (n.nodes[0].linkId !== mapLink.nodes[0].linkId) {
|
if (n.nodes[0].linkId !== mapLink.nodes[0].linkId) {
|
||||||
if ((mapLink.nodes[0].nodeId === n.nodes[0].nodeId && mapLink.nodes[1].nodeId === n.nodes[1].nodeId) ||
|
if (
|
||||||
|
(mapLink.nodes[0].nodeId === n.nodes[0].nodeId && mapLink.nodes[1].nodeId === n.nodes[1].nodeId) ||
|
||||||
(mapLink.nodes[0].nodeId === n.nodes[1].nodeId && mapLink.nodes[1].nodeId === n.nodes[0].nodeId) ||
|
(mapLink.nodes[0].nodeId === n.nodes[1].nodeId && mapLink.nodes[1].nodeId === n.nodes[0].nodeId) ||
|
||||||
(mapLink.nodes[1].nodeId === n.nodes[0].nodeId && mapLink.nodes[0].nodeId === n.nodes[1].nodeId)) {
|
(mapLink.nodes[1].nodeId === n.nodes[0].nodeId && mapLink.nodes[0].nodeId === n.nodes[1].nodeId)
|
||||||
|
) {
|
||||||
mapLink.isMultiplied = true;
|
mapLink.isMultiplied = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,37 +48,42 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
|
|
||||||
if (link_path.node().getTotalLength() > 2 * 45 + 130) {
|
if (link_path.node().getTotalLength() > 2 * 45 + 130) {
|
||||||
if (l.source && l.target) {
|
if (l.source && l.target) {
|
||||||
let sourcePort = l.nodes.find(node => node.nodeId === l.source.id).label.text;
|
let sourcePort = l.nodes.find((node) => node.nodeId === l.source.id).label.text;
|
||||||
let destinationPort = l.nodes.find(node => node.nodeId === l.target.id).label.text;
|
let destinationPort = l.nodes.find((node) => node.nodeId === l.target.id).label.text;
|
||||||
statuses = [
|
statuses = [
|
||||||
new LinkStatus(start_point.x, start_point.y, (l.capturing && l.suspend) ? 'suspended' : l.source.status, sourcePort),
|
new LinkStatus(
|
||||||
new LinkStatus(end_point.x, end_point.y, (l.capturing && l.suspend) ? 'suspended' : l.target.status, destinationPort)
|
start_point.x,
|
||||||
|
start_point.y,
|
||||||
|
l.capturing && l.suspend ? 'suspended' : l.source.status,
|
||||||
|
sourcePort
|
||||||
|
),
|
||||||
|
new LinkStatus(
|
||||||
|
end_point.x,
|
||||||
|
end_point.y,
|
||||||
|
l.capturing && l.suspend ? 'suspended' : l.target.status,
|
||||||
|
destinationPort
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
link_group
|
link_group.selectAll<SVGCircleElement, LinkStatus>('circle.status_started').remove();
|
||||||
.selectAll<SVGCircleElement, LinkStatus>('circle.status_started').remove();
|
link_group.selectAll<SVGCircleElement, LinkStatus>('circle.status_stopped').remove();
|
||||||
link_group
|
link_group.selectAll<SVGCircleElement, LinkStatus>('circle.status_suspended').remove();
|
||||||
.selectAll<SVGCircleElement, LinkStatus>('circle.status_stopped').remove();
|
|
||||||
link_group
|
|
||||||
.selectAll<SVGCircleElement, LinkStatus>('circle.status_suspended').remove();
|
|
||||||
|
|
||||||
link_group
|
link_group.selectAll<SVGRectElement, LinkStatus>('rect.status_started').remove();
|
||||||
.selectAll<SVGRectElement, LinkStatus>('rect.status_started').remove();
|
link_group.selectAll<SVGTextElement, LinkStatus>('text.status_started_label').remove();
|
||||||
link_group
|
link_group.selectAll<SVGRectElement, LinkStatus>('rect.status_stopped').remove();
|
||||||
.selectAll<SVGTextElement, LinkStatus>('text.status_started_label').remove();
|
link_group.selectAll<SVGTextElement, LinkStatus>('text.status_stopped_label').remove();
|
||||||
link_group
|
link_group.selectAll<SVGRectElement, LinkStatus>('rect.status_suspended').remove();
|
||||||
.selectAll<SVGRectElement, LinkStatus>('rect.status_stopped').remove();
|
link_group.selectAll<SVGTextElement, LinkStatus>('text.status_suspended_label').remove();
|
||||||
link_group
|
|
||||||
.selectAll<SVGTextElement, LinkStatus>('text.status_stopped_label').remove();
|
|
||||||
link_group
|
|
||||||
.selectAll<SVGRectElement, LinkStatus>('rect.status_suspended').remove();
|
|
||||||
link_group
|
|
||||||
.selectAll<SVGTextElement, LinkStatus>('text.status_suspended_label').remove();
|
|
||||||
|
|
||||||
if (self.mapSettingsService.showInterfaceLabels && self.mapSettingsService.integrateLinkLabelsToLinks && !l.isMultiplied) {
|
if (
|
||||||
|
self.mapSettingsService.showInterfaceLabels &&
|
||||||
|
self.mapSettingsService.integrateLinkLabelsToLinks &&
|
||||||
|
!l.isMultiplied
|
||||||
|
) {
|
||||||
const status_started = link_group
|
const status_started = link_group
|
||||||
.selectAll<SVGRectElement, LinkStatus>('rect.status_started')
|
.selectAll<SVGRectElement, LinkStatus>('rect.status_started')
|
||||||
.data(statuses.filter((link_status: LinkStatus) => link_status.status === 'started'));
|
.data(statuses.filter((link_status: LinkStatus) => link_status.status === 'started'));
|
||||||
@ -87,7 +92,7 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
.merge(status_started_enter)
|
.merge(status_started_enter)
|
||||||
.attr('class', 'status_started')
|
.attr('class', 'status_started')
|
||||||
.attr('width', (ls: LinkStatus) => {
|
.attr('width', (ls: LinkStatus) => {
|
||||||
return (ls.port.length * 8) + 10;
|
return ls.port.length * 8 + 10;
|
||||||
})
|
})
|
||||||
.attr('height', 20)
|
.attr('height', 20)
|
||||||
.attr('x', (ls: LinkStatus) => ls.x - 30)
|
.attr('x', (ls: LinkStatus) => ls.x - 30)
|
||||||
@ -119,7 +124,7 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
.merge(status_stopped_enter)
|
.merge(status_stopped_enter)
|
||||||
.attr('class', 'status_stopped')
|
.attr('class', 'status_stopped')
|
||||||
.attr('width', (ls: LinkStatus) => {
|
.attr('width', (ls: LinkStatus) => {
|
||||||
return (ls.port.length * 8) + 10;
|
return ls.port.length * 8 + 10;
|
||||||
})
|
})
|
||||||
.attr('height', 20)
|
.attr('height', 20)
|
||||||
.attr('x', (ls: LinkStatus) => ls.x - 30)
|
.attr('x', (ls: LinkStatus) => ls.x - 30)
|
||||||
@ -151,7 +156,7 @@ export class InterfaceStatusWidget implements Widget {
|
|||||||
.merge(status_suspended_enter)
|
.merge(status_suspended_enter)
|
||||||
.attr('class', 'status_suspended')
|
.attr('class', 'status_suspended')
|
||||||
.attr('width', (ls: LinkStatus) => {
|
.attr('width', (ls: LinkStatus) => {
|
||||||
return (ls.port.length * 8) + 10;
|
return ls.port.length * 8 + 10;
|
||||||
})
|
})
|
||||||
.attr('height', 20)
|
.attr('height', 20)
|
||||||
.attr('x', (ls: LinkStatus) => ls.x - 30)
|
.attr('x', (ls: LinkStatus) => ls.x - 30)
|
||||||
|
@ -43,9 +43,7 @@ export class LabelWidget implements Widget {
|
|||||||
.attr('class', 'label_container')
|
.attr('class', 'label_container')
|
||||||
.attr('label_id', (label: MapLabel) => label.id);
|
.attr('label_id', (label: MapLabel) => label.id);
|
||||||
|
|
||||||
const merge = label_view
|
const merge = label_view.merge(label_enter).on('contextmenu', (n: MapLabel, i: number) => {
|
||||||
.merge(label_enter)
|
|
||||||
.on('contextmenu', (n: MapLabel, i: number) => {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
self.onContextMenu.emit(new LabelContextMenu(event, n));
|
self.onContextMenu.emit(new LabelContextMenu(event, n));
|
||||||
});
|
});
|
||||||
@ -60,20 +58,16 @@ export class LabelWidget implements Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private drawLabel(view: SVGSelection) {
|
private drawLabel(view: SVGSelection) {
|
||||||
const label_body = view.selectAll<SVGGElement, MapLabel>('g.label_body').data(label => [label]);
|
const label_body = view.selectAll<SVGGElement, MapLabel>('g.label_body').data((label) => [label]);
|
||||||
|
|
||||||
const label_body_enter = label_body
|
const label_body_enter = label_body.enter().append<SVGGElement>('g').attr('class', 'label_body');
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.attr('class', 'label_body');
|
|
||||||
|
|
||||||
// add label of node
|
// add label of node
|
||||||
label_body_enter.append<SVGTextElement>('text').attr('class', 'label');
|
label_body_enter.append<SVGTextElement>('text').attr('class', 'label');
|
||||||
|
|
||||||
label_body_enter.append<SVGRectElement>('rect').attr('class', 'label_selection');
|
label_body_enter.append<SVGRectElement>('rect').attr('class', 'label_selection');
|
||||||
|
|
||||||
const label_body_merge = label_body
|
const label_body_merge = label_body.merge(label_body_enter);
|
||||||
.merge(label_body_enter);
|
|
||||||
|
|
||||||
label_body_merge
|
label_body_merge
|
||||||
.select<SVGTextElement>('text.label')
|
.select<SVGTextElement>('text.label')
|
||||||
@ -93,7 +87,7 @@ export class LabelWidget implements Widget {
|
|||||||
label_body_merge
|
label_body_merge
|
||||||
.select<SVGRectElement>('rect.label_selection')
|
.select<SVGRectElement>('rect.label_selection')
|
||||||
.attr('visibility', (l: MapLabel) => {
|
.attr('visibility', (l: MapLabel) => {
|
||||||
return (this.selectionManager.isSelected(l) ? 'visible' : 'hidden')
|
return this.selectionManager.isSelected(l) ? 'visible' : 'hidden';
|
||||||
})
|
})
|
||||||
.attr('stroke', 'black')
|
.attr('stroke', 'black')
|
||||||
.attr('stroke-dasharray', '3,3')
|
.attr('stroke-dasharray', '3,3')
|
||||||
|
@ -21,10 +21,7 @@ export class LayersWidget implements Widget {
|
|||||||
return layer.index.toString();
|
return layer.index.toString();
|
||||||
});
|
});
|
||||||
|
|
||||||
const layers_enter = layers_selection
|
const layers_enter = layers_selection.enter().append<SVGGElement>('g').attr('class', 'layer');
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.attr('class', 'layer');
|
|
||||||
|
|
||||||
// add container for links
|
// add container for links
|
||||||
layers_enter.append<SVGGElement>('g').attr('class', 'links');
|
layers_enter.append<SVGGElement>('g').attr('class', 'links');
|
||||||
|
@ -26,53 +26,71 @@ export class LinkWidget implements Widget {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
public draw(view: SVGSelection) {
|
public draw(view: SVGSelection) {
|
||||||
const link_body = view.selectAll<SVGGElement, MapLink>('g.link_body').data(l => [l]);
|
const link_body = view.selectAll<SVGGElement, MapLink>('g.link_body').data((l) => [l]);
|
||||||
|
|
||||||
const link_body_enter = link_body
|
const link_body_enter = link_body.enter().append<SVGGElement>('g').attr('class', 'link_body');
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.attr('class', 'link_body');
|
|
||||||
|
|
||||||
const link_body_merge = link_body.merge(link_body_enter).attr('transform', link => {
|
const link_body_merge = link_body.merge(link_body_enter).attr('transform', (link) => {
|
||||||
const translation = this.multiLinkCalculatorHelper.linkTranslation(link.distance, link.source, link.target);
|
const translation = this.multiLinkCalculatorHelper.linkTranslation(link.distance, link.source, link.target);
|
||||||
return `translate (${translation.dx}, ${translation.dy})`;
|
return `translate (${translation.dx}, ${translation.dy})`;
|
||||||
});
|
});
|
||||||
|
|
||||||
link_body.select('.capture-icon').remove();
|
link_body.select('.capture-icon').remove();
|
||||||
link_body
|
link_body
|
||||||
.filter(l => { return l.capturing && !l.suspend && !(l.filters.bpf || l.filters.corrupt || l.filters.delay || l.filters.frequency_drop || l.filters.packet_loss)})
|
.filter((l) => {
|
||||||
|
return (
|
||||||
|
l.capturing &&
|
||||||
|
!l.suspend &&
|
||||||
|
!(l.filters.bpf || l.filters.corrupt || l.filters.delay || l.filters.frequency_drop || l.filters.packet_loss)
|
||||||
|
);
|
||||||
|
})
|
||||||
.append<SVGGElement>('g')
|
.append<SVGGElement>('g')
|
||||||
.on('contextmenu', (datum: MapLink) => {
|
.on('contextmenu', (datum: MapLink) => {
|
||||||
const evt = event;
|
const evt = event;
|
||||||
this.onContextMenu.emit(new LinkContextMenu(evt, datum));
|
this.onContextMenu.emit(new LinkContextMenu(evt, datum));
|
||||||
})
|
})
|
||||||
.attr('class', 'capture-icon')
|
.attr('class', 'capture-icon')
|
||||||
.attr('transform', link => {
|
.attr('transform', (link) => {
|
||||||
return `translate (${(link.source.x + link.target.x)/2 + 24}, ${(link.source.y + link.target.y)/2 + 24}) scale(0.5)`
|
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${
|
||||||
|
(link.source.y + link.target.y) / 2 + 24
|
||||||
|
}) scale(0.5)`;
|
||||||
})
|
})
|
||||||
.attr('viewBox', '0 0 20 20')
|
.attr('viewBox', '0 0 20 20')
|
||||||
.append<SVGImageElement>('image')
|
.append<SVGImageElement>('image')
|
||||||
.attr("xlink:href", "assets/resources/images/inspect.svg");
|
.attr('xlink:href', 'assets/resources/images/inspect.svg');
|
||||||
|
|
||||||
link_body.select('.filter-capture-icon').remove();
|
link_body.select('.filter-capture-icon').remove();
|
||||||
link_body
|
link_body
|
||||||
.filter(l => { return l.capturing && !l.suspend && (l.filters.bpf || l.filters.corrupt || l.filters.delay || l.filters.frequency_drop || l.filters.packet_loss)})
|
.filter((l) => {
|
||||||
|
return (
|
||||||
|
l.capturing &&
|
||||||
|
!l.suspend &&
|
||||||
|
(l.filters.bpf || l.filters.corrupt || l.filters.delay || l.filters.frequency_drop || l.filters.packet_loss)
|
||||||
|
);
|
||||||
|
})
|
||||||
.append<SVGGElement>('g')
|
.append<SVGGElement>('g')
|
||||||
.on('contextmenu', (datum: MapLink) => {
|
.on('contextmenu', (datum: MapLink) => {
|
||||||
const evt = event;
|
const evt = event;
|
||||||
this.onContextMenu.emit(new LinkContextMenu(evt, datum));
|
this.onContextMenu.emit(new LinkContextMenu(evt, datum));
|
||||||
})
|
})
|
||||||
.attr('class', 'filter-capture-icon')
|
.attr('class', 'filter-capture-icon')
|
||||||
.attr('transform', link => {
|
.attr('transform', (link) => {
|
||||||
return `translate (${(link.source.x + link.target.x)/2 + 24}, ${(link.source.y + link.target.y)/2 + 24}) scale(0.5)`
|
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${
|
||||||
|
(link.source.y + link.target.y) / 2 + 24
|
||||||
|
}) scale(0.5)`;
|
||||||
})
|
})
|
||||||
.attr('viewBox', '0 0 20 20')
|
.attr('viewBox', '0 0 20 20')
|
||||||
.append<SVGImageElement>('image')
|
.append<SVGImageElement>('image')
|
||||||
.attr("xlink:href", "assets/resources/images/filter-capture.svg");
|
.attr('xlink:href', 'assets/resources/images/filter-capture.svg');
|
||||||
|
|
||||||
link_body.select('.filter-icon').remove();
|
link_body.select('.filter-icon').remove();
|
||||||
link_body
|
link_body
|
||||||
.filter(l => { return !l.capturing && (l.filters.bpf || l.filters.corrupt || l.filters.delay || l.filters.frequency_drop || l.filters.packet_loss)})
|
.filter((l) => {
|
||||||
|
return (
|
||||||
|
!l.capturing &&
|
||||||
|
(l.filters.bpf || l.filters.corrupt || l.filters.delay || l.filters.frequency_drop || l.filters.packet_loss)
|
||||||
|
);
|
||||||
|
})
|
||||||
.append<SVGGElement>('g')
|
.append<SVGGElement>('g')
|
||||||
.on('contextmenu', (datum: MapLink) => {
|
.on('contextmenu', (datum: MapLink) => {
|
||||||
const evt = event;
|
const evt = event;
|
||||||
@ -81,30 +99,40 @@ export class LinkWidget implements Widget {
|
|||||||
.attr('class', 'filter-icon')
|
.attr('class', 'filter-icon')
|
||||||
.attr('width', '48px')
|
.attr('width', '48px')
|
||||||
.attr('height', '48px')
|
.attr('height', '48px')
|
||||||
.attr('transform', link => {
|
.attr('transform', (link) => {
|
||||||
return `translate (${(link.source.x + link.target.x)/2 + 24}, ${(link.source.y + link.target.y)/2 + 24}) scale(0.5)`
|
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${
|
||||||
|
(link.source.y + link.target.y) / 2 + 24
|
||||||
|
}) scale(0.5)`;
|
||||||
})
|
})
|
||||||
.attr('viewBox', '0 0 20 20')
|
.attr('viewBox', '0 0 20 20')
|
||||||
.append<SVGImageElement>('image')
|
.append<SVGImageElement>('image')
|
||||||
.attr('width', '48px')
|
.attr('width', '48px')
|
||||||
.attr('height', '48px')
|
.attr('height', '48px')
|
||||||
.attr("xlink:href", "assets/resources/images/filter.svg");
|
.attr('xlink:href', 'assets/resources/images/filter.svg');
|
||||||
|
|
||||||
link_body.select('.pause-icon').remove();
|
link_body.select('.pause-icon').remove();
|
||||||
link_body
|
link_body
|
||||||
.filter(l => { return l.capturing && l.suspend && !(l.filters.bpf || l.filters.corrupt || l.filters.delay || l.filters.frequency_drop || l.filters.packet_loss)})
|
.filter((l) => {
|
||||||
|
return (
|
||||||
|
l.capturing &&
|
||||||
|
l.suspend &&
|
||||||
|
!(l.filters.bpf || l.filters.corrupt || l.filters.delay || l.filters.frequency_drop || l.filters.packet_loss)
|
||||||
|
);
|
||||||
|
})
|
||||||
.append<SVGGElement>('g')
|
.append<SVGGElement>('g')
|
||||||
.on('contextmenu', (datum: MapLink) => {
|
.on('contextmenu', (datum: MapLink) => {
|
||||||
const evt = event;
|
const evt = event;
|
||||||
this.onContextMenu.emit(new LinkContextMenu(evt, datum));
|
this.onContextMenu.emit(new LinkContextMenu(evt, datum));
|
||||||
})
|
})
|
||||||
.attr('class', 'pause-icon')
|
.attr('class', 'pause-icon')
|
||||||
.attr('transform', link => {
|
.attr('transform', (link) => {
|
||||||
return `translate (${(link.source.x + link.target.x)/2 + 24}, ${(link.source.y + link.target.y)/2 + 24}) scale(0.5)`
|
return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${
|
||||||
|
(link.source.y + link.target.y) / 2 + 24
|
||||||
|
}) scale(0.5)`;
|
||||||
})
|
})
|
||||||
.attr('viewBox', '0 0 20 20')
|
.attr('viewBox', '0 0 20 20')
|
||||||
.append<SVGImageElement>('image')
|
.append<SVGImageElement>('image')
|
||||||
.attr("xlink:href", "assets/resources/images/pause.svg");
|
.attr('xlink:href', 'assets/resources/images/pause.svg');
|
||||||
|
|
||||||
this.serialLinkWidget.draw(link_body_merge);
|
this.serialLinkWidget.draw(link_body_merge);
|
||||||
this.ethernetLinkWidget.draw(link_body_merge);
|
this.ethernetLinkWidget.draw(link_body_merge);
|
||||||
|
@ -46,10 +46,7 @@ describe('LinksWidget', () => {
|
|||||||
|
|
||||||
const layersSelection = svg.canvas.selectAll<SVGGElement, Layer>('g.layer').data(layers);
|
const layersSelection = svg.canvas.selectAll<SVGGElement, Layer>('g.layer').data(layers);
|
||||||
|
|
||||||
layersEnter = layersSelection
|
layersEnter = layersSelection.enter().append<SVGGElement>('g').attr('class', 'layer');
|
||||||
.enter()
|
|
||||||
.append<SVGGElement>('g')
|
|
||||||
.attr('class', 'layer');
|
|
||||||
|
|
||||||
layersSelection.exit().remove();
|
layersSelection.exit().remove();
|
||||||
});
|
});
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user