<commit_before>import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {MdDialog, MdMenuTrigger, MdSlider} from '@angular/material';
import {Observable, Subject} from 'rxjs/Rx';
import * as ol from 'openlayers';
import cytoscape from 'cytoscape';
import html2canvas from 'html2canvas';
import {ResizeSensor} from 'css-element-queries';

import {DialogPromptComponent, DialogPromptData} from '../dialog/dialog-prompt/dialog-prompt.component';
import {StationPropertiesComponent, StationPropertiesData} from '../dialog/station-properties/station-properties.component';
import {DeliveryPropertiesComponent, DeliveryPropertiesData} from '../dialog/delivery-properties/delivery-properties.component';
import {Utils} from '../util/utils';
import {TracingService} from '../tracing/tracing.service';
import {Color, CyEdge, CyNode, DeliveryData, FclElements, Layout, ObservedType, Position, Size, StationData} from '../util/datatypes';
import {Constants} from '../util/constants';

interface MenuAction {
  name: string;
  enabled: boolean;
  action: (event: MouseEvent) => void;
}

@Component({
  selector: 'app-gis',
  templateUrl: './gis.component.html',
  styleUrls: ['./gis.component.css']
})
export class GisComponent implements OnInit {

  private static readonly MIN_ZOOM = 0.1;
  private static readonly MAX_ZOOM = 100.0;
  private static readonly ZOOM_FACTOR = 1.5;

  private static readonly NODE_SIZES: Map<Size, number> = new Map([
    [Size.SMALL, 50],
    [Size.MEDIUM, 75],
    [Size.LARGE, 100]
  ]);

  private static readonly FONT_SIZES: Map<Size, number> = new Map([
    [Size.SMALL, 10],
    [Size.MEDIUM, 14],
    [Size.LARGE, 18]
  ]);

  @ViewChild('container') containerElement: ElementRef;
  @ViewChild('map') mapElement: ElementRef;
  @ViewChild('graph') graphElement: ElementRef;

  @ViewChild('slider') slider: MdSlider;
  @ViewChild('graphMenuTrigger') graphMenuTrigger: MdMenuTrigger;
  @ViewChild('stationMenuTrigger') stationMenuTrigger: MdMenuTrigger;
  @ViewChild('deliveryMenuTrigger') deliveryMenuTrigger: MdMenuTrigger;
  @ViewChild('traceMenuTrigger') traceMenuTrigger: MdMenuTrigger;

  graphMenuActions = this.createGraphActions();
  stationMenuActions = this.createStationActions(null);
  deliveryMenuActions = this.createDeliveryActions(null);
  traceMenuActions = this.createTraceActions(null);

  showZoom = Constants.DEFAULT_GRAPH_SHOW_ZOOM;
  showLegend = Constants.DEFAULT_GRAPH_SHOW_LEGEND;
  legend: { name: string; color: string }[] = Constants.PROPERTIES_WITH_COLORS.toArray().map(p => {
    const prop = Constants.PROPERTIES.get(p);

    return {
      name: prop.name,
      color: Utils.colorToCss(prop.color)
    };
  });
  zoomSliderValue: number;

  private zoom = 5.0;
  private sliding = false;

  private cy: any;
  private map: ol.Map;
  private data: FclElements;
  private mergeMap: Map<string, string[]>;
  private mergeToMap: Map<string, string>;
  private changeFunction: () => void;

  private mergeDeliveries = Constants.DEFAULT_GRAPH_MERGE_DELIVERIES;
  private nodeSize = Constants.DEFAULT_GRAPH_NODE_SIZE;
  private fontSize = Constants.DEFAULT_GRAPH_FONT_SIZE;

  private contextMenuElement: any;
  private selectTimerActivated = true;
  private resizeTimer: any;
  private selectTimer: any;
  private hoverDeliveries: Subject<string[]> = new Subject();
  private hoverableEdges: any;

  constructor(private tracingService: TracingService, private dialogService: MdDialog) {
  }

