1 /* DrawOfPages: Take notes with touchscreen input. 2 * Copyright (C) 2017 Marko Semet(Marko10_000) 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 */ 17 module drawofpages.tools.interaction; 18 19 private 20 { 21 import core.thread; 22 import drawofpages.draw; 23 import drawofpages.gui; 24 import drawofpages.tools; 25 import structuresd.containers.queue; 26 } 27 28 package struct CursorInteraction 29 { 30 Point2D pos; 31 CURSOR_TYPE ctype; 32 double pressure; 33 string id; 34 } 35 package struct RedrawInteraction 36 { 37 Square box; 38 Draw target; 39 } 40 41 public class DrawThread : Thread 42 { 43 private enum INTERACTION_TYPE 44 { 45 REDRAW = 0, 46 CURSOR_DOWN = 1, 47 CURSOR_CONTIN = 2, 48 CURSOR_UP = 3 49 } 50 private static struct Interaction 51 { 52 public INTERACTION_TYPE itype; 53 public Document doc; 54 public Tool tool; 55 public Draw draw; 56 union 57 { 58 public CursorInteraction cursor; 59 public RedrawInteraction redraw; 60 } 61 } 62 63 private Queue!(Interaction, true) queue; 64 public bool stop; 65 66 private void run() 67 { 68 Interaction tmp; 69 while(!this.stop) 70 { 71 bool[Draw] redraw; 72 while(this.queue.fetch(tmp)) 73 { 74 if(tmp.tool is null) 75 { 76 continue; 77 } 78 final switch(tmp.itype) 79 { 80 case INTERACTION_TYPE.REDRAW: 81 redraw[tmp.draw] = true; 82 tmp.doc.redraw(tmp.redraw.box, tmp.redraw.target); 83 break; 84 case INTERACTION_TYPE.CURSOR_DOWN: 85 redraw[tmp.draw] = true; 86 tmp.tool.cursorDown(tmp.doc, tmp.cursor.pos, tmp.cursor.ctype, tmp.cursor.pressure, tmp.cursor.id); 87 break; 88 case INTERACTION_TYPE.CURSOR_CONTIN: 89 redraw[tmp.draw] = true; 90 tmp.tool.cursorContin(tmp.doc, tmp.cursor.pos, tmp.cursor.ctype, tmp.cursor.pressure, tmp.cursor.id); 91 break; 92 case INTERACTION_TYPE.CURSOR_UP: 93 redraw[tmp.draw] = true; 94 tmp.tool.cursorUp(tmp.doc, tmp.cursor.pos, tmp.cursor.ctype, tmp.cursor.pressure, tmp.cursor.id); 95 break; 96 } 97 } 98 foreach(Draw draw; redraw.keys) 99 { 100 draw.redraw(); 101 } 102 yield(); 103 } 104 } 105 106 public this() 107 { 108 this.queue = new Queue!(Interaction, true); 109 this.stop = false; 110 super(&this.run); 111 this.start(); 112 } 113 114 pragma(inline, true) 115 private void add(ref Interaction interact) 116 { 117 this.queue.insert(interact); 118 } 119 120 pragma(inline, true) 121 public void add(string TYPE)(Document doc, Draw draw, Tool tool, CursorInteraction ci) 122 { 123 Interaction tmp; 124 static if(TYPE == "DOWN") 125 { 126 tmp.itype = INTERACTION_TYPE.CURSOR_DOWN; 127 } 128 else static if(TYPE == "CONTIN") 129 { 130 tmp.itype = INTERACTION_TYPE.CURSOR_CONTIN; 131 } 132 else static if(TYPE == "UP") 133 { 134 tmp.itype = INTERACTION_TYPE.CURSOR_UP; 135 } 136 else 137 { 138 static assert(false); 139 } 140 tmp.doc = doc; 141 tmp.tool = tool; 142 tmp.cursor = ci; 143 tmp.draw = draw; 144 this.add(tmp); 145 } 146 147 pragma(inline, true) 148 public void add(Document doc, Draw draw, RedrawInteraction redraw) 149 { 150 Interaction tmp; 151 tmp.itype = INTERACTION_TYPE.REDRAW; 152 tmp.doc = doc; 153 tmp.tool = voidTool; 154 tmp.draw = draw; 155 tmp.redraw = redraw; 156 this.add(tmp); 157 } 158 }; 159 160 public class InteractionSafer : GuiInteraction 161 { 162 private Document document; 163 public Tool currentTool; 164 private DrawThread thread; 165 private Draw draw; 166 167 public this(DrawThread thread, Draw draw) 168 { 169 this.document = new Document(); 170 this.currentTool = null; 171 this.thread = thread; 172 this.draw = draw; 173 } 174 175 public void down(Point2D point, CURSOR_TYPE cursor, double pressure, string cursorID) 176 { 177 CursorInteraction ci; 178 ci.pos = point; 179 ci.ctype = cursor; 180 ci.pressure = pressure; 181 ci.id = cursorID; 182 thread.add!"DOWN"(this.document, this.draw, this.currentTool, ci); 183 } 184 public void contin(Point2D point, CURSOR_TYPE cursor, double pressure, string cursorID) 185 { 186 CursorInteraction ci; 187 ci.pos = point; 188 ci.ctype = cursor; 189 ci.pressure = pressure; 190 ci.id = cursorID; 191 thread.add!"CONTIN"(this.document, this.draw, this.currentTool, ci); 192 } 193 public void up(Point2D point, CURSOR_TYPE cursor, double pressure, string cursorID) 194 { 195 CursorInteraction ci; 196 ci.pos = point; 197 ci.ctype = cursor; 198 ci.pressure = pressure; 199 ci.id = cursorID; 200 thread.add!"UP"(this.document, this.draw, this.currentTool, ci); 201 } 202 public void redraw(Square area, Draw target) 203 { 204 RedrawInteraction ri; 205 ri.box = area; 206 ri.target = target; 207 this.thread.add(this.document, this.draw, ri); 208 } 209 }