AbstractDisplayInteractionManager.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { IDisplayInteractionListener } from "../Common/Interfaces/IDisplayInteractionListener";
  2. export abstract class AbstractDisplayInteractionManager {
  3. protected listeners: IDisplayInteractionListener[] = [];
  4. private zoomGestureActive: boolean = false;
  5. protected touchCount: number = 0;
  6. protected touchActive: boolean = false;
  7. protected touchMoving: boolean = false;
  8. private lastRelPosX: number;
  9. private lastRelPosY: number;
  10. protected lastPixelX: number;
  11. protected lastPixelY: number;
  12. protected displayWidth: number = 1;
  13. protected displayHeight: number = 1;
  14. protected displayDpi: number = 96;
  15. protected maxNumerOfFingers: number = 2;
  16. protected movementThreshInch: number = 0.075;
  17. protected interactionWasZoomGesture: boolean = false;
  18. constructor() {
  19. // TODO MB: Linter doesn't like empty constructors. Can we just remove this?
  20. }
  21. public addListener(listener: IDisplayInteractionListener): void {
  22. this.listeners.push(listener);
  23. }
  24. public get ZoomGestureActive(): boolean {
  25. return this.zoomGestureActive;
  26. }
  27. public get WasZoomGestureActive(): boolean {
  28. return this.interactionWasZoomGesture;
  29. }
  30. public displaySizeChanged(displayWidthInPixel: number, displayHeightInPixel: number): void {
  31. this.displayWidth = displayWidthInPixel;
  32. this.displayHeight = displayHeightInPixel;
  33. for (const listener of this.listeners) {
  34. listener.displaySizeChanged(this.displayWidth, this.displayHeight);
  35. }
  36. }
  37. public Dispose(): void {
  38. this.dispose();
  39. }
  40. public Initialize(): void {
  41. this.initialize();
  42. }
  43. public get DisplayDpi(): number {
  44. return this.displayDpi;
  45. }
  46. public get TouchActive(): boolean {
  47. return this.touchActive;
  48. }
  49. public get TouchMoving(): boolean {
  50. return this.touchMoving;
  51. }
  52. protected abstract dispose(): void;
  53. protected abstract initialize(): void;
  54. protected touchDown(positionInPixelX: number, positionInPixelY: number, leftMouseButton: boolean): void {
  55. this.interactionWasZoomGesture = false;
  56. const relativePositionX: number = positionInPixelX / this.displayWidth;
  57. const relativePositionY: number = positionInPixelY / this.displayHeight;
  58. this.lastRelPosX = relativePositionX;
  59. this.lastRelPosY = relativePositionY;
  60. this.lastPixelX = positionInPixelX;
  61. this.lastPixelY = positionInPixelY;
  62. this.touchActive = true;
  63. this.touchMoving = false;
  64. this.touchCount = Math.min(this.touchCount + 1, this.maxNumerOfFingers);
  65. for (const listener of this.listeners) {
  66. //JL: Why is this negating the leftmousebutton? i guess it expects it to be undefined since it is a touch?
  67. listener.mouseDown(relativePositionX, relativePositionY, !leftMouseButton);
  68. }
  69. }
  70. protected move(positionInPixelX: number, positionInPixelY: number): void {
  71. if (this.touchActive && !this.zoomGestureActive) {
  72. const relativePositionX: number = positionInPixelX / this.displayWidth;
  73. const relativePositionY: number = positionInPixelY / this.displayHeight;
  74. const deltaX: number = (relativePositionX - this.lastRelPosX);
  75. const deltaY: number = (relativePositionY - this.lastRelPosY);
  76. this.touchMoving = true;
  77. for (const listener of this.listeners) {
  78. listener.mouseMove(relativePositionX, relativePositionY, deltaX, deltaY);
  79. }
  80. }
  81. }
  82. protected zoomGestureStarted(): void {
  83. this.zoomGestureActive = true;
  84. }
  85. protected zoomGestureCompleted(): void {
  86. this.zoomGestureActive = false;
  87. this.interactionWasZoomGesture = true;
  88. }
  89. protected zoomGestureMove(scale: number): void {
  90. if (this.zoomGestureActive) {
  91. this.listeners.forEach(function (dil: IDisplayInteractionListener): void {
  92. dil.zoom(scale);
  93. });
  94. }
  95. }
  96. protected touchUp(positionInPixelX: number, positionInPixelY: number): void {
  97. this.touchActive = false;
  98. this.touchMoving = false;
  99. this.touchCount = Math.max(0, this.touchCount - 1);
  100. const relativePositionX: number = positionInPixelX / this.displayWidth;
  101. const relativePositionY: number = positionInPixelY / this.displayHeight;
  102. for (const listener of this.listeners) {
  103. listener.mouseUp(relativePositionX, relativePositionY);
  104. }
  105. }
  106. protected click(positionInPixelX: number, positionInPixelY: number): void {
  107. // don't click, if it was a move:
  108. // changed to still fire click even for small movements (needed for ios, as no touches began fires at view border.)
  109. if (!this.mouseDidMove(this.lastPixelX, positionInPixelX, this.lastPixelY, positionInPixelY) && !this.ZoomGestureActive) {
  110. const relativePositionX: number = positionInPixelX / this.displayWidth;
  111. const relativePositionY: number = positionInPixelY / this.displayHeight;
  112. for (const listener of this.listeners) {
  113. listener.positionTouched(relativePositionX, relativePositionY);
  114. }
  115. }
  116. }
  117. protected doubleClick(positionInPixelX: number, positionInPixelY: number): void {
  118. // don't click, if it was a move:
  119. // changed to still fire click even for small movements (needed for ios, as no touches began fired at view border.)
  120. if (!this.mouseDidMove(this.lastPixelX, positionInPixelX, this.lastPixelY, positionInPixelY) && !this.ZoomGestureActive) {
  121. const relativePositionX: number = positionInPixelX / this.displayWidth;
  122. const relativePositionY: number = positionInPixelY / this.displayHeight;
  123. for (const listener of this.listeners) {
  124. listener.positionDoubleTouched(relativePositionX, relativePositionY);
  125. }
  126. }
  127. }
  128. protected mouseDidMove(oldPosX: number, newPosX: number, oldPosY: number, newPosY: number): boolean {
  129. const movementDpiX: number = Math.abs(oldPosX - newPosX) / this.displayDpi;
  130. const movementDpiY: number = Math.abs(oldPosY - newPosY) / this.displayDpi;
  131. return movementDpiX > this.movementThreshInch || movementDpiY > this.movementThreshInch;
  132. }
  133. }