InsertBlockItem.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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("scripts/File/SvgImport/SvgImport.js");
  20. include("scripts/Block/BlockInsert.js");
  21. /**
  22. * \class InsertBlockItem
  23. * \brief Called when a block is inserted from the part library.
  24. * \ingroup ecma_block
  25. */
  26. function InsertBlockItem(guiAction) {
  27. BlockInsert.call(this, guiAction);
  28. if (!isNull(guiAction)) {
  29. this.setUiOptions("InsertBlockItem.ui");
  30. }
  31. this.diItem = undefined;
  32. this.docItem = undefined;
  33. this.blockName = undefined;
  34. // set to flatten all entities to this one layer:
  35. this.layerName = undefined;
  36. this.offset = undefined;
  37. this.scale = 1.0;
  38. this.rotation = 0.0;
  39. this.flipHorizontal = false;
  40. this.flipVertical = false;
  41. this.toCurrentLayer = false;
  42. this.overwriteLayers = false;
  43. this.overwriteBlocks = false;
  44. this.referencePoint = new RVector(0,0);
  45. this.attributes = {};
  46. this.attributeTags = [];
  47. this.url = undefined;
  48. if (!isNull(guiAction)) {
  49. this.url = this.guiAction.data();
  50. }
  51. this.autoTerminate = false;
  52. }
  53. InsertBlockItem.State = {
  54. SettingPosition : 0
  55. };
  56. InsertBlockItem.prototype = new BlockInsert();
  57. InsertBlockItem.prototype.beginEvent = function() {
  58. // part library item is loaded into this document:
  59. if (isNull(this.diItem)) {
  60. var ms = new RMemoryStorage();
  61. var si = createSpatialIndex();
  62. this.docItem = new RDocument(ms, si);
  63. this.diItem = new RDocumentInterface(this.docItem);
  64. this.diItem.setNotifyListeners(false);
  65. }
  66. // TODO refactor
  67. BlockInsert.prototype.beginEvent.call(this);
  68. var path = undefined;
  69. if (!isNull(this.url)) {
  70. var err;
  71. if (this.url.isLocalFile()) {
  72. path = this.url.toLocalFile();
  73. qDebug("importing file: " + path);
  74. err = this.diItem.importFile(path, "", false);
  75. }
  76. else {
  77. qDebug("importing URL: " + this.url);
  78. if (isFunction(this.url.encodedPath)) {
  79. path = QUrl.fromPercentEncoding(this.url.encodedPath());
  80. }
  81. else {
  82. path = this.url.path();
  83. }
  84. err = this.diItem.importUrl(this.url, "", false);
  85. }
  86. if (err!==RDocumentInterface.IoErrorNoError) {
  87. EAction.handleUserWarning(qsTr("Cannot import file from URL: ") + this.url.toString());
  88. this.terminate();
  89. return;
  90. }
  91. }
  92. // no block name given:
  93. // create block name from file name:
  94. if (isNull(this.blockName)) {
  95. if (isNull(path)) {
  96. this.terminate();
  97. return;
  98. }
  99. this.blockName = new QFileInfo(path).completeBaseName();
  100. // fix block name if necessary:
  101. this.blockName = fixSymbolTableName(this.blockName);
  102. }
  103. // invalid block name characters:
  104. if (isNull(this.blockName)) {
  105. var doc = this.getDocument();
  106. var c = 1;
  107. while (isNull(this.blockName) || doc.hasBlock(this.blockName)) {
  108. this.blockName = 'block_' + c++;
  109. }
  110. EAction.handleUserMessage(qsTr("Adjusted invalid block name to \"%1\"").arg(this.blockName));
  111. }
  112. if (this.docItem.hasBlock(this.blockName)) {
  113. // if the item contains a block with the same name as the file base name,
  114. // insert without creating a new block:
  115. this.blockName = undefined;
  116. }
  117. var i, id;
  118. // init block attribute inputs to options tool bar:
  119. // assign values to attributes:
  120. var first = true;
  121. var optionsToolBar = EAction.getOptionsToolBar();
  122. var tagCombo = optionsToolBar.findChild("AttributeTag");
  123. var tags = {};
  124. if (!isNull(tagCombo)) {
  125. var ids = this.docItem.queryAllEntities();
  126. for (i=0; i<ids.length; i++) {
  127. id = ids[i];
  128. var attDef = this.docItem.queryEntity(id);
  129. if (!isAttributeDefinitionEntity(attDef)) {
  130. continue;
  131. }
  132. if (first) {
  133. this.showAttributeControls(true);
  134. first = false;
  135. }
  136. var tag = attDef.getTag();
  137. var prompt = attDef.getPrompt();
  138. var defaultValue = attDef.getEscapedText();
  139. if (tags[tag]===true) {
  140. // tag already added:
  141. continue;
  142. }
  143. tagCombo.addItem(prompt, [tag, defaultValue]);
  144. tags[tag] = true;
  145. }
  146. }
  147. this.setState(InsertBlockItem.State.SettingPosition);
  148. };
  149. InsertBlockItem.prototype.initUiOptions = function(resume, optionsToolBar) {
  150. BlockInsert.prototype.initUiOptions.call(this, resume, optionsToolBar);
  151. //var optionsToolBar = EAction.getOptionsToolBar();
  152. var combo = optionsToolBar.findChild("Scale");
  153. if (!isNull(combo)) {
  154. combo.setCompleter(null);
  155. }
  156. combo = optionsToolBar.findChild("Rotation");
  157. if (!isNull(combo)) {
  158. combo.setCompleter(null);
  159. }
  160. };
  161. InsertBlockItem.prototype.setState = function(state) {
  162. BlockInsert.prototype.setState.call(this, state);
  163. this.setCrosshairCursor();
  164. this.getDocumentInterface().setClickMode(RAction.PickCoordinate);
  165. var appWin = RMainWindowQt.getMainWindow();
  166. var trPos = qsTr("Position");
  167. this.setCommandPrompt(trPos);
  168. this.setLeftMouseTip(trPos);
  169. this.setRightMouseTip(EAction.trCancel);
  170. EAction.showSnapTools();
  171. };
  172. InsertBlockItem.prototype.finishEvent = function() {
  173. if (!isNull(this.diItem)) {
  174. destr(this.diItem);
  175. }
  176. BlockInsert.prototype.finishEvent.call(this);
  177. };
  178. InsertBlockItem.prototype.generate = function() {
  179. return;
  180. };
  181. InsertBlockItem.prototype.pickCoordinate = function(event, preview) {
  182. var di = this.getDocumentInterface();
  183. if (this.state===InsertBlockItem.State.SettingPosition) {
  184. this.generate();
  185. this.offset = event.getModelPosition();
  186. if (preview) {
  187. this.updatePreview();
  188. }
  189. else {
  190. var prev = true;
  191. var op = this.getOperation();
  192. if (!isNull(op)) {
  193. var t = di.applyOperation(op);
  194. prev = t.isPreview();
  195. di.clearPreview();
  196. di.setRelativeZero(this.offset);
  197. di.repaintViews();
  198. }
  199. if (this.autoTerminate===true && !prev) {
  200. this.terminate();
  201. }
  202. }
  203. }
  204. };
  205. InsertBlockItem.prototype.getRotation = function(preview) {
  206. return this.rotation;
  207. };
  208. InsertBlockItem.prototype.getOperation = function(preview) {
  209. var rotation = this.getRotation();
  210. if (isNull(rotation)) {
  211. return undefined;
  212. }
  213. if (isNull(this.offset)) {
  214. return undefined;
  215. }
  216. var op = new RPasteOperation(this.docItem);
  217. op.setText(this.getToolTitle());
  218. if (this.referencePoint.isZero()) {
  219. op.setOffset(this.offset);
  220. }
  221. else {
  222. var off1 = this.offset;
  223. var off2 = this.referencePoint.copy();
  224. if (this.flipHorizontal) {
  225. off2.flipHorizontal();
  226. }
  227. if (this.flipVertical) {
  228. off2.flipVertical();
  229. }
  230. off2.scale(this.scale);
  231. off2.rotate(rotation);
  232. op.setOffset(off1.operator_subtract(off2));
  233. }
  234. if (!isNull(this.blockName)) {
  235. op.setBlockName(this.blockName);
  236. }
  237. if (!isNull(this.layerName)) {
  238. op.setLayerName(this.layerName);
  239. }
  240. op.setScale(this.scale);
  241. op.setRotation(rotation);
  242. op.setFlipHorizontal(this.flipHorizontal);
  243. op.setFlipVertical(this.flipVertical);
  244. op.setToCurrentLayer(this.toCurrentLayer);
  245. op.setOverwriteLayers(this.overwriteLayers);
  246. op.setOverwriteBlocks(this.overwriteBlocks);
  247. // assign values to attributes:
  248. var ids = this.docItem.queryAllEntities();
  249. for (var i=0; i<ids.length; i++) {
  250. var id = ids[i];
  251. var attDef = this.docItem.queryEntity(id);
  252. if (!isAttributeDefinitionEntity(attDef)) {
  253. continue;
  254. }
  255. var tag = attDef.getTag();
  256. if (!isNull(this.attributes[tag])) {
  257. op.setAttribute(tag, this.attributes[tag]);
  258. }
  259. }
  260. return op;
  261. };
  262. InsertBlockItem.prototype.slotScaleChanged = function(value) {
  263. if (isNumber(value)) {
  264. this.scale = value;
  265. }
  266. else {
  267. this.scale = 1.0;
  268. }
  269. this.updatePreview(true);
  270. };
  271. InsertBlockItem.prototype.slotRotationChanged = function(value) {
  272. if (isNumber(value)) {
  273. this.rotation = value;
  274. }
  275. else {
  276. this.rotation = 0.0;
  277. }
  278. this.updatePreview(true);
  279. };
  280. InsertBlockItem.prototype.slotFlipHorizontalChanged = function(value) {
  281. this.flipHorizontal = value;
  282. this.updatePreview(true);
  283. };
  284. InsertBlockItem.prototype.slotFlipVerticalChanged = function(value) {
  285. this.flipVertical = value;
  286. this.updatePreview(true);
  287. };
  288. InsertBlockItem.prototype.slotToCurrentLayerChanged = function(value) {
  289. this.toCurrentLayer = value;
  290. this.updatePreview(true);
  291. };
  292. InsertBlockItem.prototype.slotOverwriteLayersChanged = function(value) {
  293. this.overwriteLayers = value;
  294. this.updatePreview(true);
  295. };
  296. InsertBlockItem.prototype.slotOverwriteBlocksChanged = function(value) {
  297. this.overwriteBlocks = value;
  298. this.updatePreview(true);
  299. };