PageRenderTime 55ms CodeModel.GetById 17ms app.highlight 30ms RepoModel.GetById 1ms app.codeStats 1ms

/src/name/carter/mark/flex/project/mdoc/MSegment.as

http://transcriptstudio4isha.googlecode.com/
ActionScript | 187 lines | 164 code | 14 blank | 9 comment | 38 complexity | 71eaf62f0d11719a23d8af929e3de8ac MD5 | raw file
  1package name.carter.mark.flex.project.mdoc
  2{
  3	import name.carter.mark.flex.util.Utils;
  4	import name.carter.mark.flex.util.XMLUtils;
  5
  6	public class MSegment extends TaggableMNode
  7	{
  8		public static var TAG_NAME:String = "segment";
  9		public static var ID_PREFIX:String = "s";
 10		
 11		public function MSegment(segmentElement:XML, xmlBasedDoc:MDocument)
 12		{
 13			super(segmentElement, xmlBasedDoc);
 14		}
 15		
 16		public function get props():MSegmentProperties {
 17			return new MSegmentProperties(nodeElement);
 18		}
 19		
 20		public function get precedingSegment():MSegment {
 21			var segments:Array = MUtils.getDescendantsOrSelfByClass(document, MSegment);
 22			var index:int = segments.indexOf(this);
 23			if (index == 0) {
 24				// this is the first segment
 25				return null;
 26			}
 27			else {
 28				return segments[index - 1];
 29			}
 30		}
 31		
 32		public function get followingSegment():MSegment {
 33			var segments:Array = MUtils.getDescendantsOrSelfByClass(document, MSegment);
 34			var index:int = segments.indexOf(this);
 35			if (index == segments.length - 1) {
 36				// this is the last segment
 37				return null;
 38			}
 39			else {
 40				return segments[index + 1];
 41			}
 42		}
 43		
 44		public function toContentRange():MContentRange {
 45			var contents:Array = MUtils.getDescendantsOrSelfByClass(this, MContent);
 46			var contentRange:MContentRange = new MContentRange(contents[0], contents[contents.length - 1]);
 47			return contentRange;			
 48		}
 49		
 50		public function allowEditText():Boolean {
 51			var inline:MSuperContent = toContentRange().toSuperContent();
 52			if (inline != null) {
 53				// this segment has an inline for all the text
 54				for each (var childNode:MNode in inline.childNodes) {
 55					if (MUtils.getDescendantsOrSelfByClass(childNode, MSuperContent).length > 0) {					
 56						return false;
 57					}
 58				}
 59				// no nested inlines
 60				return true;
 61			}
 62			else {
 63				return MUtils.getDescendantsOrSelfByClass(this, MSuperContent).length == 0;				
 64			} 
 65		}
 66		
 67		public function editText(newSegmentTexts:Array):MSegmentRange {
 68			if (!allowEditText()) {
 69				throw new Error("Not allowed to edit segment: " + this);
 70			}
 71			if (newSegmentTexts.length == 1 && newSegmentTexts[0] == getText()) {
 72				return null;
 73			}
 74			newSegmentTexts = Utils.condenseWhitespaceForArray(newSegmentTexts);
 75			switch (newSegmentTexts.length) {
 76				case 0:
 77					throw new Error("Passed an empty array of new texts");
 78				case 1:
 79					var firstContent:MContent = toContentRange().first;
 80					var firstContentElement:XML = (firstContent as MContent).nodeElement;
 81					XMLUtils.setElementText(firstContentElement, newSegmentTexts[0]);
 82					// if the segment is also an inline then remove the children of the inline instead of the children of the segment
 83					var parentOfNodesToRemove:MNode;
 84					if (childNodes.length == 1 && childNodes[0] is MSuperContent) {
 85						parentOfNodesToRemove = childNodes[0] as MNode;
 86					}
 87					else {
 88						parentOfNodesToRemove = this;
 89					}
 90					for each (var nodeToRemove:MNode in parentOfNodesToRemove.childNodes) {
 91						nodeToRemove.remove();
 92					}
 93					parentOfNodesToRemove.nodeElement.appendChild(firstContentElement);
 94					return MSegmentRange.createSingleSegmentInstance(this);
 95				default:
 96					return breakSegment(newSegmentTexts);
 97			}
 98		}
 99
100		private function breakSegment(newSegmentTexts:Array):MSegmentRange {
101			var oldContentElement:XML = nodeElement..content[0];
102			var newSegmentElements:XMLList = new XMLList();
103			for (var i:int = 0; i < newSegmentTexts.length; i++) {
104				var newExternalContent:String = newSegmentTexts[i];
105				var newSegmentElement:XML = document.createSegmentElement(nodeElement);
106				newSegmentElements += newSegmentElement;
107				var newContentElement:XML = document.createContentElement(oldContentElement);
108				newContentElement.appendChild(newExternalContent);
109				if (i > 0) {
110					delete newContentElement.@startSyncPointId;
111				}
112				if (i < newSegmentTexts.length - 1) {
113					delete newContentElement.@endSyncPointId;
114				}
115				newSegmentElement.appendChild(newContentElement);
116			}
117			parent.modified = true;
118			var thisDocument:MDocument = document; // before we lose the reference to the document
119			XMLUtils.replaceElement(nodeElement, newSegmentElements);
120			var first:MSegment = thisDocument.resolveElement(newSegmentElements[0]) as MSegment;
121			var last:MSegment = thisDocument.resolveElement(newSegmentElements[newSegmentElements.length() - 1]) as MSegment;
122			remove();
123			return new MSegmentRange(first, last);
124		}
125		
126		public function allowNudgeUp():Boolean {
127			return MSegmentRange.createSingleSegmentInstance(this).allowNudgeUp();
128		}
129
130		public function nudgeUp():void {
131			if (!allowNudgeUp()) {
132				throw new Error("Nudge up not allowed for: " + id);				
133			}
134			if (precedingSibling == null) {
135				// must be moving it out of its current outline
136				var parentOutline:MSuperSegment = parent as MSuperSegment; // grab this reference before its deleted
137				parentOutline.modified = true;
138				parentOutline.parent.modified = true; // because this is the new parent of the segment
139				XMLUtils.removeElement(nodeElement);
140				parentOutline.insertSiblingBefore(nodeElement);
141			} else if (precedingSibling is MSuperSegment) {
142				// move it into the previous outline
143				var precedingOutline:MSuperSegment = precedingSibling as MSuperSegment; // grab this reference before its deleted
144				parent.modified = true; // moving from this parent...
145				precedingOutline.modified = true; // ...to this new parent
146				XMLUtils.removeElement(nodeElement);
147				precedingOutline.appendChild(nodeElement);
148			}
149			else {
150				throw new Error("Unexpected state");
151			}
152		}
153		
154		public function allowNudgeDown():Boolean {
155			return MSegmentRange.createSingleSegmentInstance(this).allowNudgeDown();
156		}
157		
158		public function nudgeDown():void {
159			if (!allowNudgeDown()) {
160				throw new Error("Nudge down not allowed for: " + id);				
161			}
162			if (followingSibling == null) {
163				// must be moving it out of its current outline
164				var parentOutline:MSuperSegment = parent as MSuperSegment; // grab this reference before its deleted
165				parentOutline.modified = true;
166				parentOutline.parent.modified = true; // this is the new parent of the segment
167				XMLUtils.removeElement(nodeElement);
168				parentOutline.insertSiblingAfter(nodeElement);
169			}
170			else if (followingSibling is MSuperSegment) {
171				// move it into the following outline
172				var followingOutline:MSuperSegment = followingSibling as MSuperSegment; // grab this reference before its deleted
173				parent.modified = true; // moved from here...
174				followingOutline.modified = true; // ... to here
175				XMLUtils.removeElement(nodeElement);
176				followingOutline.prependChild(nodeElement);
177			}
178			else {
179				throw new Error("Unexpected state");
180			}
181		}
182		
183		public function getText():String {
184			return toContentRange().getText();
185		}
186	}
187}