Shape.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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. /**
  20. * \defgroup ecma_draw_shape Shape Drawing Tools
  21. * \ingroup ecma_draw
  22. *
  23. * \brief This module contains ECMAScript implementations of various
  24. * shape drawing tools.
  25. */
  26. include("scripts/Draw/Draw.js");
  27. include("scripts/Modify/Round/Round.js");
  28. /**
  29. * \class Shape
  30. * \brief Base class for all shape drawing tools.
  31. * \ingroup ecma_draw_shape
  32. */
  33. function Shape(guiAction) {
  34. Draw.call(this, guiAction);
  35. this.createPolyline = false;
  36. this.fill = false;
  37. this.roundCorners = false;
  38. this.radius = 1.0;
  39. }
  40. Shape.prototype = new Draw();
  41. Shape.includeBasePath = includeBasePath;
  42. Shape.prototype.beginEvent = function() {
  43. Draw.prototype.beginEvent.call(this);
  44. if (!isNull(this.getGuiAction()) && this.getGuiAction().objectName==="ShapeToolsPanelAction") {
  45. EAction.showCadToolBarPanel("ShapeToolsPanel");
  46. this.terminate();
  47. }
  48. };
  49. Shape.getMenu = function() {
  50. // var menu = EAction.getSubMenu(
  51. // Draw.getMenu(),
  52. // 20, 800,
  53. // Shape.getTitle(),
  54. // "DrawShapeMenu",
  55. // Shape.includeBasePath + "/Shape.svg"
  56. // );
  57. // menu.setProperty("scriptFile", Shape.includeBasePath + "/Shape.js");
  58. // return menu;
  59. };
  60. Shape.getToolBar = function() {
  61. var tb = EAction.getToolBar(Shape.getTitle(), "ShapeToolBar", Qt.TopToolBarArea, Draw.getContextMenuCategory());
  62. tb.visible = false;
  63. return tb;
  64. };
  65. Shape.getCadToolBarPanel = function() {
  66. var mtb = Draw.getCadToolBarPanel();
  67. var actionName = "ShapeToolsPanelAction";
  68. if (!isNull(mtb) && mtb.findChild(actionName)==undefined) {
  69. var action = new RGuiAction(qsTr("Shape Tools"), mtb);
  70. action.setScriptFile(Shape.includeBasePath + "/Shape.js");
  71. action.objectName = actionName;
  72. action.setRequiresDocument(true);
  73. action.setIcon(Shape.includeBasePath + "/Shape.svg");
  74. //action.setStatusTip(qsTr("Show shape tools"));
  75. action.setDefaultShortcut(new QKeySequence("w,h"));
  76. action.setNoState();
  77. action.setDefaultCommands(["shapemenu"]);
  78. action.setGroupSortOrder(20);
  79. action.setSortOrder(800);
  80. action.setWidgetNames(["MainToolsPanel"]);
  81. }
  82. var tb = EAction.getCadToolBarPanel(
  83. Shape.getTitle(),
  84. "ShapeToolsPanel",
  85. true
  86. );
  87. return tb;
  88. };
  89. Shape.getToolMatrixPanel = function() {
  90. return EAction.getToolMatrixPanel(Shape.getTitle(), "ShapeMatrixPanel", 800);
  91. };
  92. Shape.getTitle = function() {
  93. return qsTr("&Shape");
  94. };
  95. Shape.prototype.getTitle = function() {
  96. return Shape.getTitle();
  97. };
  98. Shape.init = function() {
  99. Shape.getMenu();
  100. Shape.getToolBar();
  101. Shape.getCadToolBarPanel();
  102. Shape.getToolMatrixPanel();
  103. };
  104. Shape.prototype.initUiOptions = function(resume, optionsToolBar) {
  105. Draw.prototype.initUiOptions.call(this, resume, optionsToolBar);
  106. this.createPolyline = RSettings.getBoolValue(this.settingsGroup + "/CreatePolyline", false);
  107. this.fill = RSettings.getBoolValue(this.settingsGroup + "/Fill", false);
  108. this.roundCorners = RSettings.getBoolValue(this.settingsGroup + "/RoundCorners", false);
  109. this.radius = RSettings.getDoubleValue(this.settingsGroup + "/Radius", 1.0);
  110. var w = optionsToolBar.findChild("CreatePolyline");
  111. if (!isNull(w)) {
  112. w.checked = this.createPolyline;
  113. }
  114. w = optionsToolBar.findChild("Fill");
  115. if (!isNull(w)) {
  116. w.checked = this.fill;
  117. }
  118. w = optionsToolBar.findChild("RoundCorners");
  119. if (!isNull(w)) {
  120. w.checked = this.roundCorners;
  121. }
  122. w = optionsToolBar.findChild("Radius");
  123. if (!isNull(w)) {
  124. w.setValue(this.radius);
  125. }
  126. };
  127. Shape.prototype.hideUiOptions = function(saveToSettings) {
  128. Draw.prototype.hideUiOptions.call(this, saveToSettings);
  129. RSettings.setValue(this.settingsGroup + "/CreatePolyline", this.createPolyline);
  130. RSettings.setValue(this.settingsGroup + "/Fill", this.fill);
  131. RSettings.setValue(this.settingsGroup + "/RoundCorners", this.roundCorners);
  132. RSettings.setValue(this.settingsGroup + "/Radius", this.radius);
  133. };
  134. Shape.prototype.slotCreatePolylineChanged = function(checked) {
  135. Shape.slotCreatePolylineChanged(this, checked);
  136. };
  137. Shape.slotCreatePolylineChanged = function(action, checked) {
  138. action.createPolyline = checked;
  139. action.updatePreview(true);
  140. };
  141. Shape.prototype.slotFillChanged = function(checked) {
  142. Shape.slotFillChanged(this, checked);
  143. };
  144. Shape.slotFillChanged = function(action, checked) {
  145. action.fill = checked;
  146. action.updatePreview(true);
  147. };
  148. Shape.prototype.slotRoundCornersChanged = function(checked) {
  149. Shape.slotRoundCornersChanged(this, checked);
  150. };
  151. Shape.slotRoundCornersChanged = function(action, checked) {
  152. action.roundCorners = checked;
  153. action.updatePreview(true);
  154. };
  155. Shape.prototype.slotRadiusChanged = function(v) {
  156. Shape.slotRadiusChanged(this, v);
  157. };
  158. Shape.slotRadiusChanged = function(action, v) {
  159. action.radius = v;
  160. action.updatePreview(true);
  161. };
  162. Shape.prototype.getShapes = function(vertices) {
  163. return Shape.getShapes(this, vertices);
  164. };
  165. Shape.getShapes = function(action, vertices) {
  166. var i;
  167. var shapes = [];
  168. for (i=0; i<vertices.length; ++i) {
  169. shapes.push(new RLine(vertices[i], vertices[(i+1)%vertices.length]));
  170. }
  171. if (action.roundCorners===true && isNumberGreaterZero(action.radius)) {
  172. var newShapes = [];
  173. var cursor = undefined;
  174. for (i=0; i<shapes.length; ++i) {
  175. var s1 = shapes[i];
  176. var clickPos1 = s1.getPointWithDistanceToEnd(s1.getLength()/3);
  177. var s2 = shapes[(i+1)%shapes.length];
  178. var clickPos2 = s2.getPointWithDistanceToStart(s2.getLength()/3);
  179. var pos = RVector.getAverage(clickPos1, clickPos2);
  180. var res;
  181. if (RSettings.getQtVersion()>=0x060000) {
  182. s1 = s1.clone();
  183. s2 = s2.clone();
  184. }
  185. res = RShape.roundShapes(s1, clickPos1, s2, clickPos2, true, false, action.radius, pos);
  186. if (res.length>2) {
  187. if (!isNull(cursor)) {
  188. newShapes.push(new RLine(cursor, res[1].getStartPoint()));
  189. }
  190. newShapes.push(res[1].clone());
  191. cursor = res[1].getEndPoint();
  192. }
  193. }
  194. if (newShapes.length>0) {
  195. newShapes.unshift(new RLine(newShapes[newShapes.length-1].getEndPoint(), newShapes[0].getStartPoint()));
  196. }
  197. shapes = newShapes;
  198. }
  199. if (action.createPolyline===true) {
  200. var pl = new RPolyline();
  201. for (i=0; i<shapes.length; ++i) {
  202. pl.appendShape(shapes[i]);
  203. }
  204. pl.autoClose();
  205. return [pl];
  206. }
  207. else {
  208. return shapes;
  209. }
  210. };
  211. Shape.prototype.complementOperation = function(op, shapes) {
  212. Shape.complementOperation(this, this.getDocument(), op, shapes);
  213. };
  214. Shape.complementOperation = function(action, doc, op, shapes) {
  215. if (action.fill) {
  216. var hatchData = new RHatchData();
  217. hatchData.setDocument(doc);
  218. hatchData.setAngle(0.0);
  219. hatchData.setScale(1.0);
  220. hatchData.setSolid(true);
  221. hatchData.setPatternName("SOLID");
  222. hatchData.newLoop();
  223. for (var k=0; k<shapes.length; ++k) {
  224. if (RSettings.getQtVersion()>=0x060000) {
  225. hatchData.addBoundary(shapes[k].clone());
  226. }
  227. else {
  228. hatchData.addBoundary(shapes[k]);
  229. }
  230. }
  231. op.addObject(new RHatchEntity(doc, hatchData));
  232. }
  233. };