Table.hx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. package hide.comp.cdb;
  2. import js.jquery.Helper.*;
  3. enum DisplayMode {
  4. Table;
  5. Properties;
  6. AllProperties;
  7. }
  8. class Table extends Component {
  9. public var editor : Editor;
  10. public var parent : Table;
  11. public var sheet : cdb.Sheet;
  12. public var lines : Array<Line>;
  13. public var displayMode(default,null) : DisplayMode;
  14. public function new(editor, sheet, root, mode) {
  15. super(null,root);
  16. this.displayMode = mode;
  17. this.editor = editor;
  18. this.sheet = sheet;
  19. @:privateAccess editor.tables.push(this);
  20. root.addClass("cdb-sheet");
  21. refresh();
  22. }
  23. public function close() {
  24. element.remove();
  25. dispose();
  26. }
  27. public function dispose() {
  28. editor.tables.remove(this);
  29. }
  30. public function refresh() {
  31. element.empty();
  32. switch( displayMode ) {
  33. case Table:
  34. refreshTable();
  35. case Properties, AllProperties:
  36. refreshProperties();
  37. }
  38. }
  39. public function cloneTableHead() {
  40. var target = J('.head');
  41. if (target.length == 0) {
  42. trace("Fail clone table head");
  43. return;
  44. }
  45. var target_children = target.children();
  46. J(".floating-thead").remove();
  47. var clone = J("<div>").addClass("floating-thead");
  48. for (i in 0...target_children.length) {
  49. var targetElt = target_children.eq(i);
  50. var elt = targetElt.clone(true); // clone with events
  51. elt.width(targetElt.width());
  52. elt.css("max-width", targetElt.width());
  53. var txt = elt[0].innerHTML;
  54. elt.empty();
  55. J("<span>" + txt + "</span>").appendTo(elt);
  56. clone.append(elt);
  57. }
  58. J('.cdb').prepend(clone);
  59. }
  60. function refreshTable() {
  61. var cols = J("<thead>").addClass("head");
  62. J("<th>").addClass("start").appendTo(cols);
  63. lines = [for( index in 0...sheet.lines.length ) {
  64. var l = J("<tr>");
  65. var head = J("<td>").addClass("start").text("" + index);
  66. head.appendTo(l);
  67. var line = new Line(this, sheet.columns, index, l);
  68. l.mousedown(function(e) {
  69. if( e.which == 3 ) {
  70. head.click();
  71. editor.popupLine(line);
  72. e.preventDefault();
  73. return;
  74. }
  75. }).click(function(e) {
  76. editor.cursor.clickLine(line, e.shiftKey);
  77. });
  78. line;
  79. }];
  80. var colCount = sheet.columns.length;
  81. for( cindex in 0...sheet.columns.length ) {
  82. var c = sheet.columns[cindex];
  83. var col = J("<th>");
  84. col.text(c.name);
  85. col.addClass( "t_"+c.type.getName().substr(1).toLowerCase() );
  86. if( sheet.props.displayColumn == c.name )
  87. col.addClass("display");
  88. col.mousedown(function(e) {
  89. if( e.which == 3 ) {
  90. editor.popupColumn(this, c);
  91. e.preventDefault();
  92. return;
  93. }
  94. });
  95. col.dblclick(function(_) {
  96. editor.editColumn(sheet, c);
  97. });
  98. cols.append(col);
  99. for( index in 0...sheet.lines.length ) {
  100. var v = J("<td>").addClass("c");
  101. var line = lines[index];
  102. v.appendTo(line.element);
  103. var cell = new Cell(v, line, c);
  104. v.click(function(e) {
  105. editor.cursor.clickCell(cell, e.shiftKey);
  106. e.stopPropagation();
  107. });
  108. switch( c.type ) {
  109. case TList, TProperties:
  110. cell.element.click(function(e) {
  111. if( e.shiftKey ) return;
  112. e.stopPropagation();
  113. toggleList(cell);
  114. });
  115. default:
  116. cell.element.dblclick(function(_) cell.edit());
  117. }
  118. }
  119. }
  120. element.append(cols);
  121. var tbody = J("<tbody>");
  122. var snext = 0;
  123. for( i in 0...lines.length+1 ) {
  124. while( sheet.separators[snext] == i ) {
  125. makeSeparator(snext, colCount).appendTo(tbody);
  126. snext++;
  127. }
  128. if( i == lines.length ) break;
  129. tbody.append(lines[i].element);
  130. }
  131. element.append(tbody);
  132. if( sheet.lines.length == 0 ) {
  133. var l = J('<tr><td colspan="${sheet.columns.length + 1}"><a>Insert Line</a></td></tr>');
  134. l.find("a").click(function(_) {
  135. editor.insertLine(this);
  136. editor.cursor.set(this);
  137. });
  138. element.append(l);
  139. }
  140. cols.ready(cloneTableHead);
  141. cols.on("resize", cloneTableHead);
  142. }
  143. function makeSeparator( sindex : Int, colCount : Int ) {
  144. var sep = J("<tr>").addClass("separator").append('<td colspan="${colCount+1}">');
  145. var content = sep.find("td");
  146. var title = if( sheet.props.separatorTitles != null ) sheet.props.separatorTitles[sindex] else null;
  147. if( title != null ) content.text(title);
  148. sep.dblclick(function(e) {
  149. content.empty();
  150. J("<input>").appendTo(content).focus().val(title == null ? "" : title).blur(function(_) {
  151. title = JTHIS.val();
  152. JTHIS.remove();
  153. content.text(title);
  154. var old = sheet.props.separatorTitles;
  155. var titles = sheet.props.separatorTitles;
  156. if( titles == null ) titles = [] else titles = titles.copy();
  157. while( titles.length < sindex )
  158. titles.push(null);
  159. titles[sindex] = title == "" ? null : title;
  160. while( titles[titles.length - 1] == null && titles.length > 0 )
  161. titles.pop();
  162. if( titles.length == 0 ) titles = null;
  163. editor.beginChanges();
  164. sheet.props.separatorTitles = titles;
  165. editor.endChanges();
  166. }).keypress(function(e) {
  167. e.stopPropagation();
  168. }).keydown(function(e) {
  169. if( e.keyCode == 13 ) { JTHIS.blur(); e.preventDefault(); } else if( e.keyCode == 27 ) content.text(title);
  170. e.stopPropagation();
  171. });
  172. });
  173. return sep;
  174. }
  175. function refreshProperties() {
  176. lines = [];
  177. var available = [];
  178. var props = sheet.lines[0];
  179. for( c in sheet.columns ) {
  180. if( c.opt && !Reflect.hasField(props,c.name) && displayMode != AllProperties ) {
  181. available.push(c);
  182. continue;
  183. }
  184. var v = Reflect.field(props, c.name);
  185. var l = new Element("<tr>").appendTo(element);
  186. var th = new Element("<th>").text(c.name).appendTo(l);
  187. var td = new Element("<td>").addClass("c").appendTo(l);
  188. var line = new Line(this, [c], lines.length, l);
  189. var cell = new Cell(td, line, c);
  190. lines.push(line);
  191. td.click(function(e) {
  192. editor.cursor.clickCell(cell, e.shiftKey);
  193. e.stopPropagation();
  194. });
  195. th.mousedown(function(e) {
  196. if( e.which == 3 ) {
  197. editor.popupColumn(this, c);
  198. editor.cursor.clickCell(cell, false);
  199. e.preventDefault();
  200. return;
  201. }
  202. });
  203. cell.element.dblclick(function(_) cell.edit());
  204. }
  205. // add/edit properties
  206. var end = new Element("<tr>").appendTo(element);
  207. end = new Element("<td>").attr("colspan", "2").appendTo(end);
  208. var sel = new Element("<select class='insertField'>").appendTo(end);
  209. new Element("<option>").attr("value", "").text("--- Choose ---").appendTo(sel);
  210. for( c in available )
  211. J("<option>").attr("value",c.name).text(c.name).appendTo(sel);
  212. J("<option>").attr("value","$new").text("New property...").appendTo(sel);
  213. sel.change(function(e) {
  214. var v = sel.val();
  215. if( v == "" )
  216. return;
  217. sel.val("");
  218. editor.element.focus();
  219. if( v == "$new" ) {
  220. editor.newColumn(sheet);
  221. return;
  222. }
  223. insertProperty(v);
  224. });
  225. }
  226. public function insertProperty( p : String ) {
  227. var props = sheet.lines[0];
  228. for( c in sheet.columns )
  229. if( c.name == p ) {
  230. var val = editor.base.getDefault(c, true);
  231. editor.beginChanges();
  232. Reflect.setField(props, c.name, val);
  233. editor.endChanges();
  234. refresh();
  235. return true;
  236. }
  237. return false;
  238. }
  239. function toggleList( cell : Cell, ?immediate : Bool, ?make : Void -> SubTable ) {
  240. var line = cell.line;
  241. var cur = line.subTable;
  242. if( cur != null ) {
  243. cur.close();
  244. if( cur.cell == cell ) return; // toggle
  245. }
  246. var sub = make == null ? new SubTable(editor, cell) : make();
  247. sub.show(immediate);
  248. editor.cursor.set(sub);
  249. }
  250. function toString() {
  251. return "Table#"+sheet.name;
  252. }
  253. }