Tools.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /**
  2. * Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
  3. *
  4. * @licstart
  5. * This file is part of WebODF.
  6. *
  7. * WebODF is free software: you can redistribute it and/or modify it
  8. * under the terms of the GNU Affero General Public License (GNU AGPL)
  9. * as published by the Free Software Foundation, either version 3 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * WebODF is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with WebODF. If not, see <http://www.gnu.org/licenses/>.
  19. * @licend
  20. *
  21. * @source: http://www.webodf.org/
  22. * @source: https://github.com/kogmbh/WebODF/
  23. */
  24. /*global window, define, require, document, dijit, dojo, runtime, ops*/
  25. define("webodf/editor/Tools", [
  26. "dojo/ready",
  27. "dijit/MenuItem",
  28. "dijit/DropDownMenu",
  29. "dijit/form/Button",
  30. "dijit/form/DropDownButton",
  31. "dijit/Toolbar",
  32. "webodf/editor/widgets/paragraphAlignment",
  33. "webodf/editor/widgets/simpleStyles",
  34. "webodf/editor/widgets/undoRedoMenu",
  35. "webodf/editor/widgets/toolbarWidgets/currentStyle",
  36. "webodf/editor/widgets/annotation",
  37. "webodf/editor/widgets/editHyperlinks",
  38. "webodf/editor/widgets/imageInserter",
  39. "webodf/editor/widgets/paragraphStylesDialog",
  40. "webodf/editor/widgets/zoomSlider",
  41. "webodf/editor/widgets/aboutDialog",
  42. "webodf/editor/EditorSession"],
  43. function (ready, MenuItem, DropDownMenu, Button, DropDownButton, Toolbar, ParagraphAlignment, SimpleStyles, UndoRedoMenu, CurrentStyle, AnnotationControl, EditHyperlinks, ImageInserter, ParagraphStylesDialog, ZoomSlider, AboutDialog, EditorSession) {
  44. "use strict";
  45. return function Tools(toolbarElementId, args) {
  46. var tr = runtime.tr,
  47. onToolDone = args.onToolDone,
  48. loadOdtFile = args.loadOdtFile,
  49. saveOdtFile = args.saveOdtFile,
  50. saveAsOdtFile = args.saveAsOdtFile,
  51. downloadOdtFile = args.downloadOdtFile,
  52. close = args.close,
  53. toolbar,
  54. loadButton, saveButton, closeButton, aboutButton,
  55. saveAsButton, downloadButton,
  56. formatDropDownMenu, formatMenuButton,
  57. paragraphStylesMenuItem, paragraphStylesDialog,
  58. editorSession,
  59. aboutDialog,
  60. sessionSubscribers = [];
  61. function placeAndStartUpWidget(widget) {
  62. widget.placeAt(toolbar);
  63. widget.startup();
  64. }
  65. /**
  66. * Creates a tool and installs it, if the enabled flag is set to true.
  67. * Only supports tool classes whose constructor has a single argument which
  68. * is a callback to pass the created widget object to.
  69. * @param {!function(new:Object, function(!Object):undefined)} Tool constructor method of the tool
  70. * @param {!boolean} enabled
  71. * @param {!Object|undefined=} config
  72. * @return {?Object}
  73. */
  74. function createTool(Tool, enabled, config) {
  75. var tool = null;
  76. if (enabled) {
  77. if (config) {
  78. tool = new Tool(config, placeAndStartUpWidget);
  79. } else {
  80. tool = new Tool(placeAndStartUpWidget);
  81. }
  82. sessionSubscribers.push(tool);
  83. tool.onToolDone = onToolDone;
  84. tool.setEditorSession(editorSession);
  85. }
  86. return tool;
  87. }
  88. function handleCursorMoved(cursor) {
  89. var disabled = cursor.getSelectionType() === ops.OdtCursor.RegionSelection;
  90. if (formatMenuButton) {
  91. formatMenuButton.setAttribute('disabled', disabled);
  92. }
  93. }
  94. function setEditorSession(session) {
  95. if (editorSession) {
  96. editorSession.unsubscribe(EditorSession.signalCursorMoved, handleCursorMoved);
  97. }
  98. editorSession = session;
  99. if (editorSession) {
  100. editorSession.subscribe(EditorSession.signalCursorMoved, handleCursorMoved);
  101. }
  102. sessionSubscribers.forEach(function (subscriber) {
  103. subscriber.setEditorSession(editorSession);
  104. });
  105. [saveButton, saveAsButton, downloadButton, closeButton, formatMenuButton].forEach(function (button) {
  106. if (button) {
  107. button.setAttribute('disabled', !editorSession);
  108. }
  109. });
  110. }
  111. this.setEditorSession = setEditorSession;
  112. /**
  113. * @param {!function(!Error=)} callback, passing an error object in case of error
  114. * @return {undefined}
  115. */
  116. this.destroy = function (callback) {
  117. // TODO:
  118. // 1. We don't want to use `document`
  119. // 2. We would like to avoid deleting all widgets
  120. // under document.body because this might interfere with
  121. // other apps that use the editor not-in-an-iframe,
  122. // but dojo always puts its dialogs below the body,
  123. // so this works for now. Perhaps will be obsoleted
  124. // once we move to a better widget toolkit
  125. var widgets = dijit.findWidgets(document.body);
  126. dojo.forEach(widgets, function(w) {
  127. w.destroyRecursive(false);
  128. });
  129. callback();
  130. };
  131. // init
  132. ready(function () {
  133. toolbar = new Toolbar({}, toolbarElementId);
  134. // About
  135. if (args.aboutEnabled) {
  136. aboutButton = new Button({
  137. label: tr('About WebODF Text Editor'),
  138. showLabel: false,
  139. iconClass: 'webodfeditor-dijitWebODFIcon'
  140. });
  141. aboutDialog = new AboutDialog(function (dialog) {
  142. aboutButton.onClick = function () {
  143. dialog.startup();
  144. dialog.show();
  145. };
  146. });
  147. aboutDialog.onToolDone = onToolDone;
  148. aboutButton.placeAt(toolbar);
  149. }
  150. // Load
  151. if (loadOdtFile) {
  152. loadButton = new Button({
  153. label: tr('Open'),
  154. showLabel: false,
  155. iconClass: 'dijitIcon dijitIconFolderOpen',
  156. onClick: function () {
  157. loadOdtFile();
  158. }
  159. });
  160. loadButton.placeAt(toolbar);
  161. }
  162. // Save
  163. if (saveOdtFile) {
  164. saveButton = new Button({
  165. label: tr('Save'),
  166. showLabel: false,
  167. disabled: true,
  168. iconClass: 'dijitEditorIcon dijitEditorIconSave',
  169. onClick: function () {
  170. saveOdtFile();
  171. onToolDone();
  172. }
  173. });
  174. saveButton.placeAt(toolbar);
  175. }
  176. // SaveAs
  177. if (saveAsOdtFile) {
  178. saveAsButton = new Button({
  179. label: tr('Save as...'),
  180. showLabel: false,
  181. disabled: true,
  182. iconClass: 'webodfeditor-dijitSaveAsIcon',
  183. onClick: function () {
  184. saveAsOdtFile();
  185. onToolDone();
  186. }
  187. });
  188. saveAsButton.placeAt(toolbar);
  189. }
  190. // Download
  191. if (downloadOdtFile) {
  192. downloadButton = new Button({
  193. label: tr('Download'),
  194. showLabel: true,
  195. disabled: true,
  196. style: {
  197. float: 'right'
  198. },
  199. onClick: function () {
  200. downloadOdtFile();
  201. onToolDone();
  202. }
  203. });
  204. downloadButton.placeAt(toolbar);
  205. }
  206. // Format menu
  207. if (args.paragraphStyleEditingEnabled) {
  208. formatDropDownMenu = new DropDownMenu({});
  209. paragraphStylesMenuItem = new MenuItem({
  210. label: tr("Paragraph...")
  211. });
  212. formatDropDownMenu.addChild(paragraphStylesMenuItem);
  213. paragraphStylesDialog = new ParagraphStylesDialog(function (dialog) {
  214. paragraphStylesMenuItem.onClick = function () {
  215. if (editorSession) {
  216. dialog.startup();
  217. dialog.show();
  218. }
  219. };
  220. });
  221. sessionSubscribers.push(paragraphStylesDialog);
  222. paragraphStylesDialog.onToolDone = onToolDone;
  223. formatMenuButton = new DropDownButton({
  224. dropDown: formatDropDownMenu,
  225. disabled: true,
  226. label: tr('Format'),
  227. iconClass: "dijitIconEditTask"
  228. });
  229. formatMenuButton.placeAt(toolbar);
  230. }
  231. // Undo/Redo
  232. createTool(UndoRedoMenu, args.undoRedoEnabled);
  233. // Add annotation
  234. createTool(AnnotationControl, args.annotationsEnabled);
  235. // Simple Style Selector [B, I, U, S]
  236. createTool(SimpleStyles, args.directTextStylingEnabled);
  237. // Paragraph direct alignment buttons
  238. createTool(ParagraphAlignment, args.directParagraphStylingEnabled);
  239. // Paragraph Style Selector
  240. createTool(CurrentStyle, args.paragraphStyleSelectingEnabled);
  241. // Zoom Level Selector
  242. createTool(ZoomSlider, args.zoomingEnabled);
  243. // hyper links
  244. createTool(EditHyperlinks, args.hyperlinkEditingEnabled);
  245. // image insertion
  246. createTool(ImageInserter, args.imageInsertingEnabled);
  247. // close button
  248. if (close) {
  249. closeButton = new Button({
  250. label: tr('Close'),
  251. showLabel: false,
  252. disabled: true,
  253. iconClass: 'dijitEditorIcon dijitEditorIconCancel',
  254. style: {
  255. float: 'right'
  256. },
  257. onClick: function () {
  258. close();
  259. }
  260. });
  261. closeButton.placeAt(toolbar);
  262. }
  263. // This is an internal hook for debugging/testing.
  264. // Yes, you discovered something interesting. But:
  265. // Do NOT rely on it, it will not be supported and can and will change in any version.
  266. // It is not officially documented for a reason. A real plugin system is only on the wishlist
  267. // so far, please file your suggestions/needs at the official WebODF issue system.
  268. // You have been warned.
  269. if (window.wodo_plugins) {
  270. window.wodo_plugins.forEach(function (plugin) {
  271. runtime.log("Creating plugin: "+plugin.id);
  272. require([plugin.id], function (Plugin) {
  273. runtime.log("Creating as tool now: "+plugin.id);
  274. createTool(Plugin, true, plugin.config);
  275. });
  276. });
  277. }
  278. setEditorSession(editorSession);
  279. });
  280. };
  281. });