  ngOnInit() {
    this.map = new ol.Map({
      target: this.mapElement.nativeElement,
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM()
        })
      ],
      controls: []
    });

    window.onresize = () => {
      Observable.timer(500).subscribe(() => {
        if (this.cy != null) {
          this.resizeGraphAndMap();
        }
      });
    };

    new ResizeSensor(this.containerElement.nativeElement, () => {
      if (this.resizeTimer != null) {
        this.resizeTimer.unsubscribe();
      }

      if (this.cy != null) {
        this.resizeTimer = Observable.timer(100).subscribe(() => this.resizeGraphAndMap());
      }
    });

    this.stationMenuTrigger.onMenuOpen.subscribe(() => this.updateOverlay());
    this.stationMenuTrigger.onMenuClose.subscribe(() => this.updateOverlay());
    this.deliveryMenuTrigger.onMenuOpen.subscribe(() => this.updateOverlay());
    this.deliveryMenuTrigger.onMenuClose.subscribe(() => this.updateOverlay());
    this.traceMenuTrigger.onMenuClose.subscribe(() => this.updateOverlay());
  }

  init(data: FclElements, layout: Layout) {
    this.data = data;
    this.tracingService.init(data);


    let pan: Position;

    if (layout != null) {
      this.zoom = layout.zoom;
      pan = layout.pan;
    }

    const nodes = this.createNodes();

    if (pan == null) {
      pan = {x: Infinity, y: Infinity};

      for (const n of nodes) {
        pan.x = Math.min(pan.x, n.position.x);
        pan.y = Math.min(pan.y, n.position.y);
      }

      pan.x = -pan.x;
      pan.y = -pan.y;
    }

    this.cy = cytoscape({
      container: this.graphElement.nativeElement,

      elements: {
        nodes: nodes,
        edges: this.createEdges()
      },

      layout: {name: 'preset', zoom: 1, pan: pan},
      style: this.createStyle(),
      zoomingEnabled: false,
      autoungrabify: true
    });

    const hammer = new Hammer.Manager(this.cy.container().children.item(0).children.item(0));
    let pinchCenter: Position;

    hammer.add(new Hammer.Pinch());
    hammer.on('pinch', e => {
      if (pinchCenter == null) {
        pinchCenter = e.center;
      }

      this.zoomTo(this.zoom * Math.pow(10, Math.log10(e.scale) / 10), pinchCenter.x, pinchCenter.y);
    });
    hammer.on('pinchend', () => pinchCenter = null);
    this.cy.container().children.item(0).children.item(0).addEventListener('wheel', (e: WheelEvent) => {
      this.zoomTo(this.zoom * Math.pow(10, e.deltaMode === 1 ? e.deltaY / -25 : e.deltaY / -250), e.offsetX, e.offsetY);<commit_msg>info for multi touch debuggging added<commit_after>import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {MdDialog, MdMenuTrigger, MdSlider} from '@angular/material';
import {Observable, Subject} from 'rxjs/Rx';
import * as ol from 'openlayers';
import cytoscape from 'cytoscape';
import html2canvas from 'html2canvas';
import {ResizeSensor} from 'css-element-queries';

import {DialogPromptComponent, DialogPromptData} from '../dialog/dialog-prompt/dialog-prompt.component';
import {StationPropertiesComponent, StationPropertiesData} from '../dialog/station-properties/station-properties.component';
import {DeliveryPropertiesComponent, DeliveryPropertiesData} from '../dialog/delivery-properties/delivery-properties.component';
import {Utils} from '../util/utils';
import {TracingService} from '../tracing/tracing.service';
import {Color, CyEdge, CyNode, DeliveryData, FclElements, Layout, ObservedType, Position, Size, StationData} from '../util/datatypes';
import {Constants} from '../util/constants';

interface MenuAction {
  name: string;
  enabled: boolean;
  action: (event: MouseEvent) => void;
}

@Component({
  selector: 'app-gis',
  templateUrl: './gis.component.html',
  styleUrls: ['./gis.component.css']
})
export class GisComponent implements OnInit {

  private static readonly MIN_ZOOM = 0.1;
  private static readonly MAX_ZOOM = 100.0;
  private static readonly ZOOM_FACTOR = 1.5;

  private static readonly NODE_SIZES: Map<Size, number> = new Map([
    [Size.SMALL, 50],
    [Size.MEDIUM, 75],
    [Size.LARGE, 100]
  ]);

  private static readonly FONT_SIZES: Map<Size, number> = new Map([
    [Size.SMALL, 10],
    [Size.MEDIUM, 14],
    [Size.LARGE, 18]
  ]);

  @ViewChild('container') containerElement: ElementRef;
  @ViewChild('map') mapElement: ElementRef;
  @ViewChild('graph') graphElement: ElementRef;

  @ViewChild('slider') slider: MdSlider;
  @ViewChild('graphMenuTrigger') graphMenuTrigger: MdMenuTrigger;
  @ViewChild('stationMenuTrigger') stationMenuTrigger: MdMenuTrigger;
  @ViewChild('deliveryMenuTrigger') deliveryMenuTrigger: MdMenuTrigger;
  @ViewChild('traceMenuTrigger') traceMenuTrigger: MdMenuTrigger;

  graphMenuActions = this.createGraphActions();
  stationMenuActions = this.createStationActions(null);
  deliveryMenuActions = this.createDeliveryActions(null);
  traceMenuActions = this.createTraceActions(null);

  showZoom = Constants.DEFAULT_GRAPH_SHOW_ZOOM;
  showLegend = Constants.DEFAULT_GRAPH_SHOW_LEGEND;
  legend: { name: string; color: string }[] = Constants.PROPERTIES_WITH_COLORS.toArray().map(p => {
    const prop = Constants.PROPERTIES.get(p);

    return {
      name: prop.name,
      color: Utils.colorToCss(prop.color)
    };
  });
  zoomSliderValue: number;

  private zoom = 5.0;
  private sliding = false;

  private cy: any;
  private map: ol.Map;
  private data: FclElements;
  private mergeMap: Map<string, string[]>;
  private mergeToMap: Map<string, string>;
  private changeFunction: () => void;

  private mergeDeliveries = Constants.DEFAULT_GRAPH_MERGE_DELIVERIES;
  private nodeSize = Constants.DEFAULT_GRAPH_NODE_SIZE;
  private fontSize = Constants.DEFAULT_GRAPH_FONT_SIZE;

  private contextMenuElement: any;
  private selectTimerActivated = true;
  private resizeTimer: any;
  private selectTimer: any;
  private hoverDeliveries: Subject<string[]> = new Subject();
  private hoverableEdges: any;

  constructor(private tracingService: TracingService, private dialogService: MdDialog) {
  }

  ngOnInit() {
    this.map = new ol.Map({
      target: this.mapElement.nativeElement,
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM()
        })
      ],
      controls: []
    });

    window.onresize = () => {
      Observable.timer(500).subscribe(() => {
        if (this.cy != null) {
          this.resizeGraphAndMap();
        }
      });
    };

    new ResizeSensor(this.containerElement.nativeElement, () => {
      if (this.resizeTimer != null) {
        this.resizeTimer.unsubscribe();
      }

      if (this.cy != null) {
        this.resizeTimer = Observable.timer(100).subscribe(() => this.resizeGraphAndMap());
      }
    });

    this.stationMenuTrigger.onMenuOpen.subscribe(() => this.updateOverlay());
    this.stationMenuTrigger.onMenuClose.subscribe(() => this.updateOverlay());
    this.deliveryMenuTrigger.onMenuOpen.subscribe(() => this.updateOverlay());
    this.deliveryMenuTrigger.onMenuClose.subscribe(() => this.updateOverlay());
    this.traceMenuTrigger.onMenuClose.subscribe(() => this.updateOverlay());
  }

  init(data: FclElements, layout: Layout) {
    this.data = data;
    this.tracingService.init(data);


    let pan: Position;

    if (layout != null) {
      this.zoom = layout.zoom;
      pan = layout.pan;
    }

    const nodes = this.createNodes();

    if (pan == null) {
      pan = {x: Infinity, y: Infinity};

      for (const n of nodes) {
        pan.x = Math.min(pan.x, n.position.x);
        pan.y = Math.min(pan.y, n.position.y);
      }

      pan.x = -pan.x;
      pan.y = -pan.y;
    }

    this.cy = cytoscape({
      container: this.graphElement.nativeElement,

      elements: {
        nodes: nodes,
        edges: this.createEdges()
      },

      layout: {name: 'preset', zoom: 1, pan: pan},
      style: this.createStyle(),
      zoomingEnabled: false,
      autoungrabify: true
    });

    const hammer = new Hammer.Manager(this.cy.container().children.item(0).children.item(0));
    let pinchCenter: Position;

    hammer.add(new Hammer.Pinch());
    hammer.on('pinch', e => {
      if (pinchCenter == null) {
        pinchCenter = e.center;
      }

      document.getElementById('homeButton').innerText = pinchCenter.x + '/' + pinchCenter.y;
      this.zoomTo(this.zoom * Math.pow(10, Math.log10(e.scale) / 10), pinchCenter.x, pinchCenter.y);
    });
    hammer.on('pinchend', () => pinchCenter = null);
    this.cy.container().children.item(0).children.item(0).addEventListener('wheel', (e: WheelEvent) => {
      this.zoomTo(this.zoom * Math.pow(10, e.deltaMode === 1 ? e.deltaY / -25 : e.deltaY / -250), e.offsetX, e.offsetY);
{'fraction_non_alphanumeric': 0.1401792320973444, 'fraction_numerical': 0.008221655841486476, 'mean_word_length': 3.7001545595054095, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1436487', 'n_tokens_mistral': 3957, 'n_tokens_neox': 3790, 'n_words': 801}