InsertBlock.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /**
  2. * Copyright (c) 2011-2018 by Andrew Mustun. All rights reserved.
  3. *
  4. * This file is part of the QCAD project.
  5. *
  6. * QCAD is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * QCAD is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with QCAD.
  18. */
  19. include("../BlockInsert.js");
  20. /**
  21. * \class InsertBlock
  22. * \ingroup ecma_block
  23. * \brief This action handles the user interaction to insert a block
  24. * from the block list into the drawing.
  25. */
  26. function InsertBlock(guiAction) {
  27. BlockInsert.call(this, guiAction);
  28. this.setUiOptions("InsertBlock.ui");
  29. this.blockReferenceData = new RBlockReferenceData();
  30. this.blockReferenceData.setPosition(new RVector(0.0,0.0));
  31. this.blockReferenceData.setScaleFactors(new RVector(1.0,1.0));
  32. this.blockReferenceData.setRotation(0.0);
  33. }
  34. InsertBlock.State = {
  35. SettingPosition : 0
  36. };
  37. InsertBlock.prototype = new BlockInsert();
  38. InsertBlock.includeBasePath = includeBasePath;
  39. InsertBlock.prototype.beginEvent = function() {
  40. BlockInsert.prototype.beginEvent.call(this);
  41. var blockId = Block.getActiveBlockId();
  42. if (blockId===RObject.INVALID_ID) {
  43. this.terminate();
  44. return;
  45. }
  46. this.blockReferenceData.setReferencedBlockId(blockId);
  47. var i, label, edit, sep, a;
  48. var optionsToolBar = EAction.getOptionsToolBar();
  49. // init block attribute inputs to options tool bar:
  50. var doc = this.getDocument();
  51. if (!isNull(doc)) {
  52. var ids = doc.queryBlockEntities(blockId);
  53. var first = true;
  54. var items = [];
  55. for (i=0; i<ids.length; i++) {
  56. var id = ids[i];
  57. var e = doc.queryEntityDirect(id);
  58. if (!isAttributeDefinitionEntity(e)) {
  59. continue;
  60. }
  61. if (first) {
  62. this.showAttributeControls(true);
  63. first = false;
  64. }
  65. var tag = e.getTag();
  66. var prompt = e.getPrompt();
  67. var defaultValue = e.getEscapedText();
  68. items.push([prompt, [tag, defaultValue]]);
  69. }
  70. items.sort(function(a, b) {
  71. return Array.alphaNumericalSorter(a[0], b[0]);
  72. });
  73. var tagCombo = optionsToolBar.findChild("AttributeTag");
  74. for (i=0; i<items.length; i++) {
  75. var item = items[i];
  76. tagCombo.addItem(item[0], item[1]);
  77. }
  78. }
  79. this.setState(InsertBlock.State.SettingPosition);
  80. };
  81. InsertBlock.prototype.initUiOptions = function(resume, optionsToolBar) {
  82. BlockInsert.prototype.initUiOptions.call(this, resume, optionsToolBar);
  83. //var optionsToolBar = EAction.getOptionsToolBar();
  84. var combo = optionsToolBar.findChild("ScaleX");
  85. combo.setCompleter(null);
  86. combo = optionsToolBar.findChild("ScaleY");
  87. combo.setCompleter(null);
  88. combo = optionsToolBar.findChild("Rotation");
  89. combo.setCompleter(null);
  90. };
  91. InsertBlock.prototype.setState = function(state) {
  92. BlockInsert.prototype.setState.call(this, state);
  93. this.setCrosshairCursor();
  94. this.getDocumentInterface().setClickMode(RAction.PickCoordinate);
  95. var appWin = RMainWindowQt.getMainWindow();
  96. var trPos = qsTr("Position");
  97. this.setCommandPrompt(trPos);
  98. this.setLeftMouseTip(trPos);
  99. this.setRightMouseTip(EAction.trCancel);
  100. EAction.showSnapTools();
  101. };
  102. InsertBlock.prototype.pickCoordinate = function(event, preview) {
  103. var di = this.getDocumentInterface();
  104. var pos = event.getModelPosition();
  105. this.blockReferenceData.setPosition(pos);
  106. if (preview) {
  107. di.previewOperation(this.getOperation(true));
  108. }
  109. else {
  110. var op = this.getOperation(false);
  111. if (!isNull(op)) {
  112. di.applyOperation(op);
  113. di.setRelativeZero(pos);
  114. }
  115. }
  116. };
  117. InsertBlock.prototype.getOperation = function(preview) {
  118. var doc = this.getDocument();
  119. if (isNull(doc)) {
  120. return undefined;
  121. }
  122. var blockId = this.blockReferenceData.getReferencedBlockId();
  123. var ids = doc.queryBlockEntities(blockId);
  124. var bd = this.blockReferenceData;
  125. if (preview) {
  126. bd = bd.copy();
  127. // reduce columns / rows for preview:
  128. if (bd.getColumnCount()>1 || bd.getRowCount()>1) {
  129. // max insertions:
  130. var max = RSettings.getPreviewEntities() / ids.length;
  131. // reduce rows:
  132. if (max<2) {
  133. bd.setColumnCount(1);
  134. bd.setRowCount(1);
  135. }
  136. else if (max<bd.getColumnCount()) {
  137. bd.setColumnCount(max);
  138. bd.setRowCount(1);
  139. }
  140. else {
  141. bd.setRowCount(Math.min(bd.getRowCount(), max/bd.getColumnCount()));
  142. }
  143. }
  144. }
  145. var op = new RAddObjectsOperation();
  146. op.setText(this.getToolTitle());
  147. var blockRef = new RBlockReferenceEntity(
  148. doc,
  149. bd
  150. );
  151. op.addObject(blockRef);
  152. // create attribute for each attribute definition in block:
  153. var blockRefId = doc.getStorage().getMaxObjectId();
  154. for (var i=0; i<ids.length; i++) {
  155. var id = ids[i];
  156. var e = doc.queryEntity(id);
  157. if (!isAttributeDefinitionEntity(e)) {
  158. continue;
  159. }
  160. var att = new RAttributeEntity(
  161. doc,
  162. new RAttributeData(e.getData(), blockRefId, e.getTag())
  163. );
  164. att.setBlockId(doc.getCurrentBlockId());
  165. blockRef.applyTransformationTo(att);
  166. // assign values to attributes:
  167. var tag = att.getTag();
  168. if (!isNull(this.attributes[tag])) {
  169. att.setText(this.attributes[tag]);
  170. }
  171. op.addObject(att, false);
  172. }
  173. return op;
  174. };
  175. InsertBlock.prototype.slotKeepProportionsChanged = function(value) {
  176. var optionsToolBar = EAction.getOptionsToolBar();
  177. var scaleXCombo = optionsToolBar.findChild("ScaleX");
  178. var scaleYCombo = optionsToolBar.findChild("ScaleY");
  179. var scaleYLabel = optionsToolBar.findChild("ScaleYLabel");
  180. var keepProportionsSwitch = optionsToolBar.findChild("KeepProportions");
  181. if (value===true) {
  182. scaleYCombo.setEditText(scaleXCombo.currentText);
  183. scaleYCombo.enabled = false;
  184. scaleYLabel.enabled = false;
  185. keepProportionsSwitch.icon = new QIcon(InsertBlock.includeBasePath + "/KeepProportionsOn.svg");
  186. }
  187. else {
  188. scaleYCombo.enabled = true;
  189. scaleYLabel.enabled = true;
  190. keepProportionsSwitch.icon = new QIcon(InsertBlock.includeBasePath + "/KeepProportionsOff.svg");
  191. }
  192. }
  193. InsertBlock.prototype.slotScaleXChanged = function(value) {
  194. if (!isNumber(value)) {
  195. this.blockReferenceData.setScaleFactors(new RVector(1, 1));
  196. return;
  197. }
  198. var optionsToolBar = EAction.getOptionsToolBar();
  199. var keepProportionsSwitch = optionsToolBar.findChild("KeepProportions");
  200. var keepProportions = keepProportionsSwitch.checked;
  201. var scaleX = value;
  202. var scaleY = this.blockReferenceData.getScaleFactors().y;
  203. // if keep proportions is checked, adjust y scale proportionally to x scale:
  204. if (keepProportions) {
  205. var previousScaleX = this.blockReferenceData.getScaleFactors().x;
  206. var factor = scaleX / previousScaleX;
  207. scaleY = scaleY * factor;
  208. var scaleYCombo = optionsToolBar.findChild("ScaleY");
  209. scaleYCombo.setEditText("%1".arg(scaleY));
  210. }
  211. this.blockReferenceData.setScaleFactors(new RVector(scaleX, scaleY));
  212. };
  213. InsertBlock.prototype.slotScaleYChanged = function(value) {
  214. if (isNumber(value)) {
  215. this.blockReferenceData.setScaleFactors(new RVector(this.blockReferenceData.getScaleFactors().x, value));
  216. } else {
  217. this.blockReferenceData.setScaleFactors(new RVector(this.blockReferenceData.getScaleFactors().x, 1.0));
  218. }
  219. };
  220. InsertBlock.prototype.slotRotationChanged = function(value) {
  221. if (isNumber(value)) {
  222. this.blockReferenceData.setRotation(value);
  223. } else {
  224. this.blockReferenceData.setRotation(0);
  225. }
  226. this.updatePreview(true);
  227. };
  228. InsertBlock.prototype.slotFlipHorizontal = function() {
  229. this.blockReferenceData.flipHorizontal();
  230. this.updateOptionsToolBar();
  231. };
  232. InsertBlock.prototype.slotFlipVertical = function() {
  233. this.blockReferenceData.flipVertical();
  234. this.updateOptionsToolBar();
  235. };
  236. InsertBlock.prototype.slotSingle = function() {
  237. this.blockReferenceData.setColumnCount(1);
  238. this.blockReferenceData.setRowCount(1);
  239. this.blockReferenceData.setColumnSpacing(0);
  240. this.blockReferenceData.setRowSpacing(0);
  241. this.updatePreview();
  242. };
  243. InsertBlock.prototype.slotArray = function() {
  244. // show array options in dialog:
  245. var dialog = WidgetFactory.createDialog(InsertBlock.includeBasePath, "InsertBlockDialog.ui");
  246. WidgetFactory.restoreState(dialog, this.settingsGroup, this);
  247. dialog.exec();
  248. WidgetFactory.saveState(dialog, this.settingsGroup);
  249. destr(dialog);
  250. EAction.activateMainWindow();
  251. };
  252. InsertBlock.prototype.slotColumnCountChanged = function(value) {
  253. this.blockReferenceData.setColumnCount(parseInt(value));
  254. this.updatePreview(true);
  255. };
  256. InsertBlock.prototype.slotRowCountChanged = function(value) {
  257. this.blockReferenceData.setRowCount(parseInt(value));
  258. this.updatePreview(true);
  259. };
  260. InsertBlock.prototype.slotColumnSpacingChanged = function(value) {
  261. this.blockReferenceData.setColumnSpacing(value);
  262. this.updatePreview(true);
  263. };
  264. InsertBlock.prototype.slotRowSpacingChanged = function(value) {
  265. this.blockReferenceData.setRowSpacing(value);
  266. this.updatePreview(true);
  267. };
  268. InsertBlock.prototype.updateOptionsToolBar = function() {
  269. var optionsToolBar = EAction.getOptionsToolBar();
  270. var rotationCombo = optionsToolBar.findChild("Rotation");
  271. var scaleXCombo = optionsToolBar.findChild("ScaleX");
  272. var scaleYCombo = optionsToolBar.findChild("ScaleY");
  273. rotationCombo.setEditText("%1".arg(RMath.rad2deg(this.blockReferenceData.getRotation())));
  274. scaleXCombo.setEditText("%1".arg(this.blockReferenceData.getScaleFactors().x));
  275. scaleYCombo.setEditText("%1".arg(this.blockReferenceData.getScaleFactors().y));
  276. };
  277. InsertBlock.prototype.slotReset = function() {
  278. BlockInsert.prototype.slotReset.call(this);
  279. var optionsToolBar = EAction.getOptionsToolBar();
  280. var scaleYCombo = optionsToolBar.findChild("ScaleY");
  281. scaleYCombo.setEditText("1");
  282. };