From fb98f4837192086a2fd062cdf7a47237cfdeb369 Mon Sep 17 00:00:00 2001
From: Eugen Ciur <eugen@papermerge.com>
Date: Tue, 1 Mar 2022 20:58:32 +0100
Subject: [PATCH] correct selection and multiple items dragging

---
 app/components/commander/index.js             |  4 ----
 app/components/viewer/document/index.hbs      |  8 +++++++
 app/components/viewer/document/index.js       | 13 ++++++++++
 app/components/viewer/index.hbs               |  9 +++----
 app/components/viewer/index.js                |  7 +++++-
 app/components/viewer/page.hbs                |  8 +++++--
 app/components/viewer/pages.hbs               |  4 +++-
 .../{thumbnail.hbs => thumbnail/index.hbs}    |  4 +++-
 app/components/viewer/thumbnail/index.js      | 11 +++++++++
 app/components/viewer/thumbnails.hbs          |  4 +++-
 app/modifiers/draggable.js                    | 23 +++++++++++++++++-
 app/modifiers/scroll_into_view.js             | 24 +++++++++++++++++++
 app/modifiers/ui_select.js                    |  4 ++++
 app/utils/rectangle.js                        |  8 ++++++-
 tests/unit/rectangle-test.js                  | 14 +++++++++++
 15 files changed, 129 insertions(+), 16 deletions(-)
 create mode 100644 app/components/viewer/document/index.hbs
 create mode 100644 app/components/viewer/document/index.js
 rename app/components/viewer/{thumbnail.hbs => thumbnail/index.hbs} (63%)
 create mode 100644 app/components/viewer/thumbnail/index.js
 create mode 100644 app/modifiers/scroll_into_view.js

diff --git a/app/components/commander/index.js b/app/components/commander/index.js
index 924236d..789840e 100644
--- a/app/components/commander/index.js
+++ b/app/components/commander/index.js
@@ -258,10 +258,6 @@ export default class CommanderComponent extends Component {
       succeeded. It is invoked on the SOURCE panel.
       `model` is instance of `model.document` or `model.folder`
     */
-    console.log(
-      `onDragendSuccess on ${this.args.hint}: id=${model.id} type=${model.nodeType}`
-    );
-    console.log(`onDragendSuccess selected_nodes=${sel_nodes}`);
     this.selected_nodes = []; // reset currect selected nodes list
   }
 
diff --git a/app/components/viewer/document/index.hbs b/app/components/viewer/document/index.hbs
new file mode 100644
index 0000000..f3128a6
--- /dev/null
+++ b/app/components/viewer/document/index.hbs
@@ -0,0 +1,8 @@
+<div class="d-flex">
+  <Viewer::Thumbnails
+    @pages={{@pages}}
+    @onDblClick={{this.onThumbnailDblClick}} />
+  <Viewer::Pages
+    @pages={{@pages}}
+    @scroll_to_page={{this.scroll_to_page}} />
+</div>
\ No newline at end of file
diff --git a/app/components/viewer/document/index.js b/app/components/viewer/document/index.js
new file mode 100644
index 0000000..e22025e
--- /dev/null
+++ b/app/components/viewer/document/index.js
@@ -0,0 +1,13 @@
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { action } from '@ember/object';
+
+
+export default class ViewerDocumentComponent extends Component {
+  @tracked scroll_to_page;
+
+  @action
+  onThumbnailDblClick(page) {
+    this.scroll_to_page = page;
+  }
+}
\ No newline at end of file
diff --git a/app/components/viewer/index.hbs b/app/components/viewer/index.hbs
index db0f1d1..97a21d6 100644
--- a/app/components/viewer/index.hbs
+++ b/app/components/viewer/index.hbs
@@ -16,10 +16,11 @@
     @node={{@doc}}
     @extranode={{@extranode}}
     @extradoc={{@extradoc}}
+    @onNodeClicked={{this.onNodeClicked}}
     @hint={{@hint}} />
 
