EAction.js 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307
  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/library.js");
  20. include("scripts/WidgetFactory.js");
  21. include("scripts/Widgets/OptionsToolBar/OptionsToolBar.js");
  22. /**
  23. * Base class for all ECMAScript based actions.
  24. */
  25. function EAction(guiAction) {
  26. RActionAdapter.call(this);
  27. this.guiAction = guiAction;
  28. if (!isNull(guiAction)) {
  29. this.setGuiAction(guiAction);
  30. }
  31. // Constructor is called without arguments to create prototype
  32. // for derived class. At this point, includeBasePath is set correctly:
  33. if (isNull(guiAction)) {
  34. this.includeBasePath = includeBasePath;
  35. }
  36. this.delegate = undefined;
  37. this.state = undefined;
  38. this.settingsGroup = undefined;
  39. this.uiFile = undefined;
  40. this.splitUiOptions = false;
  41. this.additionalOptionsToolBars = undefined;
  42. this.optionsToolBarEnabled = false;
  43. this.relativeZeroPos = undefined;
  44. // set to true to prefer dialog over options tool bar:
  45. this.useDialog = false;
  46. this.dialogUiFile = undefined;
  47. this.waitingForContextMenu = false;
  48. this.optOutRelativeZeroResume = false;
  49. this.resuming = false;
  50. }
  51. EAction.prototype = new RActionAdapter();
  52. EAction.includeBasePath = includeBasePath;
  53. // some commonly used translated strings:
  54. EAction.trBack = qsTr("Back");
  55. EAction.trCancel = qsTr("Cancel");
  56. EAction.trDone = qsTr("Done");
  57. EAction.crossCursor = undefined;
  58. EAction.noRelativeZeroResume = false;
  59. /**
  60. * Called when the user starts this action by clicking a button, choosing a
  61. * menu, entering a command, etc.
  62. *
  63. * Shows the GUI elements that refer to this action as checked. Displays GUI
  64. * options if this.uiFile is set to a valid UI file. Displays tool help in Help
  65. * Viewer if available.
  66. */
  67. EAction.prototype.beginEvent = function() {
  68. if (this.delegate) {
  69. this.delegate.beginEvent();
  70. }
  71. if (this.hasNoState()) {
  72. return;
  73. }
  74. var appWin = EAction.getMainWindow();
  75. if (!isNull(this.getGuiAction())) {
  76. this.getGuiAction().setChecked(true);
  77. }
  78. this.showUiOptions(false);
  79. // reset snap to auto snap / no restriction:
  80. if (isNull(this.getGuiAction())
  81. || (this.getGuiAction().getGroup() !== "snaps" &&
  82. this.getGuiAction().getGroup() !== "snaprestrictions" &&
  83. this.getGuiAction().property("NoSnapReset")!==true)) {
  84. var di = this.getDocumentInterface();
  85. if (!isNull(di)) {
  86. if (!di.isSnapLocked()) {
  87. var guiAction = RGuiAction.getByScriptFile("scripts/Snap/SnapAuto/SnapAuto.js");
  88. if (!isNull(guiAction)) {
  89. guiAction.slotTrigger();
  90. }
  91. di.setSnap(new RSnapAuto());
  92. guiAction = RGuiAction.getByScriptFile("scripts/Snap/RestrictOff/RestrictOff.js");
  93. if (!isNull(guiAction)) {
  94. guiAction.slotTrigger();
  95. }
  96. di.setSnapRestriction(new RRestrictOff(di));
  97. }
  98. }
  99. }
  100. };
  101. /**
  102. * Called when this action is terminated.
  103. *
  104. * Shows the GUI elements that refer to this action as un-checked. Hides GUI
  105. * options if this.uiFile is set to a valid UI file. Clears up mouse tips, etc.
  106. */
  107. EAction.prototype.finishEvent = function() {
  108. if (this.hasNoState()) {
  109. return;
  110. }
  111. var guiAction = this.getGuiAction();
  112. // unckeck tool GUI action:
  113. if (!isNull(guiAction) && !isDeleted(guiAction)) {
  114. if (guiAction.getGroup().isEmpty() || guiAction.isOverride()) {
  115. guiAction.setChecked(false);
  116. }
  117. }
  118. this.hideUiOptions();
  119. // clear mouse tips:
  120. if (!isNull(EAction.getMainWindow())) {
  121. this.setLeftMouseTip("");
  122. this.setRightMouseTip("");
  123. }
  124. // reset CAD tool bar:
  125. if (!isNull(guiAction) && guiAction.getGroup() === "") {
  126. var appWin = EAction.getMainWindow();
  127. var cadToolBar = appWin.findChild("CadToolBar");
  128. if (!isNull(cadToolBar) && cadToolBar.getCurrentPanelName()==="SnapToolsPanel") {
  129. cadToolBar.back();
  130. }
  131. }
  132. // to remove snap info:
  133. var di = this.getDocumentInterface();
  134. if (!isNull(di)) {
  135. di.repaintViews();
  136. }
  137. this.setCommandPrompt();
  138. };
  139. /**
  140. * Does nothing. Needs to be implemented here to avoid recursion when child
  141. * classes call the base class implementation.
  142. */
  143. EAction.prototype.mousePressEvent = function(event) {
  144. };
  145. EAction.prototype.mouseReleaseEvent = function(event) {
  146. if (event.button() === Qt.RightButton) {
  147. this.escapeEvent();
  148. }
  149. };
  150. EAction.prototype.mouseDoubleClickEvent = function(event) {
  151. if (event.button() == Qt.RightButton) {
  152. // right double-click to reset:
  153. if (RSettings.getBoolValue("GraphicsView/RightDoubleClickToReset", false)) {
  154. var di = this.getDocumentInterface();
  155. if (!isNull(di)) {
  156. di.killAllActions();
  157. }
  158. EAction.showMainTools();
  159. }
  160. }
  161. };
  162. /**
  163. * Sets the UI options toolbar content for this tool. By default, a tool shows
  164. * the options toolbar defined in "DefaultOptions.ui".
  165. *
  166. * \param uiFile A path to a single UI file or an array of UI file paths.
  167. * \param split If true, the options are split up into multiple toolbars.
  168. */
  169. EAction.prototype.setUiOptions = function(uiFile, split) {
  170. if (isNull(split)) {
  171. split = false;
  172. }
  173. this.splitUiOptions = split;
  174. if (isNull(uiFile)) {
  175. this.uiFile = undefined;
  176. return;
  177. }
  178. if (isArray(uiFile)) {
  179. this.uiFile = uiFile;
  180. } else {
  181. this.uiFile = [ uiFile ];
  182. }
  183. };
  184. /**
  185. * Set the state of this action. Action implementations overwrite this function
  186. * to initialize this action for the given state. This includes setting the
  187. * appropriate click mode, displaying the appropriate CAD toolbar, setting
  188. * mouse tips, mouse cursor, etc.
  189. */
  190. EAction.prototype.setState = function(state) {
  191. if (!isNumber(state)) {
  192. qWarning("EAction.prototype.setState: invalid state");
  193. debugger;
  194. return;
  195. }
  196. this.state = state;
  197. this.initState();
  198. if (state!==-1) {
  199. this.simulateMouseMoveEvent();
  200. }
  201. };
  202. /**
  203. * Called to initialize a new state of this action. Overwrite to
  204. * set mouse tips, show desired toolbars, etc.
  205. */
  206. EAction.prototype.initState = function() {
  207. };
  208. /**
  209. * Called whenever the action resumes its operation, for example after it was
  210. * temporary suspended for another action.
  211. */
  212. EAction.prototype.resumeEvent = function() {
  213. if (this.hasNoState()) {
  214. return;
  215. }
  216. var appWin = EAction.getMainWindow();
  217. if (!isNull(this.getGuiAction())) {
  218. this.getGuiAction().setChecked(true);
  219. }
  220. this.showUiOptions(true);
  221. if (!isNull(this.state)) {
  222. this.setState(this.state);
  223. }
  224. if (!this.optOutRelativeZeroResume) {
  225. // restore relative zero position when returning from another command:
  226. var di = this.getDocumentInterface();
  227. if (!isNull(di) && isValidVector(this.relativeZeroPos)) {
  228. if (EAction.noRelativeZeroResume===true) {
  229. EAction.noRelativeZeroResume = false;
  230. }
  231. else {
  232. di.setRelativeZero(this.relativeZeroPos);
  233. }
  234. }
  235. this.relativeZeroPos = undefined;
  236. }
  237. };
  238. /**
  239. * Called whenever the action is suspended, for example if another action is
  240. * started while this action is active.
  241. */
  242. EAction.prototype.suspendEvent = function() {
  243. if (this.hasNoState()) {
  244. return;
  245. }
  246. if (!isNull(this.getGuiAction())) {
  247. this.getGuiAction().setChecked(false);
  248. }
  249. this.hideUiOptions();
  250. // store relative zero position:
  251. var di = this.getDocumentInterface();
  252. if (!isNull(di)) {
  253. this.relativeZeroPos = di.getRelativeZero();
  254. }
  255. };
  256. /**
  257. * Shows the UI options of this action if this.uiFile is set. UI options are
  258. * typically shown in a horizontal toolbar at the top of the drawing area.
  259. *
  260. * Usually this function does not need to be called directly by implementing
  261. * actions.
  262. *
  263. * \param resume Action was resumed from suspension.
  264. * \param restoreFromSettings Restore settings from document / config file (default).
  265. */
  266. EAction.prototype.showUiOptions = function(resume, restoreFromSettings) {
  267. if (isNull(restoreFromSettings)) {
  268. restoreFromSettings = true;
  269. }
  270. if (!isNull(this.optionWidgetActions)) {
  271. return;
  272. }
  273. if (this.optionsToolBarEnabled === false) {
  274. return;
  275. }
  276. var optionsToolBar = EAction.getOptionsToolBar();
  277. if (isNull(optionsToolBar)) {
  278. qWarning("EAction.prototype.showUiOptions: no options toolbar");
  279. return;
  280. }
  281. this.optionWidgetActions = [];
  282. var guiAction = this.getGuiAction();
  283. if (!isNull(guiAction) &&
  284. guiAction.getGroup() !== "snaps" &&
  285. guiAction.getGroup() !== "snaprestrictions") {
  286. // automatically add icon of current action to toolbar:
  287. if (!guiAction.icon.isNull() && !guiAction.isOverride()) {
  288. var iconLabel = optionsToolBar.findChild("Icon");
  289. if (!isNull(iconLabel)) {
  290. iconLabel.toolTip = qsTr("Active Tool:") + " " + guiAction.text.replace("&", "");
  291. OptionsToolBar.setIcon(guiAction.icon);
  292. iconLabel.setFixedWidth(iconLabel.height + 12);
  293. }
  294. }
  295. }
  296. // add widgets from action specific options toolbar:
  297. if (isNull(this.uiFile)) {
  298. return;
  299. }
  300. this.resuming = true;
  301. this.optionWidgetActions = [];
  302. for (var i = 0; i < this.uiFile.length; ++i) {
  303. var uiFile = this.uiFile[i];
  304. var wOptions = this.createWidget(uiFile);
  305. //qDebug("adjust icons for uiFile: ", uiFile);
  306. if (isNull(wOptions)) {
  307. qWarning("Cannot create widget from UI file: ", uiFile);
  308. continue;
  309. }
  310. // create new toolbar for additional tool options:
  311. if (this.splitUiOptions === true && i != 0) {
  312. EAction.getMainWindow().addToolBarBreak();
  313. optionsToolBar = new QToolBar(EAction.getMainWindow());
  314. optionsToolBar.objectName = wOptions.objectName;
  315. EAction.getMainWindow().addToolBar(Qt.TopToolBarArea, optionsToolBar);
  316. if (isNull(this.additionalOptionsToolBars)) {
  317. this.additionalOptionsToolBars = [];
  318. }
  319. this.additionalOptionsToolBars.push(optionsToolBar);
  320. }
  321. // show:
  322. this.settingsGroup = wOptions.objectName;
  323. this.optionWidgetActions = this.optionWidgetActions
  324. .concat(WidgetFactory.moveChildren(wOptions, optionsToolBar,
  325. this.settingsGroup));
  326. // required for undocked options tool bar:
  327. if (optionsToolBar.floating) {
  328. optionsToolBar.resize(optionsToolBar.sizeHint.width(), optionsToolBar.height);
  329. }
  330. destr(wOptions);
  331. // automatically add separator to toolbar:
  332. var a = optionsToolBar.addSeparator();
  333. a.objectName = "LastSeparator" + i;
  334. this.optionWidgetActions.push(a);
  335. // give action a chance to initialize toolbar widgets that cannot
  336. // be initialized in Qt Designer:
  337. this.initUiOptions(resume, optionsToolBar);
  338. // restore previously stored state:
  339. if (restoreFromSettings===true) {
  340. WidgetFactory.restoreState(optionsToolBar, this.settingsGroup, this);
  341. }
  342. }
  343. // hide options tool bar widgets which are shown in a dialog instead:
  344. this.hideOptionsToolBarWidgets();
  345. this.resuming = false;
  346. };
  347. /**
  348. * Overwrite to initialize combo boxes and other UI elements of the options tool
  349. * bar.
  350. */
  351. EAction.prototype.initUiOptions = function(resume, optionsToolBar) {
  352. var prefixChar = RSettings.getStringValue("ToolBar/PrefixChar", ",");
  353. if (isNull(optionsToolBar)) {
  354. return;
  355. }
  356. var children = optionsToolBar.children();
  357. for (var i=0; i<children.length; i++) {
  358. var child = children[i];
  359. if (isNull(child)) {
  360. continue;
  361. }
  362. var shortCut = child.shortcut;
  363. if (!isNull(shortCut) && !shortCut.isEmpty()) {
  364. var str = shortCut.toString();
  365. var firstChar = str[0];
  366. // if first key is Ctrl then the string starts with Ctrl+
  367. // so check for a + sign, which indicates a modifier key has been used
  368. // '+' and '-' should not be used as prefix, as they zoom in and out
  369. if (str.indexOf('+') === -1) { // no plus sign
  370. if (firstChar >= '!' && firstChar <= '~') { // isgraph()
  371. str = str.replace(firstChar, prefixChar);
  372. child.shortcut = new QKeySequence(str);
  373. child.toolTip = RGuiAction.formatToolTip(child.toolTip, str);
  374. }
  375. }
  376. }
  377. }
  378. };
  379. /**
  380. * Hides the UI options of this action.
  381. *
  382. * Usually this function does not need to be called directly by implementing
  383. * actions.
  384. * \param saveToSettings if true, the state is saved to settings
  385. */
  386. EAction.prototype.hideUiOptions = function(saveToSettings) {
  387. if (isNull(saveToSettings)) {
  388. saveToSettings = true;
  389. }
  390. if (isNull(this.optionWidgetActions)) {
  391. return;
  392. }
  393. if (this.optionsToolBarEnabled === false) {
  394. return;
  395. }
  396. var optionsToolBar = EAction.getOptionsToolBar();
  397. if (isNull(optionsToolBar)) {
  398. return;
  399. }
  400. if (saveToSettings) {
  401. WidgetFactory.saveState(optionsToolBar, this.settingsGroup);
  402. }
  403. // automatically reset icon of current action from toolbar:
  404. if (!isNull(this.getGuiAction()) &&
  405. this.getGuiAction().getGroup() !== "snaps" &&
  406. this.getGuiAction().getGroup() !== "snaprestrictions") {
  407. if (!this.getGuiAction().icon.isNull()) {
  408. var iconLabel = optionsToolBar.findChild("Icon");
  409. if (!isNull(iconLabel)) {
  410. OptionsToolBar.setIcon("scripts/Reset/Reset.svg");
  411. iconLabel.toolTip = qsTr("Active Tool:") + " " + qsTr("None");
  412. }
  413. }
  414. }
  415. // delete all option widgets / actions of this tool:
  416. var i;
  417. while (this.optionWidgetActions.length>0) {
  418. var a = this.optionWidgetActions.pop();
  419. if (!isNull(optionsToolBar)) {
  420. optionsToolBar.removeAction(a);
  421. }
  422. destr(a);
  423. }
  424. // delete additional toolbars of this tool if available:
  425. if (!isNull(this.additionalOptionsToolBars)) {
  426. for (i = 0; i < this.additionalOptionsToolBars.length; ++i) {
  427. var tb = this.additionalOptionsToolBars[i];
  428. if (isDeleted(tb)) {
  429. continue;
  430. }
  431. destr(tb);
  432. }
  433. }
  434. // required for undocked options tool bar:
  435. if (optionsToolBar.floating) {
  436. optionsToolBar.resize(optionsToolBar.sizeHint.width(), optionsToolBar.height);
  437. }
  438. this.optionWidgetActions = undefined;
  439. this.additionalOptionsToolBars = undefined;
  440. };
  441. /**
  442. * Hides all widgets in the options tool bar which are shown in the tool dialog instead.
  443. */
  444. EAction.prototype.hideOptionsToolBarWidgets = function(widgets, noSyncWidgets) {
  445. if (!this.useDialog) {
  446. return;
  447. }
  448. if (isNull(widgets)) {
  449. widgets = [];
  450. }
  451. if (isNull(noSyncWidgets)) {
  452. noSyncWidgets = [];
  453. }
  454. // collect widgets which are tagged to be shown in the dialog:
  455. var i, c;
  456. //var widgets = [];
  457. //var noSyncWidgets = [];
  458. var optionsToolBar = EAction.getOptionsToolBar();
  459. var children = optionsToolBar.children();
  460. for (i = 0; i < children.length; ++i) {
  461. c = children[i];
  462. if (isNull(c)) {
  463. continue;
  464. }
  465. if (c["HideInDialogMode"]===true) {
  466. destr(c);
  467. }
  468. else if (c["MoveToDialog"]===true) {
  469. widgets.push(c);
  470. }
  471. else {
  472. if (isQWidget(c)) {
  473. noSyncWidgets.push(c);
  474. }
  475. }
  476. }
  477. if (widgets.length===0) {
  478. // no widgets to show in dialog, return to normal operation without dialog:
  479. return;
  480. }
  481. WidgetFactory.saveState(optionsToolBar, this.settingsGroup);
  482. for (i = 0; i < widgets.length; i++) {
  483. var a = optionsToolBar.findChild(widgets[i].objectName + "Action");
  484. if (!isNull(a)) {
  485. a.visible = false;
  486. }
  487. }
  488. // remove double separators:
  489. OptionsToolBar.normalizeSeparators(this);
  490. };
  491. /**
  492. * Called when user presses enter. Default implementation calls showDialog if configured.
  493. */
  494. EAction.prototype.enterEvent = function() {
  495. if (RSettings.getBoolValue("Transform/EnterShowsDialog", false)===true) {
  496. this.showDialog();
  497. }
  498. };
  499. /**
  500. * Show dialog to enter some or all of the options.
  501. * The default implementation creates a dialog based on this.dialogUiFile.
  502. * Widgets in the options tool bar which have the property "MoveToDialog" or
  503. * "HideInDialogMode" set are hidden in the options tool bar.
  504. */
  505. EAction.prototype.showDialog = function() {
  506. if (!this.useDialog) {
  507. return QDialog.Rejected;
  508. }
  509. var di = this.getDocumentInterface();
  510. if (!isNull(di)) {
  511. di.clearPreview();
  512. di.repaintViews();
  513. }
  514. var widgets = [];
  515. var noSyncWidgets = [];
  516. this.hideOptionsToolBarWidgets(widgets, noSyncWidgets);
  517. // show dialog and move tool bar widgets to its layout:
  518. var formLayout = undefined;
  519. if (isNull(this.dialogUiFile)) {
  520. return QDialog.Rejected;
  521. }
  522. this.dialog = WidgetFactory.createDialog(this.includeBasePath, this.dialogUiFile, EAction.getMainWindow());
  523. this.initUiOptions(false, this.dialog);
  524. WidgetFactory.restoreState(this.dialog, this.settingsGroup, this);
  525. var title = this.getToolTitle();
  526. if (title.indexOf("\t")!==-1) {
  527. // remove shortcuts Windows:
  528. title = title.replace(/\t.*/g, "");
  529. }
  530. this.dialog.windowTitle = title;
  531. this.dialog.windowIcon = new QIcon();
  532. // give focus to control with custom property 'DefaultFocus':
  533. var children = this.dialog.children();
  534. var i;
  535. for (i=0; i<children.length; i++) {
  536. if (children[i].property("DefaultFocus")===true) {
  537. children[i].setFocus();
  538. if (isFunction(children[i].selectAll)) {
  539. // select all text in line edits:
  540. children[i].selectAll();
  541. }
  542. break;
  543. }
  544. }
  545. this.initDialog(this.dialog);
  546. var ret = this.dialog.exec();
  547. // TODO:
  548. //WidgetFactory.saveState(this.dialog, "Shape");
  549. WidgetFactory.saveState(this.dialog, this.settingsGroup);
  550. // sync invisible part of options tool bar with dialog:
  551. for (i=0; i<noSyncWidgets.length; i++) {
  552. if (isDeleted(noSyncWidgets[i])) {
  553. continue;
  554. }
  555. noSyncWidgets[i].setProperty("Loaded", true);
  556. }
  557. var optionsToolBar = EAction.getOptionsToolBar();
  558. WidgetFactory.restoreState(optionsToolBar, this.settingsGroup, this);
  559. for (i=0; i<noSyncWidgets.length; i++) {
  560. if (isDeleted(noSyncWidgets[i])) {
  561. continue;
  562. }
  563. noSyncWidgets[i].setProperty("Loaded", false);
  564. }
  565. destr(this.dialog);
  566. this.dialog = undefined;
  567. // var view = EAction.getGraphicsView();
  568. // if (!isNull(view)) {
  569. // // view loses focus because of dialog:
  570. // view.giveFocus();
  571. // }
  572. EAction.activateMainWindow();
  573. this.simulateMouseMoveEvent();
  574. //this.updatePreview(true);
  575. return ret;
  576. };
  577. /**
  578. * Called before dialog is shown. Default implementation does nothing.
  579. */
  580. EAction.prototype.initDialog = function(dialog) {
  581. };
  582. /**
  583. * Called if the user clicks the reset button of an action. A reset button may
  584. * be displayed as part of the UI options of this action and must have the
  585. * object name "Reset".
  586. */
  587. EAction.prototype.slotReset = function() {
  588. if (this.optionsToolBarEnabled === false) {
  589. return;
  590. }
  591. var optionsToolBar = EAction.getOptionsToolBar();
  592. if (isNull(optionsToolBar)) {
  593. return;
  594. }
  595. WidgetFactory.resetState(optionsToolBar, this.settingsGroup);
  596. };
  597. /**
  598. * Called when the user presses Escape or clicks the right mouse button.
  599. */
  600. EAction.prototype.escapeEvent = function() {
  601. this.setArrowCursor();
  602. this.getDocumentInterface().clearPreview();
  603. this.getDocumentInterface().repaintViews();
  604. this.terminate();
  605. };
  606. /**
  607. * Called when the user presses a key. By default, the event is ignored.
  608. */
  609. EAction.prototype.keyPressEvent = function(event) {
  610. if (isNull(event)) {
  611. return;
  612. }
  613. // prevent focus shift when entering keycode (e.g. "D2"):
  614. var appWin = EAction.getMainWindow();
  615. if (appWin.getKeyLog().length===0) {
  616. if ((event.key() >= Qt.Key_0.valueOf() && event.key() <= Qt.Key_9.valueOf()) || event.key() === Qt.Key_Period.valueOf()) {
  617. // number or dot entered:
  618. // give focus to first input widget in options tool bar and set text to number entered:
  619. var w = OptionsToolBar.getFirstInputWidget();
  620. if (!isNull(w)) {
  621. w.setFocus(Qt.OtherFocusReason);
  622. w.text = String.fromCharCode(event.key());
  623. event.accept();
  624. return;
  625. }
  626. }
  627. }
  628. event.ignore();
  629. };
  630. /**
  631. * Called when the user releases a key. By default, the event is ignored.
  632. */
  633. EAction.prototype.keyReleaseEvent = function(event) {
  634. event.ignore();
  635. };
  636. /**
  637. * Sets the current cursor of the current document interface (all views attached
  638. * to it) to crosshair cursor.
  639. */
  640. EAction.prototype.setCrosshairCursor = function() {
  641. if (isNull(EAction.crossCursor)) {
  642. if (RSettings.getBoolValue("GraphicsView/SystemCursors", false)===true) {
  643. EAction.crossCursor = new QCursor(Qt.CrossCursor);
  644. }
  645. else {
  646. var bitmap, mask
  647. if (RSettings.getDevicePixelRatio()===2 && RS.getSystemId()!=="osx") {
  648. bitmap = new QBitmap(EAction.includeBasePath + "/CrosshairCursor@2x.png", "PNG");
  649. mask = new QBitmap(EAction.includeBasePath + "/CrosshairCursorMask@2x.png", "PNG");
  650. //bitmap.setDevicePixelRatio(2);
  651. //mask.setDevicePixelRatio(2);
  652. EAction.crossCursor = new QCursor(bitmap, mask, 30, 30);
  653. }
  654. else {
  655. bitmap = new QBitmap(EAction.includeBasePath + "/CrosshairCursor.png", "PNG");
  656. mask = new QBitmap(EAction.includeBasePath + "/CrosshairCursorMask.png", "PNG");
  657. EAction.crossCursor = new QCursor(bitmap, mask, 15, 15);
  658. }
  659. }
  660. }
  661. this.setCursor(EAction.crossCursor, "CrossCursor");
  662. };
  663. /**
  664. * Sets the current cursor of the current document interface (all views attached
  665. * to it) to the normal arrow cursor.
  666. */
  667. EAction.prototype.setArrowCursor = function() {
  668. this.setCursor(new QCursor(Qt.ArrowCursor));
  669. };
  670. EAction.prototype.setCursor = function(cursor, name) {
  671. var di = this.getDocumentInterface();
  672. if (!isNull(di)) {
  673. di.setCursor(cursor);
  674. }
  675. // if (!isNull(name)) {
  676. // var views = this.getGraphicsViews();
  677. // for (var i=0; i<views.length; i++) {
  678. // if (isFunction(views[i].setProperty)) {
  679. // views[i].setProperty("CursorName", name);
  680. // }
  681. // }
  682. // }
  683. };
  684. /**
  685. * Creates a new widget based on the given UI file with the given parent. This
  686. * is a helper function for WidgetFactory.createWidget.
  687. */
  688. EAction.prototype.createWidget = function(uiFile, parent) {
  689. return WidgetFactory.createWidget(this.includeBasePath, uiFile, parent);
  690. };
  691. /**
  692. * Creates a new dialog based on the given UI file with the given parent. This
  693. * is a helper function for WidgetFactory.createDialog.
  694. */
  695. EAction.prototype.createDialog = function(uiFile, parent) {
  696. return WidgetFactory.createDialog(this.includeBasePath, uiFile, parent);
  697. };
  698. /**
  699. * \return The current document or null.
  700. */
  701. EAction.getDocument = function() {
  702. var di = EAction.getDocumentInterface();
  703. if (isNull(di)) {
  704. return undefined;
  705. }
  706. return di.getDocument();
  707. };
  708. /**
  709. * \return The storage of the current document or null.
  710. */
  711. EAction.getStorage = function() {
  712. var doc = EAction.getDocument();
  713. if (isNull(doc)) {
  714. return undefined;
  715. }
  716. return doc.getStorage();
  717. };
  718. EAction.prototype.getDocumentInterface = function() {
  719. if (!isNull(global.gDocumentInterface)) {
  720. return global.gDocumentInterface;
  721. }
  722. return RAction.prototype.getDocumentInterface.call(this);
  723. };
  724. /**
  725. * \return The current document interface or null.
  726. */
  727. EAction.getDocumentInterface = function() {
  728. if (!isNull(global.gDocumentInterface)) {
  729. return global.gDocumentInterface;
  730. }
  731. var appWin = EAction.getMainWindow();
  732. if (isNull(appWin)) {
  733. return undefined;
  734. }
  735. return appWin.getDocumentInterface();
  736. };
  737. /**
  738. * \return The current main window.
  739. */
  740. EAction.getMainWindow = function() {
  741. if (!isNull(global.gMainWindow)) {
  742. return global.gMainWindow;
  743. }
  744. return RMainWindowQt.getMainWindow();
  745. };
  746. /**
  747. * Reactivates the main window after showing a dialog.
  748. * This is necessary with Qt>=5.
  749. * Not necessary with Qt>=5.10.
  750. */
  751. EAction.activateMainWindow = function() {
  752. // if (RSettings.isQt(5)) {
  753. // var appWin = EAction.getMainWindow();
  754. // if (isNull(appWin)) {
  755. // return;
  756. // }
  757. // appWin.activateWindow();
  758. // var view = EAction.getGraphicsView();
  759. // if (!isNull(view)) {
  760. // // view loses focus because of dialogs:
  761. // view.giveFocus();
  762. // }
  763. // }
  764. };
  765. /**
  766. * \return The current MDI child or null.
  767. */
  768. EAction.getMdiChild = function() {
  769. var appWin = RMainWindowQt.getMainWindow();
  770. if (isNull(appWin)) {
  771. return undefined;
  772. }
  773. return appWin.getMdiChild();
  774. };
  775. /**
  776. * \return The MDI area or null.
  777. */
  778. EAction.getMdiArea = function() {
  779. var appWin = EAction.getMainWindow();
  780. if (isNull(appWin)) {
  781. return undefined;
  782. }
  783. return appWin.getMdiArea();
  784. };
  785. /**
  786. * \return List of all graphics views attached to the current document interface.
  787. */
  788. EAction.prototype.getGraphicsViews = function() {
  789. var di = this.getDocumentInterface();
  790. if (isNull(di)) {
  791. return [];
  792. }
  793. return EAction.getGraphicsViews(di);
  794. };
  795. EAction.getGraphicsViews = function(di) {
  796. var ret = [];
  797. var scenes = di.getGraphicsScenes();
  798. for (var i=0; i<scenes.length; i++) {
  799. var views = scenes[i].getGraphicsViews();
  800. ret = ret.concat(views);
  801. }
  802. return ret;
  803. }
  804. EAction.prototype.getGraphicsView = function() {
  805. var di = this.getDocumentInterface();
  806. if (isNull(di)) {
  807. return undefined;
  808. }
  809. return di.getLastKnownViewWithFocus();
  810. };
  811. /**
  812. * \return Graphics view with focus or last known graphics view with focus.
  813. */
  814. EAction.getGraphicsView = function() {
  815. var di = EAction.getDocumentInterface();
  816. if (isNull(di)) {
  817. return undefined;
  818. }
  819. return di.getLastKnownViewWithFocus();
  820. };
  821. /**
  822. * \return the existing menu with the given object name or, if no such menu
  823. * exists, a new menu with the given title and the given object name.
  824. *
  825. * \param title Translated title to use for the menu. E.g. qsTr("&File"). \param
  826. * objectName Object name to use for the menu. Used mainly for later
  827. * identification of the menu. E.g. "file". \param initFunction Function that is
  828. * called only if a new menu is created. Used to initialize the menu, e.g.
  829. * connecting signals, etc.
  830. */
  831. EAction.getMenu = function(title, objectName, initFunction) {
  832. if (isNull(objectName)) {
  833. objectName = "";
  834. }
  835. var appWin = EAction.getMainWindow();
  836. var menuBar = appWin.menuBar();
  837. var menu;
  838. var children = menuBar.children();
  839. for (var i in children) {
  840. menu = children[i];
  841. if (!isNull(menu) && menu.objectName === objectName) {
  842. break;
  843. }
  844. menu = undefined;
  845. }
  846. if (isNull(menu)) {
  847. menu = new QMenu(title, menuBar);
  848. menu.objectName = objectName;
  849. menuBar.addMenu(menu);
  850. if (initFunction != undefined) {
  851. initFunction(menu);
  852. }
  853. }
  854. return menu;
  855. };
  856. /**
  857. * \return the existing submenu with the given object name or creates a new
  858. * submenu as child of the given menu, with the given sort order, title and
  859. * icon.
  860. *
  861. * \param menu Parent menu.
  862. * \param sortOrder Sort order among other submenus. All
  863. * submenus within the same menu are ordered by this number.
  864. * \param title Translated title of the submenu. E.g. qsTr("&Line").
  865. * \param objectName Object name to use for the menu. Used mainly for
  866. * later identification of the menu.
  867. * E.g. "line". \param iconFile Path and file name of icon to use for this
  868. * submenu.
  869. */
  870. EAction.getSubMenu = function(menu, groupSortOrder, sortOrder, title, objectName, iconFile) {
  871. var subMenu = menu.findChild(objectName);
  872. if (isNull(subMenu)) {
  873. //var action = menu.addMenu(subMenu);
  874. var action = new RGuiAction(title, menu);
  875. action.objectName = objectName + "Action";
  876. //subMenu = new QMenu(title + " {%1,%2}".arg(groupSortOrder).arg(sortOrder), menu);
  877. subMenu = new QMenu(title, menu);
  878. subMenu.objectName = objectName;
  879. if (!isNull(iconFile)) {
  880. subMenu.icon = new QIcon(iconFile);
  881. }
  882. action.setMenu(subMenu);
  883. RGuiAction.setGroupSortOrderStatic(action, groupSortOrder);
  884. RGuiAction.setSortOrderStatic(action, sortOrder);
  885. RGuiAction.setWidgetNamesStatic(action, [menu.objectName]);
  886. // re-add action at correct position:
  887. //RGuiAction.addToWidget(action, menu);
  888. // subMenu = new QMenu(title, menu);
  889. // var subMenuActions = menu.actions();
  890. // var actionBefore = undefined;
  891. // for (var i = 0; i < subMenuActions.length; ++i) {
  892. // var so = subMenuActions[i].property("SortOrder");
  893. // if (!isNull(so) && so > sortOrder) {
  894. // actionBefore = subMenuActions[i];
  895. // break;
  896. // }
  897. // }
  898. // subMenu = new QMenu(title, menu);
  899. // if (!isNull(iconFile)) {
  900. // subMenu.icon = new QIcon(iconFile);
  901. // }
  902. // var separator;
  903. // if (addSeparator) {
  904. // separator = new RGuiAction("", RMainWindowQt.getMainWindow());
  905. // separator.setSeparator(true);
  906. // separator.setSortOrder(sortOrder - 1);
  907. // separator.addToMenu(menu);
  908. // }
  909. // var subMenuAction;
  910. // if (isNull(actionBefore)) {
  911. // subMenuAction = menu.addMenu(subMenu);
  912. // } else {
  913. // subMenuAction = menu.insertMenu(actionBefore, subMenu);
  914. // }
  915. // subMenu.objectName = objectName;
  916. // subMenuAction.setProperty("SortOrder", sortOrder);
  917. }
  918. return subMenu;
  919. };
  920. /**
  921. * \return Existing or new toolbar.
  922. *
  923. * \param title Translated title of the toolbar. E.g. qsTr("Snap").
  924. * \param objectName Object name to use for the toolbar. Used mainly for later
  925. * identification of the toolbar. E.g. "line".
  926. * \param toolBarArea Area where the new toolbar should be added. Note that the
  927. * actual location where the toolbar is added may also depend on the previously
  928. * saved state of the tool bars. Defaults to Qt.TopToolBarArea.
  929. */
  930. EAction.getToolBar = function(title, objectName, toolBarArea, category, before) {
  931. if (isNull(objectName)) {
  932. objectName = "";
  933. }
  934. if (isNull(toolBarArea)) {
  935. toolBarArea = Qt.TopToolBarArea;
  936. }
  937. var appWin = EAction.getMainWindow();
  938. if (isNull(appWin)) {
  939. return undefined;
  940. }
  941. var tb = undefined;
  942. if (objectName.length !== 0) {
  943. tb = appWin.findChild(objectName);
  944. }
  945. if (!isNull(tb) && !isOfType(tb, QToolBar)) {
  946. qWarning("Not a toolbar: " + tb);
  947. return undefined;
  948. }
  949. if (isNull(tb)) {
  950. tb = new QToolBar(title);
  951. tb.objectName = objectName;
  952. if (!isNull(category)) {
  953. tb.setProperty("Category", category);
  954. }
  955. var s = RSettings.getIntValue("ToolBar/IconSize", tb.iconSize.width());
  956. tb.iconSize = new QSize(s,s);
  957. if (isNull(before)) {
  958. appWin.addToolBar(toolBarArea, tb);
  959. }
  960. else {
  961. appWin.insertToolBar(before, tb);
  962. }
  963. }
  964. return tb;
  965. };
  966. /**
  967. * \return Existing or new dock.
  968. *
  969. * \param title Translated title of the dock widget. E.g. qsTr("Snap").
  970. * \param objectName Object name to use for the dock widget. Used mainly for later
  971. * identification of the dock widget. E.g. "line".
  972. * \param toolBarArea Area where the new dock should be added. Note that the
  973. * actual location where the dock is added may also depend on the previously
  974. * saved state of the docks. Defaults to Qt.LeftDockWidgetArea.
  975. */
  976. EAction.getToolMatrixPanel = function(title, objectName, order) {
  977. if (isNull(objectName)) {
  978. objectName = "";
  979. }
  980. include("scripts/Widgets/CadToolMatrix/CadToolMatrix.js");
  981. return CadToolMatrix.getToolMatrixPanel(title, objectName, order);
  982. };
  983. /**
  984. * \return Existing or new options toolbar (used to display options for the
  985. * current tool).
  986. */
  987. EAction.getOptionsToolBar = function() {
  988. var appWin = EAction.getMainWindow();
  989. if (isNull(EAction.optionsToolBar)) {
  990. if (!isNull(appWin)) {
  991. appWin.addToolBarBreak();
  992. }
  993. EAction.optionsToolBar = EAction.getToolBar(qsTr("Options"), "Options");
  994. }
  995. if (!isNull(EAction.optionsToolBar)) {
  996. if (!RSettings.getOriginalArguments().contains("-no-show")) {
  997. EAction.optionsToolBar.visible = false;
  998. }
  999. }
  1000. return EAction.optionsToolBar;
  1001. };
  1002. /**
  1003. * \return Existing or new block toolbar (used to display options for the
  1004. * current block).
  1005. */
  1006. //EAction.getBlockToolBar = function() {
  1007. // if (isNull(EAction.blockToolBar)) {
  1008. // EAction.blockToolBar = EAction.getToolBar(qsTr("Block Options"), "BlockOptions");
  1009. // }
  1010. // return EAction.blockToolBar;
  1011. //};
  1012. /**
  1013. * \return The main (top) CAD toolbar panel.
  1014. */
  1015. EAction.getMainCadToolBarPanel = function() {
  1016. return EAction.getCadToolBarPanel(qsTr("Main Tools"), "MainToolsPanel", false);
  1017. };
  1018. /**
  1019. * \return Existing or new CAD toolbar panel. Each CAD toolbar panel contains
  1020. * a set of tools, e.g. to draw lines, change the snap tool, etc. The CAD tool
  1021. * bar itself is created automatically when this function is called for the
  1022. * first time.
  1023. *
  1024. * \param title Translated title to use for the CAD toolbar panel. E.g.
  1025. * qsTr("Snap"). \param objectName Object name to use for the panel. Used mainly
  1026. * for later identification of the panel. E.g. "snap". \param hasBackButton True
  1027. * to display a back button at the top or left to allow the user to navigate
  1028. * back to the main CAD toolbar panel.
  1029. */
  1030. EAction.getCadToolBarPanel = function(title, objectName, hasBackButton) {
  1031. var appWin = EAction.getMainWindow();
  1032. var cadToolBar = appWin.findChild("CadToolBar");
  1033. // create CAD toolbar if it does not exist already:
  1034. if (isNull(cadToolBar)) {
  1035. cadToolBar = new RCadToolBar(qsTr("CAD Tools"), appWin);
  1036. cadToolBar.objectName = "CadToolBar";
  1037. // cadToolBar.updateIconSize();
  1038. cadToolBar.topLevelChanged.connect(function(onOff) {
  1039. RSettings.setValue("CadToolBar/VerticalWhenFloating", false);
  1040. });
  1041. cadToolBar.orientationChanged.connect(function(orientation) {
  1042. RSettings.setValue("CadToolBar/VerticalWhenFloating", false);
  1043. });
  1044. }
  1045. return cadToolBar.getPanel(title, objectName, hasBackButton);
  1046. };
  1047. /**
  1048. * Shows the CAD toolbar panel with the given objectName.
  1049. */
  1050. EAction.showCadToolBarPanel = function(objectName) {
  1051. var appWin = EAction.getMainWindow();
  1052. if (isNull(appWin)) {
  1053. return;
  1054. }
  1055. var toolBar = appWin.findChild("CadToolBar");
  1056. toolBar.showPanel(objectName);
  1057. };
  1058. /**
  1059. * Shows the CAD toolbar panel with the snap tools.
  1060. */
  1061. EAction.showSnapTools = function() {
  1062. EAction.showCadToolBarPanel("SnapToolsPanel");
  1063. };
  1064. /**
  1065. * Shows the CAD toolbar panel with the main tools.
  1066. */
  1067. EAction.showMainTools = function() {
  1068. EAction.showCadToolBarPanel("MainToolsPanel");
  1069. };
  1070. /**
  1071. * Shows the CAD toolbar panel with the point tools.
  1072. */
  1073. EAction.showPointTools = function() {
  1074. EAction.showCadToolBarPanel("PointToolsPanel");
  1075. };
  1076. /**
  1077. * Shows the CAD toolbar panel with the line tools.
  1078. */
  1079. EAction.showLineTools = function() {
  1080. EAction.showCadToolBarPanel("LineToolsPanel");
  1081. };
  1082. /**
  1083. * Shows the CAD toolbar panel with the arc tools.
  1084. */
  1085. EAction.showArcTools = function() {
  1086. EAction.showCadToolBarPanel("ArcToolsPanel");
  1087. };
  1088. /**
  1089. * Shows the CAD toolbar panel with the circle tools.
  1090. */
  1091. EAction.showCircleTools = function() {
  1092. EAction.showCadToolBarPanel("CircleToolsPanel");
  1093. };
  1094. /**
  1095. * Shows the CAD toolbar panel with the dimension tools.
  1096. */
  1097. EAction.showDimensionTools = function() {
  1098. EAction.showCadToolBarPanel("DimensionToolsPanel");
  1099. };
  1100. /**
  1101. * Shows the CAD toolbar panel with the ellipse tools.
  1102. */
  1103. EAction.showEllipseTools = function() {
  1104. EAction.showCadToolBarPanel("EllipseToolsPanel");
  1105. };
  1106. /**
  1107. * Shows the CAD toolbar panel with the spline tools.
  1108. */
  1109. EAction.showSplineTools = function() {
  1110. EAction.showCadToolBarPanel("SplineToolsPanel");
  1111. };
  1112. /**
  1113. * Shows the CAD toolbar panel with the polyline tools.
  1114. */
  1115. EAction.showPolylineTools = function() {
  1116. EAction.showCadToolBarPanel("PolylineToolsPanel");
  1117. };
  1118. /**
  1119. * Shows the CAD toolbar panel with the shape tools.
  1120. */
  1121. EAction.showShapeTools = function() {
  1122. EAction.showCadToolBarPanel("ShapeToolsPanel");
  1123. };
  1124. /**
  1125. * Shows the CAD toolbar panel with the modification tools.
  1126. */
  1127. EAction.showModificationTools = function() {
  1128. EAction.showCadToolBarPanel("ModifyToolsPanel");
  1129. };
  1130. /**
  1131. * Shows the CAD toolbar panel with the measuring / info tools.
  1132. */
  1133. EAction.showInformationTools = function() {
  1134. EAction.showCadToolBarPanel("InformationToolsPanel");
  1135. };
  1136. /**
  1137. * Shows the CAD toolbar panel with the selection tools.
  1138. */
  1139. EAction.showSelectTools = function() {
  1140. EAction.showCadToolBarPanel("SelectToolsPanel");
  1141. };
  1142. /**
  1143. * Helper function to conveniently add the given action to a menu, toolbar and
  1144. * CAD toolbar.
  1145. *
  1146. * \param action RAction object.
  1147. * \param iface Interface to use to retrieve the appropriate menu, toolbar and CAD toolbar panel.
  1148. * \param addToMenu True to add this action to the appropriate menu.
  1149. * \param addToToolbar True to add this action to the appropriate toolbar.
  1150. * \param addToCadToolbar True to add this action to the appropriate CAD toolbar panel.
  1151. * \param addSeparator True to add a separator before this action.
  1152. */
  1153. EAction.addGuiActionTo = function(action, iface, addToMenu, addToToolBar,
  1154. addToCadToolBar, addSeparator) {
  1155. var className = action.getScriptClass();
  1156. if (isNull(addToMenu)) {
  1157. addToMenu = false;
  1158. }
  1159. if (isNull(addToToolBar)) {
  1160. addToToolBar = false;
  1161. }
  1162. if (isNull(addToCadToolBar)) {
  1163. addToCadToolBar = false;
  1164. }
  1165. if (isNull(addSeparator)) {
  1166. addSeparator = false;
  1167. }
  1168. var addToUserToolBar1 = false;
  1169. var addToUserToolBar2 = false;
  1170. if (className.length!==0) {
  1171. var key = className + "/VisibleInMenu";
  1172. addToMenu = RSettings.getBoolValue(key, addToMenu);
  1173. if (!RSettings.hasValue(key)) {
  1174. RSettings.setValue(key, addToMenu);
  1175. }
  1176. key = className + "/VisibleInToolBar";
  1177. addToToolBar = RSettings.getBoolValue(key, addToToolBar);
  1178. if (!RSettings.hasValue(key)) {
  1179. RSettings.setValue(key, addToToolBar);
  1180. }
  1181. key = className + "/VisibleInCadToolBar";
  1182. addToCadToolBar = RSettings.getBoolValue(key, addToCadToolBar);
  1183. if (!RSettings.hasValue(key)) {
  1184. RSettings.setValue(key, addToCadToolBar);
  1185. }
  1186. key = className + "/VisibleInUserToolBar1";
  1187. addToUserToolBar1 = RSettings.getBoolValue(key, addToUserToolBar1);
  1188. if (!RSettings.hasValue(key)) {
  1189. RSettings.setValue(key, addToUserToolBar1);
  1190. }
  1191. key = className + "/VisibleInUserToolBar2";
  1192. addToUserToolBar2 = RSettings.getBoolValue(key, addToUserToolBar2);
  1193. if (!RSettings.hasValue(key)) {
  1194. RSettings.setValue(key, addToUserToolBar2);
  1195. }
  1196. }
  1197. if (isNull(iface)) {
  1198. qWarning("EAction.js:", "addGuiActionTo(): iface not defined");
  1199. }
  1200. if (action.icon.isNull() && !action.isIconDisabled()) {
  1201. action.setIcon(autoPath("scripts/Empty.svg"));
  1202. }
  1203. var separator;
  1204. if (addSeparator) {
  1205. separator = new RGuiAction("", RMainWindowQt.getMainWindow());
  1206. separator.setSeparator(true);
  1207. //separator.setSortOrder(action.getSortOrder() - 1);
  1208. }
  1209. if (addToMenu) {
  1210. if (isFunction(iface.getMenu)) {
  1211. var menu = iface.getMenu();
  1212. if (!isNull(menu)) {
  1213. if (!isNull(separator)) {
  1214. separator.addToMenu(menu);
  1215. }
  1216. action.addToMenu(menu);
  1217. }
  1218. }
  1219. }
  1220. if (addToToolBar) {
  1221. if (isFunction(iface.getToolBar)) {
  1222. var tb = iface.getToolBar();
  1223. if (!isNull(tb)) {
  1224. action.addToToolBar(tb);
  1225. if (addSeparator) {
  1226. var sp = new RGuiAction("", RMainWindowQt.getMainWindow());
  1227. sp.setSeparator(true);
  1228. sp.setSortOrder(action.getSortOrder() - 1);
  1229. sp.addToToolBar(tb);
  1230. }
  1231. }
  1232. }
  1233. }
  1234. if (addToCadToolBar) {
  1235. if (isFunction(iface.getCadToolBarPanel)) {
  1236. var ctb = iface.getCadToolBarPanel();
  1237. if (!isNull(ctb)) {
  1238. // if (!isNull(separator)) {
  1239. // CadToolBarPanel.prototype.addAction.call(ctb, separator);
  1240. // }
  1241. //CadToolBarPanel.prototype.addAction.call(ctb, action);
  1242. //ctb.addAction(action);
  1243. action.addToWidget(ctb);
  1244. }
  1245. }
  1246. }
  1247. var appWin = EAction.getMainWindow();
  1248. if (addToUserToolBar1) {
  1249. var tb = appWin.findChild("UserToolBar1");
  1250. if (!isNull(tb)) {
  1251. action.addToToolBar(tb);
  1252. }
  1253. }
  1254. if (addToUserToolBar2) {
  1255. var tb = appWin.findChild("UserToolBar2");
  1256. if (!isNull(tb)) {
  1257. action.addToToolBar(tb);
  1258. }
  1259. }
  1260. };
  1261. //EAction.addGuiActionToWidgets = function(action, widgetNames) {
  1262. // var appWin = EAction.getMainWindow();
  1263. // var className = action.getScriptClass();
  1264. // var addToMenu, addToToolBar, addToCadToolBar;
  1265. // if (className.length!==0) {
  1266. // var key = className + "/VisibleInMenu";
  1267. // addToMenu = RSettings.getBoolValue(key, addToMenu);
  1268. // if (!RSettings.hasValue(key)) {
  1269. // RSettings.setValue(key, addToMenu);
  1270. // }
  1271. // key = className + "/VisibleInToolBar";
  1272. // addToToolBar = RSettings.getBoolValue(key, addToToolBar);
  1273. // if (!RSettings.hasValue(key)) {
  1274. // RSettings.setValue(key, addToToolBar);
  1275. // }
  1276. // key = className + "/VisibleInCadToolBar";
  1277. // addToCadToolBar = RSettings.getBoolValue(key, addToCadToolBar);
  1278. // if (!RSettings.hasValue(key)) {
  1279. // RSettings.setValue(key, addToCadToolBar);
  1280. // }
  1281. // }
  1282. // var i, w;
  1283. // var oldWidgets = action.associatedWidgets();
  1284. // for (i=0; i<oldWidgets.length; i++) {
  1285. // w = oldWidgets[i];
  1286. // w.removeAction(action);
  1287. // }
  1288. // for (i=0; i<widgetNames.length; i++) {
  1289. // var wn = widgetNames[i];
  1290. // w = appWin.findChild(wn);
  1291. // action.addToWidget(w);
  1292. // }
  1293. //};
  1294. /**
  1295. * \return The boolean value of the given variable from the document if it
  1296. * exists in the document, from the settings file if it exists there. If the
  1297. * variable does not exist in the document nor the settings file, the given
  1298. * defaultValue is returned.
  1299. */
  1300. EAction.getBoolValue = function(varName, defaultValue, document) {
  1301. if (isNull(document)) {
  1302. document = EAction.getDocument();
  1303. }
  1304. if (!isNull(document)) {
  1305. var val = document.getVariable(varName);
  1306. if (typeof (val) != "undefined") {
  1307. return val;
  1308. }
  1309. }
  1310. return RSettings.getBoolValue(varName, defaultValue);
  1311. };
  1312. /**
  1313. * \return The int value of the given variable from the document if it exists in
  1314. * the document, from the settings file if it exists there. If the variable does
  1315. * not exist in the document nor the settings file, the given defaultValue is
  1316. * returned.
  1317. */
  1318. EAction.getIntValue = function(varName, defaultValue, document) {
  1319. if (isNull(document)) {
  1320. document = EAction.getDocument();
  1321. }
  1322. if (!isNull(document)) {
  1323. var val = document.getVariable(varName);
  1324. if (typeof (val) != "undefined") {
  1325. return parseInt(val, 10);
  1326. }
  1327. }
  1328. return RSettings.getIntValue(varName, parseInt(defaultValue, 10));
  1329. };
  1330. /**
  1331. * \return The float value of the given variable from the document if it exists
  1332. * in the document, from the settings file if it exists there. If the variable
  1333. * does not exist in the document nor the settings file, the given defaultValue
  1334. * is returned.
  1335. */
  1336. EAction.getDoubleValue = function(varName, defaultValue, document) {
  1337. if (isNull(document)) {
  1338. document = EAction.getDocument();
  1339. }
  1340. if (!isNull(document)) {
  1341. var val = document.getVariable(varName);
  1342. if (typeof (val) != "undefined") {
  1343. return parseFloat(val);
  1344. }
  1345. }
  1346. return RSettings.getDoubleValue(varName, parseFloat(defaultValue));
  1347. };
  1348. /**
  1349. * \return The string value of the given variable from the document if it exists
  1350. * in the document, from the settings file if it exists there. If the variable
  1351. * does not exist in the document nor the settings file, the given defaultValue
  1352. * is returned.
  1353. */
  1354. EAction.getStringValue = function(varName, defaultValue, document) {
  1355. if (isNull(document)) {
  1356. document = EAction.getDocument();
  1357. }
  1358. if (!isNull(document)) {
  1359. var val = document.getVariable(varName);
  1360. if (typeof (val) != "undefined") {
  1361. return val.toString();
  1362. }
  1363. }
  1364. return RSettings.getStringValue(varName, defaultValue);
  1365. };
  1366. /**
  1367. * \return The value of the given variable from the document if it exists in the
  1368. * document, from the settings file if it exists there. If the variable does not
  1369. * exist in the document nor the settings file, the given defaultValue is
  1370. * returned.
  1371. */
  1372. EAction.getValue = function(varName, defaultValue, document) {
  1373. if (isNull(document)) {
  1374. document = EAction.getDocument();
  1375. }
  1376. if (!isNull(document)) {
  1377. var val = document.getVariable(varName, defaultValue);
  1378. if (!isNull(val)) {
  1379. return val;
  1380. }
  1381. }
  1382. return RSettings.getValue(varName, defaultValue);
  1383. };
  1384. /**
  1385. * Adds the given widgets to the status bar of the application.
  1386. * \param sortOrder Defines the sort order of widgets in the status bar.
  1387. */
  1388. EAction.addToStatusBar = function(widget, sortOrder) {
  1389. include("scripts/Widgets/StatusBar/StatusBar.js");
  1390. StatusBar.addWidget(widget, sortOrder);
  1391. };
  1392. EAction.prototype.getScales = function() {
  1393. var doc = this.getDocument();
  1394. if (isNull(doc)) {
  1395. return [];
  1396. }
  1397. return EAction.getScales(doc.getUnit());
  1398. };
  1399. EAction.getScales = function(unit) {
  1400. var scales;
  1401. if (RUnit.isMetric(unit)) {
  1402. // common metric scales:
  1403. scales = new Array(
  1404. "1:1", "1:2", "1:5", "1:10", "1:20", "1:25", "1:50", "1:75",
  1405. "1:100", "1:125", "1:150", "1:175",
  1406. "1:200", "1:250", "1:500", "1:750",
  1407. "1:1000", "1:2500", "1:5000", "1:7500",
  1408. "1:10000", "1:25000", "1:50000", "1:75000",
  1409. "1:100000", "1:250000", "1:500000", "1:750000",
  1410. "1:1000000",
  1411. "2:1", "5:1", "10:1", "20:1", "25:1", "50:1", "75:1",
  1412. "100:1", "125:1", "150:1", "175:1",
  1413. "200:1", "250:1", "500:1", "750:1",
  1414. "1000:1", "2500:1", "5000:1", "7500:1",
  1415. "10000:1", "25000:1", "50000:1", "75000:1",
  1416. "100000:1", "250000:1", "500000:1", "750000:1",
  1417. "1000000:1");
  1418. } else {
  1419. // common imperial scales:
  1420. scales = new Array(
  1421. '1" = 1"', '1" = 2"', '1" = 4"', '1" = 8"', '1" = 16"',
  1422. '1" = 32"', '1" = 64"', '1" = 128"', '1" = 256"',
  1423. '1" = 512"', '1" = 1024"', '1" = 2048"', '1" = 4096"',
  1424. '1/4096" = 1\'-0"', '1/2048" = 1\'-0"', '1/1024" = 1\'-0"',
  1425. '1/512" = 1\'-0"', '1/256" = 1\'-0"', '1/128" = 1\'-0"',
  1426. '1/64" = 1\'-0"',
  1427. '1/32" = 1\'-0"',
  1428. '1/16" = 1\'-0"',
  1429. '3/32" = 1\'-0"',
  1430. '1/8" = 1\'-0"',
  1431. '3/16" = 1\'-0"',
  1432. '1/4" = 1\'-0"',
  1433. '3/8" = 1\'-0"',
  1434. '1/2" = 1\'-0"',
  1435. '3/4" = 1\'-0"',
  1436. '1" = 1\'-0"', '2" = 1\'-0"', '3" = 1\'-0"', '4" = 1\'-0"',
  1437. '5" = 1\'-0"', '6" = 1\'-0"', '7" = 1\'-0"', '8" = 1\'-0"',
  1438. '9" = 1\'-0"', '10" = 1\'-0"', '11" = 1\'-0"');
  1439. }
  1440. return scales;
  1441. };
  1442. /**
  1443. * Called by updatePreview. Implementations must return an ROperation subclass
  1444. * object for the operation that should be previewed.
  1445. */
  1446. EAction.prototype.getOperation = function(preview) {
  1447. return undefined;
  1448. };
  1449. /**
  1450. * Called by updatePreview. Implementations must return an array of RShape
  1451. * objects that should be displayed as auxiliary construction.
  1452. */
  1453. EAction.prototype.getAuxPreview = function() {
  1454. return undefined;
  1455. };
  1456. /**
  1457. * Called by updatePreview. Implementations must return an array of entity IDs
  1458. * which should be highlighted.
  1459. */
  1460. EAction.prototype.getHighlightedEntities = function() {
  1461. return undefined;
  1462. };
  1463. /**
  1464. * Called by updatePreview. Implementations must handle errors during preview.
  1465. */
  1466. EAction.prototype.handlePreviewError = function() {
  1467. return;
  1468. };
  1469. /**
  1470. * Updates the preview based on the operation returned by getOperation and the
  1471. * auxiliary construction returned be getAuxPreview.
  1472. *
  1473. * \param clear True to clear the preview first. This is necessary if the
  1474. * preview is updated not as a result of a mouse move event, e.g. when changing
  1475. * action parameters in the options toolbar.
  1476. */
  1477. EAction.prototype.updatePreview = function(clear) {
  1478. if (isNull(clear)) {
  1479. clear = false;
  1480. }
  1481. var di = this.getDocumentInterface();
  1482. if (isNull(di)) {
  1483. return;
  1484. }
  1485. if (clear === true) {
  1486. di.clearPreview();
  1487. }
  1488. var op = this.getOperation(true);
  1489. if (!isNull(op)) {
  1490. di.previewOperation(op);
  1491. }
  1492. else {
  1493. this.handlePreviewError();
  1494. }
  1495. var i;
  1496. var previewShapes = this.getAuxPreview();
  1497. if (!isNull(previewShapes)) {
  1498. for (i = 0; i < previewShapes.length; ++i) {
  1499. di.addAuxShapeToPreview(previewShapes[i]);
  1500. }
  1501. }
  1502. var highlightedEntities = this.getHighlightedEntities();
  1503. if (!isNull(highlightedEntities)) {
  1504. for (i = 0; i < highlightedEntities.length; ++i) {
  1505. di.highlightEntity(highlightedEntities[i]);
  1506. }
  1507. }
  1508. di.repaintViews();
  1509. };
  1510. /**
  1511. * Applies the operation returned by this.getOperation().
  1512. */
  1513. EAction.prototype.applyOperation = function() {
  1514. var di = this.getDocumentInterface();
  1515. var op = this.getOperation(false);
  1516. if (isNull(op)) {
  1517. qWarning("Operation returned by this.getOperation() is undefined");
  1518. return false;
  1519. }
  1520. this.complementOperation(op);
  1521. var t = di.applyOperation(op);
  1522. this.postOperation(t);
  1523. return true;
  1524. };
  1525. /**
  1526. * Can be reimplemented to complement the operation of an action.
  1527. */
  1528. EAction.prototype.complementOperation = function(op) {
  1529. return;
  1530. };
  1531. /**
  1532. * Can be reimplemented to work with the transaction returned by the operation.
  1533. */
  1534. EAction.prototype.postOperation = function(transaction) {
  1535. return;
  1536. };
  1537. /**
  1538. * High level event triggered when a coordinate was specified by the user of a
  1539. * coordinate specification should be previewed.
  1540. */
  1541. EAction.prototype.pickCoordinate = function(event, preview) {
  1542. };
  1543. /**
  1544. * Default implementation. Calls pickCoordinate(event, false)
  1545. */
  1546. EAction.prototype.coordinateEvent = function(event) {
  1547. // don't let invalid positions go through for most cases (this is overridden for DefaultAction):
  1548. var pos = event.getModelPosition();
  1549. if (!isValidVector(pos)) {
  1550. EAction.handleUserWarning(qsTr("Invalid position"));
  1551. return;
  1552. }
  1553. this.pickCoordinate(event, false);
  1554. };
  1555. /**
  1556. * Default implementation. Calls pickCoordinate(event, true)
  1557. */
  1558. EAction.prototype.coordinateEventPreview = function(event) {
  1559. this.pickCoordinate(event, true);
  1560. };
  1561. /**
  1562. * High level event triggered when an entity was picked by the user or to
  1563. * preview picking an entity.
  1564. */
  1565. EAction.prototype.pickEntity = function(event, preview) {
  1566. };
  1567. /**
  1568. * Default implementation. Calls pickEntity(event, false)
  1569. */
  1570. EAction.prototype.entityPickEvent = function(event) {
  1571. this.pickEntity(event, false);
  1572. };
  1573. /**
  1574. * Default implementation. Calls pickEntity(event, true)
  1575. */
  1576. EAction.prototype.entityPickEventPreview = function(event) {
  1577. this.pickEntity(event, true);
  1578. };
  1579. /**
  1580. * High level event triggered when a command line command should be applied or
  1581. * previewed.
  1582. */
  1583. EAction.prototype.applyCommand = function(event, preview) {
  1584. };
  1585. /**
  1586. * Default implementation. Calls applyCommand(event, false)
  1587. */
  1588. EAction.prototype.commandEvent = function(event) {
  1589. this.applyCommand(event, false);
  1590. };
  1591. /**
  1592. * Default implementation. Calls applyCommand(event, true)
  1593. */
  1594. EAction.prototype.commandEventPreview = function(event) {
  1595. this.applyCommand(event, true);
  1596. };
  1597. EAction.prototype.simulateMouseMoveEvent = function() {
  1598. var di = this.getDocumentInterface();
  1599. if (isNull(di)) {
  1600. return;
  1601. }
  1602. var view = di.getLastKnownViewWithFocus();
  1603. if (isNull(view)) {
  1604. return;
  1605. }
  1606. view = getRGraphicsView(view);
  1607. if (isNull(view)) {
  1608. return;
  1609. }
  1610. view.simulateMouseMoveEvent();
  1611. };
  1612. /**
  1613. * Shows the given warning to the user.
  1614. *
  1615. * \param escape True to escape rich text and disaply the message
  1616. * exactly as given (default), false to allow rich text in message
  1617. * (colors, indentation, links, etc.)
  1618. */
  1619. EAction.handleUserWarning = function(message, escape) {
  1620. if (isNull(message)) {
  1621. return;
  1622. }
  1623. if (isNull(escape)) {
  1624. escape = true;
  1625. }
  1626. var appWin = EAction.getMainWindow();
  1627. if (isNull(appWin)) {
  1628. return;
  1629. }
  1630. appWin.handleUserWarning(message, false, escape);
  1631. };
  1632. EAction.handleUserMessage = function(message, escape) {
  1633. if (isNull(message)) {
  1634. return;
  1635. }
  1636. if (isNull(escape)) {
  1637. escape = true;
  1638. }
  1639. var appWin = EAction.getMainWindow();
  1640. if (isNull(appWin)) {
  1641. return;
  1642. }
  1643. appWin.handleUserMessage(message, escape);
  1644. };
  1645. EAction.handleUserInfo = function(message, escape) {
  1646. if (isNull(message)) {
  1647. return;
  1648. }
  1649. if (isNull(escape)) {
  1650. escape = true;
  1651. }
  1652. var appWin = EAction.getMainWindow();
  1653. if (isNull(appWin)) {
  1654. return;
  1655. }
  1656. appWin.handleUserInfo(message, escape);
  1657. };
  1658. EAction.handleUserCommand = function(message, escape) {
  1659. if (isNull(message)) {
  1660. return;
  1661. }
  1662. if (isNull(escape)) {
  1663. escape = true;
  1664. }
  1665. var appWin = EAction.getMainWindow();
  1666. if (isNull(appWin)) {
  1667. return;
  1668. }
  1669. appWin.handleUserCommand(message, escape);
  1670. };
  1671. EAction.setProgress = function(p) {
  1672. var appWin = EAction.getMainWindow();
  1673. if (isNull(appWin)) {
  1674. return;
  1675. }
  1676. appWin.setProgress(p);
  1677. };
  1678. EAction.setProgressText = function(t) {
  1679. var appWin = EAction.getMainWindow();
  1680. if (isNull(appWin)) {
  1681. return;
  1682. }
  1683. EAction.handleUserMessage(t);
  1684. appWin.setProgressText(t);
  1685. };
  1686. EAction.setProgressEnd = function() {
  1687. var appWin = EAction.getMainWindow();
  1688. if (isNull(appWin)) {
  1689. return;
  1690. }
  1691. appWin.setProgressEnd();
  1692. };
  1693. /**
  1694. * Checks if the given entity is editable (not on a locked layer) and prints a
  1695. * warning if quiet is false and this is not the case.
  1696. */
  1697. EAction.assertEditable = function(entity, quiet) {
  1698. if (!entity.isEditable()) {
  1699. if (!quiet) {
  1700. if (!entity.isInWorkingSet()) {
  1701. EAction.handleUserWarning(qsTr("Entity is not in working set."));
  1702. }
  1703. else {
  1704. EAction.handleUserWarning(qsTr("Entity is on a locked layer."));
  1705. }
  1706. }
  1707. return false;
  1708. }
  1709. return true;
  1710. };
  1711. /**
  1712. * Allows all actions to handle property change events. This is necessary to
  1713. * ensure that properties can be changed even if a tool is active (e.g. while
  1714. * drawing lines).
  1715. */
  1716. EAction.prototype.propertyChangeEvent = function(event) {
  1717. var di = this.getDocumentInterface();
  1718. if (isNull(di)) {
  1719. return;
  1720. }
  1721. var operation = new RChangePropertyOperation(event);
  1722. di.applyOperation(operation);
  1723. di.clearPreview();
  1724. di.repaintViews();
  1725. };
  1726. EAction.prototype.setLeftMouseTip = function(tip) {
  1727. var appWin = EAction.getMainWindow();
  1728. if (!isNull(appWin) && isFunction(appWin.setLeftMouseTip)) {
  1729. appWin.setLeftMouseTip(tip);
  1730. }
  1731. };
  1732. EAction.prototype.setRightMouseTip = function(tip) {
  1733. var appWin = EAction.getMainWindow();
  1734. if (!isNull(appWin) && isFunction(appWin.setRightMouseTip)) {
  1735. appWin.setRightMouseTip(tip);
  1736. }
  1737. };
  1738. EAction.prototype.setCommandPrompt = function(prompt) {
  1739. if (isNull(prompt)) {
  1740. prompt = "";
  1741. }
  1742. var appWin = EAction.getMainWindow();
  1743. if (!isNull(appWin) && isFunction(appWin.setCommandPrompt)) {
  1744. appWin.setCommandPrompt(prompt);
  1745. }
  1746. };
  1747. EAction.prototype.getToolTitle = function() {
  1748. var guiAction = this.getGuiAction();
  1749. if (isNull(guiAction)) {
  1750. return "";
  1751. }
  1752. return guiAction.text.replace("&", "");
  1753. };
  1754. EAction.disableCoordinateWidget = function() {
  1755. EAction.enableCoordinateWidget(false);
  1756. };
  1757. EAction.enableCoordinateWidget = function(enable) {
  1758. if (isNull(enable)) {
  1759. enable=true;
  1760. }
  1761. var appWin = EAction.getMainWindow();
  1762. if (isNull(appWin)) {
  1763. return;
  1764. }
  1765. var statusBar = appWin.findChild("StatusBar");
  1766. if (isNull(statusBar)) {
  1767. return;
  1768. }
  1769. var cd = statusBar.findChild("CoordinateDisplay");
  1770. if (!isNull(cd)) {
  1771. cd.enabled = enable;
  1772. }
  1773. };
  1774. /**
  1775. * \return ID of entity closest to the mouse cursor. No handling of ambiguous results.
  1776. * \param event RRInputEvent
  1777. * \param range Cursor range in pixels
  1778. */
  1779. EAction.getEntityIdUnderCursor = function(di, event, range, selectable) {
  1780. if (isNull(di)) {
  1781. return [];
  1782. }
  1783. if (isNull(selectable)) {
  1784. selectable = false;
  1785. }
  1786. var view = event.getGraphicsView();
  1787. if (isNull(range)) {
  1788. range = RSettings.getPickRange();
  1789. }
  1790. range = view.mapDistanceFromView(range);
  1791. var strictRange = view.mapDistanceFromView(10);
  1792. return di.getClosestEntity(event.getModelPosition(), range, strictRange, !selectable);
  1793. };
  1794. /**
  1795. * \return Array of entity IDs of entities closest to the mouse cursor.
  1796. * \param event RRInputEvent
  1797. * \param range Cursor range in pixels
  1798. */
  1799. EAction.getEntityIdsUnderCursor = function(di, event, range, selectable) {
  1800. if (isNull(di)) {
  1801. return [];
  1802. }
  1803. if (isNull(selectable)) {
  1804. selectable = false;
  1805. }
  1806. var view = event.getGraphicsView();
  1807. if (isNull(range)) {
  1808. range = RSettings.getPickRange();
  1809. }
  1810. range = view.mapDistanceFromView(range);
  1811. var doc = di.getDocument();
  1812. return doc.queryIntersectedEntitiesXY(new RBox(event.getModelPosition(), range), false, !selectable);
  1813. };
  1814. /**
  1815. * \return Entity ID under the mouse cursor. User may choose between multiple candidates if
  1816. * result is ambiguous and Alt key is pressed.
  1817. *
  1818. * \param event RInputEvent
  1819. * \param preview for previewing purposes
  1820. * \param selectable Only return selectable (editable) entities
  1821. */
  1822. EAction.prototype.getEntityId = function(event, preview, selectable) {
  1823. if (isNull(preview)) {
  1824. preview = false;
  1825. }
  1826. if (isNull(selectable)) {
  1827. selectable = false;
  1828. }
  1829. var di = this.getDocumentInterface();
  1830. if (isNull(di)) {
  1831. return RObject.INVALID_ID;
  1832. }
  1833. return EAction.getEntityId(di, this, event, preview, selectable);
  1834. };
  1835. EAction.getEntityId = function(di, action, event, preview, selectable) {
  1836. if (isNull(preview)) {
  1837. preview = false;
  1838. }
  1839. if (isNull(selectable)) {
  1840. selectable = false;
  1841. }
  1842. var altPressed = isAltPressed(event);
  1843. if (!altPressed || preview || RSettings.getBoolValue("GraphicsView/DisableAltPicking", false)===true) {
  1844. if (!isNull(action.idFromContextMenu)) {
  1845. // user already chose an entity from the context menu:
  1846. return action.idFromContextMenu;
  1847. }
  1848. else {
  1849. return EAction.getEntityIdUnderCursor(di, event, undefined, selectable);
  1850. }
  1851. }
  1852. // fixed range, we never want to show a lot of entities in the context menu:
  1853. var r = 10 * (RSettings.getHighResolutionGraphicsView() ? RSettings.getDevicePixelRatio() : 1);
  1854. var entityIds = EAction.getEntityIdsUnderCursor(di, event, r, selectable);
  1855. entityIds = di.getStorage().orderBackToFront(entityIds);
  1856. if (entityIds.length===0) {
  1857. // no entity under cursor:
  1858. return RObject.INVALID_ID;
  1859. }
  1860. if (entityIds.length===1) {
  1861. // one single entity under cursor:
  1862. return entityIds[0];
  1863. }
  1864. // multiple entities under cursor, offer context menu:
  1865. var ret = RObject.INVALID_ID;
  1866. var doc = di.getDocument();
  1867. var menu = new QMenu(EAction.getGraphicsView());
  1868. menu.objectName = "EntityContextMenu";
  1869. // reacts to hovering and clicking of context menu items:
  1870. function Reactor(id) {
  1871. this.id = id;
  1872. }
  1873. Reactor.prototype.trigger = function() {
  1874. ret = this.id;
  1875. };
  1876. Reactor.prototype.hover = function() {
  1877. di.clearPreview();
  1878. di.highlightEntity(this.id);
  1879. action.idFromContextMenu = this.id;
  1880. action.entityPickEventPreview(event);
  1881. action.idFromContextMenu = undefined;
  1882. di.repaintViews();
  1883. };
  1884. // invalid entity id is used to to cancel:
  1885. entityIds.push(RObject.INVALID_ID);
  1886. var a, reactor;
  1887. for (var i=0; i<entityIds.length && i<20; i++) {
  1888. var id = entityIds[i];
  1889. var str;
  1890. var icon = undefined;
  1891. if (id!==RObject.INVALID_ID) {
  1892. var e = doc.queryEntityDirect(id);
  1893. str = entityTypeToString(e.getType(), false);
  1894. //str += " / " + e.getProperty(REntity.PropertyDisplayedColor)[0].getName();
  1895. str += " / " + e.getLayerName();
  1896. if (isFunction(e.getLength)) {
  1897. var l = e.getLength();
  1898. if (isNumber(l)) {
  1899. str += " / " + qsTr("Length:") + " " + numberToString(e.getLength(), 3);
  1900. }
  1901. }
  1902. var col = e.getProperty(REntity.PropertyDisplayedColor, true)[0];
  1903. if (!isNull(col)) {
  1904. icon = RColor.getIcon(col, new QSize(16,16));
  1905. }
  1906. }
  1907. else {
  1908. str = qsTr("Cancel");
  1909. menu.addSeparator();
  1910. }
  1911. // add menu entry in format [Type] / [Layer] / [Color] / [Length]
  1912. a = menu.addAction(str);
  1913. if (!isNull(icon)) {
  1914. a.icon = icon;
  1915. a.iconVisibleInMenu = true;
  1916. }
  1917. reactor = new Reactor(id);
  1918. a.triggered.connect(reactor, reactor.trigger);
  1919. a.hovered.connect(reactor, reactor.hover);
  1920. }
  1921. // show context menu:
  1922. if (!menu.isEmpty()) {
  1923. this.waitingForContextMenu = true;
  1924. menu.exec(new QPoint(QCursor.pos().x(), QCursor.pos().y()+10));
  1925. this.waitingForContextMenu = false;
  1926. di.clearPreview();
  1927. }
  1928. return ret;
  1929. };
  1930. EAction.prototype.isEntitySnappable = function(e) {
  1931. if (!isEntity(e)) {
  1932. return false;
  1933. }
  1934. var layerId = e.getLayerId();
  1935. var data = e.getData();
  1936. var doc = data.getDocument();
  1937. if (isNull(doc)) {
  1938. return false;
  1939. }
  1940. return doc.isLayerSnappable(layerId);
  1941. };
  1942. EAction.prototype.isEntityEditable = function(e) {
  1943. if (!isEntity(e)) {
  1944. return false;
  1945. }
  1946. return e.isEditable();
  1947. };
  1948. /**
  1949. * Some common, shared translated warnings:
  1950. */
  1951. EAction.warnNotBlockReference = function() {
  1952. EAction.handleUserWarning(qsTr("Entity is not a block reference."));
  1953. };
  1954. EAction.warnNotLineArc = function() {
  1955. EAction.handleUserWarning(qsTr("Entity is not a line or arc."))
  1956. };
  1957. EAction.warnNotLineArcPolyline = function() {
  1958. EAction.handleUserWarning(qsTr("Entity is not a line, arc or polyline."))
  1959. };
  1960. EAction.warnNotLine = function() {
  1961. EAction.handleUserWarning(qsTr("Entity is not a line."));
  1962. };
  1963. EAction.warnNotArc = function() {
  1964. EAction.handleUserWarning(qsTr("Entity is not an arc."));
  1965. };
  1966. EAction.warnNotArcCircle = function() {
  1967. EAction.handleUserWarning(qsTr("Entity is not an arc or circle."));
  1968. };
  1969. EAction.warnNotLineArcCircle = function() {
  1970. EAction.handleUserWarning(qsTr("Entity is not a line, arc or circle."));
  1971. };
  1972. EAction.warnNotLineArcSplineEllipseArcPolyline = function() {
  1973. EAction.handleUserWarning(qsTr("Entity is not a line, arc, spline, ellipse arc or polyline."));
  1974. };
  1975. EAction.warnNotArcCircleEllipse = function() {
  1976. EAction.handleUserWarning(qsTr("Entity is not an arc, circle or ellipse."));
  1977. };
  1978. EAction.warnNotLineArcCircleEllipse = function() {
  1979. EAction.handleUserWarning(qsTr("Entity is not a line, arc, circle or ellipse."));
  1980. };
  1981. EAction.warnNotLineArcCircleEllipsePolyline = function() {
  1982. EAction.handleUserWarning(qsTr("Entity is not a line, arc, circle, ellipse or polyline."));
  1983. };
  1984. EAction.warnNotLineArcCircleEllipseSpline = function() {
  1985. EAction.handleUserWarning(qsTr("Entity is not a line, arc, circle, ellipse or spline."));
  1986. };
  1987. EAction.warnNotLineArcCircleSplinePolyline = function() {
  1988. EAction.handleUserWarning(qsTr("Entity is not a line, arc, circle, spline or polyline."));
  1989. };
  1990. EAction.warnNotLineArcCircleEllipseSplinePolyline = function() {
  1991. EAction.handleUserWarning(qsTr("Entity is not a line, arc, circle, ellipse, spline or polyline."));
  1992. };
  1993. EAction.warnNotPolyline = function() {
  1994. EAction.handleUserWarning(qsTr("Entity is not a polyline."));
  1995. };
  1996. EAction.warnNotSplineWithFitPoints = function() {
  1997. EAction.handleUserWarning(qsTr("Entity is not a spline with fit points."));
  1998. };