diff --git a/src/app/boot.js b/src/app/boot.js index 89f52222..6b1a71a1 100644 --- a/src/app/boot.js +++ b/src/app/boot.js @@ -442,15 +442,19 @@ thin.init_ = function() { dialog.addEventListener(goog.ui.Dialog.EventType.SELECT, function(e) { if (e.isOk()) { + var margin = []; + goog.array.insertAt(margin, pageMarginTop.getValue() || 0, 0); + goog.array.insertAt(margin, pageMarginRight.getValue() || 0, 1); + goog.array.insertAt(margin, pageMarginBottom.getValue() || 0, 2); + goog.array.insertAt(margin, pageMarginLeft.getValue() || 0, 3); + var paperTypeValue = paperTypeSelectbox.getValue(); - var formatConfig = { + var report = { 'paper-type': paperTypeValue, 'orientation': pageDirectionSelectbox.getValue(), - 'margin-top': pageMarginTop.getValue() || 0, - 'margin-bottom': pageMarginBottom.getValue() || 0, - 'margin-left': pageMarginLeft.getValue() || 0, - 'margin-right': pageMarginRight.getValue() || 0 + 'margin': margin }; + if (thin.layout.FormatPage.isUserType(paperTypeValue)) { var userWidth = pageWidthInput.getValue(); var userHeight = pageHeightInput.getValue(); @@ -462,14 +466,13 @@ thin.init_ = function() { }); return false; } - formatConfig['width'] = Number(userWidth); - formatConfig['height'] = Number(userHeight); + report['width'] = Number(userWidth); + report['height'] = Number(userHeight); } var format = new thin.layout.Format(); - format.page = format.setPage({ - 'title': pageTitleInput.getValue(), - 'page': formatConfig - }); + format.page = format.setPage(report); + format.page.setTitle(pageTitleInput.getValue()); + var workspace = new thin.core.Workspace(format); tabpane.addPage(new thin.ui.TabPane.TabPage(workspace.getTabName(), workspace)); workspace.setup(); @@ -490,10 +493,11 @@ thin.init_ = function() { pageHeightInput.setEnabled(false); pageHeightInput.setValue(''); - pageMarginTop.setValue(thin.layout.FormatPage.DEFAULT_SETTINGS['margin-top']); - pageMarginBottom.setValue(thin.layout.FormatPage.DEFAULT_SETTINGS['margin-bottom']); - pageMarginLeft.setValue(thin.layout.FormatPage.DEFAULT_SETTINGS['margin-left']); - pageMarginRight.setValue(thin.layout.FormatPage.DEFAULT_SETTINGS['margin-right']); + var defaultMargin = thin.layout.FormatPage.DEFAULT_SETTINGS['margin']; + pageMarginTop.setValue(defaultMargin[0]); + pageMarginRight.setValue(defaultMargin[1]); + pageMarginBottom.setValue(defaultMargin[2]); + pageMarginLeft.setValue(defaultMargin[3]); dialog.setVisible(true); }); diff --git a/src/app/core/abstracttextgroup.js b/src/app/core/abstracttextgroup.js index bdcb9db9..e6510bdf 100644 --- a/src/app/core/abstracttextgroup.js +++ b/src/app/core/abstracttextgroup.js @@ -44,55 +44,19 @@ thin.core.AbstractTextGroup = function(element, layout) { goog.inherits(thin.core.AbstractTextGroup, thin.core.AbstractBoxGroup); -/** - * The latest fill applied to this element. - * @type {goog.graphics.Fill?} - * @protected - */ -thin.core.AbstractTextGroup.prototype.fill = null; - - -/** - * The latest stroke applied to this element. - * @type {goog.graphics.Stroke?} - * @private - */ -thin.core.AbstractTextGroup.prototype.stroke_ = null; - - /** * Sets the fill for this element. - * @param {goog.graphics.Fill?} fill The fill object. - */ -thin.core.AbstractTextGroup.prototype.setFill = function(fill) { - this.fill = fill; - this.getLayout().setElementFill(this, fill); -}; - - -/** - * @return {goog.graphics.Fill?} fill The fill object. */ -thin.core.AbstractTextGroup.prototype.getFill = function() { - return this.fill; +thin.core.AbstractTextGroup.prototype.setFillInternal = function() { + this.getLayout().setElementFill(this, this.fill); }; /** * Sets the stroke for this element. - * @param {goog.graphics.Stroke?} stroke The stroke object. - */ -thin.core.AbstractTextGroup.prototype.setStroke = function(stroke) { - this.stroke_ = stroke; - this.getLayout().setElementStroke(this, stroke); -}; - - -/** - * @return {goog.graphics.Stroke?} stroke The stroke object. */ -thin.core.AbstractTextGroup.prototype.getStroke = function() { - return this.stroke_; +thin.core.AbstractTextGroup.prototype.setStrokeInternal = function() { + this.getLayout().setElementStroke(this, this.stroke_); }; @@ -178,12 +142,29 @@ thin.core.AbstractTextGroup.prototype.setTextLineHeightRatio = function(ratio) { }; +/** + * @deprecated See: https://github.com/thinreports/thinreports-editor/issues/38 + * @param {string|number} spacing + * @return {string} + */ +thin.core.AbstractTextGroup.prototype.convertKerningToDefaultInSince06 = function(spacing) { + if (isNaN(Number(spacing))) { + spacing = thin.core.TextStyle.DEFAULT_KERNING; + } + + return spacing; +}; + + /** * @param {string} spacing */ thin.core.AbstractTextGroup.prototype.setKerning = function(spacing) { var layout = this.getLayout(); var element = this.getElement(); + + spacing = this.convertKerningToDefaultInSince06(spacing); + if (thin.isExactlyEqual(spacing, thin.core.TextStyle.DEFAULT_KERNING)) { layout.setElementAttributes(element, { 'kerning': thin.core.TextStyle.DEFAULT_ELEMENT_KERNING, @@ -300,6 +281,15 @@ thin.core.AbstractTextGroup.prototype.getTextLineHeightRatio = function() { }; +/** + * @return {string} + */ +thin.core.AbstractTextGroup.prototype.getTextLineHeight = function() { + return /** @type {string} */ (thin.getValIfNotDef(this.getLayout().getElementAttribute( + this.getElement(), 'x-line-height'), thin.core.TextStyle.DEFAULT_LINEHEIGHT)); +}; + + /** * @return {string} */ @@ -399,3 +389,190 @@ thin.core.AbstractTextGroup.prototype.disposeInternal = function() { delete this.fontStyle_; delete this.textStyle_; }; + + +/** + * @return {string} + */ +thin.core.AbstractTextGroup.prototype.getTextAnchorAsJSON = function() { + var textAlignAsJSON = ''; + var horizonAlignType = thin.core.TextStyle.HorizonAlignType; + + // SVG: start, middle, end + // TLF: left, center, right + switch(this.getTextAnchor()) { + case horizonAlignType.MIDDLE: + textAlignAsJSON = 'center'; + break; + case horizonAlignType.END: + textAlignAsJSON = 'right'; + break; + default: + textAlignAsJSON = 'left'; + break; + } + + return textAlignAsJSON; +}; + + +/** + * @param {string} textAlignFromJSON + */ +thin.core.AbstractTextGroup.prototype.setTextAnchorFromJSON = function(textAlignFromJSON) { + var anchor = ''; + var horizonAlignType = thin.core.TextStyle.HorizonAlignType; + + // SVG: start, middle, end + // TLF: left, center, right + switch(textAlignFromJSON) { + case 'center': + anchor = horizonAlignType.MIDDLE; + break; + case 'right': + anchor = horizonAlignType.END; + break; + default: + anchor = horizonAlignType.START; + break; + } + + this.setTextAnchor(anchor); +}; + + +/** + * @return {string} + */ +thin.core.AbstractTextGroup.prototype.getVerticalAlignAsJSON = function() { + var verticalAlignAsJSON = ''; + var verticalAlignType = thin.core.TextStyle.VerticalAlignType; + + // SVG: top, center, bottom + // TLF: top, middle, bottom + switch(this.getVerticalAlign()) { + case verticalAlignType.CENTER: + verticalAlignAsJSON = 'middle'; + break; + case verticalAlignType.BOTTOM: + verticalAlignAsJSON = verticalAlignType.BOTTOM; + break; + default: + verticalAlignAsJSON = verticalAlignType.TOP; + break; + } + + return verticalAlignAsJSON; +}; + + +/** + * @param {string} verticalAlignFromJSON + */ +thin.core.AbstractTextGroup.prototype.setVerticalAlignFromJSON = function(verticalAlignFromJSON) { + var valign = ''; + var verticalAlignType = thin.core.TextStyle.VerticalAlignType; + + // SVG: top, center, bottom + // TLF: top, middle, bottom + switch(verticalAlignFromJSON) { + case 'middle': + valign = verticalAlignType.CENTER; + break; + default: + valign = verticalAlignFromJSON; + break; + } + + this.setVerticalAlign(valign); +}; + + +/** + * @return {Object} + */ +thin.core.AbstractTextGroup.prototype.asJSON = function() { + var object = this.asJSON_(); + + var lineHeight = this.getTextLineHeight(); + var lineHeightRatio = this.getTextLineHeightRatio(); + if (!thin.isExactlyEqual(lineHeightRatio, thin.core.TextStyle.DEFAULT_LINEHEIGHT)) { + lineHeight = Number(lineHeight); + lineHeightRatio = Number(lineHeightRatio); + } + + var letterSpecing = this.getKerning(); + if (!thin.isExactlyEqual(letterSpecing, thin.core.TextStyle.DEFAULT_KERNING)) { + letterSpecing = Number(letterSpecing); + } + + goog.object.extend(object['style'], { + 'font-family': [ this.getFontFamily() ], + 'font-size': this.getFontSize(), + 'color': goog.object.get(object['style'], 'fill-color'), + 'text-align': this.getTextAnchorAsJSON(), + 'vertical-align': this.getVerticalAlignAsJSON(), + 'line-height': lineHeight, + 'line-height-ratio': lineHeightRatio, + 'letter-spacing': letterSpecing + }); + goog.object.extend(object['style'], this.fontStyle_.asJSON()); + + goog.object.remove(object['style'], 'fill-color'); + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.AbstractTextGroup.prototype.update = function(attrs) { + this.update_(attrs); + + goog.object.forEach(attrs, function(value, attr) { + switch (attr) { + case 'font-family': + this.setFontFamily(value[0]); + break; + case 'font-size': + this.setFontSize(value); + break; + case 'color': + this.setFillColor(value); + break; + case 'text-align': + this.setTextAnchorFromJSON(value); + break; + case 'vertical-align': + this.setVerticalAlignFromJSON(value); + break; + case 'line-height-ratio': + this.setTextLineHeightRatio(value); + break; + case 'letter-spacing': + this.setKerning(value); + break; + case 'font-style': + goog.array.forEach(value, function(font_style) { + switch(font_style) { + case 'bold': + this.setFontBold(true); + break; + case 'italic': + this.setFontItalic(true); + break; + case 'linethrough': + this.setFontLinethrough(true); + break; + case 'underline': + this.setFontUnderline(true); + break; + } + }, this); + default: + // Do Nothing + break; + } + }, this); +}; diff --git a/src/app/core/action.js b/src/app/core/action.js index 14e3a852..8cfc352b 100644 --- a/src/app/core/action.js +++ b/src/app/core/action.js @@ -1338,7 +1338,6 @@ thin.core.Action.prototype.actionDeleteShapes = function(historyMode) { var targetIndexByShapes = layout.getTargetIndexOfShapes(targetShapes, parentGroup); var captureShapeIdArray = []; var captureRefIdArray = []; - var captureReferenceShapesArray = []; var captureReferringShapesArray = []; var defaultRefId = thin.core.TblockShape.DEFAULT_REFID; @@ -1347,11 +1346,9 @@ thin.core.Action.prototype.actionDeleteShapes = function(historyMode) { if (shape.instanceOfTblockShape()) { goog.array.insertAt(captureRefIdArray, shape.getRefId(), count); - goog.array.insertAt(captureReferenceShapesArray, shape.getReferenceShape(), count); goog.array.insertAt(captureReferringShapesArray, shape.getReferringShapes(), count); } else { goog.array.insertAt(captureRefIdArray, defaultRefId, count); - goog.array.insertAt(captureReferenceShapesArray, null, count); goog.array.insertAt(captureReferringShapesArray, null, count); } @@ -1399,7 +1396,7 @@ thin.core.Action.prototype.actionDeleteShapes = function(historyMode) { if (shape.instanceOfTblockShape()) { var captureRefId = captureRefIdArray[count]; if (!thin.isExactlyEqual(captureRefId, defaultRefId)) { - shape.setRefId(captureRefId, captureReferenceShapesArray[count]); + shape.setRefId(captureRefId); } } @@ -1413,10 +1410,9 @@ thin.core.Action.prototype.actionDeleteShapes = function(historyMode) { goog.array.forEach(captureReferringShapesArray, function(referringShapes, count) { if (goog.isArray(referringShapes) && !goog.array.isEmpty(referringShapes)) { var refId = captureShapeIdArray[count]; - var referencesShape = shapes[count]; goog.array.forEach(referringShapes, function(shape) { if (!shape.isReferring()) { - shape.setRefId(refId, referencesShape); + shape.setRefId(refId); } }); } @@ -1477,7 +1473,7 @@ thin.core.Action.prototype.actionDeleteShapes = function(historyMode) { if (shape.instanceOfTblockShape()) { var captureRefId = captureRefIdArray[count]; if (!thin.isExactlyEqual(captureRefId, defaultRefId)) { - shape.setRefId(captureRefId, captureReferenceShapesArray[count]); + shape.setRefId(captureRefId); } } @@ -1491,10 +1487,9 @@ thin.core.Action.prototype.actionDeleteShapes = function(historyMode) { goog.array.forEach(captureReferringShapesArray, function(referringShapes, count) { if (goog.isArray(referringShapes) && !goog.array.isEmpty(referringShapes)) { var refId = captureShapeIdArray[count]; - var referencesShape = shapes[count]; goog.array.forEach(referringShapes, function(shape) { if (!shape.isReferring()) { - shape.setRefId(refId, referencesShape); + shape.setRefId(refId); } }); } diff --git a/src/app/core/component.js b/src/app/core/component.js index 77d376b5..9b99b60c 100644 --- a/src/app/core/component.js +++ b/src/app/core/component.js @@ -44,6 +44,67 @@ goog.mixin(thin.core.Component.prototype, thin.core.ModuleElement.prototype); thin.core.Component.prototype.setup = goog.nullFunction; +/** + * The latest fill applied to this element. + * @type {goog.graphics.Fill?} + * @protected + */ +thin.core.Component.prototype.fill = null; + + +/** + * The latest stroke applied to this element. + * @type {goog.graphics.Stroke?} + * @private + */ +thin.core.Component.prototype.stroke_ = null; + + +/** + * Sets the fill for this element. + * @param {goog.graphics.Fill?} fill The fill object. + */ +thin.core.Component.prototype.setFill = function(fill) { + this.fill = fill; + this.setFillInternal(); +}; + + +/** + * @return {goog.graphics.Fill?} fill The fill object. + */ +thin.core.Component.prototype.getFill = function() { + return this.fill; +}; + + +/** + * Sets the stroke for this element. + * @param {goog.graphics.Stroke?} stroke The stroke object. + */ +thin.core.Component.prototype.setStroke = function(stroke) { + this.stroke_ = stroke; + this.setStrokeInternal(); +}; + + +/** + * @return {goog.graphics.Stroke?} stroke The stroke object. + */ +thin.core.Component.prototype.getStroke = function() { + return this.stroke_; +}; + + +thin.core.Component.prototype.setFillInternal = goog.abstractMethod; + + +thin.core.Component.prototype.setStrokeInternal = goog.abstractMethod; + + +thin.core.Component.prototype.getStrokeWidth = goog.abstractMethod; + + /** @inheritDoc */ thin.core.Component.prototype.disposeInternal = function() { thin.core.Component.superClass_.disposeInternal.call(this); diff --git a/src/app/core/ellipse.js b/src/app/core/ellipse.js index dcd28e86..ae2f3d12 100644 --- a/src/app/core/ellipse.js +++ b/src/app/core/ellipse.js @@ -35,13 +35,13 @@ thin.core.Ellipse = function(element, layout, stroke, fill) { var cy = Number(layout.getElementAttribute(element, 'cy')); var rx = Number(layout.getElementAttribute(element, 'rx')); var ry = Number(layout.getElementAttribute(element, 'ry')); - + /** * @type {number} * @private */ this.left_ = thin.numberWithPrecision(cx - rx); - + /** * @type {number} * @private @@ -59,7 +59,7 @@ thin.core.Ellipse = function(element, layout, stroke, fill) { * @private */ this.height_ = thin.numberWithPrecision(ry * 2); - + /** * @type {number} * @private @@ -94,8 +94,18 @@ goog.mixin(thin.core.Ellipse.prototype, thin.core.ModuleElement.prototype); thin.core.Ellipse.prototype.setLeft = function(left) { left = thin.numberWithPrecision(left - this.getParentTransLateX()); this.left_ = left; - var cx = thin.numberWithPrecision(left + this.rx_, 2); + + this.setCx(left + this.rx_); +}; + + +/** + * @param {number} cx + */ +thin.core.Ellipse.prototype.setCx = function(cx) { + cx = thin.numberWithPrecision(cx, 2); this.cx_ = cx; + this.getLayout().setElementAttributes(this.getElement(), { 'cx': cx }); @@ -108,8 +118,18 @@ thin.core.Ellipse.prototype.setLeft = function(left) { thin.core.Ellipse.prototype.setTop = function(top) { top = thin.numberWithPrecision(top - this.getParentTransLateY()); this.top_ = top; - var cy = thin.numberWithPrecision(top + this.ry_, 2); + + this.setCy(top + this.ry_); +}; + + +/** + * @param {number} cy + */ +thin.core.Ellipse.prototype.setCy = function(cy) { + cy = thin.numberWithPrecision(cy, 2); this.cy_ = cy; + this.getLayout().setElementAttributes(this.getElement(), { 'cy': cy }); @@ -122,8 +142,18 @@ thin.core.Ellipse.prototype.setTop = function(top) { thin.core.Ellipse.prototype.setWidth = function(width) { width = thin.numberWithPrecision(width); this.width_ = width; - var rx = thin.numberWithPrecision(width / 2, 2); + + this.setRx(width / 2); +}; + + +/** + * @param {number} rx + */ +thin.core.Ellipse.prototype.setRx = function(rx) { + rx = thin.numberWithPrecision(rx, 2) this.rx_ = rx; + this.getLayout().setElementAttributes(this.getElement(), { 'rx': rx }); @@ -136,7 +166,16 @@ thin.core.Ellipse.prototype.setWidth = function(width) { thin.core.Ellipse.prototype.setHeight = function(height) { height = thin.numberWithPrecision(height); this.height_ = height; - var ry = thin.numberWithPrecision(height / 2, 2); + + this.setRy(height / 2); +}; + + +/** + * @param {number} ry + */ +thin.core.Ellipse.prototype.setRy = function(ry) { + ry = thin.numberWithPrecision(ry, 2); this.ry_ = ry; this.getLayout().setElementAttributes(this.getElement(), { 'ry': ry @@ -144,11 +183,45 @@ thin.core.Ellipse.prototype.setHeight = function(height) { }; +thin.core.Ellipse.prototype.resetTop = function() { + if ((goog.isNumber(this.ry_) && this.ry_ != 0) && + (goog.isNumber(this.cy_) && this.cy_ != 0)) { + + this.top_ = thin.numberWithPrecision(this.cy_ - this.ry_); + } +}; + + +thin.core.Ellipse.prototype.resetLeft = function() { + if ((goog.isNumber(this.rx_) && this.rx_ != 0) && + (goog.isNumber(this.cx_) && this.cx_ != 0)) { + + this.left_ = thin.numberWithPrecision(this.cx_ - this.rx_); + } +}; + + +thin.core.Ellipse.prototype.resetWidth = function() { + if (goog.isNumber(this.rx_) && this.rx_ != 0) { + + this.width_ = thin.numberWithPrecision(this.rx_ * 2); + } +}; + + +thin.core.Ellipse.prototype.resetHeight = function() { + if (goog.isNumber(this.ry_) && this.ry_ != 0) { + + this.height_ = thin.numberWithPrecision(this.ry_ * 2); + } +}; + + /** * @return {goog.math.Coordinate} */ thin.core.Ellipse.prototype.getCenterCoordinate = function() { - return new goog.math.Coordinate(this.cx_ + this.getParentTransLateX(), + return new goog.math.Coordinate(this.cx_ + this.getParentTransLateX(), this.cy_ + this.getParentTransLateY()); }; @@ -167,8 +240,11 @@ thin.core.Ellipse.prototype.getRadius = function() { * @param {number} cy Center Y coordinate. */ thin.core.Ellipse.prototype.setCenter = function(cx, cy) { - this.setLeft(cx - this.rx_); - this.setTop(cy - this.ry_); + this.setCx(cx); + this.setCy(cy); + + this.resetLeft(); + this.resetTop(); }; @@ -178,8 +254,9 @@ thin.core.Ellipse.prototype.setCenter = function(cx, cy) { * @param {number} ry Radius length for the y-axis. */ thin.core.Ellipse.prototype.setRadius = function(rx, ry) { - this.setWidth(rx * 2); - this.setHeight(ry * 2); - this.setLeft(this.getLeft()); - this.setTop(this.getTop()); -}; \ No newline at end of file + this.setRx(rx); + this.setRy(ry); + + this.resetWidth(); + this.resetHeight(); +}; diff --git a/src/app/core/ellipseshape.js b/src/app/core/ellipseshape.js index d8adef00..c940014b 100644 --- a/src/app/core/ellipseshape.js +++ b/src/app/core/ellipseshape.js @@ -63,27 +63,6 @@ thin.core.EllipseShape.prototype.getClassId = function() { }; -/** - * @param {Element} element - * @param {thin.core.Layout} layout - * @param {thin.core.ShapeIdManager=} opt_shapeIdManager - * @return {thin.core.EllipseShape} - */ -thin.core.EllipseShape.createFromElement = function(element, layout, opt_shapeIdManager) { - var shape = new thin.core.EllipseShape(element, layout, - new goog.graphics.Stroke( - Number(layout.getElementAttribute(element, 'stroke-width')), - layout.getElementAttribute(element, 'stroke')), - new goog.graphics.SolidFill(layout.getElementAttribute(element, 'fill'))); - shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); - shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); - shape.setDesc(layout.getElementAttribute(element, 'x-desc')); - shape.setStrokeDashFromType(layout.getElementAttribute(element, 'x-stroke-type')); - shape.initIdentifier(); - return shape; -}; - - thin.core.EllipseShape.prototype.setDefaultOutline = function() { this.setTargetOutline(this.getLayout().getHelpers().getEllipseOutline()); }; @@ -114,7 +93,7 @@ thin.core.EllipseShape.prototype.getCloneCreator = function() { var fill = this.getFill(); var display = this.getDisplay(); var isAffiliationListShape = this.isAffiliationListShape(); - + /** * @param {thin.core.Layout} layout * @param {boolean=} opt_isAdaptDeltaForList @@ -148,17 +127,17 @@ thin.core.EllipseShape.prototype.createPropertyComponent_ = function() { var scope = this; var propEventType = thin.ui.PropertyPane.Property.EventType; var proppane = thin.ui.getComponent('proppane'); - + var baseGroup = proppane.addGroup(thin.t('property_group_basis')); - - + + var leftInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_left_position')); var leftInput = leftInputProperty.getValueControl(); leftInput.getNumberValidator().setAllowDecimal(true, 1); - + leftInputProperty.addEventListener(propEventType.CHANGE, this.setLeftForPropertyUpdate, false, this); - + proppane.addProperty(leftInputProperty, baseGroup, 'left'); @@ -168,56 +147,56 @@ thin.core.EllipseShape.prototype.createPropertyComponent_ = function() { topInputProperty.addEventListener(propEventType.CHANGE, this.setTopForPropertyUpdate, false, this); - + proppane.addProperty(topInputProperty, baseGroup, 'top'); - - + + var widthInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_width')); var widthInput = widthInputProperty.getValueControl(); widthInput.getNumberValidator().setAllowDecimal(true, 1); - + widthInputProperty.addEventListener(propEventType.CHANGE, this.setWidthForPropertyUpdate, false, this); - + proppane.addProperty(widthInputProperty, baseGroup, 'width'); - - + + var heightInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_height')); var heightInput = heightInputProperty.getValueControl(); heightInput.getNumberValidator().setAllowDecimal(true, 1); - + heightInputProperty.addEventListener(propEventType.CHANGE, this.setHeightForPropertyUpdate, false, this); - + proppane.addProperty(heightInputProperty, baseGroup, 'height'); - - + + var displayCheckProperty = new thin.ui.PropertyPane.CheckboxProperty(thin.t('field_display')); displayCheckProperty.addEventListener(propEventType.CHANGE, this.setDisplayForPropertyUpdate, false, this); - + proppane.addProperty(displayCheckProperty, baseGroup, 'display'); - + var shapeGroup = proppane.addGroup(thin.t('property_group_shape')); - - + + var fillInputProperty = new thin.ui.PropertyPane.ColorProperty(thin.t('field_fill_color')); fillInputProperty.getValueControl().getInput().setLabel('none'); fillInputProperty.addEventListener(propEventType.CHANGE, this.setFillForPropertyUpdate, false, this); - + proppane.addProperty(fillInputProperty , shapeGroup, 'fill'); - - + + var strokeInputProperty = new thin.ui.PropertyPane.ColorProperty(thin.t('field_stroke_color')); strokeInputProperty.getValueControl().getInput().setLabel('none'); strokeInputProperty.addEventListener(propEventType.CHANGE, this.setStrokeForPropertyUpdate, false, this); - + proppane.addProperty(strokeInputProperty , shapeGroup, 'stroke'); - - + + var strokeWidthCombProperty = new thin.ui.PropertyPane.ComboBoxProperty(thin.t('field_stroke_width')); var strokeWidthComb = strokeWidthCombProperty.getValueControl(); var strokeWidthInput = strokeWidthComb.getInput(); @@ -236,7 +215,7 @@ thin.core.EllipseShape.prototype.createPropertyComponent_ = function() { }); strokeWidthCombProperty.addEventListener(propEventType.CHANGE, this.setStrokeWidthForPropertyUpdate, false, this); - + proppane.addProperty(strokeWidthCombProperty , shapeGroup, 'stroke-width'); var strokeType = thin.core.ModuleElement.StrokeType; @@ -251,25 +230,25 @@ thin.core.EllipseShape.prototype.createPropertyComponent_ = function() { new thin.ui.Option(thin.core.ModuleElement.getStrokeName(strokeType.DASHED), strokeType.DASHED)); strokeDashSelect.addItem( new thin.ui.Option(thin.core.ModuleElement.getStrokeName(strokeType.DOTTED), strokeType.DOTTED)); - + strokeDashSelectProperty.addEventListener(propEventType.CHANGE, this.setStrokeDashTypeForPropertyUpdate, false, this); - + proppane.addProperty(strokeDashSelectProperty , shapeGroup, 'stroke-dash-type'); var cooperationGroup = proppane.addGroup(thin.t('property_group_association')); - + var idInputProperty = new thin.ui.PropertyPane.IdInputProperty(this, 'ID'); idInputProperty.addEventListener(propEventType.CHANGE, this.setShapeIdForPropertyUpdate, false, this); - + proppane.addProperty(idInputProperty, cooperationGroup, 'shape-id'); - + var descProperty = new thin.ui.PropertyPane.InputProperty(thin.t('field_description')); descProperty.addEventListener(propEventType.CHANGE, this.setDescPropertyUpdate, false, this); - + proppane.addProperty(descProperty, cooperationGroup, 'desc'); }; @@ -306,7 +285,7 @@ thin.core.EllipseShape.prototype.updateProperties = function() { var properties = this.getProperties(); var proppaneBlank = thin.core.ModuleShape.PROPPANE_SHOW_BLANK; var noneColor = thin.core.ModuleShape.NONE; - + proppane.getPropertyControl('left').setValue(properties['left']); proppane.getPropertyControl('top').setValue(properties['top']); proppane.getPropertyControl('width').setValue(properties['width']); @@ -327,7 +306,7 @@ thin.core.EllipseShape.prototype.updateProperties = function() { strokeWidth = proppaneBlank; } proppane.getPropertyControl('stroke-width').setInternalValue(strokeWidth); - + proppane.getPropertyControl('stroke-dash-type').setValue(properties['stroke-dash-type']); proppane.getPropertyControl('shape-id').setValue(properties['shape-id']); proppane.getPropertyControl('desc').setValue(properties['desc']); @@ -351,3 +330,62 @@ thin.core.EllipseShape.prototype.disposeInternal = function() { thin.core.EllipseShape.superClass_.disposeInternal.call(this); this.disposeInternalForShape(); }; + + +/** + * @return {Object} + */ +thin.core.EllipseShape.prototype.asJSON = function() { + var object = this.asJSON_(); + + goog.object.extend(object, { + 'cx': this.cx_, + 'cy': this.cy_, + 'rx': this.rx_, + 'ry': this.ry_ + }); + + goog.object.remove(object, 'x'); + goog.object.remove(object, 'y'); + goog.object.remove(object, 'width'); + goog.object.remove(object, 'height'); + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.EllipseShape.prototype.update = function(attrs) { + goog.object.forEach(attrs, function(value, attr) { + switch (attr) { + case 'rx': + this.setRx(value); + this.resetLeft(); + this.resetWidth(); + + break; + case 'ry': + this.setRy(value); + this.resetTop(); + this.resetHeight(); + + break; + case 'cx': + this.setCx(value); + this.resetLeft(); + + break; + case 'cy': + this.setCy(value); + this.resetTop(); + + break; + default: + break; + } + }, this); + + this.update_(attrs); +}; diff --git a/src/app/core/fontstyle.js b/src/app/core/fontstyle.js index a54c8349..cafd911f 100644 --- a/src/app/core/fontstyle.js +++ b/src/app/core/fontstyle.js @@ -70,4 +70,29 @@ thin.core.FontStyle.prototype.linethrough = false; /** * @type {string} */ -thin.core.FontStyle.prototype.decoration; \ No newline at end of file +thin.core.FontStyle.prototype.decoration; + + +/** + * @return {Object} + */ +thin.core.FontStyle.prototype.asJSON = function() { + var array = []; + + if (this.bold) { + array.push('bold'); + } + if (this.italic) { + array.push('italic'); + } + if (this.linethrough) { + array.push('linethrough'); + } + if (this.underline) { + array.push('underline'); + } + + return { + 'font-style': array + }; +}; diff --git a/src/app/core/formatstyle/abstractformat.js b/src/app/core/formatstyle/abstractformat.js index caa6e898..3f8ba38d 100644 --- a/src/app/core/formatstyle/abstractformat.js +++ b/src/app/core/formatstyle/abstractformat.js @@ -27,4 +27,8 @@ thin.core.formatstyles.AbstractFormat = function() { }; goog.inherits(thin.core.formatstyles.AbstractFormat, goog.Disposable); -thin.core.formatstyles.AbstractFormat.prototype.inspect = goog.abstractMethod; \ No newline at end of file + +thin.core.formatstyles.AbstractFormat.prototype.inspect = goog.abstractMethod; + + +thin.core.formatstyles.AbstractFormat.prototype.asJSON = goog.abstractMethod; diff --git a/src/app/core/formatstyle/datetimeformat.js b/src/app/core/formatstyle/datetimeformat.js index 2e697689..2dafad3f 100644 --- a/src/app/core/formatstyle/datetimeformat.js +++ b/src/app/core/formatstyle/datetimeformat.js @@ -25,7 +25,7 @@ goog.require('thin.core.formatstyles.AbstractFormat'); */ thin.core.formatstyles.DatetimeFormat = function(datetimeFormat) { thin.core.formatstyles.AbstractFormat.call(this); - + /** * @type {string} * @private @@ -65,6 +65,18 @@ thin.core.formatstyles.DatetimeFormat.prototype.inspect = function() { /** @inheritDoc */ thin.core.formatstyles.DatetimeFormat.prototype.disposeInternal = function() { goog.base(this, 'disposeInternal'); - + delete this.format_; -}; \ No newline at end of file +}; + + +/** + * @return {Object} + */ +thin.core.formatstyles.DatetimeFormat.prototype.asJSON = function() { + return { + 'datetime': { + 'format': this.getFormat() + } + }; +}; diff --git a/src/app/core/formatstyle/numberformat.js b/src/app/core/formatstyle/numberformat.js index fd151bbc..259724a9 100644 --- a/src/app/core/formatstyle/numberformat.js +++ b/src/app/core/formatstyle/numberformat.js @@ -27,9 +27,9 @@ goog.require('thin.core.formatstyles.AbstractFormat'); */ thin.core.formatstyles.NumberFormat = function(delimiter, precision, enabled) { thin.core.formatstyles.AbstractFormat.call(this); - + var disableDelimiter = thin.core.formatstyles.NumberFormat.DISABLE_DELIMITER; - + if (enabled) { if (thin.isExactlyEqual(delimiter, disableDelimiter)) { delimiter = thin.core.formatstyles.NumberFormat.DEFAULT_DELIMITER; @@ -43,14 +43,14 @@ thin.core.formatstyles.NumberFormat = function(delimiter, precision, enabled) { * @private */ this.delimiter_ = delimiter; - + /** * @type {number} * @private */ this.precision_ = precision; - - + + /** * @type {boolean} * @private @@ -122,7 +122,20 @@ thin.core.formatstyles.NumberFormat.prototype.inspect = function() { /** @inheritDoc */ thin.core.formatstyles.NumberFormat.prototype.disposeInternal = function() { goog.base(this, 'disposeInternal'); - + delete this.delimiter_; delete this.precision_; }; + + +/** + * @return {Object} + */ +thin.core.formatstyles.NumberFormat.prototype.asJSON = function() { + return { + 'number': { + 'delimiter': this.getDelimiter(), + 'precision': this.getPrecision() + } + }; +}; diff --git a/src/app/core/formatstyle/paddingformat.js b/src/app/core/formatstyle/paddingformat.js index 3c1a2d86..0830b952 100644 --- a/src/app/core/formatstyle/paddingformat.js +++ b/src/app/core/formatstyle/paddingformat.js @@ -141,3 +141,17 @@ thin.core.formatstyles.PaddingFormat.prototype.disposeInternal = function() { delete this.len_; delete this.char_; }; + + +/** + * @return {Object} + */ +thin.core.formatstyles.PaddingFormat.prototype.asJSON = function() { + return { + 'padding': { + 'length': this.getLength(), + 'char': this.getChar(), + 'direction': this.getDirection() + } + }; +}; diff --git a/src/app/core/imageblockshape.js b/src/app/core/imageblockshape.js index 7ba6e6b0..753408d6 100644 --- a/src/app/core/imageblockshape.js +++ b/src/app/core/imageblockshape.js @@ -237,26 +237,6 @@ thin.core.ImageblockShape.prototype.getStrokeWidth = function() { }; -/** - * @param {Element} element - * @param {thin.core.Layout} layout - * @param {thin.core.ShapeIdManager=} opt_shapeIdManager - * @return {thin.core.ImageblockShape} - */ -thin.core.ImageblockShape.createFromElement = function(element, layout, opt_shapeIdManager) { - var shape = new thin.core.ImageblockShape(element, layout); - - shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); - shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); - shape.setDesc(layout.getElementAttribute(element, 'x-desc')); - shape.setPositionX(layout.getElementAttribute(element, 'x-position-x')); - shape.setPositionY(layout.getElementAttribute(element, 'x-position-y')); - shape.initIdentifier(); - - return shape; -}; - - /** * @param {Element=} opt_element * @return {thin.core.Box} @@ -688,3 +668,110 @@ thin.core.ImageblockShape.prototype.disposeInternal = function() { delete this.positionX_; delete this.positionY_; }; + + +/** + * @return {string} + */ +thin.core.ImageblockShape.prototype.getPositionXAsJSON = function() { + return this.getPositionX(); +}; + + +/** + * @return {string} + */ +thin.core.ImageblockShape.prototype.getPositionYAsJSON = function() { + var postionYAsJSON = ''; + var postionYType = thin.core.ImageblockShape.PositionY; + + // SVG: top, center, bottom + // TLF: top, middle, bottom + switch(this.getPositionY()) { + case postionYType.CENTER: + postionYAsJSON = 'middle'; + break; + case postionYType.BOTTOM: + postionYAsJSON = postionYType.BOTTOM; + break; + default: + postionYAsJSON = postionYType.TOP; + break; + } + + return postionYAsJSON; +}; + + +/** + * @param {string|thin.core.ImageblockShape.PositionX} positionXFromJSON + */ +thin.core.ImageblockShape.prototype.setPositionXFromJSON = function(positionXFromJSON) { + this.setPositionX(positionXFromJSON); +}; + + +/** + * @param {string|thin.core.ImageblockShape.PositionY} postionYFromJSON + */ +thin.core.ImageblockShape.prototype.setPositionYFromJSON = function(postionYFromJSON) { + var position = ''; + var postionYType = thin.core.ImageblockShape.PositionY; + + // SVG: top, center, bottom + // TLF: top, middle, bottom + switch(postionYFromJSON) { + case 'middle': + position = postionYType.CENTER; + break; + default: + position = postionYFromJSON; + break; + } + + this.setPositionY(position); +}; + + +/** + * @return {string} + */ +thin.core.ImageblockShape.prototype.getType = function() { + return 'image-block'; +}; + + +/** + * @return {Object} + */ +thin.core.ImageblockShape.prototype.asJSON = function() { + var object = this.asJSON_(); + + goog.object.extend(object['style'], { + 'position-x': this.getPositionXAsJSON(), + 'position-y': this.getPositionYAsJSON() + }); + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.ImageblockShape.prototype.update = function(attrs) { + this.update_(attrs); + + goog.object.forEach(attrs, function(value, attr) { + switch (attr) { + case 'position-x': + this.setPositionXFromJSON(value); + break; + case 'position-y': + this.setPositionYFromJSON(value); + break; + default: + break; + } + }, this); +}; diff --git a/src/app/core/imagefile.js b/src/app/core/imagefile.js index ea53257c..25d707fe 100644 --- a/src/app/core/imagefile.js +++ b/src/app/core/imagefile.js @@ -131,18 +131,6 @@ thin.core.ImageFile.handleSelectFileToOpen = function(callbacks, entry) { }; -/** - * @param {Element} element - * @return {thin.core.ImageFile} - */ -thin.core.ImageFile.createFromElement = function(element) { - var entry = thin.File.createDummyEntry('DummyImageFile'); - var coreFile = new thin.File(entry, '', element.href.baseVal); - - return new thin.core.ImageFile(coreFile); -}; - - /** * @return {string} */ diff --git a/src/app/core/imageshape.js b/src/app/core/imageshape.js index 56e776f2..8d16ecee 100644 --- a/src/app/core/imageshape.js +++ b/src/app/core/imageshape.js @@ -81,24 +81,6 @@ thin.core.ImageShape.prototype.getClassId = function() { }; -/** - * @param {Element} element - * @param {thin.core.Layout} layout - * @param {thin.core.ShapeIdManager=} opt_shapeIdManager - * @return {thin.core.ImageShape} - */ -thin.core.ImageShape.createFromElement = function(element, layout, opt_shapeIdManager) { - var shape = new thin.core.ImageShape(element, layout); - shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); - shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); - shape.setDesc(layout.getElementAttribute(element, 'x-desc')); - shape.setFile(thin.core.ImageFile.createFromElement(element)); - shape.initIdentifier(); - - return shape; -}; - - /** * @param {number} width * @param {number} height @@ -455,3 +437,69 @@ thin.core.ImageShape.prototype.disposeInternal = function() { goog.base(this, 'disposeInternal'); this.disposeInternalForShape(); }; + + +/** + * @return {null} + */ +thin.core.ImageShape.prototype.getStroke = function() { + return null; +}; + + +/** + * @return {null} + */ +thin.core.ImageShape.prototype.getFill = function() { + return null; +}; + + +/** + * @return {Object} + */ +thin.core.ImageShape.prototype.asJSON = function() { + var object = this.asJSON_(); + + // data:image/png;base64,xxxxxxxx + var content = this.getFile().getContent(); + var dataUri = content.match(/^data:(.+?);base64,(.+)/); + if (dataUri) { + goog.object.set(object, 'data', { + 'mime-type': dataUri[1], + 'base64': dataUri[2] + }); + } + + if (goog.object.isEmpty(object['style'])) { + goog.object.remove(object, 'style'); + } + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.ImageShape.prototype.update = function(attrs) { + this.update_(attrs); + + if (goog.object.containsKey(attrs, 'data')) { + this.setFile(thin.core.ImageShape.createImageFileFromDataURISchema(attrs['data'])); + } +}; + + +/** + * @param {Object} factors + * @return {thin.core.ImageFile} + */ +thin.core.ImageShape.createImageFileFromDataURISchema = function(factors) { + var entry = thin.File.createDummyEntry('DummyImageFile'); + var path = ''; + // data:;base64, + var content = 'data:' + factors['mime-type'] + ';base64,' + factors['base64']; + + return new thin.core.ImageFile(new thin.File(entry, path, content)); +}; diff --git a/src/app/core/layout.js b/src/app/core/layout.js index 8f55e65c..bdf0d30d 100644 --- a/src/app/core/layout.js +++ b/src/app/core/layout.js @@ -38,7 +38,6 @@ goog.require('thin.core.Helpers'); goog.require('thin.core.StateManager'); goog.require('thin.core.ShapeIdManager'); goog.require('thin.core.ShapeIdManager.DefaultPrefix'); -goog.require('thin.core.LayoutStructure'); goog.require('thin.core.ClipboardShapeManager'); @@ -95,10 +94,11 @@ thin.core.Layout.prototype.canvasElement = null; /** + * @deprecated * @param {Element} element */ thin.core.Layout.prototype.drawListShapeFromElement = function(element) { - var shape = thin.core.ListShape.createFromElement(element, this); + var shape = thin.core.ShapeStructure.createListShapeFromElement(element, this); this.setOutlineForSingle(shape); this.manager_.addShape(shape); this.appendChild(shape); @@ -106,6 +106,7 @@ thin.core.Layout.prototype.drawListShapeFromElement = function(element) { /** + * @deprecated * @param {Element} element * @param {thin.core.ListSectionShape=} opt_sectionShape */ @@ -125,35 +126,35 @@ thin.core.Layout.prototype.drawBasicShapeFromElement = function(element, opt_sec switch (this.getElementAttribute(element, 'class')) { case thin.core.RectShape.CLASSID: - shape = thin.core.RectShape.createFromElement(element, this, opt_shapeIdManager); + shape = thin.core.ShapeStructure.createRectShapeFromElement(element, this, opt_shapeIdManager); break; case thin.core.EllipseShape.CLASSID: - shape = thin.core.EllipseShape.createFromElement(element, this, opt_shapeIdManager); + shape = thin.core.ShapeStructure.createEllipseShapeFromElement(element, this, opt_shapeIdManager); break; case thin.core.LineShape.CLASSID: - shape = thin.core.LineShape.createFromElement(element, this, opt_shapeIdManager); + shape = thin.core.ShapeStructure.createLineShapeFromElement(element, this, opt_shapeIdManager); break; case thin.core.TblockShape.CLASSID: - shape = thin.core.TblockShape.createFromElement(element, this, opt_shapeIdManager); + shape = thin.core.ShapeStructure.createTblockShapeFromElement(element, this, opt_shapeIdManager); break; case thin.core.PageNumberShape.CLASSID: - shape = thin.core.PageNumberShape.createFromElement(element, this, opt_shapeIdManager); + shape = thin.core.ShapeStructure.createPageNumberShapeFromElement(element, this, opt_shapeIdManager); break; case thin.core.TextShape.CLASSID: - shape = thin.core.TextShape.createFromElement(element, this, opt_shapeIdManager); + shape = thin.core.ShapeStructure.createTextShapeFromElement(element, this, opt_shapeIdManager); break; case thin.core.ImageShape.CLASSID: - shape = thin.core.ImageShape.createFromElement(element, this, opt_shapeIdManager); + shape = thin.core.ShapeStructure.createImageShapeFromElement(element, this, opt_shapeIdManager); break; case thin.core.ImageblockShape.CLASSID: - shape = thin.core.ImageblockShape.createFromElement(element, this, opt_shapeIdManager); + shape = thin.core.ShapeStructure.createImageblockShapeFromElement(element, this, opt_shapeIdManager); break; default: @@ -168,6 +169,7 @@ thin.core.Layout.prototype.drawBasicShapeFromElement = function(element, opt_sec /** + * @deprecated * @param {NodeList} elements * @param {thin.core.ListSectionShape=} opt_sectionShape */ @@ -185,6 +187,88 @@ thin.core.Layout.prototype.drawShapeFromElements = function(elements, opt_sectio }; +/** + * @param {Object} items + * @param {thin.core.ListSectionShape=} opt_sectionShape + */ +thin.core.Layout.prototype.drawShapes = function(items, opt_sectionShape) { + var shape; + goog.array.forEach(items, function(item) { + shape = this.drawShape(item, opt_sectionShape); + }, this); +}; + + +/** + * @param {Object} item + * @param {thin.core.ListSectionShape=} opt_sectionShape + * + * @return {goog.graphics.SvgGroupElement} + */ +thin.core.Layout.prototype.drawShape = function(item, opt_sectionShape) { + var opt_group; + var shape; + + if (opt_sectionShape) { + var manager = opt_sectionShape.getManager(); + opt_group = opt_sectionShape.getGroup(); + } else { + var manager = this.getManager(); + } + + switch (item['type']) { + case 'rect': + shape = this.createRectShape(); + break; + + case 'ellipse': + shape = this.createEllipseShape(); + break; + + case 'line': + shape = this.createLineShape(); + break; + + case 'text-block': + shape = this.createTblockShape(); + break; + + case 'page-number': + shape = this.createPageNumberShape(); + break; + + case 'text': + shape = this.createTextShape(); + break; + + case 'image': + shape = this.createImageShape(); + break; + + case 'image-block': + shape = this.createImageblockShape(); + break; + + case 'list': + shape = this.createListShape(); + break; + + default: + throw new Error('Unknown shape.'); + break; + } + + this.setOutlineForSingle(shape); + manager.addShape(shape, opt_sectionShape); + this.appendChild(shape, opt_group); + shape.setupEventHandlers(); + + shape.update(item); + + return shape; +}; + + /** * @return {thin.core.Workspace} */ @@ -389,10 +473,18 @@ thin.core.Layout.prototype.createHelpersElement = function(tagName, attrs) { /** - * @return {string} + * @return {Object} */ -thin.core.Layout.prototype.toXML = function() { - return thin.core.LayoutStructure.serialize(this); +thin.core.Layout.prototype.asJSON = function() { + var childNodes = this.getCanvasElement().getElement().childNodes; + var identifiers = goog.array.map(childNodes, function(element, i) { + return element.getAttribute('id'); + }); + + var manager = this.getManager().getShapesManager(); + return goog.array.map(identifiers, function(identifier, i) { + return manager.getShapeByIdentifier(identifier).asJSON(); + }); }; @@ -870,7 +962,7 @@ thin.core.Layout.prototype.pasteShapes = function() { var referringShape = pasteShapes[count]; if (referringShape.instanceOfTblockShape()) { if (!thin.isExactlyEqual(refId, defaultRefId) && !referringShape.isReferences()) { - referringShape.setRefId(refId, layout.getShapeForShapeId(refId, shapeIdManager)); + referringShape.setRefId(refId); } } }); @@ -889,7 +981,7 @@ thin.core.Layout.prototype.pasteShapes = function() { var referringShape = pasteShapes[count]; if (referringShape.instanceOfTblockShape()) { if (!thin.isExactlyEqual(refId, defaultRefId) && !referringShape.isReferences()) { - referringShape.setRefId(refId, layout.getShapeForShapeId(refId)); + referringShape.setRefId(refId); } } }); @@ -1023,23 +1115,23 @@ thin.core.Layout.prototype.removeShape = function(shape) { listHelper.clearChangingPageSetShape(); } goog.array.forEach(shape.getPageNumberReferences(), function(target) { - target.removeTargetShape(); + target.removeTargetShapeId(); }); } if (shape.instanceOfTblockShape()) { if (shape.isReferences()) { goog.array.forEach(shape.getReferringShapes(), function(target) { - target.removeReferenceShape(); + target.removeReferenceShapeId(); }); } if (shape.isReferring()) { - shape.removeReferenceShape(); + shape.removeReferenceShapeId(); } } if (shape.instanceOfPageNumberShape()) { - shape.removeTargetShape(); + shape.removeTargetShapeId(); } if (shape.isAffiliationListShape()) { @@ -1275,7 +1367,7 @@ thin.core.Layout.prototype.createTblockShape = function() { shape.setFormatType(thin.core.TblockShape.DEFAULT_FORMAT_TYPE); shape.setDefaultValueOfLink(thin.core.TblockShape.DEFAULT_VALUE); shape.setBaseFormat(thin.core.TblockShape.DEFAULT_FORMAT_BASE); - shape.setInternalRefId(thin.core.TblockShape.DEFAULT_REFID); + shape.setRefId(thin.core.TblockShape.DEFAULT_REFID); shape.setKerning(thin.core.TextStyle.DEFAULT_KERNING); shape.setDisplay(thin.core.ModuleShape.DEFAULT_DISPLAY); shape.setMultiModeInternal(thin.core.TblockShape.DEFAULT_MULTIPLE); diff --git a/src/app/core/layoutstructure.js b/src/app/core/layoutstructure.js index ab820ee6..2007c7ab 100644 --- a/src/app/core/layoutstructure.js +++ b/src/app/core/layoutstructure.js @@ -16,13 +16,11 @@ goog.provide('thin.core.LayoutStructure'); goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.string'); -goog.require('thin.core.ShapeStructure'); goog.require('thin.platform.String'); /** + * @deprecated * @enum {string} * @private */ @@ -34,6 +32,7 @@ thin.core.LayoutStructure.Template_ = { /** + * @deprecated * @enum {RegExp} * @private */ @@ -44,19 +43,7 @@ thin.core.LayoutStructure.Regexp_ = { /** - * @param {thin.core.Layout} layout - * @return {string} - */ -thin.core.LayoutStructure.serialize = function(layout) { - var xml; - thin.core.LayoutStructure.inRawLayout_(layout, function() { - xml = thin.core.LayoutStructure.serializeForFormat_(layout); - }); - return xml; -}; - - -/** + * @deprecated * @param {string} svg * @return {string} */ @@ -67,60 +54,25 @@ thin.core.LayoutStructure.restoreStructure = function(svg) { /** + * @deprecated * @param {thin.core.Layout} layout * @return {string} The base64 encoded string. */ thin.core.LayoutStructure.createScreenShot = function(layout) { var svg; - + thin.core.LayoutStructure.inRawLayout_(layout, function() { svg = layout.getElement().cloneNode(true); }); thin.core.LayoutStructure.finalizeLayoutElement_(svg); - + return thin.platform.String.toBase64( thin.core.serializeToXML(/** @type {Element} */ (svg))); }; /** - * @param {thin.core.Layout} layout - * @return {string} - */ -thin.core.LayoutStructure.createBackup = function(layout) { - var svg = layout.getElement().cloneNode(true); - thin.core.LayoutStructure.finalizeLayoutElement_(svg); - - return thin.core.serializeToXML(/** @type {Element} */(svg)); -}; - - -/** - * @param {thin.core.Layout} layout - * @return {string} - * @private - */ -thin.core.LayoutStructure.serializeForFormat_ = function(layout) { - var layoutSize = layout.getNormalLayoutSize(); - var svg = layout.getElement().cloneNode(true); - - thin.core.LayoutStructure.finalizeLayoutElement_(svg); - - svg.setAttribute('width', layoutSize.width); - svg.setAttribute('height', layoutSize.height); - svg.removeAttribute('id'); - svg.removeAttribute('style'); - svg.removeAttribute('class'); - - thin.core.LayoutStructure.serializeShapes( - goog.dom.getElementsByTagNameAndClass('g', thin.core.Layout.CANVAS_CLASS_ID, - /** @type {Element} */(svg))[0].childNodes); - - return thin.core.serializeToXML(/** @type {Element} */(svg)); -}; - - -/** + * @deprecated * @param {thin.core.Layout} layout * @param {Function} f * @private @@ -129,7 +81,7 @@ thin.core.LayoutStructure.inRawLayout_ = function(layout, f) { var workspace = layout.getWorkspace(); var zoomRate = workspace.getUiStatusForZoom(); var listHelper = layout.getHelpers().getListHelper(); - + // Set zoom-rate to 100%. var scrollTarget = workspace.getParent().getParent().getContentElement(); var scrollLeft = Number(scrollTarget.scrollLeft); @@ -147,15 +99,15 @@ thin.core.LayoutStructure.inRawLayout_ = function(layout, f) { shapes: listHelper.getActiveShape().getClone() }; listHelper.inactive(); - + f(); - + // Activate list and restore states. listHelper.active(listStates.target); listHelper.getActiveShape().set(listStates.shapes); listHelper.setActiveSectionName(listStates.activeSection); } - + // Restore original zoom-rate. workspace.getAction().actionSetZoom(zoomRate); scrollTarget.scrollLeft = scrollLeft; @@ -164,62 +116,13 @@ thin.core.LayoutStructure.inRawLayout_ = function(layout, f) { /** - * @param {NodeList} shapes - * @param {number=} opt_sectionDepth - * @return {NodeList} - */ -thin.core.LayoutStructure.serializeShapes = function(shapes, opt_sectionDepth) { - var layoutUtilTemplate = thin.core.LayoutStructure.Template_; - - var shapeTemplateFactor = layoutUtilTemplate.SHAPE; - var layoutTemplateFactor = layoutUtilTemplate.LAYOUT; - - var layoutTemplate = goog.array.repeat(layoutTemplateFactor, 2); - var shapeTemplate = goog.array.repeat(shapeTemplateFactor, 2); - - if (opt_sectionDepth) { - var depth = goog.string.repeat(layoutUtilTemplate.CONNECT, opt_sectionDepth); - - shapeTemplate[0] = depth + shapeTemplate[0]; - shapeTemplate[1] += depth; - layoutTemplate[0] = depth + layoutTemplate[0]; - layoutTemplate[1] += depth; - - goog.array.forEachRight(shapes, function(shape, i) { - if (thin.core.LayoutStructure.isSerializableShape_(shape)) { - goog.dom.replaceNode(thin.core.LayoutStructure.formatStructure_( - thin.core.ShapeStructure.serialize(shape), shapeTemplate), shape); - // When visibility of shape is hidden and shape has not id. - } else if (thin.core.LayoutStructure.isHiddenShape_(shape)) { - goog.dom.replaceNode(thin.core.LayoutStructure.formatStructure_( - thin.core.serializeToXML(shape), layoutTemplate), shape); - } - }); - } else { - goog.array.forEachRight(shapes, function(shape, i) { - if (thin.core.LayoutStructure.isSerializableShape_(shape)) { - goog.dom.insertSiblingBefore(thin.core.LayoutStructure.formatStructure_( - thin.core.ShapeStructure.serialize(shape), shapeTemplate), shape); - goog.dom.replaceNode(thin.core.LayoutStructure.formatStructure_( - thin.core.serializeToXML(shape), layoutTemplate), shape); - // When visibility of shape is hidden and shape has not id. - } else if (thin.core.LayoutStructure.isHiddenShape_(shape)) { - goog.dom.replaceNode(thin.core.LayoutStructure.formatStructure_( - thin.core.serializeToXML(shape), layoutTemplate), shape); - } - }); - } - return shapes; -}; - - -/** + * @deprecated * @param {Element} layoutElement * @private */ thin.core.LayoutStructure.finalizeLayoutElement_ = function(layoutElement) { var canvasId = thin.core.Layout.CANVAS_CLASS_ID; - + goog.array.forEachRight(layoutElement.childNodes, function(node, i, nodes) { if (canvasId != node.getAttribute('class')) { layoutElement.removeChild(nodes[i]); @@ -229,33 +132,48 @@ thin.core.LayoutStructure.finalizeLayoutElement_ = function(layoutElement) { /** - * @param {Element} element - * @return {boolean} - * @private + * @deprecated + * @param {thin.core.Layout} layout */ -thin.core.LayoutStructure.isSerializableShape_ = function(element) { - var type = element.getAttribute('class'); - return goog.array.contains(['s-tblock', 's-iblock', 's-list', 's-pageno'], type) || !goog.string.isEmpty(element.getAttribute('x-id')); -}; +thin.core.LayoutStructure.convertToNewLayoutSchema = function(layout) { + var format = layout.getFormat(); + var xmlString = thin.core.LayoutStructure.restoreStructure(format.getItems()); + var doc = new DOMParser().parseFromString(xmlString, "application/xml"); + var canvasNode = goog.dom.getLastElementChild(doc.documentElement); -/** - * @param {Element} element - * @return {boolean} - * @private - */ -thin.core.LayoutStructure.isHiddenShape_ = function(element) { - return !thin.core.LayoutStructure.isSerializableShape_(element) && - element.getAttribute('x-display') == 'false'; + layout.drawShapeFromElements(canvasNode.childNodes); + + var shapes = layout.getManager().getShapesManager().get(); + thin.core.LayoutStructure.applyRefId(layout, shapes); + + format.setItems(layout.asJSON()); + layout.removeShapes(shapes); }; /** - * @param {string} content - * @param {Array} template - * @return {Comment} - * @private + * @deprecated + * @param {thin.core.Layout} layout + * @param {Array} shapes + * @param {thin.core.ListSectionShape=} opt_shapeIdManager */ -thin.core.LayoutStructure.formatStructure_ = function(content, template) { - return goog.dom.getDocument().createComment(template[0] + content + template[1]); +thin.core.LayoutStructure.applyRefId = function(layout, shapes, opt_shapeIdManager) { + goog.array.forEach(shapes, function(shape) { + if (shape.instanceOfListShape()) { + shape.forEachSectionShape(function(sectionShapeForEach, sectionNameForEach) { + var managerForList = sectionShapeForEach.getManager(); + thin.core.LayoutStructure.applyRefId(layout, + managerForList.getShapesManager().get(), + managerForList.getShapeIdManager()); + }); + } else { + if (shape.instanceOfTblockShape()) { + var refId = layout.getElementAttribute(shape.getElement(), 'x-ref-id'); + if (!thin.isExactlyEqual(refId, thin.core.TblockShape.DEFAULT_REFID)) { + shape.setRefId(refId); + } + } + } + }); }; diff --git a/src/app/core/lineshape.js b/src/app/core/lineshape.js index 507a0a01..14db9f96 100644 --- a/src/app/core/lineshape.js +++ b/src/app/core/lineshape.js @@ -58,28 +58,6 @@ thin.core.LineShape.prototype.getClassId = function() { }; -/** - * @param {Element} element - * @param {thin.core.Layout} layout - * @param {thin.core.ShapeIdManager=} opt_shapeIdManager - * @return {thin.core.LineShape} - */ -thin.core.LineShape.createFromElement = function(element, layout, opt_shapeIdManager) { - - var shape = new thin.core.LineShape(element, layout, - new goog.graphics.Stroke( - Number(layout.getElementAttribute(element, 'stroke-width')), - layout.getElementAttribute(element, 'stroke'))); - - shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); - shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); - shape.setDesc(layout.getElementAttribute(element, 'x-desc')); - shape.setStrokeDashFromType(layout.getElementAttribute(element, 'x-stroke-type')); - shape.initIdentifier(); - return shape; -}; - - thin.core.LineShape.prototype.setDefaultOutline = function() { this.setTargetOutline(this.getLayout().getHelpers().getLineOutline()); }; @@ -112,7 +90,7 @@ thin.core.LineShape.prototype.getCloneCreator = function() { var fill = this.getFill(); var strokeDashType = this.getStrokeDashType(); var display = this.getDisplay(); - + var isAffiliationListShape = this.isAffiliationListShape(); var deltaCoordinate = this.getDeltaCoordinateForList(); @@ -124,10 +102,10 @@ thin.core.LineShape.prototype.getCloneCreator = function() { * @return {thin.core.LineShape} */ return function(layout, opt_isAdaptDeltaForList, opt_renderTo, opt_basisCoordinate) { - + var shape = layout.createLineShape(); layout.appendChild(shape, opt_renderTo); - + var pasteCoordinate = layout.calculatePasteCoordinate(isAffiliationListShape, deltaCoordinateForList, deltaCoordinateForGuide, sourceCoordinate, opt_isAdaptDeltaForList, opt_renderTo, opt_basisCoordinate); @@ -149,62 +127,62 @@ thin.core.LineShape.prototype.getCloneCreator = function() { * @private */ thin.core.LineShape.prototype.createPropertyComponent_ = function() { - + var scope = this; var layout = this.getLayout(); var propEventType = thin.ui.PropertyPane.Property.EventType; var proppane = thin.ui.getComponent('proppane'); - + var baseGroup = proppane.addGroup(thin.t('property_group_basis')); - - + + var leftInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_left_position')); var leftInput = leftInputProperty.getValueControl(); leftInput.getNumberValidator().setAllowDecimal(true, 1); - + leftInputProperty.addEventListener(propEventType.CHANGE, this.setLeftForPropertyUpdate, false, this); - + proppane.addProperty(leftInputProperty, baseGroup, 'left'); var topInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_top_position')); var topInput = topInputProperty.getValueControl(); topInput.getNumberValidator().setAllowDecimal(true, 1); - + topInputProperty.addEventListener(propEventType.CHANGE, this.setTopForPropertyUpdate, false, this); - + proppane.addProperty(topInputProperty, baseGroup, 'top'); - - + + var widthInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_width')); var widthInput = widthInputProperty.getValueControl(); widthInput.getNumberValidator().setAllowDecimal(true, 1); - + widthInputProperty.addEventListener(propEventType.CHANGE, this.setWidthForPropertyUpdate, false, this); - + proppane.addProperty(widthInputProperty, baseGroup, 'width'); - - + + var heightInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_height')); var heightInput = heightInputProperty.getValueControl(); heightInput.getNumberValidator().setAllowDecimal(true, 1); - + heightInputProperty.addEventListener(propEventType.CHANGE, this.setHeightForPropertyUpdate, false, this); - + proppane.addProperty(heightInputProperty, baseGroup, 'height'); - - + + var displayCheckProperty = new thin.ui.PropertyPane.CheckboxProperty(thin.t('field_display')); displayCheckProperty.addEventListener(propEventType.CHANGE, this.setDisplayForPropertyUpdate, false, this); - + proppane.addProperty(displayCheckProperty, baseGroup, 'display'); - + var shapeGroup = proppane.addGroup(thin.t('property_group_shape')); @@ -212,10 +190,10 @@ thin.core.LineShape.prototype.createPropertyComponent_ = function() { strokeInputProperty.getValueControl().getInput().setLabel('none'); strokeInputProperty.addEventListener(propEventType.CHANGE, this.setStrokeForPropertyUpdate, false, this); - + proppane.addProperty(strokeInputProperty , shapeGroup, 'stroke'); - - + + var strokeWidthCombProperty = new thin.ui.PropertyPane.ComboBoxProperty(thin.t('field_stroke_width')); var strokeWidthComb = strokeWidthCombProperty.getValueControl(); var strokeWidthInput = strokeWidthComb.getInput(); @@ -234,10 +212,10 @@ thin.core.LineShape.prototype.createPropertyComponent_ = function() { }); strokeWidthCombProperty.addEventListener(propEventType.CHANGE, this.setStrokeWidthForPropertyUpdate, false, this); - + proppane.addProperty(strokeWidthCombProperty , shapeGroup, 'stroke-width'); - + var strokeType = thin.core.ModuleElement.StrokeType; var strokeDashSelectProperty = new thin.ui.PropertyPane.SelectProperty(thin.t('field_stroke_type')); var strokeDashSelect = strokeDashSelectProperty.getValueControl(); @@ -250,25 +228,25 @@ thin.core.LineShape.prototype.createPropertyComponent_ = function() { new thin.ui.Option(thin.core.ModuleElement.getStrokeName(strokeType.DASHED), strokeType.DASHED)); strokeDashSelect.addItem( new thin.ui.Option(thin.core.ModuleElement.getStrokeName(strokeType.DOTTED), strokeType.DOTTED)); - + strokeDashSelectProperty.addEventListener(propEventType.CHANGE, this.setStrokeDashTypeForPropertyUpdate, false, this); - + proppane.addProperty(strokeDashSelectProperty , shapeGroup, 'stroke-dash-type'); var cooperationGroup = proppane.addGroup(thin.t('property_group_association')); - + var idInputProperty = new thin.ui.PropertyPane.IdInputProperty(this, 'ID'); idInputProperty.addEventListener(propEventType.CHANGE, this.setShapeIdForPropertyUpdate, false, this); - + proppane.addProperty(idInputProperty, cooperationGroup, 'shape-id'); - + var descProperty = new thin.ui.PropertyPane.InputProperty(thin.t('field_description')); descProperty.addEventListener(propEventType.CHANGE, this.setDescPropertyUpdate, false, this); - + proppane.addProperty(descProperty, cooperationGroup, 'desc'); }; @@ -301,16 +279,16 @@ thin.core.LineShape.prototype.updateProperties = function() { proppane.setTarget(this); this.createPropertyComponent_(); } - + var properties = this.getProperties(); var proppaneBlank = thin.core.ModuleShape.PROPPANE_SHOW_BLANK; - + proppane.getPropertyControl('left').setValue(properties['left']); proppane.getPropertyControl('top').setValue(properties['top']); proppane.getPropertyControl('width').setValue(properties['width']); proppane.getPropertyControl('height').setValue(properties['height']); proppane.getPropertyControl('display').setChecked(properties['display']); - + var stroke = properties['stroke']; if (thin.isExactlyEqual(stroke, thin.core.ModuleShape.NONE)) { stroke = proppaneBlank @@ -321,9 +299,9 @@ thin.core.LineShape.prototype.updateProperties = function() { strokeWidth = proppaneBlank; } proppane.getPropertyControl('stroke-width').setInternalValue(strokeWidth); - + proppane.getPropertyControl('stroke-dash-type').setValue(properties['stroke-dash-type']); - + proppane.getPropertyControl('shape-id').setValue(properties['shape-id']); proppane.getPropertyControl('desc').setValue(properties['desc']); }; @@ -351,3 +329,60 @@ thin.core.LineShape.prototype.disposeInternal = function() { thin.core.LineShape.superClass_.disposeInternal.call(this); this.disposeInternalForShape(); }; + + +/** + * @return {Object} + */ +thin.core.LineShape.prototype.asJSON = function() { + var object = this.asJSON_(); + + var layout = this.getLayout(); + var element = this.getElement(); + goog.object.extend(object, { + 'x1': Number(layout.getElementAttribute(element, 'x1')), + 'y1': Number(layout.getElementAttribute(element, 'y1')), + 'x2': Number(layout.getElementAttribute(element, 'x2')), + 'y2': Number(layout.getElementAttribute(element, 'y2')) + }); + + goog.object.remove(object, 'x'); + goog.object.remove(object, 'y'); + goog.object.remove(object, 'width'); + goog.object.remove(object, 'height'); + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.LineShape.prototype.update = function(attrs) { + this.update_(attrs); + + var keys = goog.object.getKeys(attrs); + var result_index = goog.array.findIndex(keys, function(key, index) { + return key == 'x1' || key == 'x2' || key == 'y1' || key == 'y2' + }); + + if (result_index > -1) { + var x1 = attrs['x1']; + var x2 = attrs['x2']; + var y1 = attrs['y1']; + var y2 = attrs['y2']; + + this.setX1(x1); + this.setX2(x2); + this.setY1(y1); + this.setY2(y2); + + this.calculateDirection(y1, y2); + + this.setLeft(Math.min(x1, x2) + this.getParentTransLateX()); + this.setTop(Math.min(y1, y2) + this.getParentTransLateY()); + this.setWidth(Math.abs(x1 - x2)); + this.setHeight(Math.abs(y1 - y2)); + } + +}; diff --git a/src/app/core/listsectionshape.js b/src/app/core/listsectionshape.js index 3328da4b..f07e13fd 100644 --- a/src/app/core/listsectionshape.js +++ b/src/app/core/listsectionshape.js @@ -38,19 +38,19 @@ goog.require('thin.core.ModuleShape'); * @extends {goog.Disposable} */ thin.core.ListSectionShape = function(layout, affiliationGroup, sectionName, opt_element) { - + /** * @type {thin.core.Layout} * @private */ this.layout_ = layout; - + /** * @type {thin.core.ListShape} * @private */ this.affiliationGroup_ = affiliationGroup; - + /** * @type {string} * @private @@ -138,7 +138,7 @@ thin.core.ListSectionShape.prototype.setup = function(opt_element) { 'class': thin.core.ListShape.CLASSID + classId[this.sectionName_] }), layout); group.setTransformation(0, 0, 0, 0, 0); - + this.group_ = group; this.manager_ = new thin.core.StateManager(layout); @@ -173,7 +173,7 @@ thin.core.ListSectionShape.prototype.setEnabled = function(enabled) { * @return {boolean} */ thin.core.ListSectionShape.prototype.isEnabled = function() { - return /** @type {boolean} */(thin.getValIfNotDef(this.isEnabled_, + return /** @type {boolean} */(thin.getValIfNotDef(this.isEnabled_, thin.core.ListSectionShape.DEFAULT_ENABLED)); }; @@ -286,7 +286,7 @@ thin.core.ListSectionShape.prototype.getNextSectionShape = function() { */ thin.core.ListSectionShape.prototype.getNextSectionShapes = function() { var sectionShapes = []; - + /** * @param {thin.core.ListSectionShape=} opt_sectionShape */ @@ -317,7 +317,7 @@ thin.core.ListSectionShape.prototype.disposeInternal = function() { thin.core.ListSectionShape.superClass_.disposeInternal.call(this); this.group_.dispose(); this.manager_.dispose(); - + delete this.group_; delete this.manager_; delete this.affiliationGroup_; @@ -326,6 +326,74 @@ thin.core.ListSectionShape.prototype.disposeInternal = function() { }; +thin.core.ListSectionShape.prototype.getType = function() { + return thin.core.ListShape.ClassIds[this.getSectionName()].replace(/^\-/, ''); +}; + + +/** + * @return {Object} + */ +thin.core.ListSectionShape.prototype.asJSON = function() { + var object = { + 'enabled': this.isEnabled(), + 'height': this.height_ + }; + + var transform = this.getGroup().getTransform(); + + if (this.isEnabled()) { + var childNodes = this.getGroup().getElement().childNodes; + var identifiers = goog.array.map(childNodes, function(element, i) { + return element.getAttribute('id'); + }); + + var manager = this.getManager().getShapesManager(); + var items = goog.array.map(identifiers, function(identifier, i) { + return manager.getShapeByIdentifier(identifier).asJSON(); + }); + } else { + var items = []; + } + + goog.object.extend(object, { + 'translate': { + 'x': transform.getTranslateX(), + 'y': transform.getTranslateY() + }, + 'items': items + }); + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.ListSectionShape.prototype.update = function(attrs) { + goog.object.forEach(attrs, function(value, attr) { + switch (attr) { + case 'enabled': + this.setEnabled(value); + break; + case 'height': + this.setHeight(value); + break; + case 'translate': + this.setTransLate(new goog.math.Coordinate( + value['x'], value['y'])); + break; + case 'items': + this.getLayout().drawShapes(value, this); + break; + default: + break; + } + }, this); +}; + + /** * @param {thin.core.Layout} layout * @param {thin.core.ListShape} affiliationGroup @@ -357,7 +425,7 @@ thin.core.HeaderSectionShape.prototype.defaultHeightRate_ = 0.2; * @return {boolean} */ thin.core.HeaderSectionShape.prototype.isEnabled = function() { - return /** @type {boolean} */(thin.getValIfNotDef(this.isEnabled_, + return /** @type {boolean} */(thin.getValIfNotDef(this.isEnabled_, thin.core.HeaderSectionShape.DEFAULT_ENABLED)); }; @@ -372,28 +440,28 @@ thin.core.HeaderSectionShape.prototype.createPropertyComponent_ = function() { var sectionName = this.sectionName_; var propEventType = thin.ui.PropertyPane.Property.EventType; var proppane = thin.ui.getComponent('proppane'); - + var containerGroup = proppane.addGroup(thin.t('property_group_list_header')); - + var heightInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_height')); var heightInput = heightInputProperty.getValueControl(); heightInput.getNumberValidator().setAllowDecimal(true, 1); - + heightInputProperty.addEventListener(propEventType.CHANGE, function(e) { listShape.setHeightForSectionShape( Number(e.target.getValue()), sectionName); }, false, this); - + proppane.addProperty(heightInputProperty, containerGroup, 'section-header-height'); - - + + var displayCheckProperty = new thin.ui.PropertyPane.CheckboxProperty(thin.t('field_display')); displayCheckProperty.addEventListener(propEventType.CHANGE, function(e) { scope.setSectionEnabled(e.target.isChecked(), sectionName); }, false, this); - + proppane.addProperty(displayCheckProperty, containerGroup, 'section-header-enable'); }; @@ -441,7 +509,7 @@ thin.core.DetailSectionShape.prototype.defaultHeightRate_ = 0.2; * @return {boolean} */ thin.core.DetailSectionShape.prototype.isEnabled = function() { - return /** @type {boolean} */(thin.getValIfNotDef(this.isEnabled_, + return /** @type {boolean} */(thin.getValIfNotDef(this.isEnabled_, thin.core.DetailSectionShape.DEFAULT_ENABLED)); }; @@ -456,19 +524,19 @@ thin.core.DetailSectionShape.prototype.createPropertyComponent_ = function() { var sectionName = this.sectionName_; var propEventType = thin.ui.PropertyPane.Property.EventType; var proppane = thin.ui.getComponent('proppane'); - + var containerGroup = proppane.addGroup(thin.t('property_group_list_detail')); - + var heightInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_height')); var heightInput = heightInputProperty.getValueControl(); heightInput.getNumberValidator().setAllowDecimal(true, 1); - + heightInputProperty.addEventListener(propEventType.CHANGE, function(e) { listShape.setHeightForSectionShape( Number(e.target.getValue()), sectionName); }, false, this); - + proppane.addProperty(heightInputProperty, containerGroup, 'section-detail-height'); }; @@ -484,6 +552,18 @@ thin.core.DetailSectionShape.prototype.updateProperties = function() { }; +/** + * @return {Object} + */ +thin.core.DetailSectionShape.prototype.asJSON = function() { + var object = goog.base(this, 'asJSON'); + + goog.object.remove(object, 'enabled'); + + return object; +}; + + /** * @param {thin.core.Layout} layout * @param {thin.core.ListShape} affiliationGroup @@ -515,7 +595,7 @@ thin.core.PageFooterSectionShape.prototype.defaultHeightRate_ = 0.15; * @return {boolean} */ thin.core.PageFooterSectionShape.prototype.isEnabled = function() { - return /** @type {boolean} */(thin.getValIfNotDef(this.isEnabled_, + return /** @type {boolean} */(thin.getValIfNotDef(this.isEnabled_, thin.core.PageFooterSectionShape.DEFAULT_ENABLED)); }; @@ -530,28 +610,28 @@ thin.core.PageFooterSectionShape.prototype.createPropertyComponent_ = function() var sectionName = this.sectionName_; var propEventType = thin.ui.PropertyPane.Property.EventType; var proppane = thin.ui.getComponent('proppane'); - + var containerGroup = proppane.addGroup(thin.t('property_group_list_page_footer')); - + var heightInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_height')); var heightInput = heightInputProperty.getValueControl(); heightInput.getNumberValidator().setAllowDecimal(true, 1); - + heightInputProperty.addEventListener(propEventType.CHANGE, function(e) { listShape.setHeightForSectionShape( Number(e.target.getValue()), sectionName); }, false, this); - + proppane.addProperty(heightInputProperty, containerGroup, 'section-pagefooter-height'); - - + + var displayCheckProperty = new thin.ui.PropertyPane.CheckboxProperty(thin.t('field_display')); displayCheckProperty.addEventListener(propEventType.CHANGE, function(e) { scope.setSectionEnabled(e.target.isChecked(), sectionName); }, false, this); - + proppane.addProperty(displayCheckProperty, containerGroup, 'section-pagefooter-enable'); }; @@ -599,7 +679,7 @@ thin.core.FooterSectionShape.prototype.defaultHeightRate_ = 0.15; * @return {boolean} */ thin.core.FooterSectionShape.prototype.isEnabled = function() { - return /** @type {boolean} */(thin.getValIfNotDef(this.isEnabled_, + return /** @type {boolean} */(thin.getValIfNotDef(this.isEnabled_, thin.core.FooterSectionShape.DEFAULT_ENABLED)); }; @@ -614,28 +694,28 @@ thin.core.FooterSectionShape.prototype.createPropertyComponent_ = function() { var sectionName = this.sectionName_; var propEventType = thin.ui.PropertyPane.Property.EventType; var proppane = thin.ui.getComponent('proppane'); - + var containerGroup = proppane.addGroup(thin.t('property_group_list_footer')); - + var heightInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_height')); var heightInput = heightInputProperty.getValueControl(); heightInput.getNumberValidator().setAllowDecimal(true, 1); - + heightInputProperty.addEventListener(propEventType.CHANGE, function(e) { listShape.setHeightForSectionShape( Number(e.target.getValue()), sectionName); }, false, this); - + proppane.addProperty(heightInputProperty, containerGroup, 'section-footer-height'); - - + + var displayCheckProperty = new thin.ui.PropertyPane.CheckboxProperty(thin.t('field_display')); displayCheckProperty.addEventListener(propEventType.CHANGE, function(e) { scope.setSectionEnabled(e.target.isChecked(), sectionName); }, false, this); - + proppane.addProperty(displayCheckProperty, containerGroup, 'section-footer-enable'); }; diff --git a/src/app/core/listshape.js b/src/app/core/listshape.js index 9b002dd8..dcfc17fd 100644 --- a/src/app/core/listshape.js +++ b/src/app/core/listshape.js @@ -135,64 +135,6 @@ thin.core.ListShape.prototype.getClassId = function() { }; -/** - * @param {Element} groupElement - * @param {thin.core.Layout} layout - * @return {thin.core.ListShape} - */ -thin.core.ListShape.createFromElement = function(groupElement, layout) { - var shape = new thin.core.ListShape(layout, - /** @type {Element} */(groupElement.cloneNode(false)), groupElement); - var classId = thin.core.ListShape.ClassIds; - - shape.setIdShape(layout.getElementAttribute(groupElement, 'x-id'), - thin.core.getElementByClassNameForChildNodes(thin.core.ListShape.CLASSID + classId['ID'], - shape.getElement().childNodes)); - shape.setBounds(new goog.math.Rect( - Number(layout.getElementAttribute(groupElement, 'x')), - Number(layout.getElementAttribute(groupElement, 'y')), - Number(layout.getElementAttribute(groupElement, 'width')), - Number(layout.getElementAttribute(groupElement, 'height')))); - - shape.setDisplay(layout.getElementAttribute(groupElement, 'x-display') == 'true'); - shape.setDesc(layout.getElementAttribute(groupElement, 'x-desc')); - if (layout.getElementAttribute(groupElement, 'x-changing-page') == 'true') { - shape.setChangingPage(true); - layout.getHelpers().getListHelper().setChangingPageSetShape(shape); - } else { - shape.setChangingPage(false); - } - - shape.forEachSectionShape(function(sectionShapeForScope, sectionNameForScope) { - var sectionGroup = sectionShapeForScope.getGroup(); - var sectionElement = thin.core.getElementByClassNameForChildNodes( - layout.getElementAttribute(sectionGroup.getElement(), 'class'), - groupElement.childNodes); - var transLateCoordinate = thin.core.ShapeStructure.getTransLateCoordinate(sectionElement); - sectionGroup.setTransformation(transLateCoordinate.x, transLateCoordinate.y, 0, 0, 0); - sectionShapeForScope.setTop(Number(layout.getElementAttribute(sectionElement, 'x-top'))); - sectionShapeForScope.setHeight(Number(layout.getElementAttribute(sectionElement, 'x-height'))); - - goog.array.forEach(sectionElement.childNodes, function(element) { - layout.drawBasicShapeFromElement(element, sectionShapeForScope); - }); - }); - - var shapeElement = shape.getElement(); - shape.forEachSectionShape(function(sectionShapeForScope, sectionNameForScope) { - if (thin.core.ShapeStructure.getEnabledOfSection( - sectionShapeForScope.getGroup().getElement(), shapeElement) == "false") { - - shape.setEnabledForSection(false, sectionNameForScope); - sectionShapeForScope.initHeightForLastActive(); - } - }); - shape.initIdentifier(); - - return shape; -}; - - /** * @param {Element=} opt_referenceElement */ @@ -912,27 +854,22 @@ thin.core.ListShape.prototype.updateProperties = function() { }; -/** - * @param {thin.core.PageNumberShape} pageNumber - */ -thin.core.ListShape.prototype.setPageNumberReference = function(pageNumber) { - goog.array.insert(this.pageNumberReferences_, pageNumber); -}; - - /** * @return {Array.} */ thin.core.ListShape.prototype.getPageNumberReferences = function() { - return goog.array.clone(this.pageNumberReferences_); -}; + var refereces = []; + var shapeId = this.getShapeId(); + var layout = this.getLayout(); + layout.forPageNumberShapesEach( + layout.getManager().getShapesManager().get(), function(shape, i) { + if (thin.isExactlyEqual(shapeId, shape.getTargetId())) { + goog.array.insert(refereces, shape); + } + }); -/** - * @param {thin.core.PageNumberShape} pageNumber - */ -thin.core.ListShape.prototype.removePageNumberReference = function(pageNumber) { - goog.array.remove(this.pageNumberReferences_, pageNumber); + return goog.array.clone(refereces); }; @@ -953,3 +890,67 @@ thin.core.ListShape.prototype.disposeInternal = function() { delete this.activeshapes_; delete this.sectionShapes_; }; + + +/** + * @return {string} + */ +thin.core.ListShape.prototype.getType = function() { + return 'list'; +}; + + +/** + * @return {Object} + */ +thin.core.ListShape.prototype.asJSON = function() { + var object = this.asJSON_(); + var header = this.getSectionShape( + thin.core.ListHelper.SectionName.HEADER); + + this.forEachSectionShape(function(section, name) { + goog.object.set(object, section.getType(), section.asJSON()); + }); + + goog.object.extend(object, { + 'content-height': this.getHeight() - header.getHeight(), + 'auto-page-break': this.isChangingPage() + }); + + if (goog.object.isEmpty(object['style'])) { + goog.object.remove(object, 'style'); + } + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.ListShape.prototype.update = function(attrs) { + var sectionName = thin.core.ListHelper.SectionName; + this.update_(attrs); + + goog.object.forEach(attrs, function(value, attr) { + switch (attr) { + case 'auto-page-break': + this.setChangingPage(value); + break; + case 'header': + this.getSectionShape(sectionName.HEADER).update(value); + break; + case 'detail': + this.getSectionShape(sectionName.DETAIL).update(value); + break; + case 'page-footer': + this.getSectionShape(sectionName.PAGEFOOTER).update(value); + break; + case 'footer': + this.getSectionShape(sectionName.FOOTER).update(value); + break; + default: + break; + } + }, this); +}; diff --git a/src/app/core/moduleshape.js b/src/app/core/moduleshape.js index a976ecb5..e74fe892 100644 --- a/src/app/core/moduleshape.js +++ b/src/app/core/moduleshape.js @@ -173,6 +173,21 @@ thin.core.ModuleShape.prototype.setStrokeWidth = function(width) { }; +/** + * @this {goog.graphics.Element} + * @param {string?} color + */ +thin.core.ModuleShape.prototype.setStrokeColor = function(color) { + var strokeNone = thin.core.ModuleShape.NONE; + + var strokeColor = /** @type {string} */(thin.getValIfNotDef(color, '')); + var stroke = new goog.graphics.Stroke(this.getStroke().getWidth(), + thin.isExactlyEqual(strokeColor, '') ? strokeNone : strokeColor); + + this.setStroke(stroke); +}; + + /** * @this {goog.graphics.Element} * @param {string} shapeId @@ -195,7 +210,7 @@ thin.core.ModuleShape.prototype.setShapeId_ = function(newShapeId, opt_shapeIdMa if (!opt_shapeIdManager && this.isAffiliationListShape()) { opt_shapeIdManager = this.getAffiliationSectionShape().getManager().getShapeIdManager(); } - + var shapeIdManager = opt_shapeIdManager || this.getLayout().getManager().getShapeIdManager(); var newPrefix = thin.core.ShapeIdManager.getShapeIdPrefix(newShapeId); this.deleteShapeId_(shapeIdManager); @@ -232,7 +247,7 @@ thin.core.ModuleShape.prototype.setShapeId = function(newShapeId, opt_shapeIdMan if (!opt_shapeIdManager && this.isAffiliationListShape()) { opt_shapeIdManager = this.getAffiliationSectionShape().getManager().getShapeIdManager(); } - + if (thin.isExactlyEqual(newShapeId, thin.core.ModuleShape.DEFAULT_SHAPEID)) { this.deleteShapeId_(opt_shapeIdManager); } else { @@ -397,7 +412,7 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { thin.core.ListShape.CLASSID + goog.object.get(listShapeClassIdTemp, 'FACE'); var isAffiliationListShape = this.isAffiliationListShape(); var affiliationSectionName = this.getAffiliationSectionName(); - + goog.events.listen(this, goog.events.EventType.MOUSEDOWN, function(e) { layout.getWorkspace().focusElement(e); var singleShapeByGlobal = activeShapeManager.getIfSingle(); @@ -408,7 +423,7 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { var captureProperties = multipleShapesHelper.getCloneProperties(); var captureActive = listHelper.isActive(); var captureCtrlKey = e.ctrlKey || e.metaKey; - + if (captureActive) { var activeShapeManagerByListShape = listHelper.getActiveShape(); var singleShapeByListShape = activeShapeManagerByListShape.getIfSingle(); @@ -418,10 +433,10 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { var isMultipleByListShape = activeShapeManagerByListShape.isMultiple(); var captureActiveSectionName = listHelper.getActiveSectionName(); } - + e.stopPropagation(); e.preventDefault(); - + layout.getWorkspace().normalVersioning(function(version) { version.setChanged(false); @@ -438,9 +453,9 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { listHelper.active(listShape); listShape.updateProperties(); thin.ui.setEnabledForFontUi(false); - + } else { - + if (captureCtrlKey) { this.dragger_.setEnabled(false); if (isAffiliationListShape) { @@ -493,14 +508,14 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { guide.setEnableAndTargetShape(this); layout.setOutlineForSingle(this); this.updateProperties(); - + } else { if (isSelfMouseDown) { activeShapeManager.clear(); layout.updatePropertiesForEmpty(); thin.ui.setEnabledForFontUi(false); } else { - + manager.setActiveShape(this); var shapes = activeShapeManager.get(); layout.setOutlineForMultiple(shapes); @@ -524,7 +539,7 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { listHelper.inactive(); } } - + } else { this.dragger_.setEnabled(true); if (isAffiliationListShape) { @@ -548,12 +563,12 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { } } }, scope); - + version.downHandler(function() { if (isListShapeFace) { activeShapeManager.set(oldShapesByGlobal); listHelper.inactive(); - + if (!captureActive) { if (isEmptyByGlobal) { layout.updatePropertiesForEmpty(); @@ -577,7 +592,7 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { } else { listHelper.active(singleShapeByGlobal); listHelper.setActiveSectionName(captureActiveSectionName); - + if (isEmptyByListShape) { singleShapeByGlobal.updateProperties(); thin.ui.setEnabledForFontUi(false); @@ -635,7 +650,7 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { if (isAffiliationListShape) { activeShapeManagerByListShape.set(oldShapesByListShape); listHelper.setActiveSectionName(captureActiveSectionName); - + if (isSelfMouseDown) { singleShapeByListShape.updateToolbarUI(); guide.setEnableAndTargetShape(singleShapeByListShape); @@ -672,7 +687,7 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { activeShapeManager.set(oldShapesByGlobal); listHelper.active(singleShapeByGlobal); listHelper.setActiveSectionName(captureActiveSectionName); - + if (isEmptyByListShape) { guide.setDisable(); singleShapeByGlobal.updateProperties(); @@ -751,7 +766,7 @@ thin.core.ModuleShape.prototype.setMouseDownHandlers = function() { activeShapeManager.set(oldShapesByGlobal); listHelper.active(singleShapeByGlobal); listHelper.setActiveSectionName(captureActiveSectionName); - + if (isEmptyByListShape) { singleShapeByGlobal.updateProperties(); thin.ui.setEnabledForFontUi(false); @@ -793,14 +808,14 @@ thin.core.ModuleShape.prototype.setupDragHandlers = function() { var body = goog.dom.getDocument().body; var dragLayer = helpers.getDragLayer(); var eventType = goog.fx.Dragger.EventType; - + var dragger = new thin.core.SvgDragger(this.getTargetOutline(), this); this.dragger_ = dragger; - + goog.events.listen(dragger, thin.core.AbstractDragger.EventType.BEFORESTART, function(e) { this.getTargetOutline().setBounds(this.getBounds()); }, false, this); - + goog.events.listen(dragger, eventType.START, function(e) { dragger.setAdsorptionX(helpers.getAdsorptionX()); dragger.setAdsorptionY(helpers.getAdsorptionY()); @@ -811,7 +826,7 @@ thin.core.ModuleShape.prototype.setupDragHandlers = function() { layout.setElementCursor(dragLayer.getElement(), cursorMove); dragLayer.setVisibled(true); }, false, this); - + goog.events.listen(dragger, eventType.BEFOREDRAG, function(e) { var outline = this.getTargetOutline(); if (!outline.isEnable()) { @@ -819,7 +834,7 @@ thin.core.ModuleShape.prototype.setupDragHandlers = function() { } }, false, this); goog.events.listen(dragger, eventType.END, function(e) { - + var cursorTypeDefault = thin.core.Cursor.Type.DEFAULT; var cursorDefault = new thin.core.Cursor(cursorTypeDefault); goog.style.setStyle(body, 'cursor', cursorTypeDefault); @@ -830,7 +845,7 @@ thin.core.ModuleShape.prototype.setupDragHandlers = function() { var outlineBounds = outline.getBounds(); var shapeBounds = this.getBounds(); var enabled = outline.isEnable(); - + layout.getWorkspace().normalVersioning(function(version) { if (goog.math.Rect.equals(shapeBounds, outlineBounds)) { version.setChanged(false); @@ -845,7 +860,7 @@ thin.core.ModuleShape.prototype.setupDragHandlers = function() { outline.disable(); } }, scope); - + version.downHandler(function() { if (enabled) { outline.setTargetShape(this); @@ -865,22 +880,22 @@ thin.core.ModuleShape.prototype.setupDragHandlers = function() { * @param {e} thin.ui.PropertyPane.PropertyEvent */ thin.core.ModuleShape.prototype.setLeftForPropertyUpdate = function(e) { - + var scope = this; var layout = this.getLayout(); var guide = layout.getHelpers().getGuideHelper(); var proppane = thin.ui.getComponent('proppane'); var captureLeft = this.getLeft(); var allowLeft = this.getAllowLeft(Number(e.target.getValue())); - + layout.getWorkspace().normalVersioning(function(version) { - + version.upHandler(function() { this.setLeft(allowLeft); guide.adjustToTargetShapeBounds(); proppane.getPropertyControl('left').setValue(allowLeft); }, scope); - + version.downHandler(function() { this.setLeft(captureLeft); guide.adjustToTargetShapeBounds(); @@ -901,15 +916,15 @@ thin.core.ModuleShape.prototype.setTopForPropertyUpdate = function(e) { var proppane = thin.ui.getComponent('proppane'); var captureTop = this.getTop(); var allowTop = this.getAllowTop(Number(e.target.getValue())); - + layout.getWorkspace().normalVersioning(function(version) { - + version.upHandler(function() { this.setTop(allowTop); guide.adjustToTargetShapeBounds(); proppane.getPropertyControl('top').setValue(allowTop); }, scope); - + version.downHandler(function() { this.setTop(captureTop); guide.adjustToTargetShapeBounds(); @@ -933,14 +948,14 @@ thin.core.ModuleShape.prototype.setWidthForPropertyUpdate = function(e) { var allowWidth = Number(e.target.getValue()); layout.getWorkspace().normalVersioning(function(version) { - + version.upHandler(function() { this.setWidth(allowWidth); this.setLeft(captureLeft); guide.adjustToTargetShapeBounds(); proppane.getPropertyControl('width').setValue(allowWidth); }, scope); - + version.downHandler(function() { this.setWidth(captureWidth); this.setLeft(captureLeft); @@ -963,16 +978,16 @@ thin.core.ModuleShape.prototype.setHeightForPropertyUpdate = function(e) { var captureHeight = this.getHeight(); var captureTop = this.getTop(); var allowHeight = Number(e.target.getValue()); - + layout.getWorkspace().normalVersioning(function(version) { - + version.upHandler(function() { this.setHeight(allowHeight); this.setTop(captureTop); guide.adjustToTargetShapeBounds(); proppane.getPropertyControl('height').setValue(allowHeight); }, scope); - + version.downHandler(function() { this.setHeight(captureHeight); this.setTop(captureTop); @@ -1003,12 +1018,12 @@ thin.core.ModuleShape.prototype.setFillForPropertyUpdate = function(e) { } this.getLayout().getWorkspace().normalVersioning(function(version) { - + version.upHandler(function() { this.setFill(fill); proppane.getPropertyControl('fill').setValue(fillColor); }, scope); - + version.downHandler(function() { this.setFill(captureFill); proppane.getPropertyControl('fill').setValue(captureFillColor); @@ -1030,7 +1045,7 @@ thin.core.ModuleShape.prototype.setStrokeForPropertyUpdate = function(e) { var captureStrokeColor = captureStroke.getColor(); // choose none color returned null. var strokeColor = /** @type {string} */(thin.getValIfNotDef(e.target.getValue(), proppaneBlank)); - var stroke = new goog.graphics.Stroke(captureStroke.getWidth(), + var stroke = new goog.graphics.Stroke(captureStroke.getWidth(), thin.isExactlyEqual(strokeColor, proppaneBlank) ? strokeNone : strokeColor); if (thin.isExactlyEqual(captureStrokeColor, strokeNone)) { @@ -1038,12 +1053,12 @@ thin.core.ModuleShape.prototype.setStrokeForPropertyUpdate = function(e) { } this.getLayout().getWorkspace().normalVersioning(function(version) { - + version.upHandler(function() { this.setStroke(stroke); proppane.getPropertyControl('stroke').setValue(strokeColor); }, scope); - + version.downHandler(function() { this.setStroke(captureStroke); proppane.getPropertyControl('stroke').setValue(captureStrokeColor); @@ -1063,17 +1078,17 @@ thin.core.ModuleShape.prototype.setStrokeWidthForPropertyUpdate = function(e) { var propStrokeWidth = thin.core.ModuleElement.DEFAULT_STROKEWIDTH_OF_PROPPANE; var strokeWidth = Number(e.target.getValue()); var captureStrokeWidth = this.getStroke().getWidth(); - var showStrokeWidth = thin.isExactlyEqual(strokeWidth, propStrokeWidth) ? + var showStrokeWidth = thin.isExactlyEqual(strokeWidth, propStrokeWidth) ? proppaneBlank : strokeWidth; - var showCaptureStrokeWidth = thin.isExactlyEqual(captureStrokeWidth, propStrokeWidth) ? + var showCaptureStrokeWidth = thin.isExactlyEqual(captureStrokeWidth, propStrokeWidth) ? proppaneBlank : captureStrokeWidth; - + this.getLayout().getWorkspace().normalVersioning(function(version) { version.upHandler(function() { this.setStrokeWidth(strokeWidth); proppane.getPropertyControl('stroke-width').setInternalValue(showStrokeWidth); }, scope); - + version.downHandler(function() { this.setStrokeWidth(captureStrokeWidth); proppane.getPropertyControl('stroke-width').setInternalValue(showCaptureStrokeWidth); @@ -1091,14 +1106,14 @@ thin.core.ModuleShape.prototype.setStrokeDashTypeForPropertyUpdate = function(e) var proppane = thin.ui.getComponent('proppane'); var strokeType = e.target.getValue(); var captureStrokeType = this.getStrokeDashType(); - + this.getLayout().getWorkspace().normalVersioning(function(version) { - + version.upHandler(function() { this.setStrokeDashFromType(strokeType); proppane.getPropertyControl('stroke-dash-type').setValue(strokeType); }, scope); - + version.downHandler(function() { this.setStrokeDashFromType(captureStrokeType); proppane.getPropertyControl('stroke-dash-type').setValue(captureStrokeType); @@ -1116,14 +1131,14 @@ thin.core.ModuleShape.prototype.setShapeIdForPropertyUpdate = function(e) { var proppane = thin.ui.getComponent('proppane'); var shapeId = e.target.getValue(); var captureShapeId = this.getShapeId(); - + this.getLayout().getWorkspace().normalVersioning(function(version) { version.upHandler(function() { this.setShapeId(shapeId); proppane.getPropertyControl('shape-id').setValue(shapeId); }, scope); - + version.downHandler(function() { this.setShapeId(captureShapeId); proppane.getPropertyControl('shape-id').setValue(captureShapeId); @@ -1141,13 +1156,13 @@ thin.core.ModuleShape.prototype.setDescPropertyUpdate = function(e) { var proppane = thin.ui.getComponent('proppane'); var desc = e.target.getValue(); var captureDesc = this.getDesc(); - + this.getLayout().getWorkspace().normalVersioning(function(version) { version.upHandler(function() { this.setDesc(desc); proppane.getPropertyControl('desc').setValue(desc); }, scope); - + version.downHandler(function() { this.setDesc(captureDesc); proppane.getPropertyControl('desc').setValue(captureDesc); @@ -1165,14 +1180,14 @@ thin.core.ModuleShape.prototype.setDisplayForPropertyUpdate = function(e) { var proppane = thin.ui.getComponent('proppane'); var display = e.target.isChecked(); var captureDisplay = this.getDisplay(); - + this.getLayout().getWorkspace().normalVersioning(function(version) { - + version.upHandler(function() { this.setDisplay(display); proppane.getPropertyControl('display').setChecked(display); }, scope); - + version.downHandler(function() { this.setDisplay(captureDisplay); proppane.getPropertyControl('display').setChecked(captureDisplay); @@ -1195,7 +1210,7 @@ thin.core.ModuleShape.prototype.setSectionEnabled = function( var listShape = listHelper.getTarget(); var captureBounds = listShape.getBounds(); var captureActiveSectionName = listHelper.getActiveSectionName(); - + layout.getWorkspace().normalVersioning(function(version) { version.upHandler(function() { listShape.setEnabledForSection(enabled, sectionName); @@ -1203,7 +1218,7 @@ thin.core.ModuleShape.prototype.setSectionEnabled = function( listHelper.initActiveSectionName(); listShape.updateProperties(); }, scope); - + version.downHandler(function() { listShape.setBounds(captureBounds); listShape.setEnabledForSection(!enabled, sectionName); @@ -1223,3 +1238,116 @@ thin.core.ModuleShape.prototype.setSectionEnabled = function( thin.core.ModuleShape.prototype.isIntersects = function(judgement_box) { return goog.math.Box.intersects(judgement_box, this.getBoxSize()); }; + + +/** + * @this {goog.graphics.Element} + * @param {string?} color + */ +thin.core.ModuleShape.prototype.setFillColor = function(color) { + var fillNone = thin.core.ModuleShape.NONE; + + var fillColor = /** @type {string} */(thin.getValIfNotDef(color, '')); + var fill = new goog.graphics.SolidFill( + thin.isExactlyEqual(fillColor, '') ? fillNone : fillColor); + + this.setFill(fill); +}; + + +/** + * @this {goog.graphics.Element} + * @return {string} + */ +thin.core.ModuleShape.prototype.getType = function() { + return this.getElement().tagName; +}; + + +/** + * @private + * @this {goog.graphics.Element} + * @return {Object} + */ +thin.core.ModuleShape.prototype.asJSON_ = function() { + var style = {}; + + var stroke = this.getStroke(); + if (stroke) { + goog.object.extend(style, { + 'border-color': stroke.getColor(), + 'border-width': this.getStrokeWidth(), + 'border-style': this.getStrokeDashType() + }); + } + var fill = this.getFill(); + if (fill) { + goog.object.set(style, 'fill-color', fill.getColor()); + } + + return { + 'id': this.getShapeId(), + 'type': this.getType(), + 'display': this.getDisplay(), + 'description': this.getDesc(), + // Absolute positions(without translate) + 'x': this.left_, + 'y': this.top_, + 'width': this.width_, + 'height': this.height_, + 'style': style + }; +}; + + +/** + * @private + * @this {goog.graphics.Element} + * @param {Object} + */ +thin.core.ModuleShape.prototype.update_ = function(attrs) { + goog.object.forEach(attrs, function(value, attr) { + switch (attr) { + case 'id': + this.setShapeId(value); + break; + case 'description': + this.setDesc(value); + break; + case 'x': + this.setLeft(value + this.getParentTransLateX()); + break; + case 'y': + this.setTop(value + this.getParentTransLateY()); + break; + case 'width': + this.setWidth(value); + break; + case 'height': + this.setHeight(value); + break; + case 'display': + this.setDisplay(value); + break; + case 'border-color': + this.setStrokeColor(value); + break; + case 'border-width': + this.setStrokeWidth(value); + break; + case 'border-style': + this.setStrokeDashFromType(value); + break; + case 'fill-color': + this.setFillColor(value); + break; + case 'style': + this.update(value); + break; + default: + // Do Nothing + break; + } + + }, this); +}; diff --git a/src/app/core/pagenumbershape.js b/src/app/core/pagenumbershape.js index e6f8285e..13277c65 100644 --- a/src/app/core/pagenumbershape.js +++ b/src/app/core/pagenumbershape.js @@ -112,13 +112,6 @@ thin.core.PageNumberShape.prototype.type_; thin.core.PageNumberShape.prototype.base_; -/** - * @type {goog.graphics.Element} - * @private - */ -thin.core.PageNumberShape.prototype.targetShape_; - - /** * @return {string} */ @@ -143,41 +136,6 @@ thin.core.PageNumberShape.prototype.updateToolbarUI = function() { }; -/** - * @param {Element} element - * @param {thin.core.Layout} layout - * @param {thin.core.ShapeIdManager=} opt_shapeIdManager - * @return {thin.core.PageNumberShape} - */ -thin.core.PageNumberShape.createFromElement = function(element, layout, opt_shapeIdManager) { - element.removeAttribute('clip-path'); - var shape = new thin.core.PageNumberShape(element, layout); - - shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); - shape.setFill(new goog.graphics.SolidFill(layout.getElementAttribute(element, 'fill'))); - shape.setFontSize(Number(layout.getElementAttribute(element, 'font-size'))); - shape.setFontFamily(layout.getElementAttribute(element, 'font-family')); - - var decoration = layout.getElementAttribute(element, 'text-decoration'); - var kerning = layout.getElementAttribute(element, 'kerning'); - - if (thin.isExactlyEqual(kerning, thin.core.TextStyle.DEFAULT_ELEMENT_KERNING)) { - kerning = thin.core.TextStyle.DEFAULT_KERNING; - } - shape.setKerning(/** @type {string} */ (kerning)); - shape.setFontUnderline(/underline/.test(decoration)); - shape.setFontLinethrough(/line-through/.test(decoration)); - shape.setFontItalic(layout.getElementAttribute(element, 'font-style') == 'italic'); - shape.setFontBold(layout.getElementAttribute(element, 'font-weight') == 'bold'); - shape.setTextAnchor(layout.getElementAttribute(element, 'text-anchor')); - shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); - shape.setDesc(layout.getElementAttribute(element, 'x-desc')); - shape.initIdentifier(); - - return shape; -}; - - /** * @param {Element=} opt_element * @return {thin.core.Box} @@ -328,9 +286,6 @@ thin.core.PageNumberShape.prototype.setTargetId = function(targetId) { layout.setElementAttributes(this.getElement(), { 'x-target': targetId }); - if (!goog.string.isEmpty(targetId)) { - this.setTargetShape_(layout.getShapeForShapeId(targetId)); - } }; @@ -343,30 +298,10 @@ thin.core.PageNumberShape.prototype.getTargetId = function() { }; -/** - * @param {goog.graphics.Element} targetShape - * @private - */ -thin.core.PageNumberShape.prototype.setTargetShape_ = function(targetShape) { - this.targetShape_ = targetShape; - this.targetShape_.setPageNumberReference(this); -}; - - -/** - * @return {goog.graphics.Element} - */ -thin.core.PageNumberShape.prototype.getTargetShape = function() { - return this.targetShape_; -}; - - -thin.core.PageNumberShape.prototype.removeTargetShape = function() { - if (this.targetShape_) { - this.targetShape_.removePageNumberReference(this); +thin.core.PageNumberShape.prototype.removeTargetShapeId = function() { + if (!goog.string.isEmpty(this.getTargetId())) { this.setTargetId(''); } - delete this.targetShape_; }; @@ -895,3 +830,63 @@ thin.core.PageNumberShape.Label_.prototype.disposeInternal = function() { goog.base(this, 'disposeInternal'); delete this.parent_; }; + + +/** + * @return {string} + */ +thin.core.PageNumberShape.prototype.getType = function() { + return 'page-number'; +}; + + +/** + * @return {Object} + */ +thin.core.PageNumberShape.prototype.asJSON = function() { + var object = goog.base(this, 'asJSON'); + + goog.object.extend(object, { + 'format': this.getFormat(), + 'target': this.getTargetId() + }); + + var style = goog.object.clone(object['style']); + goog.object.remove(style, 'word-wrap'); + goog.object.remove(style, 'line-height'); + goog.object.remove(style, 'line-height-ratio'); + goog.object.remove(style, 'vertical-align'); + goog.object.set(style, 'overflow', this.getOverflowType()); + + goog.object.set(object, 'style', style); + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.PageNumberShape.prototype.update = function(attrs) { + goog.base(this, 'update', attrs); + + this.label_.repositionX(); + this.label_.repositionY(); + + goog.object.forEach(attrs, function(value, attr) { + switch (attr) { + case 'format': + this.setFormat(value); + break; + case 'target': + this.setTargetId(value); + break; + case 'overflow': + this.setOverflowType(value); + break; + default: + // Do Nothing + break; + } + }, this); +}; diff --git a/src/app/core/rectshape.js b/src/app/core/rectshape.js index c411d1d8..7617040c 100644 --- a/src/app/core/rectshape.js +++ b/src/app/core/rectshape.js @@ -64,29 +64,6 @@ thin.core.RectShape.prototype.getClassId = function() { }; -/** - * @param {Element} element - * @param {thin.core.Layout} layout - * @param {thin.core.ShapeIdManager=} opt_shapeIdManager - * @return {thin.core.RectShape} - */ -thin.core.RectShape.createFromElement = function(element, layout, opt_shapeIdManager) { - var shape = new thin.core.RectShape(element, layout, - new goog.graphics.Stroke( - Number(layout.getElementAttribute(element, 'stroke-width')), - layout.getElementAttribute(element, 'stroke')), - new goog.graphics.SolidFill(layout.getElementAttribute(element, 'fill'))); - - shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); - shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); - shape.setDesc(layout.getElementAttribute(element, 'x-desc')); - shape.setStrokeDashFromType(layout.getElementAttribute(element, 'x-stroke-type')); - shape.setRounded(Number(layout.getElementAttribute(element, 'rx'))); - shape.initIdentifier(); - return shape; -}; - - thin.core.RectShape.prototype.setDefaultOutline = function() { this.setTargetOutline(this.getLayout().getHelpers().getRectOutline()); }; @@ -129,10 +106,10 @@ thin.core.RectShape.prototype.getCloneCreator = function() { * @return {thin.core.RectShape} */ return function(layout, opt_isAdaptDeltaForList, opt_renderTo, opt_basisCoordinate) { - + var shape = layout.createRectShape(); layout.appendChild(shape, opt_renderTo); - + var pasteCoordinate = layout.calculatePasteCoordinate(isAffiliationListShape, deltaCoordinateForList, deltaCoordinateForGuide, sourceCoordinate, opt_isAdaptDeltaForList, opt_renderTo, opt_basisCoordinate); @@ -154,81 +131,81 @@ thin.core.RectShape.prototype.getCloneCreator = function() { * @private */ thin.core.RectShape.prototype.createPropertyComponent_ = function() { - + var scope = this; var layout = this.getLayout(); var propEventType = thin.ui.PropertyPane.Property.EventType; var proppane = thin.ui.getComponent('proppane'); - + var baseGroup = proppane.addGroup(thin.t('property_group_basis')); - - + + var leftInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_left_position')); var leftInput = leftInputProperty.getValueControl(); leftInput.getNumberValidator().setAllowDecimal(true, 1); - + leftInputProperty.addEventListener(propEventType.CHANGE, this.setLeftForPropertyUpdate, false, this); - + proppane.addProperty(leftInputProperty, baseGroup, 'left'); var topInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_top_position')); var topInput = topInputProperty.getValueControl(); topInput.getNumberValidator().setAllowDecimal(true, 1); - + topInputProperty.addEventListener(propEventType.CHANGE, this.setTopForPropertyUpdate, false, this); - + proppane.addProperty(topInputProperty, baseGroup, 'top'); - - + + var widthInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_width')); var widthInput = widthInputProperty.getValueControl(); widthInput.getNumberValidator().setAllowDecimal(true, 1); - + widthInputProperty.addEventListener(propEventType.CHANGE, this.setWidthForPropertyUpdate, false, this); - + proppane.addProperty(widthInputProperty, baseGroup, 'width'); - - + + var heightInputProperty = new thin.ui.PropertyPane.NumberInputProperty(thin.t('field_height')); var heightInput = heightInputProperty.getValueControl(); heightInput.getNumberValidator().setAllowDecimal(true, 1); - + heightInputProperty.addEventListener(propEventType.CHANGE, this.setHeightForPropertyUpdate, false, this); - + proppane.addProperty(heightInputProperty, baseGroup, 'height'); - - + + var displayCheckProperty = new thin.ui.PropertyPane.CheckboxProperty(thin.t('field_display')); displayCheckProperty.addEventListener(propEventType.CHANGE, this.setDisplayForPropertyUpdate, false, this); - + proppane.addProperty(displayCheckProperty, baseGroup, 'display'); - + var shapeGroup = proppane.addGroup(thin.t('property_group_shape')); - - + + var fillInputProperty = new thin.ui.PropertyPane.ColorProperty(thin.t('field_fill_color')); fillInputProperty.getValueControl().getInput().setLabel('none'); fillInputProperty.addEventListener(propEventType.CHANGE, this.setFillForPropertyUpdate, false, this); - + proppane.addProperty(fillInputProperty , shapeGroup, 'fill'); - - + + var strokeInputProperty = new thin.ui.PropertyPane.ColorProperty(thin.t('field_stroke_color')); strokeInputProperty.getValueControl().getInput().setLabel('none'); strokeInputProperty.addEventListener(propEventType.CHANGE, this.setStrokeForPropertyUpdate, false, this); - + proppane.addProperty(strokeInputProperty , shapeGroup, 'stroke'); - - + + var strokeWidthCombProperty = new thin.ui.PropertyPane.ComboBoxProperty(thin.t('field_stroke_width')); var strokeWidthComb = strokeWidthCombProperty.getValueControl(); var strokeWidthInput = strokeWidthComb.getInput(); @@ -247,10 +224,10 @@ thin.core.RectShape.prototype.createPropertyComponent_ = function() { }); strokeWidthCombProperty.addEventListener(propEventType.CHANGE, this.setStrokeWidthForPropertyUpdate, false, this); - + proppane.addProperty(strokeWidthCombProperty , shapeGroup, 'stroke-width'); - - + + var strokeType = thin.core.ModuleElement.StrokeType; var strokeDashSelectProperty = new thin.ui.PropertyPane.SelectProperty(thin.t('field_stroke_type')); var strokeDashSelect = strokeDashSelectProperty.getValueControl(); @@ -262,10 +239,10 @@ thin.core.RectShape.prototype.createPropertyComponent_ = function() { new thin.ui.Option(thin.core.ModuleElement.getStrokeName(strokeType.DASHED), strokeType.DASHED)); strokeDashSelect.addItem( new thin.ui.Option(thin.core.ModuleElement.getStrokeName(strokeType.DOTTED), strokeType.DOTTED)); - + strokeDashSelectProperty.addEventListener(propEventType.CHANGE, this.setStrokeDashTypeForPropertyUpdate, false, this); - + proppane.addProperty(strokeDashSelectProperty , shapeGroup, 'stroke-dash-type'); @@ -275,36 +252,36 @@ thin.core.RectShape.prototype.createPropertyComponent_ = function() { function(e) { var radius = Number(e.target.getValue()); var captureRadius = scope.getRounded(); - + layout.getWorkspace().normalVersioning(function(version) { - + version.upHandler(function() { this.setRounded(radius); proppane.getPropertyControl('radius').setValue(radius); }, scope); - + version.downHandler(function() { this.setRounded(captureRadius); proppane.getPropertyControl('radius').setValue(captureRadius); }, scope); }); }, false, this); - + proppane.addProperty(radiusInputProperty, shapeGroup, 'radius'); var cooperationGroup = proppane.addGroup(thin.t('property_group_association')); - + var idInputProperty = new thin.ui.PropertyPane.IdInputProperty(this, 'ID'); idInputProperty.addEventListener(propEventType.CHANGE, this.setShapeIdForPropertyUpdate, false, this); - + proppane.addProperty(idInputProperty, cooperationGroup, 'shape-id'); - + var descProperty = new thin.ui.PropertyPane.InputProperty(thin.t('field_description')); descProperty.addEventListener(propEventType.CHANGE, this.setDescPropertyUpdate, false, this); - + proppane.addProperty(descProperty, cooperationGroup, 'desc'); }; @@ -338,17 +315,17 @@ thin.core.RectShape.prototype.updateProperties = function() { proppane.setTarget(this); this.createPropertyComponent_(); } - + var properties = this.getProperties(); var proppaneBlank = thin.core.ModuleShape.PROPPANE_SHOW_BLANK; var noneColor = thin.core.ModuleShape.NONE; - + proppane.getPropertyControl('left').setValue(properties['left']); proppane.getPropertyControl('top').setValue(properties['top']); proppane.getPropertyControl('width').setValue(properties['width']); proppane.getPropertyControl('height').setValue(properties['height']); proppane.getPropertyControl('display').setChecked(properties['display']); - + var fill = properties['fill']; if (thin.isExactlyEqual(fill, noneColor)) { fill = proppaneBlank @@ -364,10 +341,10 @@ thin.core.RectShape.prototype.updateProperties = function() { strokeWidth = proppaneBlank; } proppane.getPropertyControl('stroke-width').setInternalValue(strokeWidth); - + proppane.getPropertyControl('stroke-dash-type').setValue(properties['stroke-dash-type']); proppane.getPropertyControl('radius').setValue(properties['radius']); - + proppane.getPropertyControl('shape-id').setValue(properties['shape-id']); proppane.getPropertyControl('desc').setValue(properties['desc']); }; @@ -386,3 +363,29 @@ thin.core.RectShape.prototype.disposeInternal = function() { thin.core.RectShape.superClass_.disposeInternal.call(this); this.disposeInternalForShape(); }; + + +/** + * @return {Object} + */ +thin.core.RectShape.prototype.asJSON = function() { + var object = this.asJSON_(); + + goog.object.extend(object, { + 'border-radius': this.getRounded() + }); + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.RectShape.prototype.update = function(attrs) { + this.update_(attrs); + + if (goog.object.containsKey(attrs, 'border-radius')) { + this.setRounded(attrs['border-radius']); + } +}; diff --git a/src/app/core/shapestructure.js b/src/app/core/shapestructure.js index 7a1ecd07..93e7a647 100644 --- a/src/app/core/shapestructure.js +++ b/src/app/core/shapestructure.js @@ -15,489 +15,386 @@ goog.provide('thin.core.ShapeStructure'); -goog.require('goog.dom'); -goog.require('goog.array'); -goog.require('goog.object'); -goog.require('goog.json'); -goog.require('goog.json.Serializer'); goog.require('goog.math.Coordinate'); -goog.require('thin.core.TextStyle'); -goog.require('thin.core.TextStyle.HorizonAlignType'); -goog.require('thin.core.TextStyle.VerticalAlignType'); /** - * @type {string} - * @private + * @deprecated + * @param {Element|Node} transformElement + * @return {goog.math.Coordinate} */ -thin.core.ShapeStructure.BLANK_ = ''; +thin.core.ShapeStructure.getTransLateCoordinate = function(transformElement) { + var affineTransform = transformElement.getAttribute('transform'); + var x = 0; + var y = 0; + + if(goog.isDefAndNotNull(affineTransform)) { + var splitTransLate = affineTransform.match(/[\-\d\,\.]+/)[0].split(','); + if(splitTransLate.length == 1) { + x = y = Number(splitTransLate[0]); + } else { + x = Number(splitTransLate[0]); + y = Number(splitTransLate[1]); + } + } + return new goog.math.Coordinate(x, y); +}; /** - * @param {Element} shape + * @deprecated + * @param {string} sectionClassId * @return {string} */ -thin.core.ShapeStructure.serialize = function(shape) { - var shapeClassId = shape.getAttribute('class'); - var json = { - 'type': shapeClassId, - 'id': shape.getAttribute('x-id'), - 'display': shape.getAttribute('x-display') || 'true', - 'desc': shape.getAttribute('x-desc') - }; - - switch(shapeClassId) { - case thin.core.TblockShape.CLASSID: - json = thin.core.ShapeStructure.serializeForTblock_(shape, json); - break; - case thin.core.ListShape.CLASSID: - json = thin.core.ShapeStructure.serializeForList_(shape, json); - break; - case thin.core.TextShape.CLASSID: - json = thin.core.ShapeStructure.serializeForText_(shape, json); - break; - case thin.core.ImageblockShape.CLASSID: - json = thin.core.ShapeStructure.serializeForImageblock_(shape, json); - break; - case thin.core.PageNumberShape.CLASSID: - json = thin.core.ShapeStructure.serializeForPageNumber_(shape, json); - break; - default: - var attrs = {}; - thin.core.ShapeStructure.forEachShapeAttribute_(shape, - function(key, value) { - attrs[key] = value; - }); - - json['svg'] = { - 'tag': shape.tagName, - 'attrs': attrs - }; - break; - } - - return goog.json.serialize(json); +thin.core.ShapeStructure.getSectionName = function(sectionClassId) { + return sectionClassId.replace(/s\-list\-/, ''); }; /** - * @param {Element} shape - * @param {Object} json - * @return {Object} - * @private + * @deprecated + * @param {Element} element + * @param {Element} parentElement + * @return {string} */ -thin.core.ShapeStructure.serializeForText_ = function(shape, json) { - var attrs = {}; - var blank = thin.core.ShapeStructure.BLANK_; - - if (shape.hasAttribute('x-line-height')) { - json['line-height'] = Number(shape.getAttribute('x-line-height')); - json['line-height-ratio'] = Number(shape.getAttribute('x-line-height-ratio')); - } else { - json['line-height'] = blank; - json['line-height-ratio'] = blank; - } - - json['valign'] = shape.getAttribute('x-valign') || blank; - json['box'] = { - 'x': Number(shape.getAttribute('x-left')), - 'y': Number(shape.getAttribute('x-top')), - 'width': Number(shape.getAttribute('x-width')), - 'height': Number(shape.getAttribute('x-height')) - }; - - thin.core.ShapeStructure.forEachShapeAttribute_(shape, - function(key, value) { - if (key == 'space') { - key = 'xml:space' - } - attrs[key] = value; - }); - - var textLineShapes = []; - var textLineContainer = []; - - goog.array.forEach(shape.childNodes, function(textlineElement) { - if (textlineElement.tagName == 'text') { - goog.array.insertAt(textLineShapes, - textlineElement, textLineShapes.length); - goog.array.insertAt(textLineContainer, - textlineElement.firstChild.data, textLineContainer.length); - } - }); - - json['text'] = textLineContainer; - json['svg'] = { - 'tag': shape.tagName, - 'attrs': attrs, - 'content': thin.core.ShapeStructure.serializeToContent(textLineShapes) - }; - return json; +thin.core.ShapeStructure.getEnabledOfSection = function(element, parentElement) { + var sectionClassId = element.getAttribute('class'); + var sectionName = thin.core.ShapeStructure.getSectionName(sectionClassId); + return parentElement.getAttribute('x-' + sectionName + '-enabled') || 'true'; }; /** - * @param {Element} shape - * @param {Object} json - * @return {Object} - * @private + * @deprecated + * @param {Element} element + * @param {thin.core.Layout} layout + * @param {thin.core.ShapeIdManager=} opt_shapeIdManager + * @return {thin.core.EllipseShape} */ -thin.core.ShapeStructure.serializeForImageblock_ = function(shape, json) { - var left = Number(shape.getAttribute('x-left')); - var top = Number(shape.getAttribute('x-top')); - var width = Number(shape.getAttribute('x-width')); - var height = Number(shape.getAttribute('x-height')); - - json['box'] = { - 'x': left, - 'y': top, - 'width': width, - 'height': height - }; - - json['position-x'] = shape.getAttribute('x-position-x') - || thin.core.ImageblockShape.PositionX.DEFAULT; - json['position-y'] = shape.getAttribute('x-position-y') - || thin.core.ImageblockShape.PositionY.DEFAULT; - - json['svg'] = { - 'tag': 'image', - 'attrs': { - 'x': left, - 'y': top, - 'width': width, - 'height': height - } - }; - return json; +thin.core.ShapeStructure.createEllipseShapeFromElement = function(element, layout, opt_shapeIdManager) { + var shape = new thin.core.EllipseShape(element, layout, + new goog.graphics.Stroke( + Number(layout.getElementAttribute(element, 'stroke-width')), + layout.getElementAttribute(element, 'stroke')), + new goog.graphics.SolidFill(layout.getElementAttribute(element, 'fill'))); + shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); + shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); + shape.setDesc(layout.getElementAttribute(element, 'x-desc')); + shape.setStrokeDashFromType(layout.getElementAttribute(element, 'x-stroke-type')); + shape.initIdentifier(); + return shape; }; - /** - * @param {Element} shape - * @param {Object} json - * @return {Object} - * @private + * @deprecated + * @param {Element} element + * @param {thin.core.Layout} layout + * @param {thin.core.ShapeIdManager=} opt_shapeIdManager + * @return {thin.core.ImageblockShape} */ -thin.core.ShapeStructure.serializeForTblock_ = function(shape, json) { - var blank = thin.core.ShapeStructure.BLANK_; - var mutliple = shape.getAttribute('x-multiple') || 'false'; - var isMultiMode = mutliple == 'true'; - var anchor = shape.getAttribute('text-anchor'); - var tag = isMultiMode ? 'textArea' : 'text'; - var formatType = isMultiMode ? blank : shape.getAttribute('x-format-type') || blank; - - json['multiple'] = mutliple; - json['valign'] = shape.getAttribute('x-valign') || blank; - - if (shape.hasAttribute('x-line-height')) { - json['line-height'] = Number(shape.getAttribute('x-line-height')); - json['line-height-ratio'] = Number(shape.getAttribute('x-line-height-ratio')); - } else { - json['line-height'] = blank; - json['line-height-ratio'] = blank; - } +thin.core.ShapeStructure.createImageblockShapeFromElement = function(element, layout, opt_shapeIdManager) { + var shape = new thin.core.ImageblockShape(element, layout); - var format = { - 'base': shape.getAttribute('x-format-base') || blank, - 'type': formatType - }; - if (formatType != blank) { - switch (formatType) { - case 'datetime': - goog.object.set(format, formatType, { - 'format': shape.getAttribute('x-format-datetime-format') || blank - }); - break; - case 'number': - goog.object.set(format, formatType, { - 'delimiter': shape.getAttribute('x-format-number-delimiter') || blank, - 'precision': Number(shape.getAttribute('x-format-number-precision')) || 0 - }); - break; - case 'padding': - goog.object.set(format, formatType, { - 'length': Number(shape.getAttribute('x-format-padding-length')) || 0, - 'char': shape.getAttribute('x-format-padding-char') || '0', - 'direction': shape.getAttribute('x-format-padding-direction') || 'L' - }); - break; - } - } - - var attrs = {}; - - var left = Number(shape.getAttribute('x-left')); - var top = Number(shape.getAttribute('x-top')); - var width = Number(shape.getAttribute('x-width')); - var height = Number(shape.getAttribute('x-height')); - - var family = shape.getAttribute('font-family'); - var fontSize = Number(shape.getAttribute('font-size')); - var isBold = shape.getAttribute('font-weight') == 'bold'; - - json['box'] = { - 'x': left, - 'y': top, - 'width': width, - 'height': height - }; - - if (tag == 'text') { - switch(anchor) { - case thin.core.TextStyle.HorizonAlignType.MIDDLE: - left = thin.numberWithPrecision(left + (width / 2)); - break; - case thin.core.TextStyle.HorizonAlignType.END: - left = thin.numberWithPrecision(left + width); - break; - } - - var ascent = thin.Font.getAscent(family, fontSize, isBold); - - attrs['x'] = left; - attrs['y'] = thin.numberWithPrecision(top + ascent); - } else { - attrs['x'] = left; - attrs['y'] = top; - attrs['width'] = width; - attrs['height'] = height; - } - attrs['xml:space'] = 'preserve'; + shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); + shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); + shape.setDesc(layout.getElementAttribute(element, 'x-desc')); + shape.setPositionX(layout.getElementAttribute(element, 'x-position-x')); + shape.setPositionY(layout.getElementAttribute(element, 'x-position-y')); + shape.initIdentifier(); - thin.core.ShapeStructure.forEachShapeAttribute_(shape, - function(key, value) { - attrs[key] = value; - }); - - json['format'] = format; - json['value'] = shape.getAttribute('x-value') || blank; - json['ref-id'] = shape.getAttribute('x-ref-id') || blank; - json['overflow'] = shape.getAttribute('x-overflow') || blank; - json['word-wrap'] = shape.getAttribute('x-word-wrap') || thin.core.TextStyle.getDefaultWordWrap(); - json['svg'] = { - 'tag': tag, - 'attrs': attrs - }; - return json; + return shape; }; /** - * @param {Element} shape - * @param {Object} json - * @return {Object} - * @private + * @deprecated + * @param {Element} element + * @return {thin.core.ImageFile} */ -thin.core.ShapeStructure.serializeForPageNumber_ = function(shape, json) { - var left = Number(shape.getAttribute('x-left')); - var top = Number(shape.getAttribute('x-top')); - var width = Number(shape.getAttribute('x-width')); - - var attrs = {}; - - var family = shape.getAttribute('font-family'); - var fontSize = Number(shape.getAttribute('font-size')); - var isBold = shape.getAttribute('font-weight') == 'bold'; - - json['box'] = { - 'x': left, - 'y': top, - 'width': width, - 'height': Number(shape.getAttribute('x-height')) - }; - - switch(shape.getAttribute('text-anchor')) { - case thin.core.TextStyle.HorizonAlignType.MIDDLE: - attrs['x'] = thin.numberWithPrecision(left + (width / 2)); - break; - case thin.core.TextStyle.HorizonAlignType.END: - attrs['x'] = thin.numberWithPrecision(left + width); - break; - default: - attrs['x'] = left; - break; - } - - attrs['y'] = thin.numberWithPrecision(top + - thin.Font.getAscent(family, fontSize, isBold)); +thin.core.ShapeStructure.createImageFileFromElement = function(element) { + var entry = thin.File.createDummyEntry('DummyImageFile'); + var coreFile = new thin.File(entry, '', element['href']['baseVal']); - thin.core.ShapeStructure.forEachShapeAttribute_(shape, - function(key, value) { - attrs[key] = value; - }); - - json['target'] = shape.getAttribute('x-target') || ''; - json['format'] = shape.getAttribute('x-format') || ''; - json['overflow'] = shape.getAttribute('x-overflow') || ''; - json['svg'] = { - 'tag': 'text', - 'attrs': attrs - }; - return json; + return new thin.core.ImageFile(coreFile); }; /** - * @param {string} sectionClassId - * @return {string} + * @deprecated + * @param {Element} element + * @param {thin.core.Layout} layout + * @param {thin.core.ShapeIdManager=} opt_shapeIdManager + * @return {thin.core.ImageShape} */ -thin.core.ShapeStructure.getSectionName = function(sectionClassId) { - return sectionClassId.replace(/s\-list\-/, ''); +thin.core.ShapeStructure.createImageShapeFromElement = function(element, layout, opt_shapeIdManager) { + var shape = new thin.core.ImageShape(element, layout); + shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); + shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); + shape.setDesc(layout.getElementAttribute(element, 'x-desc')); + shape.setFile(thin.core.ShapeStructure.createImageFileFromElement(element)); + shape.initIdentifier(); + + return shape; }; /** + * @deprecated * @param {Element} element - * @param {Element} parentElement - * @return {string} + * @param {thin.core.Layout} layout + * @param {thin.core.ShapeIdManager=} opt_shapeIdManager + * @return {thin.core.LineShape} */ -thin.core.ShapeStructure.getEnabledOfSection = function(element, parentElement) { - var sectionClassId = element.getAttribute('class'); - var sectionName = thin.core.ShapeStructure.getSectionName(sectionClassId); - return parentElement.getAttribute('x-' + sectionName + '-enabled') || 'true'; +thin.core.ShapeStructure.createLineShapeFromElement = function(element, layout, opt_shapeIdManager) { + + var shape = new thin.core.LineShape(element, layout, + new goog.graphics.Stroke( + Number(layout.getElementAttribute(element, 'stroke-width')), + layout.getElementAttribute(element, 'stroke'))); + + shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); + shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); + shape.setDesc(layout.getElementAttribute(element, 'x-desc')); + shape.setStrokeDashFromType(layout.getElementAttribute(element, 'x-stroke-type')); + shape.initIdentifier(); + return shape; }; /** - * @param {Element} shape - * @param {Object} json - * @return {Object} - * @private + * @deprecated + * @param {Element} groupElement + * @param {thin.core.Layout} layout + * @return {thin.core.ListShape} */ -thin.core.ShapeStructure.serializeForList_ = function(shape, json) { - var listShapeClassId = thin.core.ListShape.ClassIds; - var classIdPrefix = thin.core.ListShape.CLASSID; - var headerClassId = classIdPrefix + listShapeClassId['HEADER']; - var detailClassId = classIdPrefix + listShapeClassId['DETAIL']; - var listGroupChildNodes = shape.childNodes; - var detailTop = Number(thin.core.getElementByClassNameForChildNodes( - detailClassId, listGroupChildNodes).getAttribute('x-top')); - - var enabledForSection; - var sectionName; - var childGroupClassId; - var isDetailSection; - - goog.array.forEachRight(listGroupChildNodes, function(childShape) { - childGroupClassId = childShape.getAttribute('class'); - if (childShape.tagName == 'g') { - enabledForSection = thin.core.ShapeStructure.getEnabledOfSection(childShape, shape); - sectionName = thin.core.ShapeStructure.getSectionName(childGroupClassId); - isDetailSection = childGroupClassId == detailClassId; - json[sectionName] = thin.core.ShapeStructure.serializeForListForSection_( - childShape, enabledForSection == 'true', - (childGroupClassId == headerClassId || - isDetailSection) ? null : detailTop); - if (!isDetailSection) { - json[sectionName + '-enabled'] = enabledForSection; - } +thin.core.ShapeStructure.createListShapeFromElement = function(groupElement, layout) { + var shape = new thin.core.ListShape(layout, + /** @type {Element} */(groupElement.cloneNode(false)), groupElement); + var classId = thin.core.ListShape.ClassIds; + + shape.setIdShape(layout.getElementAttribute(groupElement, 'x-id'), + thin.core.getElementByClassNameForChildNodes(thin.core.ListShape.CLASSID + classId['ID'], + shape.getElement().childNodes)); + shape.setBounds(new goog.math.Rect( + Number(layout.getElementAttribute(groupElement, 'x')), + Number(layout.getElementAttribute(groupElement, 'y')), + Number(layout.getElementAttribute(groupElement, 'width')), + Number(layout.getElementAttribute(groupElement, 'height')))); + + shape.setDisplay(layout.getElementAttribute(groupElement, 'x-display') == 'true'); + shape.setDesc(layout.getElementAttribute(groupElement, 'x-desc')); + if (layout.getElementAttribute(groupElement, 'x-changing-page') == 'true') { + shape.setChangingPage(true); + layout.getHelpers().getListHelper().setChangingPageSetShape(shape); + } else { + shape.setChangingPage(false); + } + + shape.forEachSectionShape(function(sectionShapeForScope, sectionNameForScope) { + var sectionGroup = sectionShapeForScope.getGroup(); + var sectionElement = thin.core.getElementByClassNameForChildNodes( + layout.getElementAttribute(sectionGroup.getElement(), 'class'), + groupElement.childNodes); + var transLateCoordinate = thin.core.ShapeStructure.getTransLateCoordinate(sectionElement); + sectionGroup.setTransformation(transLateCoordinate.x, transLateCoordinate.y, 0, 0, 0); + sectionShapeForScope.setTop(Number(layout.getElementAttribute(sectionElement, 'x-top'))); + sectionShapeForScope.setHeight(Number(layout.getElementAttribute(sectionElement, 'x-height'))); + + goog.array.forEach(sectionElement.childNodes, function(element) { + layout.drawBasicShapeFromElement(element, sectionShapeForScope); + }); + }); + + var shapeElement = shape.getElement(); + shape.forEachSectionShape(function(sectionShapeForScope, sectionNameForScope) { + if (thin.core.ShapeStructure.getEnabledOfSection( + sectionShapeForScope.getGroup().getElement(), shapeElement) == "false") { + + shape.setEnabledForSection(false, sectionNameForScope); + sectionShapeForScope.initHeightForLastActive(); } }); - json['svg'] = { - 'tag': shape.tagName, - 'attrs': {} - }; - - var headerStruct = json[thin.core.ShapeStructure.getSectionName(headerClassId)]; - var headerHeight = 0; - if (goog.isDef(headerStruct['height'])) { - headerHeight = Number(headerStruct['height']); - } - json['content-height'] = Number(shape.getAttribute('height')) - headerHeight; - json['page-break'] = shape.getAttribute('x-changing-page') || 'false'; - - return json; + shape.initIdentifier(); + + return shape; }; /** - * @param {Node} sectionGroup - * @param {boolean} enabled - * @param {number=} opt_detailTop - * @return {Object} - * @private + * @deprecated + * @param {Element} element + * @param {thin.core.Layout} layout + * @param {thin.core.ShapeIdManager=} opt_shapeIdManager + * @return {thin.core.PageNumberShape} */ -thin.core.ShapeStructure.serializeForListForSection_ = function( - sectionGroup, enabled, opt_detailTop) { +thin.core.ShapeStructure.createPageNumberShapeFromElement = function(element, layout, opt_shapeIdManager) { + element.removeAttribute('clip-path'); + var shape = new thin.core.PageNumberShape(element, layout); - if (!enabled) { - goog.dom.removeChildren(sectionGroup); - return {}; - } - var json = { - 'height': Number(sectionGroup.getAttribute('x-height')), - 'svg': { - 'tag': sectionGroup.tagName, - 'content': thin.core.ShapeStructure.serializeToContent( - thin.core.LayoutStructure.serializeShapes( - sectionGroup.cloneNode(true).childNodes, 1)) - } - }; + shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); + shape.setFill(new goog.graphics.SolidFill(layout.getElementAttribute(element, 'fill'))); + shape.setFontSize(Number(layout.getElementAttribute(element, 'font-size'))); + shape.setFontFamily(layout.getElementAttribute(element, 'font-family')); - var translate = thin.core.ShapeStructure.getTransLateCoordinate(sectionGroup); - var isCalculateDiff = goog.isNumber(opt_detailTop); - if (isCalculateDiff) { - var diffY = Number(sectionGroup.getAttribute('x-top')) - opt_detailTop; - } - - goog.object.set(json, 'translate', { - 'x': translate.x, - 'y': isCalculateDiff ? translate.y - diffY : translate.y - }); + var decoration = layout.getElementAttribute(element, 'text-decoration'); + var kerning = layout.getElementAttribute(element, 'kerning'); - return json; + if (thin.isExactlyEqual(kerning, thin.core.TextStyle.DEFAULT_ELEMENT_KERNING)) { + kerning = thin.core.TextStyle.DEFAULT_KERNING; + } + shape.setKerning(/** @type {string} */ (kerning)); + shape.setFontUnderline(/underline/.test(decoration)); + shape.setFontLinethrough(/line-through/.test(decoration)); + shape.setFontItalic(layout.getElementAttribute(element, 'font-style') == 'italic'); + shape.setFontBold(layout.getElementAttribute(element, 'font-weight') == 'bold'); + shape.setTextAnchor(layout.getElementAttribute(element, 'text-anchor')); + shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); + shape.setDesc(layout.getElementAttribute(element, 'x-desc')); + shape.initIdentifier(); + + return shape; }; /** - * @param {Element|Node} transformElement - * @return {goog.math.Coordinate} + * @deprecated + * @param {Element} element + * @param {thin.core.Layout} layout + * @param {thin.core.ShapeIdManager=} opt_shapeIdManager + * @return {thin.core.RectShape} */ -thin.core.ShapeStructure.getTransLateCoordinate = function(transformElement) { - var affineTransform = transformElement.getAttribute('transform'); - var x = 0; - var y = 0; - - if(goog.isDefAndNotNull(affineTransform)) { - var splitTransLate = affineTransform.match(/[\-\d\,\.]+/)[0].split(','); - if(splitTransLate.length == 1) { - x = y = Number(splitTransLate[0]); - } else { - x = Number(splitTransLate[0]); - y = Number(splitTransLate[1]); - } - } - return new goog.math.Coordinate(x, y); +thin.core.ShapeStructure.createRectShapeFromElement = function(element, layout, opt_shapeIdManager) { + var shape = new thin.core.RectShape(element, layout, + new goog.graphics.Stroke( + Number(layout.getElementAttribute(element, 'stroke-width')), + layout.getElementAttribute(element, 'stroke')), + new goog.graphics.SolidFill(layout.getElementAttribute(element, 'fill'))); + + shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); + shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); + shape.setDesc(layout.getElementAttribute(element, 'x-desc')); + shape.setStrokeDashFromType(layout.getElementAttribute(element, 'x-stroke-type')); + shape.setRounded(Number(layout.getElementAttribute(element, 'rx'))); + shape.initIdentifier(); + return shape; }; /** - * @param {goog.array.ArrayLike} childNodes - * @return {string} + * @deprecated + * @param {Element} element + * @param {thin.core.Layout} layout + * @param {thin.core.ShapeIdManager=} opt_shapeIdManager + * @return {thin.core.TblockShape} */ -thin.core.ShapeStructure.serializeToContent = function(childNodes) { - var content = ''; - goog.array.forEach(childNodes, function(element) { - content += thin.core.serializeToXML(element); - }); - - return content; +thin.core.ShapeStructure.createTblockShapeFromElement = function(element, layout, opt_shapeIdManager) { + element.removeAttribute('clip-path'); + var shape = new thin.core.TblockShape(element, layout); + + shape.setMultiModeInternal(layout.getElementAttribute(element, 'x-multiple') == 'true'); + shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); + shape.setFill(new goog.graphics.SolidFill(layout.getElementAttribute(element, 'fill'))); + shape.setFontSize(Number(layout.getElementAttribute(element, 'font-size'))); + shape.setFontFamily(layout.getElementAttribute(element, 'font-family')); + + var decoration = layout.getElementAttribute(element, 'text-decoration'); + var lineHeight = layout.getElementAttribute(element, 'x-line-height'); + var lineHeightRatio = layout.getElementAttribute(element, 'x-line-height-ratio'); + var kerning = layout.getElementAttribute(element, 'kerning'); + + if (element.hasAttribute('x-valign')) { + shape.setVerticalAlign(layout.getElementAttribute(element, 'x-valign')); + } + if (thin.isExactlyEqual(kerning, + thin.core.TextStyle.DEFAULT_ELEMENT_KERNING)) { + kerning = thin.core.TextStyle.DEFAULT_KERNING; + } + shape.setKerning(/** @type {string} */ (kerning)); + if (!goog.isNull(lineHeightRatio)) { + shape.setTextLineHeightRatio(lineHeightRatio); + } + shape.setFontUnderline(/underline/.test(decoration)); + shape.setFontLinethrough(/line-through/.test(decoration)); + shape.setFontItalic(layout.getElementAttribute(element, 'font-style') == 'italic'); + shape.setFontBold(layout.getElementAttribute(element, 'font-weight') == 'bold'); + shape.setTextAnchor(layout.getElementAttribute(element, 'text-anchor')); + shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); + shape.setDesc(layout.getElementAttribute(element, 'x-desc')); + + shape.setDefaultValueOfLink(layout.getElementAttribute(element, 'x-value')); + + shape.setBaseFormat(layout.getElementAttribute(element, 'x-format-base')); + + var formatType = layout.getElementAttribute(element, 'x-format-type'); + var formatTypeTemp = thin.core.formatstyles.FormatType; + + switch (formatType) { + case formatTypeTemp.NONE: + shape.setFormatStyle(null); + break; + case formatTypeTemp.NUMBER: + var delimiter = layout.getElementAttribute(element, 'x-format-number-delimiter'); + shape.setFormatStyle(new thin.core.formatstyles.NumberFormat( + delimiter, Number(layout.getElementAttribute(element, 'x-format-number-precision')), + !thin.isExactlyEqual(delimiter, thin.core.formatstyles.NumberFormat.DISABLE_DELIMITER))); + break; + case formatTypeTemp.DATETIME: + shape.setFormatStyle(new thin.core.formatstyles.DatetimeFormat( + layout.getElementAttribute(element, 'x-format-datetime-format'))); + break; + case formatTypeTemp.PADDING: + shape.setFormatStyle(new thin.core.formatstyles.PaddingFormat( + layout.getElementAttribute(element, 'x-format-padding-direction'), + layout.getElementAttribute(element, 'x-format-padding-char'), + Number(layout.getElementAttribute(element, 'x-format-padding-length')))); + break; + } + + shape.initIdentifier(); + return shape; }; /** - * @param {Element} shape - * @param {Function} f - * @private + * @deprecated + * @param {Element} element + * @param {thin.core.Layout} layout + * @param {thin.core.ShapeIdManager=} opt_shapeIdManager + * @return {thin.core.TextShape} */ -thin.core.ShapeStructure.forEachShapeAttribute_ = function(shape, f) { - var attrName; - for(var i = 0, attr; attr = shape.attributes[i]; i++) { - attrName = attr.name; - if (!/^x-/.test(attrName) && attrName != 'class' && attrName != 'style') { - f(attrName, attr.value); - } +thin.core.ShapeStructure.createTextShapeFromElement = function(element, layout, opt_shapeIdManager) { + var deco = layout.getElementAttribute(element, 'text-decoration'); + var lineHeightRatio = layout.getElementAttribute(element, 'x-line-height-ratio'); + var kerning = layout.getElementAttribute(element, 'kerning'); + var shape = new thin.core.TextShape(element, layout); + + shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); + shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); + shape.setDesc(layout.getElementAttribute(element, 'x-desc')); + shape.setFill(new goog.graphics.SolidFill(layout.getElementAttribute(element, 'fill'))); + shape.createTextContentFromElement(element.childNodes); + shape.setFontItalic(layout.getElementAttribute(element, 'font-style') == 'italic'); + shape.setFontFamily(layout.getElementAttribute(element, 'font-family')); + var fontSize = Number(layout.getElementAttribute(element, 'font-size')); + shape.setFontSize(fontSize); + shape.setFontUnderline(/underline/.test(deco)); + shape.setFontLinethrough(/line-through/.test(deco)); + shape.setFontBold(layout.getElementAttribute(element, 'font-weight') == 'bold'); + shape.setTextAnchor(layout.getElementAttribute(element, 'text-anchor')); + + if (element.hasAttribute('x-valign')) { + shape.setVerticalAlign(layout.getElementAttribute(element, 'x-valign')); } + if (thin.isExactlyEqual(kerning, + thin.core.TextStyle.DEFAULT_ELEMENT_KERNING)) { + kerning = thin.core.TextStyle.DEFAULT_KERNING; + } + shape.setKerning(/** @type {string} */ (kerning)); + if (!goog.isNull(lineHeightRatio)) { + shape.setTextLineHeightRatio(lineHeightRatio); + } + + shape.initIdentifier(); + return shape; }; diff --git a/src/app/core/tblockshape.js b/src/app/core/tblockshape.js index 3d1cf11e..6e4cfe03 100644 --- a/src/app/core/tblockshape.js +++ b/src/app/core/tblockshape.js @@ -53,12 +53,6 @@ thin.core.TblockShape = function(element, layout) { this.setCss(thin.core.TblockShape.CLASSID); //this.setFactors_(); - - /** - * @type {Array.} - * @private - */ - this.referringShapes_ = []; }; goog.inherits(thin.core.TblockShape, thin.core.AbstractTextGroup); goog.mixin(thin.core.TblockShape.prototype, thin.core.ModuleShape.prototype); @@ -180,20 +174,6 @@ thin.core.TblockShape.prototype.base_; thin.core.TblockShape.prototype.refId_; -/** - * @type {boolean} - * @private - */ -thin.core.TblockShape.prototype.isReferring_ = false; - - -/** - * @type {boolean} - * @private - */ -thin.core.TblockShape.prototype.isReferences_ = false; - - /** * @type {boolean} * @private @@ -207,13 +187,6 @@ thin.core.TblockShape.prototype.multiMode_; thin.core.TblockShape.prototype.formatStyle_ = null; -/** - * @type {goog.graphics.Element} - * @private - */ -thin.core.TblockShape.prototype.referenceShape_; - - /** * @return {string} */ @@ -238,80 +211,6 @@ thin.core.TblockShape.prototype.updateToolbarUI = function() { }; -/** - * @param {Element} element - * @param {thin.core.Layout} layout - * @param {thin.core.ShapeIdManager=} opt_shapeIdManager - * @return {thin.core.TblockShape} - */ -thin.core.TblockShape.createFromElement = function(element, layout, opt_shapeIdManager) { - element.removeAttribute('clip-path'); - var shape = new thin.core.TblockShape(element, layout); - - shape.setMultiModeInternal(layout.getElementAttribute(element, 'x-multiple') == 'true'); - shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); - shape.setFill(new goog.graphics.SolidFill(layout.getElementAttribute(element, 'fill'))); - shape.setFontSize(Number(layout.getElementAttribute(element, 'font-size'))); - shape.setFontFamily(layout.getElementAttribute(element, 'font-family')); - - var decoration = layout.getElementAttribute(element, 'text-decoration'); - var lineHeight = layout.getElementAttribute(element, 'x-line-height'); - var lineHeightRatio = layout.getElementAttribute(element, 'x-line-height-ratio'); - var kerning = layout.getElementAttribute(element, 'kerning'); - - if (element.hasAttribute('x-valign')) { - shape.setVerticalAlign(layout.getElementAttribute(element, 'x-valign')); - } - if (thin.isExactlyEqual(kerning, - thin.core.TextStyle.DEFAULT_ELEMENT_KERNING)) { - kerning = thin.core.TextStyle.DEFAULT_KERNING; - } - shape.setKerning(/** @type {string} */ (kerning)); - if (!goog.isNull(lineHeightRatio)) { - shape.setTextLineHeightRatio(lineHeightRatio); - } - shape.setFontUnderline(/underline/.test(decoration)); - shape.setFontLinethrough(/line-through/.test(decoration)); - shape.setFontItalic(layout.getElementAttribute(element, 'font-style') == 'italic'); - shape.setFontBold(layout.getElementAttribute(element, 'font-weight') == 'bold'); - shape.setTextAnchor(layout.getElementAttribute(element, 'text-anchor')); - shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); - shape.setDesc(layout.getElementAttribute(element, 'x-desc')); - - shape.setDefaultValueOfLink(layout.getElementAttribute(element, 'x-value')); - - shape.setBaseFormat(layout.getElementAttribute(element, 'x-format-base')); - - var formatType = layout.getElementAttribute(element, 'x-format-type'); - var formatTypeTemp = thin.core.formatstyles.FormatType; - - switch (formatType) { - case formatTypeTemp.NONE: - shape.setFormatStyle(null); - break; - case formatTypeTemp.NUMBER: - var delimiter = layout.getElementAttribute(element, 'x-format-number-delimiter'); - shape.setFormatStyle(new thin.core.formatstyles.NumberFormat( - delimiter, Number(layout.getElementAttribute(element, 'x-format-number-precision')), - !thin.isExactlyEqual(delimiter, thin.core.formatstyles.NumberFormat.DISABLE_DELIMITER))); - break; - case formatTypeTemp.DATETIME: - shape.setFormatStyle(new thin.core.formatstyles.DatetimeFormat( - layout.getElementAttribute(element, 'x-format-datetime-format'))); - break; - case formatTypeTemp.PADDING: - shape.setFormatStyle(new thin.core.formatstyles.PaddingFormat( - layout.getElementAttribute(element, 'x-format-padding-direction'), - layout.getElementAttribute(element, 'x-format-padding-char'), - Number(layout.getElementAttribute(element, 'x-format-padding-length')))); - break; - } - - shape.initIdentifier(); - return shape; -}; - - /** * @param {Element=} opt_element * @return {thin.core.Box} @@ -603,7 +502,7 @@ thin.core.TblockShape.prototype.setShapeId = function(shapeId, opt_shapeIdManage * @return {boolean} */ thin.core.TblockShape.prototype.isReferring = function() { - return this.isReferring_; + return !!this.getReferenceShape(); }; @@ -611,26 +510,12 @@ thin.core.TblockShape.prototype.isReferring = function() { * @return {boolean} */ thin.core.TblockShape.prototype.isReferences = function() { - return this.isReferences_; -}; - - -/** - * @param {goog.graphics.Element} referenceShape - */ -thin.core.TblockShape.prototype.setReferenceShape = function(referenceShape) { - this.referenceShape_ = referenceShape; - this.isReferring_ = true; + return !goog.array.isEmpty(this.getReferringShapes()); }; -thin.core.TblockShape.prototype.removeReferenceShape = function() { - if (this.isReferring()) { - this.referenceShape_.removeReferringShape(this); - } - delete this.referenceShape_; - this.isReferring_ = false; - this.setInternalRefId(thin.core.TblockShape.DEFAULT_REFID); +thin.core.TblockShape.prototype.removeReferenceShapeId = function() { + this.setRefId(thin.core.TblockShape.DEFAULT_REFID); }; @@ -638,33 +523,43 @@ thin.core.TblockShape.prototype.removeReferenceShape = function() { * @return {goog.graphics.Element} */ thin.core.TblockShape.prototype.getReferenceShape = function() { - return this.referenceShape_; + var manager; + if (this.isAffiliationListShape()) { + manager = this.getAffiliationSectionShape().getManager().getShapeIdManager(); + } + + return this.getLayout().getShapeForShapeId(this.getRefId(), manager); }; /** - * @param {string} refId - * @param {goog.graphics.Element} referenceShape + * @return {Array.} */ -thin.core.TblockShape.prototype.setRefId = function(refId, referenceShape) { - if (this.refId_ == refId) { - // Skip setRefId; - return; +thin.core.TblockShape.prototype.getReferringShapes = function() { + var manager; + var layout = this.getLayout(); + if (this.isAffiliationListShape()) { + manager = this.getAffiliationSectionShape().getManager().getShapesManager(); + } else { + manager = layout.getManager().getShapesManager(); } - this.setInternalRefId(refId); - if (this.isReferring()) { - this.referenceShape_.removeReferringShape(this); - } - this.setReferenceShape(referenceShape); - referenceShape.setReferringShape(this); + var shapeId = this.getShapeId(); + var refereces = []; + layout.forTblockShapesEach(manager.get(), function(shape, i) { + if (thin.isExactlyEqual(shapeId, shape.getRefId())) { + goog.array.insert(refereces, shape); + } + }); + + return goog.array.clone(refereces); }; /** * @param {string} refId */ -thin.core.TblockShape.prototype.setInternalRefId = function(refId) { +thin.core.TblockShape.prototype.setRefId = function(refId) { this.refId_ = refId; this.getLayout().setElementAttributes(this.getElement(), { 'x-ref-id': refId @@ -681,34 +576,6 @@ thin.core.TblockShape.prototype.getRefId = function() { }; -/** - * @param {goog.graphics.Element} referringShape - */ -thin.core.TblockShape.prototype.setReferringShape = function(referringShape) { - goog.array.insert(this.referringShapes_, referringShape); - this.isReferences_ = true; -}; - - -/** - * @return {Array.} - */ -thin.core.TblockShape.prototype.getReferringShapes = function() { - return goog.array.clone(this.referringShapes_); -}; - - -/** - * @param {goog.graphics.Element} referringShape - */ -thin.core.TblockShape.prototype.removeReferringShape = function(referringShape) { - goog.array.remove(this.referringShapes_, referringShape); - if (goog.array.isEmpty(this.referringShapes_)) { - this.isReferences_ = false; - } -}; - - /** * @param {number} left */ @@ -1567,7 +1434,7 @@ thin.core.TblockShape.prototype.createPropertyComponent_ = function() { this.setShapeId(shapeId); if (isReferences) { goog.array.forEach(referringShapes, function(shape) { - shape.setRefId(shapeId, scope); + shape.setRefId(shapeId); }); } proppane.getPropertyControl('shape-id').setValue(shapeId); @@ -1577,7 +1444,7 @@ thin.core.TblockShape.prototype.createPropertyComponent_ = function() { this.setShapeId(captureShapeId); if (isReferences) { goog.array.forEach(referringShapes, function(shape) { - shape.setRefId(captureShapeId, scope); + shape.setRefId(captureShapeId); }); } proppane.getPropertyControl('shape-id').setValue(captureShapeId); @@ -1645,17 +1512,17 @@ thin.core.TblockShape.prototype.createPropertyComponent_ = function() { workspace.normalVersioning(function(version) { version.upHandler(function() { if (isDefaultValue) { - this.removeReferenceShape(); + this.removeReferenceShapeId(); } else { - this.setRefId(refId, referenceShape); + this.setRefId(refId); } proppane.getPropertyControl('ref-id').setValue(refId); }, scope); version.downHandler(function() { - this.removeReferenceShape(); + this.removeReferenceShapeId(); if (captureIsReferring) { - this.setRefId(captureRefId, captureReferenceShape); + this.setRefId(captureRefId); } proppane.getPropertyControl('ref-id').setValue(captureRefId); }, scope); @@ -1901,7 +1768,102 @@ thin.core.TblockShape.prototype.disposeInternal = function() { } delete this.id_; - delete this.referenceShape_; - delete this.referringShapes_; delete this.formatStyle_; }; + +/** + * @return {string} + */ +thin.core.TblockShape.prototype.getType = function() { + return 'text-block'; +}; + + +/** + * @return {Object} + */ +thin.core.TblockShape.prototype.asJSON = function() { + var object = goog.base(this, 'asJSON'); + + var format = { + 'base': this.getBaseFormat(), + 'type': this.getFormatType() + }; + + if (this.formatStyle_) { + goog.object.extend(format, this.formatStyle_.asJSON()); + } + + goog.object.extend(object, { + 'reference-id': this.getRefId(), + 'value': this.getDefaultValueOfLink(), + 'multiple-line': this.isMultiMode(), + 'format': format + }); + + goog.object.extend(object['style'], { + 'overflow': this.getOverflowType(), + 'word-wrap': this.getTextWordWrap() + }); + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.TblockShape.prototype.update = function(attrs) { + if (goog.object.containsKey(attrs, 'style')) { + var isMultiple = goog.object.get(attrs, + 'multiple-line', thin.core.TblockShape.DEFAULT_MULTIPLE); + this.setMultiMode(isMultiple); + } + + goog.base(this, 'update', attrs); + + goog.object.forEach(attrs, function(value, attr) { + switch (attr) { + case 'format': + this.setBaseFormat(value['base']); + this.setFormatType(value['type']); + var format = value[value['type']]; + + switch (value['type']) { + case 'number': + this.setFormatStyle( + new thin.core.formatstyles.NumberFormat( + format['delimiter'], format['precision'], + !thin.isExactlyEqual(format['delimiter'], + thin.core.formatstyles.NumberFormat.DISABLE_DELIMITER))); + break; + case 'padding': + this.setFormatStyle( + new thin.core.formatstyles.PaddingFormat( + format['direction'], format['char'], format['length'])); + break; + case 'datetime': + this.setFormatStyle( + new thin.core.formatstyles.DatetimeFormat( + format['format'])); + break; + } + break; + case 'reference-id': + this.setRefId(value); + break; + case 'value': + this.setDefaultValueOfLink(value); + break; + case 'overflow': + this.setOverflowType(value); + break; + case 'word-wrap': + this.setTextWordWrap(value); + break; + default: + // Do Nothing + break; + } + }, this); +}; diff --git a/src/app/core/textshape.js b/src/app/core/textshape.js index d7e410a8..3f907d25 100644 --- a/src/app/core/textshape.js +++ b/src/app/core/textshape.js @@ -131,50 +131,6 @@ thin.core.TextShape.prototype.updateToolbarUI = function() { }; -/** - * @param {Element} element - * @param {thin.core.Layout} layout - * @param {thin.core.ShapeIdManager=} opt_shapeIdManager - * @return {thin.core.TextShape} - */ -thin.core.TextShape.createFromElement = function(element, layout, opt_shapeIdManager) { - - var deco = layout.getElementAttribute(element, 'text-decoration'); - var lineHeightRatio = layout.getElementAttribute(element, 'x-line-height-ratio'); - var kerning = layout.getElementAttribute(element, 'kerning'); - var shape = new thin.core.TextShape(element, layout); - - shape.setShapeId(layout.getElementAttribute(element, 'x-id'), opt_shapeIdManager); - shape.setDisplay(layout.getElementAttribute(element, 'x-display') == 'true'); - shape.setDesc(layout.getElementAttribute(element, 'x-desc')); - shape.setFill(new goog.graphics.SolidFill(layout.getElementAttribute(element, 'fill'))); - shape.createTextContentFromElement(element.childNodes); - shape.setFontItalic(layout.getElementAttribute(element, 'font-style') == 'italic'); - shape.setFontFamily(layout.getElementAttribute(element, 'font-family')); - var fontSize = Number(layout.getElementAttribute(element, 'font-size')); - shape.setFontSize(fontSize); - shape.setFontUnderline(/underline/.test(deco)); - shape.setFontLinethrough(/line-through/.test(deco)); - shape.setFontBold(layout.getElementAttribute(element, 'font-weight') == 'bold'); - shape.setTextAnchor(layout.getElementAttribute(element, 'text-anchor')); - - if (element.hasAttribute('x-valign')) { - shape.setVerticalAlign(layout.getElementAttribute(element, 'x-valign')); - } - if (thin.isExactlyEqual(kerning, - thin.core.TextStyle.DEFAULT_ELEMENT_KERNING)) { - kerning = thin.core.TextStyle.DEFAULT_KERNING; - } - shape.setKerning(/** @type {string} */ (kerning)); - if (!goog.isNull(lineHeightRatio)) { - shape.setTextLineHeightRatio(lineHeightRatio); - } - - shape.initIdentifier(); - return shape; -}; - - /** * @param {Element=} opt_element * @return {thin.core.Box} @@ -1111,3 +1067,37 @@ thin.core.TextShape.prototype.disposeInternal = function() { }); delete this.textLineContainer_; }; + + +/** + * @return {string} + */ +thin.core.TextShape.prototype.getType = function() { + return 'text'; +}; + + +/** + * @return {Object} + */ +thin.core.TextShape.prototype.asJSON = function() { + var object = goog.base(this, 'asJSON'); + + goog.object.set(object, 'texts', this.getTextContent().split("\n")); + + return object; +}; + + +/** + * @param {Object} attrs + */ +thin.core.TextShape.prototype.update = function(attrs) { + goog.base(this, 'update', attrs); + + if (goog.object.containsKey(attrs, 'texts')) { + this.createTextContent(attrs['texts'].join("\n")); + this.updateDecoration(); + this.updatePosition(); + } +}; diff --git a/src/app/core/workspace/backup.js b/src/app/core/workspace/backup.js index f0c15725..b3ab9899 100644 --- a/src/app/core/workspace/backup.js +++ b/src/app/core/workspace/backup.js @@ -29,8 +29,7 @@ goog.require('thin.core.LayoutStructure'); */ thin.core.Workspace.Backup = function(workspace) { var format = thin.layout.Format.parse(workspace.format.toJSON()); - var svg = thin.core.LayoutStructure.createBackup(workspace.getLayout()); - format.setSvg(svg); + format.setItems(workspace.getLayout().asJSON()); /** * @type {thin.layout.Format} diff --git a/src/app/core/workspace/workspace.js b/src/app/core/workspace/workspace.js index 9186594e..dd86ee93 100644 --- a/src/app/core/workspace/workspace.js +++ b/src/app/core/workspace/workspace.js @@ -322,16 +322,6 @@ thin.core.Workspace.prototype.enablingOnceKeyEventHandling_ = function(enable) { thin.core.Workspace.create = function(file) { try { var format = thin.layout.Format.parse(file.getContent()); - var version = format.getVersion(); - var userTypeCompatibilityFn = function() { - var formatPage = format.page; - if (thin.layout.FormatPage.isUserType(formatPage.getPaperType().toLowerCase())) { - formatPage.setPaperType(thin.layout.FormatPage.PaperType['USER']); - } - }; - thin.Compatibility.applyIf(version, '=', '0.7.7', userTypeCompatibilityFn); - thin.Compatibility.applyIf(version, '=', '0.7.7.1', userTypeCompatibilityFn); - var workspace = new thin.core.Workspace(format, file); workspace.createDom(); @@ -365,42 +355,14 @@ thin.core.Workspace.prototype.draw = function() { try { var layout = this.getLayout(); var format = layout.getFormat(); - var file = this.getFile(); - var xmlString = thin.core.LayoutStructure.restoreStructure(format.getSvg()); - var doc = new DOMParser().parseFromString(xmlString, "application/xml"); - var canvasNode = goog.dom.getLastElementChild(doc.documentElement); + thin.Compatibility.applyIf(format.getVersion(), '<', '0.9.0', function() { + thin.core.LayoutStructure.convertToNewLayoutSchema(layout); + }); - layout.drawShapeFromElements(canvasNode.childNodes); + layout.drawShapes(format.getItems()); this.setup(); - var listHelper = layout.getListHelper(); - /** - * @param {Array} shapes - * @param {thin.core.ListSectionShape=} opt_shapeIdManager - */ - var setupHandlers = function(shapes, opt_shapeIdManager) { - goog.array.forEach(shapes, function(shape) { - if (shape.instanceOfListShape()) { - shape.setupEventHandlers(); - shape.forEachSectionShape(function(sectionShapeForEach, sectionNameForEach) { - var managerForList = sectionShapeForEach.getManager(); - setupHandlers(managerForList.getShapesManager().get(), managerForList.getShapeIdManager()); - }); - listHelper.active(shape); - listHelper.inactive(); - } else { - shape.setupEventHandlers(); - if (shape.instanceOfTblockShape()) { - var refId = layout.getElementAttribute(shape.getElement(), 'x-ref-id'); - if (!thin.isExactlyEqual(refId, thin.core.TblockShape.DEFAULT_REFID)) { - shape.setRefId(refId, layout.getShapeForShapeId(refId, opt_shapeIdManager)); - } - } - } - }); - }; - setupHandlers(layout.getManager().getShapesManager().get()); return true; } catch (e) { return false; @@ -671,8 +633,9 @@ thin.core.Workspace.prototype.setFormat = function(format) { thin.core.Workspace.prototype.getSaveFormat_ = function() { var layout = this.layout_; var format = this.format; - format.setSvg(layout.toXML()); + format.setItems(layout.asJSON()); format.setLayoutGuides(layout.getHelpers().getLayoutGuideHelper().getGuides()); + return format.toJSON(); }; @@ -769,7 +732,7 @@ thin.core.Workspace.prototype.getFingerPrint_ = function() { /** @inheritDoc */ thin.core.Workspace.prototype.createDom = function() { - thin.core.Workspace.superClass_.createDom.call(this); + goog.base(this, 'createDom'); this.layout_.setElementAttributes(this.element_, { 'class': 'workspace' }); diff --git a/src/app/layout/format.js b/src/app/layout/format.js index 99657c7d..5e4b5473 100644 --- a/src/app/layout/format.js +++ b/src/app/layout/format.js @@ -28,15 +28,16 @@ goog.require('thin.Compatibility'); * @extends {goog.Disposable} */ thin.layout.Format = function(opt_format) { - goog.Disposable.call(this); + goog.base(this); this.state_ = {}; var currentVersion = thin.getVersion(); - + if (goog.isDefAndNotNull(opt_format) && goog.isObject(opt_format)) { - this.setSvg(opt_format['svg']); - this.page = this.setPage(opt_format['config']); - + this.setItems(opt_format['items']); + this.page = this.setPage(opt_format['report']); + this.page.setTitle(opt_format['title']); + var formatVersion = opt_format['version']; var state = opt_format['state']; var guides; @@ -44,7 +45,7 @@ thin.layout.Format = function(opt_format) { this.isOverWritableVersion_ = thin.Compatibility.check(currentVersion, '>', formatVersion); this.version_ = formatVersion; - if (state && (guides = state['layout-guide'])) { + if (state && (guides = state['layout-guides'])) { this.setLayoutGuides(guides); } } else { @@ -75,10 +76,10 @@ thin.layout.Format.prototype.isOverWritableVersion_ = false; /** - * @type {string} + * @type {Object} * @private */ -thin.layout.Format.prototype.svg_; +thin.layout.Format.prototype.items_; /** @@ -93,7 +94,45 @@ thin.layout.Format.prototype.state_; * @return {thin.layout.Format} */ thin.layout.Format.parse = function(content) { - return new thin.layout.Format(JSON.parse(content)); + var object = JSON.parse(content); + var version = object['version']; + + thin.Compatibility.applyIf(version, '<', '0.9.0', function() { + var state = goog.object.clone(object['state']); + var config = goog.object.clone(object['config']); + var page = goog.object.clone(config['page']); + + var margin = []; + goog.array.insertAt(margin, page['margin-top'], 0); + goog.array.insertAt(margin, page['margin-right'], 1); + goog.array.insertAt(margin, page['margin-bottom'], 2); + goog.array.insertAt(margin, page['margin-left'], 3); + + var report = { + 'paper-type': page['paper-type'], + 'orientation': page['orientation'], + 'margin': margin + }; + + if (thin.layout.FormatPage.isUserType(report['paper-type'])) { + goog.object.extend(report, { + 'width': page['width'], + 'height': page['height'] + }); + } + + goog.object.set(object, 'title', config['title']); + goog.object.set(object, 'report', report); + goog.object.set(object, 'items', object['svg']); + goog.object.set(object, 'state', { + 'layout-guides': state['layout-guide'] + }); + + goog.object.remove(object, 'config'); + goog.object.remove(object, 'svg'); + }); + + return new thin.layout.Format(object); }; @@ -104,23 +143,25 @@ thin.layout.Format.prototype.toJSON = function() { if (this.isOverWritableVersion_) { this.version_ = thin.getVersion(); } - - return goog.json.serialize({ + + var object = { "version": this.version_, - "config": this.page.toHash(), - "svg": this.svg_, + "items": this.items_, "state": { - "layout-guide": this.getLayoutGuides() + "layout-guides": this.getLayoutGuides() } - }); + }; + goog.object.extend(object, this.page.asJSON()); + + return JSON.stringify(object, null, ' '); }; /** - * @return {string} + * @return {object} */ -thin.layout.Format.prototype.getSvg = function() { - return this.svg_; +thin.layout.Format.prototype.getItems = function() { + return this.items_; }; @@ -128,7 +169,7 @@ thin.layout.Format.prototype.getSvg = function() { * @return {Array} */ thin.layout.Format.prototype.getLayoutGuides = function() { - return this.state_['layout-guide'] || []; + return this.state_['layout-guides'] || []; }; @@ -152,15 +193,15 @@ thin.layout.Format.prototype.getVersion = function() { * @param {Array} guides */ thin.layout.Format.prototype.setLayoutGuides = function(guides) { - this.state_['layout-guide'] = guides; + this.state_['layout-guides'] = guides; }; /** - * @param {string} svg + * @param {Object} items */ -thin.layout.Format.prototype.setSvg = function(svg) { - this.svg_ = svg; +thin.layout.Format.prototype.setItems = function(items) { + this.items_ = items; }; @@ -176,7 +217,7 @@ thin.layout.Format.prototype.setPage = function(config) { /** inheritDoc */ thin.layout.Format.prototype.disposeInternal = function() { thin.layout.Format.superClass_.disposeInternal.call(this); - + this.page.dispose(); delete this.page; -}; \ No newline at end of file +}; diff --git a/src/app/layout/formatpage.js b/src/app/layout/formatpage.js index 6f579571..9232166e 100644 --- a/src/app/layout/formatpage.js +++ b/src/app/layout/formatpage.js @@ -31,26 +31,17 @@ goog.require('goog.Disposable'); * @extends {goog.Disposable} */ thin.layout.FormatPage = function(config) { - goog.Disposable.call(this); - + goog.base(this); + var page = goog.object.clone(thin.layout.FormatPage.DEFAULT_SETTINGS); - goog.object.extend(page, Object(goog.object.get(config, 'page'))); - + goog.object.extend(page, config); this.setPaper(page['paper-type'], page['orientation'], page['width'], page['height']); - - this.setMargin(page['margin-top'], - page['margin-right'], - page['margin-bottom'], - page['margin-left']); - - /** - * @type {string} - * @private - */ - this.title_ = config['title']; + + var margin = page['margin']; + this.setMargin(margin[0], margin[1], margin[2], margin[3]); }; goog.inherits(thin.layout.FormatPage, goog.Disposable); @@ -113,13 +104,18 @@ thin.layout.FormatPage.DirectionType = { thin.layout.FormatPage.DEFAULT_SETTINGS = { 'paper-type': thin.layout.FormatPage.PaperType['A4'], 'orientation': thin.layout.FormatPage.DirectionType.PR, - 'margin-top': 20, - 'margin-bottom': 20, - 'margin-left': 20, - 'margin-right': 20 + // [top, right, bottom, left] + 'margin': [20, 20, 20, 20] }; +/** + * @type {string} + * @private + */ +thin.layout.FormatPage.prototype.title_; + + /** * @type {thin.layout.FormatPage.PaperType|string} * @private @@ -241,45 +237,45 @@ thin.layout.FormatPage.prototype.getMarginRight = function() { /** - * @param {number} top - * @param {number} right - * @param {number} bottom - * @param {number} left + * @param {number|string} top + * @param {number|string} right + * @param {number|string} bottom + * @param {number|string} left */ thin.layout.FormatPage.prototype.setMargin = function(top, right, bottom, left) { - this.marginTop_ = top; - this.marginRight_ = right; - this.marginBottom_ = bottom; - this.marginLeft_ = left; + this.marginTop_ = Number(top); + this.marginRight_ = Number(right); + this.marginBottom_ = Number(bottom); + this.marginLeft_ = Number(left); }; /** * @return {Object} */ -thin.layout.FormatPage.prototype.toHash = function() { - var hash = { - "title": this.title_, - "option": {} - }; - - var page = { +thin.layout.FormatPage.prototype.asJSON = function() { + var report = { "paper-type": this.getPaperType(), "orientation": this.getOrientation(), - "margin-top": this.marginTop_, - "margin-bottom": this.marginBottom_, - "margin-left": this.marginLeft_, - "margin-right": this.marginRight_ - } + "margin": [ + this.marginTop_, + this.marginRight_, + this.marginBottom_, + this.marginLeft_ + ] + }; if (this.isUserType()) { - page["width"] = this.getWidth(); - page["height"] = this.getHeight(); + goog.object.extend(report, { + "width": this.getWidth(), + "height": this.getHeight() + }); } - - hash["page"] = page; - return hash; + return { + "title": this.title_, + "report": report + }; }; @@ -341,18 +337,18 @@ thin.layout.FormatPage.prototype.setOrientation = function(orientation) { /** - * @param {number} width + * @param {number|string} width */ thin.layout.FormatPage.prototype.setWidth = function(width) { - this.width_ = width; + this.width_ = Number(width); }; /** - * @param {number} height + * @param {number|string} height */ thin.layout.FormatPage.prototype.setHeight = function(height) { - this.height_ = height; + this.height_ = Number(height); }; @@ -403,7 +399,7 @@ thin.layout.FormatPage.prototype.isUserType = function() { /** @inheritDoc */ thin.layout.FormatPage.prototype.disposeInternal = function() { thin.layout.FormatPage.superClass_.disposeInternal.call(this); - + delete this.paperType_; delete this.orientation_; -}; \ No newline at end of file +}; diff --git a/src/app/layout/layout.js b/src/app/layout/layout.js index 1f42ca51..f373afb8 100644 --- a/src/app/layout/layout.js +++ b/src/app/layout/layout.js @@ -35,8 +35,8 @@ thin.layout.CompatibilityRule = { * @enum {number} */ thin.layout.CompatibilityState = { - COMPLETE: 0x01, - WARNING: 0x02, + COMPLETE: 0x01, + WARNING: 0x02, ERROR: 0x03 };