-  <div class="d-flex">
-    <Viewer::Thumbnails @pages={{this.pages}} />
-    <Viewer::Pages @pages={{this.pages}} />
-  </div>
+
+  <Viewer::Document
+    @pages={{this.pages}} />
+
 </div>
diff --git a/app/components/viewer/index.js b/app/components/viewer/index.js
index 431e7e7..bb30f00 100644
--- a/app/components/viewer/index.js
+++ b/app/components/viewer/index.js
@@ -1,6 +1,6 @@
 import Component from '@glimmer/component';
 import { tracked } from '@glimmer/tracking';
-import { inject as service } from '@ember/service';
+import { service } from '@ember/service';
 import { action } from '@ember/object';
 import { A } from '@ember/array';
 
@@ -100,6 +100,11 @@ export default class ViewerComponent extends Component {
     });
   }
 
+  @action
+  onNodeClicked() {
+    console.log('node clicked');
+  }
+
   get versions() {
     /* Just a shortcut */
     return this.args.doc.versions;
diff --git a/app/components/viewer/page.hbs b/app/components/viewer/page.hbs
index 6c432f6..f32dab0 100644
--- a/app/components/viewer/page.hbs
+++ b/app/components/viewer/page.hbs
@@ -1,4 +1,7 @@
-<div class="page d-flex flex-column align-items-center">
+<div
+  class="page d-flex flex-column align-items-center"
+  {{scrollIntoView page=@page scroll_to_page=@scroll_to_page}}>
+
   {{#if @page.svg_image}}
     {{{@page.svg_image}}}
   {{else}}
@@ -7,4 +10,5 @@
   <div class="number fs-3 m-3">
     {{@page.number}}
   </div>
-</div>
\ No newline at end of file
+
+</div> <!-- .page -->
diff --git a/app/components/viewer/pages.hbs b/app/components/viewer/pages.hbs
index 1e23bbc..dca9a51 100644
--- a/app/components/viewer/pages.hbs
+++ b/app/components/viewer/pages.hbs
@@ -1,5 +1,7 @@
 <div class="d-flex flex-column pages">
   {{#each @pages as |page|}}
-    <Viewer::Page @page={{page}} />
+    <Viewer::Page
+      @page={{page}}
+      @scroll_to_page={{@scroll_to_page}} />
   {{/each}}
 </div>
\ No newline at end of file
diff --git a/app/components/viewer/thumbnail.hbs b/app/components/viewer/thumbnail/index.hbs
similarity index 63%
rename from app/components/viewer/thumbnail.hbs
rename to app/components/viewer/thumbnail/index.hbs
index 293513a..87f494b 100644
--- a/app/components/viewer/thumbnail.hbs
+++ b/app/components/viewer/thumbnail/index.hbs
@@ -1,4 +1,6 @@
-<div class="thumbnail d-flex flex-column align-items-center">
+<div
+  class="thumbnail d-flex flex-column align-items-center"
+  {{on "dblclick" this.onDblClick}} >
   {{#if @page.svg_image}}
     {{{@page.svg_image}}}
   {{else}}
diff --git a/app/components/viewer/thumbnail/index.js b/app/components/viewer/thumbnail/index.js
new file mode 100644
index 0000000..4a7220b
--- /dev/null
+++ b/app/components/viewer/thumbnail/index.js
@@ -0,0 +1,11 @@
+import Component from '@glimmer/component';
+import { action } from '@ember/object';
+
+
+export default class ViewerThumbnailComponent extends Component {
+
+  @action
+  onDblClick() {
+    this.args.onDblClick(this.args.page);
+  }
+}
\ No newline at end of file
diff --git a/app/components/viewer/thumbnails.hbs b/app/components/viewer/thumbnails.hbs
index 0752d9a..7c0a4b8 100644
--- a/app/components/viewer/thumbnails.hbs
+++ b/app/components/viewer/thumbnails.hbs
@@ -1,5 +1,7 @@
 <div class="d-flex flex-column thumbnails">
   {{#each @pages as |page|}}
-    <Viewer::Thumbnail @page={{page}} />
+    <Viewer::Thumbnail
+      @page={{page}}
+      @onDblClick={{@onDblClick}} />
   {{/each}}
 </div>
\ No newline at end of file
diff --git a/app/modifiers/draggable.js b/app/modifiers/draggable.js
index b908729..733367b 100644
--- a/app/modifiers/draggable.js
+++ b/app/modifiers/draggable.js
@@ -59,7 +59,7 @@ export default class DraggableModifier extends Modifier {
 
   @action
   onDragStart(event) {
-    let data, nodes;
+    let data, nodes, canvas;
 
     this.model = this.args.positional[0];
     this.selected_nodes = this.args.named['selectedNodes'];
@@ -77,10 +77,31 @@ export default class DraggableModifier extends Modifier {
       }
     }
 
+    canvas = this.get_drag_canvas(nodes.length);
+
     event.dataTransfer.setData(
       "application/x.node",
       JSON.stringify(data)
     );
+
+    event.dataTransfer.setDragImage(canvas, 0, -15);
+  }
+
+  get_drag_canvas(count) {
+    /*
+      Returns a canvas with `Move ${count} item(s)` text on it.
+    */
+    let canvas = document.createElement("canvas"),
+      ctx;
+
+    canvas.width = 280;
+    canvas.height = 120;
+    ctx = canvas.getContext("2d");
+    ctx.font = "18px Arial";
+
+    ctx.fillText(`Move ${count} item(s)`, 10, 20);
+
+    return canvas;
   }
 
   @action
diff --git a/app/modifiers/scroll_into_view.js b/app/modifiers/scroll_into_view.js
new file mode 100644
index 0000000..b7b887e
--- /dev/null
+++ b/app/modifiers/scroll_into_view.js
@@ -0,0 +1,24 @@
+import Modifier from 'ember-modifier';
+
+
+export default class ScrollIntoViewModifier extends Modifier {
+
+  didReceiveArguments() {
+    let page, scroll_to_page;
+
+    page = this.args.named['page'];
+    scroll_to_page = this.args.named['scroll_to_page'];
+
+    if (!page) {
+      return;
+    }
+
+    if(!scroll_to_page) {
+      return;
+    }
+
+    if (page.id == scroll_to_page.id) {
+      this.element.scrollIntoView();
+    }
+  }
+}
diff --git a/app/modifiers/ui_select.js b/app/modifiers/ui_select.js
index 5b70a01..7a8c06a 100644
--- a/app/modifiers/ui_select.js
+++ b/app/modifiers/ui_select.js
@@ -53,6 +53,10 @@ class UISelect {
   update(x, y) {
     let height, width, top, left;
 
+    if (this.is_dragging) {
+      console.log('This is draggin operation. Abort selection.');
+      return;
+    }
 
     this.show(x, y);
     this.current_x = x;
diff --git a/app/utils/rectangle.js b/app/utils/rectangle.js
index 5c89745..028a23f 100644
--- a/app/utils/rectangle.js
+++ b/app/utils/rectangle.js
@@ -38,7 +38,13 @@ export default class Rectangle {
   }
 
   contains_point(x, y) {
-    
+    /*
+      returns true if coord (x, y) is within boundries of the rectangle
+    */
+    let is_within_x = this.x <= x && x <= this.x + this.width,
+        is_within_y = this.y <= y && y <= this.y + this.height;
+
+      return is_within_x && is_within_y;
   }
 
   toString() {
diff --git a/tests/unit/rectangle-test.js b/tests/unit/rectangle-test.js
index 1e117fa..9eecdf8 100644
--- a/tests/unit/rectangle-test.js
+++ b/tests/unit/rectangle-test.js
@@ -76,5 +76,19 @@ module('Unit | Rectangle', function () {
       rect2.intersect(rect1)
     );
   });
+
+  test('contains_point', function(assert) {
+    let rect;
+
+    rect = new Rectangle(100, 100, 20, 20);
+
+    assert.true(
+      rect.contains_point(115, 110)
+    );
+
+    assert.false(
+      rect.contains_point(5, 5)
+    );
+  });
 });
 
-- 
GitLab