1 /**
  2  * Copyright (C) 2012-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 
 25 /*global ops, runtime, gui, odf, Node, core*/
 26 
 27 /**
 28  * @constructor
 29  * @implements ops.Operation
 30  */
 31 ops.OpApplyDirectStyling = function OpApplyDirectStyling() {
 32     "use strict";
 33 
 34     var memberid, timestamp,
 35         /**@type {number}*/
 36         position,
 37         /**@type {number}*/
 38         length,
 39         setProperties,
 40         odfUtils = new odf.OdfUtils(),
 41         domUtils = new core.DomUtils();
 42 
 43     /**
 44      * @param {!ops.OpApplyDirectStyling.InitSpec} data
 45      */
 46     this.init = function (data) {
 47         memberid = data.memberid;
 48         timestamp = data.timestamp;
 49         position = parseInt(data.position, 10);
 50         length = parseInt(data.length, 10);
 51         setProperties = data.setProperties;
 52     };
 53 
 54     this.isEdit = true;
 55     this.group = undefined;
 56 
 57     /**
 58      * Apply the specified style properties to all elements within the given range.
 59      * Currently, only text styles are applied.
 60      * @param {!ops.OdtDocument} odtDocument
 61      * @param {!Range} range Range to apply text style to
 62      * @param {!Object} info Style information. Only data within "style:text-properties" will be considered and applied
 63      */
 64     function applyStyle(odtDocument, range, info) {
 65         var odfCanvas = odtDocument.getOdfCanvas(),
 66             odfContainer = odfCanvas.odfContainer(),
 67             nextTextNodes = domUtils.splitBoundaries(range),
 68             textNodes = odfUtils.getTextNodes(range, false),
 69             textStyles;
 70 
 71         textStyles = new odf.TextStyleApplicator(
 72             new odf.ObjectNameGenerator(/**@type{!odf.OdfContainer}*/(odfContainer), memberid), // TODO: use the instance in SessionController
 73             odtDocument.getFormatting(),
 74             odfContainer.rootElement.automaticStyles
 75         );
 76         textStyles.applyStyle(textNodes, range, info);
 77         nextTextNodes.forEach(domUtils.normalizeTextNodes);
 78     }
 79 
 80     /**
 81      * @param {!ops.Document} document
 82      */
 83     this.execute = function (document) {
 84         var odtDocument = /**@type{ops.OdtDocument}*/(document),
 85             range = odtDocument.convertCursorToDomRange(position, length),
 86             impactedParagraphs = odfUtils.getParagraphElements(range);
 87 
 88         applyStyle(odtDocument, range, setProperties);
 89 
 90         range.detach();
 91         odtDocument.getOdfCanvas().refreshCSS();
 92         odtDocument.fixCursorPositions(); // The container splits may leave the cursor in an invalid spot
 93 
 94         impactedParagraphs.forEach(function (n) {
 95             odtDocument.emit(ops.OdtDocument.signalParagraphChanged, {
 96                 paragraphElement: n,
 97                 memberId: memberid,
 98                 timeStamp: timestamp
 99             });
100         });
101 
102         odtDocument.getOdfCanvas().rerenderAnnotations();
103         return true;
104     };
105 
106     /**
107      * @return {!ops.OpApplyDirectStyling.Spec}
108      */
109     this.spec = function () {
110         return {
111             optype: "ApplyDirectStyling",
112             memberid: memberid,
113             timestamp: timestamp,
114             position: position,
115             length: length,
116             setProperties: setProperties
117         };
118     };
119 };
120 /**@typedef{{
121     optype:string,
122     memberid:string,
123     timestamp:number,
124     position:number,
125     length:number,
126     setProperties:!Object
127 }}*/
128 ops.OpApplyDirectStyling.Spec;
129 /**@typedef{{
130     memberid:string,
131     timestamp:(number|undefined),
132     position:number,
133     length:number,
134     setProperties:!Object
135 }}*/
136 ops.OpApplyDirectStyling.InitSpec;
137