/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

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