Cursor.hx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. package hide.comp.cdb;
  2. typedef CursorState = {
  3. var sheet : String;
  4. var x : Int;
  5. var y : Int;
  6. var select : Null<{ x : Int, y : Int }>;
  7. }
  8. class Cursor {
  9. var editor : Editor;
  10. public var table : Table;
  11. public var x : Int;
  12. public var y : Int;
  13. public var select : Null<{ x : Int, y : Int }>;
  14. public var onchange : Void -> Void;
  15. public function new(editor) {
  16. this.editor = editor;
  17. set();
  18. }
  19. public function setState(state : CursorState, ?table : Table) {
  20. if( state == null )
  21. set(table);
  22. else
  23. set(table, state.x, state.y, state.select);
  24. }
  25. public function getState() : CursorState {
  26. return table == null ? null : {
  27. sheet : table.sheet.getPath(),
  28. x : x,
  29. y : y,
  30. select : Reflect.copy(select)
  31. };
  32. }
  33. public function set( ?t:Table, ?x=0, ?y=0, ?sel, update = true ) {
  34. if( t != null ) {
  35. for( t2 in editor.tables )
  36. if( t.sheet.getPath() == t2.sheet.getPath() ) {
  37. t = t2;
  38. break;
  39. }
  40. }
  41. this.table = t;
  42. this.x = x;
  43. this.y = y;
  44. this.select = sel;
  45. var ch = onchange;
  46. if( ch != null ) {
  47. onchange = null;
  48. ch();
  49. }
  50. if( update ) this.update();
  51. }
  52. public function setDefault(line, column) {
  53. set(editor.tables[0], column, line);
  54. }
  55. public function getLine() {
  56. if( table == null ) return null;
  57. return table.lines[y];
  58. }
  59. public function getCell() {
  60. var line = getLine();
  61. if( line == null ) return null;
  62. return line.cells[x];
  63. }
  64. public function save() {
  65. if( table == null ) return null;
  66. return { sheet : table.sheet, x : x, y : y, select : select == null ? null : { x : select.x, y : select.y} };
  67. }
  68. public function load( s ) {
  69. if( s == null )
  70. return false;
  71. var table = null;
  72. for( t in editor.tables )
  73. if( t.sheet == s.sheet ) {
  74. table = t;
  75. break;
  76. }
  77. if( table == null )
  78. return false;
  79. set(table, s.x, s.y, s.select);
  80. return true;
  81. }
  82. public function move( dx : Int, dy : Int, shift : Bool, ctrl : Bool ) {
  83. if( table == null )
  84. table = editor.tables[0];
  85. if( x == -1 && ctrl ) {
  86. if( dy != 0 )
  87. editor.moveLine(getLine(), dy);
  88. update();
  89. return;
  90. }
  91. // enter/leave subtable
  92. if( dx == 0 && !shift && !ctrl ) {
  93. var c = getCell();
  94. if( c != null && dy == 1 && c.line.subTable != null && c.line.subTable.cell == c ) {
  95. set(c.line.subTable);
  96. return;
  97. }
  98. var st = Std.downcast(table, SubTable);
  99. if( c != null && dy == -1 && st != null && c.line.index == 0 ) {
  100. set(st.parent, st.cell.columnIndex, st.cell.line.index);
  101. return;
  102. }
  103. }
  104. // take care of current filter
  105. var line = getLine();
  106. if( line != null && dy != 0 ) {
  107. var allLines = line.element.parent().children("tr").not(".separator");
  108. var lines = allLines.not(".filtered").not(".hidden");
  109. var index = lines.index(line.element);
  110. var targetLine = lines.get(hxd.Math.imax(index + dy,0));
  111. if( targetLine == null || targetLine == line.element.get(0) ) return;
  112. dy = allLines.index(targetLine) - allLines.index(line.element);
  113. }
  114. if( !shift )
  115. select = null;
  116. else if( select == null )
  117. select = { x : x, y : y };
  118. if( dx < 0 ) {
  119. x += dx;
  120. var minX = table.displayMode == Table ? -1 : 0;
  121. if( x < minX ) x = minX;
  122. }
  123. if( dy < 0 ) {
  124. y += dy;
  125. if( y < 0 ) y = 0;
  126. }
  127. if( dx > 0 ) {
  128. x += dx;
  129. var max = table.columns.length;
  130. if( x >= max ) x = max - 1;
  131. }
  132. if( dy > 0 ) {
  133. y += dy;
  134. var max = table.lines.length;
  135. if( y >= max ) y = max - 1;
  136. }
  137. update();
  138. }
  139. public function hide() {
  140. var elt = editor.element;
  141. elt.find(".selected").removeClass("selected");
  142. elt.find(".cursorView").removeClass("cursorView");
  143. elt.find(".cursorLine").removeClass("cursorLine");
  144. }
  145. public function update() {
  146. var elt = editor.element;
  147. hide();
  148. if( table == null )
  149. return;
  150. if( y < 0 ) {
  151. y = 0;
  152. select = null;
  153. }
  154. if( y >= table.lines.length ) {
  155. y = table.lines.length - 1;
  156. select = null;
  157. }
  158. var max = table.sheet.props.isProps || table.columns == null ? 1 : table.columns.length;
  159. if( x >= max ) {
  160. x = max - 1;
  161. select = null;
  162. }
  163. var line = getLine();
  164. if( line == null )
  165. return;
  166. if( x < 0 ) {
  167. line.element.addClass("selected");
  168. if( select != null ) {
  169. var cy = y;
  170. while( select.y != cy ) {
  171. if( select.y > cy ) cy++ else cy--;
  172. table.lines[cy].element.addClass("selected");
  173. }
  174. }
  175. } else {
  176. var c = line.cells[x];
  177. if( c != null )
  178. c.element.addClass("cursorView").closest("tr").addClass("cursorLine");
  179. if( select != null ) {
  180. var s = getSelection();
  181. for( y in s.y1...s.y2 + 1 ) {
  182. var l = table.lines[y];
  183. for( x in s.x1...s.x2+1)
  184. l.cells[x].element.addClass("selected");
  185. }
  186. }
  187. }
  188. var e = line.element[0];
  189. if( e != null ) untyped e.scrollIntoViewIfNeeded();
  190. }
  191. public function getSelection() {
  192. if( table == null )
  193. return null;
  194. var x1 = if( x < 0 ) 0 else x;
  195. var x2 = if( x < 0 ) table.columns.length-1 else if( select != null ) select.x else x1;
  196. var y1 = y;
  197. var y2 = if( select != null ) select.y else y1;
  198. if( x2 < x1 ) {
  199. var tmp = x2;
  200. x2 = x1;
  201. x1 = tmp;
  202. }
  203. if( y2 < y1 ) {
  204. var tmp = y2;
  205. y2 = y1;
  206. y1 = tmp;
  207. }
  208. return { x1 : x1, x2 : x2, y1 : y1, y2 : y2 };
  209. }
  210. public function clickLine( line : Line, shiftKey = false ) {
  211. var sheet = line.table.sheet;
  212. if( shiftKey && this.table == line.table && x < 0 ) {
  213. select = { x : -1, y : line.index };
  214. update();
  215. } else {
  216. editor.pushCursorState();
  217. set(line.table, -1, line.index);
  218. }
  219. }
  220. public function clickCell( cell : Cell, shiftKey = false ) {
  221. var xIndex = cell.table.displayMode == Table ? cell.columnIndex : 0;
  222. if( shiftKey && table == cell.table ) {
  223. select = { x : xIndex, y : cell.line.index };
  224. update();
  225. } else {
  226. editor.pushCursorState();
  227. set(cell.table, xIndex, cell.line.index);
  228. }
  229. }
  230. }