| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| package flashx.textLayout.operations |
| { |
| import flash.utils.getQualifiedClassName; |
| |
| import flashx.textLayout.edit.ElementMark; |
| import flashx.textLayout.edit.IMemento; |
| import flashx.textLayout.edit.ModelEdit; |
| import flashx.textLayout.edit.ParaEdit; |
| import flashx.textLayout.edit.SelectionState; |
| import flashx.textLayout.elements.FlowElement; |
| import flashx.textLayout.elements.FlowGroupElement; |
| import flashx.textLayout.elements.FlowLeafElement; |
| import flashx.textLayout.elements.ListItemElement; |
| import flashx.textLayout.elements.ParagraphElement; |
| import flashx.textLayout.elements.SpanElement; |
| import flashx.textLayout.elements.SubParagraphGroupElementBase; |
| import flashx.textLayout.elements.TextFlow; |
| import flashx.textLayout.formats.ITextLayoutFormat; |
| import flashx.textLayout.formats.ListMarkerFormat; |
| import flashx.textLayout.formats.TextLayoutFormat; |
| import flashx.textLayout.tlf_internal; |
| |
| |
| use namespace tlf_internal; |
| |
| |
| /** |
| * The SplitElementOperation class encapsulates a change that splits any FlowGroupElement into two elements. |
| * |
| * This operation splits target at operationState.absoluteStart. |
| * |
| * @see flashx.textLayout.elements.ParagraphElement |
| * @see flashx.textLayout.edit.EditManager |
| * @see flashx.textLayout.events.FlowOperationEvent |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public class SplitElementOperation extends FlowTextOperation |
| { |
| //range for block delete |
| private var delSelOp:DeleteTextOperation; |
| |
| // describes the target |
| private var _targetMark:ElementMark; |
| |
| // moment to undo |
| private var _memento:IMemento; |
| |
| // new element to return to client |
| private var _newElement:FlowGroupElement; |
| /** |
| * Creates a SplitElementOperation object. This operation deletes a block selection and then splits the target at absoluteStart. The block selection should not cause target to be deleted. |
| * Target is a FlowGroupElement but may not be a LinkElement, TCYElement or SubParagraphGroupElement. |
| * |
| * @param operationState Describes the point at which to split the element. |
| * If a range of text is specified, the contents of the range are deleted. |
| * |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function SplitElementOperation(operationState:SelectionState, targetElement:FlowGroupElement) |
| { |
| super(operationState); |
| this.targetElement = targetElement; |
| } |
| |
| /** |
| * Specifies the element this operation modifies. |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get targetElement():FlowGroupElement |
| { |
| return _targetMark.findElement(originalSelectionState.textFlow) as FlowGroupElement; |
| } |
| public function set targetElement(value:FlowGroupElement):void |
| { |
| _targetMark = new ElementMark(value,0); |
| } |
| |
| /** |
| * Returns the new element created by doOperation. |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @langversion 3.0 |
| */ |
| public function get newElement():FlowGroupElement |
| { return _newElement; } |
| |
| /** @private */ |
| public override function doOperation():Boolean |
| { |
| var target:FlowGroupElement = targetElement; |
| |
| if (absoluteStart < absoluteEnd) |
| { |
| // watch out for total deletion of target |
| var targStart:int = target.getAbsoluteStart(); |
| var targEnd:int = targStart + target.textLength; |
| |
| delSelOp = new DeleteTextOperation(originalSelectionState); |
| delSelOp.doOperation(); |
| |
| if (absoluteStart <= targStart && targEnd <= absoluteEnd) |
| { |
| // completely deleted |
| if (target is ParagraphElement) |
| target = textFlow.findAbsoluteParagraph(absoluteStart); |
| else |
| target = null; |
| } |
| else |
| target = targetElement; // recalculate |
| |
| } |
| |
| // SubParagraphGroupElements don't split as the target - they just merge again in normalize. |
| // Consider some sort of way to do this. Generally has to be combined with another operation or somehow marked as don't merge |
| // make sure it hasn't been deleted during the delete phase |
| if (target != null && !(target is SubParagraphGroupElementBase) && target.getTextFlow() == textFlow) |
| { |
| var oldLength:int = textFlow.textLength; |
| var relativePosition:int = absoluteStart-target.getAbsoluteStart(); |
| _memento = ModelEdit.splitElement(textFlow,target,relativePosition); |
| _newElement = target.parent.getChildAt(target.parent.getChildIndex(target)+1) as FlowGroupElement; |
| |
| // fix for 2702736 - when splitting a ListItemElement, make sure not to clone the counterReset marker format - it creates unexpected results, new items don't increment |
| if(_newElement is ListItemElement && |
| _newElement.listMarkerFormat && |
| _newElement.listMarkerFormat.counterReset !== undefined) |
| { |
| var listMarkerFormat:ListMarkerFormat = new ListMarkerFormat(_newElement.listMarkerFormat); |
| listMarkerFormat.counterReset = undefined; |
| _newElement.listMarkerFormat = listMarkerFormat; |
| } |
| |
| |
| if( target is ParagraphElement ) |
| { |
| // fix for bug#2948473 - when splitting, the contain/column break settings will not be copied to the |
| // new paragraph element |
| var newFormat:TextLayoutFormat = new TextLayoutFormat(_newElement.format); |
| newFormat.containerBreakAfter = undefined; |
| newFormat.containerBreakBefore = undefined; |
| newFormat.columnBreakAfter = undefined; |
| newFormat.columnBreakBefore = undefined; |
| _newElement.format = newFormat; |
| |
| if (textFlow.interactionManager && oldLength != textFlow.textLength) |
| textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, textFlow.textLength-oldLength); |
| } |
| |
| |
| } |
| |
| return true; |
| } |
| |
| /** @private */ |
| public override function undo():SelectionState |
| { |
| if (_memento) |
| _memento.undo(); |
| _newElement = null; |
| |
| return absoluteStart < absoluteEnd ? delSelOp.undo() : originalSelectionState; |
| } |
| |
| /** @private */ |
| public override function redo():SelectionState |
| { |
| super.redo(); |
| return textFlow.interactionManager.getSelectionState(); |
| } |
| } |
| } |