CreateBlock.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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/Block/Block.js");
  20. include("scripts/Block/BlockDialog.js");
  21. /**
  22. * \class CreateBlock
  23. * \ingroup ecma_block
  24. * \brief This action handles the user interaction to create a new block
  25. * from existing entities.
  26. */
  27. function CreateBlock(guiAction) {
  28. Block.call(this, guiAction);
  29. }
  30. CreateBlock.prototype = new Block();
  31. CreateBlock.State = {
  32. SettingPosition : 0
  33. };
  34. CreateBlock.prototype.beginEvent = function() {
  35. Block.prototype.beginEvent.call(this);
  36. this.setState(CreateBlock.State.SettingPosition);
  37. };
  38. CreateBlock.prototype.setState = function(state) {
  39. Block.prototype.setState.call(this, state);
  40. this.setCrosshairCursor();
  41. this.getDocumentInterface().setClickMode(RAction.PickCoordinate);
  42. var trRefPoint = qsTr("Reference Point");
  43. this.setCommandPrompt(trRefPoint);
  44. this.setLeftMouseTip(trRefPoint);
  45. this.setRightMouseTip(EAction.trCancel);
  46. EAction.showSnapTools();
  47. };
  48. CreateBlock.prototype.coordinateEvent = function(event) {
  49. var referencePoint = event.getModelPosition();
  50. this.getDocumentInterface().setRelativeZero(referencePoint);
  51. var dlg = new BlockDialog(this.getDocument());
  52. var block = dlg.show();
  53. if (isNull(block)) {
  54. this.terminate();
  55. return;
  56. }
  57. var di = this.getDocumentInterface();
  58. var doc = di.getDocument();
  59. var ids = doc.querySelectedEntities();
  60. CreateBlock.createBlock(di, block, referencePoint, ids, this.getToolTitle(), true);
  61. this.terminate();
  62. };
  63. /**
  64. * Adds the given block to the drawing based on the given entities.
  65. *
  66. * \param di RDocumentInterface
  67. * \param block RBlock block data.
  68. * \param referencePoint RVector reference point for block reference.
  69. * \param entityIds Entity IDs.
  70. * \param title Tool title (used for transaction log).
  71. * \param select True to select created block reference.
  72. * \param copy True to copy the entities into the new block, false to move entities.
  73. * \param createReference True to create a block reference in place of the entities.
  74. * \param startTransactionGroup True to start a transaction group, reuse current transaction group otherwise
  75. */
  76. CreateBlock.createBlock = function(di, block, referencePoint, entityIds, title, select, copy, createReference, startTransactionGroup) {
  77. if (isNull(select)) {
  78. select = false;
  79. }
  80. if (isNull(copy)) {
  81. copy = false;
  82. }
  83. if (isNull(createReference)) {
  84. createReference = true;
  85. }
  86. if (isNull(startTransactionGroup)) {
  87. startTransactionGroup = true;
  88. }
  89. var i, entity, op;
  90. var doc = di.getDocument();
  91. var storage = doc.getStorage();
  92. if (startTransactionGroup) {
  93. doc.startTransactionGroup();
  94. }
  95. op = new RAddObjectsOperation();
  96. op.setTransactionGroup(doc.getTransactionGroup());
  97. op.setText(title);
  98. op.addObject(block);
  99. var blockId;
  100. if (doc.hasBlock(block.getName())) {
  101. // add selection to existing block / overwrite block:
  102. blockId = doc.getBlockId(block.getName());
  103. // clear existing block:
  104. var oldIds = doc.queryBlockEntities(blockId);
  105. for (i=0; i<oldIds.length; i++) {
  106. entity = doc.queryEntity(oldIds[i]);
  107. if (isNull(entity)) {
  108. continue;
  109. }
  110. op.deleteObject(entity);
  111. }
  112. }
  113. else {
  114. blockId = storage.getMaxObjectId();
  115. }
  116. // map old block reference IDs to block reference entities:
  117. var blockReferenceMap = {};
  118. // list of attribute entities:
  119. var attributeEntities = [];
  120. // deselect original entities:
  121. di.deselectEntities(entityIds);
  122. // add selection to new block:
  123. for (i=0; i<entityIds.length; i++) {
  124. var id = entityIds[i];
  125. entity = doc.queryEntity(id);
  126. if (isNull(entity)) {
  127. continue;
  128. }
  129. // move entity to new block:
  130. // note that the original entity is moved to the new block (same id)
  131. entity.setBlockId(blockId);
  132. entity.move(referencePoint.getNegated());
  133. op.addObject(entity, false, copy);
  134. if (copy) {
  135. if (isBlockReferenceEntity(entity)) {
  136. blockReferenceMap[id] = entity;
  137. }
  138. else if (isAttributeEntity(entity)) {
  139. attributeEntities.push(entity);
  140. }
  141. }
  142. }
  143. // create block reference from selection:
  144. var blockReference = undefined;
  145. if (createReference) {
  146. blockReference = new RBlockReferenceEntity(doc, new RBlockReferenceData(blockId, referencePoint, new RVector(1,1,1), 0.0));
  147. if (select) {
  148. blockReference.setSelected(true);
  149. }
  150. op.addObject(blockReference, false);
  151. }
  152. di.applyOperation(op);
  153. if (copy) {
  154. op = new RAddObjectsOperation();
  155. op.setTransactionGroup(doc.getTransactionGroup());
  156. op.setText(title);
  157. // fix attribute links to block references:
  158. for (i=0; i<attributeEntities.length; i++) {
  159. var attributeEntity = attributeEntities[i];
  160. // find parent entity of attribute:
  161. var blockReferenceEntity = blockReferenceMap[attributeEntity.getParentId()];
  162. if (!isNull(blockReferenceEntity)) {
  163. // update parent ID:
  164. storage.setEntityParentId(getPtr(attributeEntity), blockReferenceEntity.getId());
  165. op.addObject(attributeEntity, false);
  166. }
  167. }
  168. di.applyOperation(op);
  169. // for (var oldId in blockReferenceMap) {
  170. // entity = blockReferenceMap[oldId];
  171. // var newId = entity.getId();
  172. // qDebug("old:", oldId);
  173. // qDebug("new:", newId);
  174. // }
  175. }
  176. if (isNull(blockReference)) {
  177. return RObject.INVALID_ID;
  178. }
  179. else {
  180. return blockReference.getId();
  181. }
  182. };