Lengthen.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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/Modify/Modify.js");
  20. /**
  21. * \class Lengthen
  22. * \brief Lengthens (or shortens) an entity by a given amount. If the amount is
  23. * positive, the entity is lengthened (extended), if the amount is negative
  24. * it is shortened.
  25. * \ingroup ecma_modify
  26. */
  27. function Lengthen(guiAction) {
  28. Modify.call(this, guiAction);
  29. this.amount = undefined;
  30. this.entity = undefined;
  31. this.pos = undefined;
  32. this.setUiOptions("Lengthen.ui");
  33. }
  34. Lengthen.prototype = new Modify();
  35. Lengthen.State = {
  36. ChoosingEntity : 0
  37. };
  38. Lengthen.prototype.beginEvent = function() {
  39. Modify.prototype.beginEvent.call(this);
  40. this.setState(Lengthen.State.ChoosingEntity);
  41. };
  42. Lengthen.prototype.setState = function(state) {
  43. Modify.prototype.setState.call(this, state);
  44. this.getDocumentInterface().setClickMode(RAction.PickEntity);
  45. this.setCrosshairCursor();
  46. var appWin = RMainWindowQt.getMainWindow();
  47. switch (this.state) {
  48. case Lengthen.State.ChoosingEntity:
  49. var tr = qsTr("Choose line or arc");
  50. this.setLeftMouseTip(tr);
  51. this.setCommandPrompt(tr);
  52. break;
  53. }
  54. this.setRightMouseTip(EAction.trCancel);
  55. };
  56. Lengthen.prototype.escapeEvent = function() {
  57. switch (this.state) {
  58. case Lengthen.State.ChoosingEntity:
  59. EAction.prototype.escapeEvent.call(this);
  60. break;
  61. }
  62. };
  63. Lengthen.prototype.pickEntity = function(event, preview) {
  64. this.error = "";
  65. var di = this.getDocumentInterface();
  66. var doc = this.getDocument();
  67. var entityId = this.getEntityId(event, preview);
  68. var entity = doc.queryEntity(entityId);
  69. var pos = event.getModelPosition();
  70. if (isNull(entity)) {
  71. this.entity = undefined;
  72. return;
  73. }
  74. switch (this.state) {
  75. case Lengthen.State.ChoosingEntity:
  76. if (!this.isSupportedEntity(entity)) {
  77. if (!preview) {
  78. this.warnUnsupportedEntity();
  79. }
  80. break;
  81. }
  82. if (!EAction.assertEditable(entity, preview)) {
  83. break;
  84. }
  85. this.entity = entity;
  86. this.pos = pos;
  87. if (preview) {
  88. this.updatePreview();
  89. }
  90. else {
  91. var op = this.getOperation(false);
  92. if (!isNull(op)) {
  93. di.applyOperation(op);
  94. if (this.error.length!==0) {
  95. EAction.handleUserWarning(this.error);
  96. }
  97. }
  98. }
  99. break;
  100. }
  101. };
  102. Lengthen.prototype.isSupportedEntity = function(entity) {
  103. return isLineEntity(entity) ||
  104. isArcEntity(entity) ||
  105. // (RSpline.hasProxy() && isSplineEntity(entity)) ||
  106. (RPolyline.hasProxy() && isPolylineEntity(entity));
  107. };
  108. Lengthen.prototype.warnUnsupportedEntity = function() {
  109. if (/*RSpline.hasProxy() && */RPolyline.hasProxy()) {
  110. EAction.warnNotLineArcPolyline();
  111. }
  112. else {
  113. EAction.warnNotLineArc();
  114. }
  115. };
  116. Lengthen.prototype.getOperation = function(preview) {
  117. if (isNull(this.pos) || isNull(this.entity) || !isNumber(this.amount)) {
  118. return undefined;
  119. }
  120. var ret = Lengthen.lengthen(this.entity, this.pos, undefined, this.amount);
  121. if (!ret) {
  122. return undefined;
  123. }
  124. return new RAddObjectOperation(this.entity, this.getToolTitle(), false);
  125. };
  126. Lengthen.prototype.getHighlightedEntities = function() {
  127. var ret = [];
  128. if (isEntity(this.entity)) {
  129. ret.push(this.entity.getId());
  130. }
  131. return ret;
  132. };
  133. Lengthen.prototype.slotAmountChanged = function(amount) {
  134. this.amount = amount;
  135. };
  136. /**
  137. * Lengthens the given entity by the given amount at its start or end point.
  138. *
  139. * \param entity Entity to lengthen
  140. * \param position Position clicked by the user or undefined if trimStartPoint is given
  141. * \param trimStartPoint True to trim start point, false to trim end point
  142. * \param amount Amount to lengthen or negative to shorten
  143. */
  144. Lengthen.lengthen = function(entity, position, trimStartPoint, amount) {
  145. if (isNull(trimStartPoint)) {
  146. if (isPolylineEntity(entity)) {
  147. trimStartPoint = entity.getLengthTo(position) < entity.getLength()/2;
  148. }
  149. else {
  150. trimStartPoint = position.getDistanceTo(entity.getStartPoint()) < position.getDistanceTo(entity.getEndPoint());
  151. }
  152. }
  153. var from;
  154. if (trimStartPoint) {
  155. from = RS.FromStart;
  156. }
  157. else {
  158. from = RS.FromEnd;
  159. }
  160. var iss;
  161. if (isPolylineEntity(entity)) {
  162. var pl = entity.castToShape();
  163. iss = pl.getPointsWithDistanceToEnd(-amount, from|RS.AlongPolyline);
  164. }
  165. else {
  166. iss = entity.getPointsWithDistanceToEnd(-amount, from|RS.AlongPolyline);
  167. }
  168. var is = position.getClosest(iss);
  169. if (!isValidVector(is)) {
  170. return false;
  171. }
  172. if (trimStartPoint) {
  173. if (!isFunction(entity.trimStartPoint)) {
  174. return false;
  175. }
  176. entity.trimStartPoint(is, is, amount>0);
  177. } else {
  178. if (!isFunction(entity.trimEndPoint)) {
  179. return false;
  180. }
  181. entity.trimEndPoint(is, is, amount>0);
  182. }
  183. return true;
  184. }