Copy link to clipboard
Copied
Is there any function to remove the list?
// I can modify the list, but I don't know how to remove the list. it seems that there is no function to remove
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:ai="http://ns.adobe.com/ai/2009"
xmlns:d="http://ns.adobe.com/fxg/2008/dt"
xmlns:flm="http://ns.adobe.com/flame/2008"
creationComplete="initApp()">
<fx:Script>
<![CDATA[
import flashx.textLayout.BuildInfo;
import flashx.textLayout.compose.IFlowComposer;
import flashx.textLayout.compose.TextFlowLine;
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.edit.IEditManager;
import flashx.textLayout.edit.SelectionFormat;
import flashx.textLayout.edit.SelectionState;
import flashx.textLayout.elements.FlowGroupElement;
import flashx.textLayout.elements.ListElement;
import flashx.textLayout.elements.ListItemElement;
import flashx.textLayout.elements.ParagraphElement;
import flashx.textLayout.elements.SpanElement;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.formats.ITextLayoutFormat;
import flashx.textLayout.formats.ListMarkerFormat;
import flashx.textLayout.formats.ListStylePosition;
import flashx.textLayout.formats.ListStyleType;
import flashx.textLayout.operations.SplitParagraphOperation;
import spark.components.TextArea;
import spark.utils.TextFlowUtil;
protected function initApp():void {
var version:String = "";
version += "TLF version: " + BuildInfo.VERSION + "<br/>"+"TLF Build number: " + BuildInfo.kBuildNumber;
var s:String = "";
s += "<TextFlow version='2.0.0' xmlns='http://ns.adobe.com/textLayout/2008'>";
s += "<p>Flex framework"+version+"</p>";
s += "<p>Flex is a free, open source framework for building highly interactive, expressive web applications that dep</p>";
s += "<p>Flex framework</p>";
s += "<p>Flex framework</p>";
s += "<p>I am a new paragraph and I'd like to start at the left below the image</p>";
s += "</TextFlow>";
messageTA.textFlow = TextConverter.importToFlow(s, TextConverter.TEXT_LAYOUT_FORMAT);
}
protected function doSetList():void
{
var interactionManager:IEditManager = messageTA.textFlow.interactionManager as IEditManager;
var selStart:int=interactionManager.anchorPosition
var selFinish:int=interactionManager.activePosition
interactionManager.selectRange(selStart,selFinish)
var lm:ListMarkerFormat=new ListMarkerFormat();
lm.listStyleType=ListStyleType.CHECK;
lm.tabStops="e20 s24";
lm.listStylePosition=ListStylePosition.INSIDE;
lm.paragraphEndIndent=5;
interactionManager.createList(null,lm)
}
private function ClearAllFormats():void{
var interactionManager:IEditManager = messageTA.textFlow.interactionManager as IEditManager;
var selStart:int=interactionManager.anchorPosition
var selFinish:int=interactionManager.activePosition
//interactionManager.selectRange(selStart,selFinish);
//interactionManager.selectAll();
//interactionManager.moveChildren()
var sState:SelectionState=new SelectionState(messageTA.textFlow,selStart,selFinish)
//interactionManager.setSelectionState(sState)
var fontF:ITextLayoutFormat=interactionManager.getCommonCharacterFormat()
var paraF:ITextLayoutFormat=interactionManager.getCommonParagraphFormat()
var conF:ITextLayoutFormat=interactionManager.getCommonContainerFormat()
interactionManager.clearFormat(fontF,paraF,conF,sState)
}
]]>
</fx:Script>
<s:VGroup left="5"
right="5"
top="10"
bottom="82">
<s:Button label="Set List At cursor position"
click="doSetList()"/>
<s:Button label="ClearAllFormat"
click="ClearAllFormats()"/>
<s:TextArea id="messageTA"
width="100%"
height="100%"
editable="true"/>
</s:VGroup>
</s:WindowedApplication>
I use clearformat function , but do nothing.........
What's more , if i want do following :
format["listStyleType"]=ListStyleType.NONE
will get an error:
ArgumentError: Error #2004: One of the parameters is invalid.
at Error$/throwError()
at flash.text.engine::TextBlock/createTextLine()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at GlobalSWFContext/callInContext()
at flashx.textLayout.compose::BaseCompose/createTextLine()
at flashx.textLayout.compose::ComposeState/createTextLine()
at flashx.textLayout.compose::ComposeState/composeNextLine()
at flashx.textLayout.compose::BaseCompose/composeParagraphElementIntoLines()
at flashx.textLayout.compose::BaseCompose/composeParagraphElement()
at flashx.textLayout.compose::ComposeState/composeParagraphElement()
at flashx.textLayout.compose::BaseCompose/composeBlockElement()
at flashx.textLayout.compose::BaseCompose/composeBlockElement()
at flashx.textLayout.compose::BaseCompose/composeBlockElement()
at flashx.textLayout.compose::BaseCompose/composeBlockElement()
at flashx.textLayout.compose::BaseCompose/composeBlockElement()
at flashx.textLayout.compose::BaseCompose/composeInternal()
at flashx.textLayout.compose::ComposeState/composeInternal()
at flashx.textLayout.compose::BaseCompose/composeTextFlow()
at flashx.textLayout.compose::ComposeState/composeTextFlow()
at flashx.textLayout.compose::StandardFlowComposer/http://ns.adobe.com/textLayout/internal/2008::callTheComposer()
at flashx.textLayout.compose::StandardFlowComposer/internalCompose()
at flashx.textLayout.compose::StandardFlowComposer/updateToController()
at flashx.textLayout.compose::StandardFlowComposer/updateAllControllers()
at flashx.textLayout.edit::EditManager/updateAllControllers()
at flashx.textLayout.edit::EditManager/handleUpdate()
at flashx.textLayout.edit::EditManager/finalizeDo()
at flashx.textLayout.edit::EditManager/doOperation()
Thanks.
Copy link to clipboard
Copied
Yes. There is a new function on IEditManager moveChildren that can take the contents out of a list and move it somewhere else.
Hope that helps,
Richard
Copy link to clipboard
Copied
Thanks, Richard
I tried, but failed, about the list,because it's new to me, and I have no APIs ,So I'm very confused.
To the list, I want to create, modify,and del when I select some paras,
Now, it can be created and moified when the paras are being selected without "ListStyleType.NONE", if I set the liststyletype to be none, in fact , it isn't removed.(at first, i think it's easy to make it. set it like linkElement--->to remove linkElement),
var em:IEditManager=IEditManager(textflow.interactionManager);
em.selectRange(beginIndex, lastIndex)
em.applyLink("", null, false, null);
Now, I have two problems:
1. How can I get the list when I click the list?
2. Remove the list really.
The following below is my full TestList source code.
Thanks.
MXML:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="initApp()">
<fx:Script>
<![CDATA[
import flashx.textLayout.BuildInfo;
import flashx.textLayout.compose.IFlowComposer;
import flashx.textLayout.compose.TextFlowLine;
import flashx.textLayout.conversion.TextConverter;
import flashx.textLayout.edit.IEditManager;
import flashx.textLayout.edit.SelectionFormat;
import flashx.textLayout.edit.SelectionState;
import flashx.textLayout.elements.FlowGroupElement;
import flashx.textLayout.elements.ListElement;
import flashx.textLayout.elements.ListItemElement;
import flashx.textLayout.elements.ParagraphElement;
import flashx.textLayout.elements.SpanElement;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.events.SelectionEvent;
import flashx.textLayout.formats.ITextLayoutFormat;
import flashx.textLayout.formats.ListMarkerFormat;
import flashx.textLayout.formats.ListStylePosition;
import flashx.textLayout.formats.ListStyleType;
import flashx.textLayout.formats.TextLayoutFormat;
import flashx.textLayout.operations.SplitParagraphOperation;
import mx.controls.Alert;
import net.diding.control.ListInsertManager;
import spark.components.TextArea;
import spark.utils.TextFlowUtil;
private var listInsertManager:ListInsertManager
public var textflow:TextFlow;
protected function initApp():void {
listInsertManager=new ListInsertManager(this);
textflow=_textArea.textFlow;
if(textflow)
textflow.addEventListener(SelectionEvent.SELECTION_CHANGE, selectionChangeListener, false, 0, true);
}
public var selStart:int;
public var selFinish:int;
private function selectionChangeListener(ev:SelectionEvent):void
{
selStart=_textArea.selectionAnchorPosition
selFinish=_textArea.selectionActivePosition;
}
protected function doSetList():void
{
if (selStart != selFinish)
{
listInsertManager.doOpenListWinHandler(null,this);
}
else
{
Alert.show("Please select paras", "Notice")
}
}
]]>
</fx:Script>
<s:VGroup left="5"
right="5"
top="10"
bottom="82">
<s:Button label="SetList"
click="doSetList()"/>
<s:TextArea id="_textArea"
width="100%"
height="100%"
editable="true"/>
</s:VGroup>
</s:WindowedApplication>
ListInsertManager.as
package net.diding.control
{
import flash.events.EventDispatcher;
import flash.events.MouseEvent;
import flash.text.engine.TextLine;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuBuiltInItems;
import flash.ui.ContextMenuItem;
import flash.ui.Mouse;
import flash.ui.MouseCursor;
import flashx.textLayout.compose.TextFlowLine;
import flashx.textLayout.edit.EditManager;
import flashx.textLayout.edit.EditingMode;
import flashx.textLayout.edit.IEditManager;
import flashx.textLayout.edit.SelectionState;
import flashx.textLayout.elements.FlowGroupElement;
import flashx.textLayout.elements.LinkElement;
import flashx.textLayout.elements.ListElement;
import flashx.textLayout.elements.ParagraphElement;
import flashx.textLayout.elements.SpanElement;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.events.CompositionCompleteEvent;
import flashx.textLayout.events.FlowElementMouseEvent;
import flashx.textLayout.events.UpdateCompleteEvent;
import flashx.textLayout.formats.ListMarkerFormat;
import flashx.textLayout.formats.TextLayoutFormat;
import mx.controls.Alert;
import mx.core.FlexGlobals;
import mx.managers.PopUpManager;
import net.diding.window.UnOrderedListWindow;
import spark.components.RichEditableText;
public class ListInsertManager extends EventDispatcher
{
private var _Manager:*;
private var showDisplay:*
private var richEditableText:RichEditableText
public function ListInsertManager(target:*=null)
{
super();
_Manager=target;
}
/***********************************************************
************************ Set list********************
* *********************************************************/
//open the window to set or modify or remove the unordered list
public function doOpenListWinHandler(listElement:ListElement=null, disPlayObj:*=null):void
{
if (listElement)
{
var window:UnOrderedListWindow=UnOrderedListWindow(PopUpManager.createPopUp(disPlayObj, UnOrderedListWindow, true));
window.getWinFindArg(this, listElement, true)
}
else if (_Manager.selStart != _Manager.selFinish)
{
var window2:UnOrderedListWindow=UnOrderedListWindow(PopUpManager.createPopUp(disPlayObj, UnOrderedListWindow, true));
window2.getWinFindArg(this);
}
else
{
Alert.show("Please select the paras", "Notice")
}
}
//set or modify the list
private var watchIndex:int;
public function setOrEditList(currentListElement:ListElement=null, listformat:TextLayoutFormat=null, lmf:ListMarkerFormat=null):void
{
var em:EditManager=EditManager(_Manager.textflow.interactionManager);
if (currentListElement != null)
{
//Edit
var beginIndex:int=currentListElement.getAbsoluteStart();
watchIndex=beginIndex
var lastIndex:int=beginIndex + currentListElement.textLength;
em.selectRange(beginIndex, lastIndex)
/**************************************
* here
* i want to set the list just the same as i set url ,but failed
*if the listformat-->ListStyleType.NONE
*not really remove the list
* *************************************/
em.createList(null, listformat, lmf)
}
else
{
//Create
em.selectRange(_Manager.selStart, _Manager.selFinish);
watchIndex=_Manager.selStart;
em.createList(null, listformat, lmf)
}
_Manager.textflow.interactionManager.setFocus();
_Manager.textflow.flowComposer.updateAllControllers()
richEditableText=_Manager.textflow.flowComposer.getControllerAt(0).container as RichEditableText;
richEditableText.addEventListener(MouseEvent.MOUSE_DOWN, ListElementHandler)
}
/***************************************************
* ----I want to get the list that I clicked ,but failed-----
* here I want to get the list to modify or remove when i click the list,but
* when i click it in the list, always I get FlowGroupElement's numChildren is one;
* outside ,i will see the list and its numchilren. Why?
* **************************************************/
private function ListElementHandler(event:MouseEvent):void
{
trace("event.target===" + event.target)
var textLine:TextLine=event.target as TextLine;
var flowGropElement:FlowGroupElement;
if (textLine)
{
trace("textLine.parent==" + textLine.parent)
if (textLine.userData)
{
var textFlowLine:TextFlowLine=textLine.userData as TextFlowLine;
if (textFlowLine)
{
var paraElement:ParagraphElement=textFlowLine.paragraph as ParagraphElement;
}
if (paraElement)
{
//The FlowGroupElement class is the base class for FlowElement objects
//that can have an array of children.
//These classes include
//TextFlow, ParagraphElement, DivElement, and LinkElement
flowGropElement=paraElement.parent as FlowGroupElement;
}
if (flowGropElement)
{
trace("flowGropElement numChildren==" + flowGropElement.numChildren)
var fgeChildNum:Number=flowGropElement.numChildren;
if (fgeChildNum == 1)
{
var tflow:TextFlow=flowGropElement.getTextFlow();
//trace(tflow.getElementByID()
trace(tflow.getChildAt(0))
var para:ParagraphElement=tflow.getChildAt(0)as ParagraphElement;
trace("para's parent" + para.parent)
}
for (var k:int=0; k < flowGropElement.numChildren; k++)
{
var childElement:*=flowGropElement.getChildAt(k);
trace(childElement)
//is listElement?
if (childElement is ListElement)
{
var currentList:ListElement=childElement as ListElement;
trace("listElement's child==" + currentList.numChildren)
//each sign as a char
trace("listElement's length==" + currentList.textLength + int(currentList.numChildren))
var absIndex:int=currentList.getAbsoluteStart();
var total:int=absIndex + currentList.textLength
//is click listElement?
//maybe there are many listelements in it
if (_Manager.selStart < total && _Manager.selStart > absIndex)
{
doOpenListWinHandler(currentList, showDisplay)
trace("cliked me")
break;
}
}
}
}
}
}
}
//remove
public function delList(currentListElement:ListElement):void
{
//get listElement absoluteStart and the last
var beginIndex:int=currentListElement.getAbsoluteStart();
watchIndex=beginIndex;
var lastIndex:int=beginIndex + currentListElement.textLength;
var em:IEditManager=IEditManager(_Manager.textflow.interactionManager);
em.selectRange(beginIndex, lastIndex)
// how to moveChildren? Problem!
//em.moveChildren()
_Manager.textflow.interactionManager.setFocus();
}
}
}
UnOrderedListWindow.as
package net.diding.window
{
import flash.events.MouseEvent;
import flashx.textLayout.edit.IEditManager;
import flashx.textLayout.elements.ListElement;
import flashx.textLayout.formats.ListMarkerFormat;
import flashx.textLayout.formats.ListStylePosition;
import flashx.textLayout.formats.ListStyleType;
import flashx.textLayout.formats.TextLayoutFormat;
import mx.containers.ControlBar;
import mx.containers.HBox;
import mx.containers.TitleWindow;
import mx.containers.VBox;
import mx.controls.Button;
import mx.controls.ComboBox;
import mx.controls.Image;
import mx.controls.Label;
import mx.controls.NumericStepper;
import mx.core.FlexGlobals;
import mx.events.CloseEvent;
import mx.events.FlexEvent;
import mx.events.NumericStepperEvent;
import mx.managers.PopUpManager;
import spark.components.FormItem;
public class UnOrderedListWindow extends TitleWindow
{
public function UnOrderedListWindow()
{
super();
this.showCloseButton=true;
this.title="-->Create--Modify--Del--List";
this.height=200;
this.width=300;
createUIFace();
this.addEventListener(CloseEvent.CLOSE, removeOwnerwindow);
this.addEventListener(FlexEvent.CREATION_COMPLETE, setViewPosition);
}
private function removeOwnerwindow(event:CloseEvent):void
{
PopUpManager.removePopUp(this);
}
private function setViewPosition(event:FlexEvent):void
{
this.x=FlexGlobals.topLevelApplication.width / 2 - this.width / 2;
this.y=FlexGlobals.topLevelApplication.height / 2 - this.height / 2
}
private var listTypeCB:ComboBox;
private var removeBtn:Button;
private function createUIFace():void
{
var MainVBox:VBox=new VBox();
MainVBox.setStyle("horizontalAlign", "center")
MainVBox.setStyle("paddingTop", 20)
MainVBox.percentHeight=100;
MainVBox.percentWidth=100;
this.addChild(MainVBox)
var unorderedHBox:HBox=new HBox();
unorderedHBox.percentWidth=100;
MainVBox.addChild(unorderedHBox)
var infoLabel:FormItem=new FormItem();
infoLabel.label="Unordered List Style:";
infoLabel.required=true;
unorderedHBox.addChild(infoLabel)
var dataArr:Array=[{label:"none", data:ListStyleType.NONE}, {label:"●", data:ListStyleType.DISC}, {label:"○", data:ListStyleType.CIRCLE}, {label:"■", data:ListStyleType.SQUARE}, {label:"□", data:ListStyleType.BOX}, {label:"√", data:ListStyleType.CHECK}, {label:"◆", data:ListStyleType.DIAMOND}, {label:"-", data:ListStyleType.HYPHEN}]
listTypeCB=new ComboBox();
listTypeCB.dataProvider=dataArr;
unorderedHBox.addChild(listTypeCB)
//---------------------------------------------------
var MyControlBar:ControlBar=new ControlBar();
MyControlBar.percentWidth=100;
MyControlBar.setStyle("horizontalAlign", "center");
MainVBox.addChild(MyControlBar)
var SubmitBtn:Button=new Button();
SubmitBtn.label="submit";
SubmitBtn.addEventListener(MouseEvent.MOUSE_DOWN, doSendDataHandler)
MyControlBar.addChild(SubmitBtn);
removeBtn=new Button();
removeBtn.label="Remove";
removeBtn.visible=false
removeBtn.addEventListener(MouseEvent.MOUSE_DOWN, doRemoveListHandler)
//------------------------------------------------
}
private function doRemoveListHandler(event:MouseEvent):void
{
editor.delList(currentListElement)
PopUpManager.removePopUp(this);
}
private function doSendDataHandler(event:MouseEvent):void
{
var listFormat:TextLayoutFormat=new TextLayoutFormat();
listFormat.listStyleType=listTypeCB.selectedItem.data;
listFormat.listStylePosition=ListStylePosition.INSIDE;
var lmf:ListMarkerFormat=new ListMarkerFormat();
lmf.listStyleType=listTypeCB.selectedItem.data;
lmf.listStylePosition=ListStylePosition.INSIDE;
lmf.afterContent=" ";
/*********************************************************
*if I don't set afterContent, when I set ListStyleType.NONE
*will get an error :
*ArgumentError: Error #2004: One of the parameters is invalid.
*************************************************************/
editor.setOrEditList(currentListElement, listFormat, lmf)
PopUpManager.removePopUp(this);
}
private var editor:*;
private var currentListElement:ListElement;
public function getWinFindArg(geditor:*, editListElement:ListElement=null, isEdit:Boolean=false):void
{
editor=geditor;
if (editListElement != null)
{
updateComboBox(listTypeCB, editListElement.listStyleType);
}
if (isEdit)
{
currentListElement=editListElement;
removeBtn.visible=true;
}
}
private function updateComboBox(box:ComboBox, val:String):void
{
for (var i:int=0; i < box.dataProvider.length; i++)
{
if (box.dataProvider.data == val)
{
box.selectedIndex=i;
return ;
}
}
box.text=val;
}
}
}
Copy link to clipboard
Copied
If you look at the EditManager API, you'll see a function called moveChildren. This can be used to "promote" the child of a list; essentially what would happen if the user typed a shift-TAB.
This should promote the children of a listItem, to be children of the list's parent:
var target:FlowGroupElement = listItem.parent.parent;
var targetIndex:int = target.getChildIndex(listItem.parent);
editManager.moveChildren(listItem, 0, listItem.numElements, target, targetIndex);
I haven't tested this exact code, but something like this should work. So try looping through the children of the list, and doing this to each one. Note that this sample code assumes that the children of a ListElement are ListItemElements, but they could be paragraphs... in which case you'll probably want to promote the child of the ListElement, and not its grandchild. That's a special case not handled by this snippet.
- robin
Copy link to clipboard
Copied
Robin,
Thanks for your reply
To my surprise:
Example One:
public function delList(currentListElement:ListElement):void
{
var em:IEditManager=IEditManager(_Manager.textflow.interactionManager);
trace(currentListElement.numChildren);
for (var j:int=0; j < currentListElement.numChildren; j++)
{
//watch paras
trace(ListItemElement(currentListElement.getChildAt(j)).getChildAt(0))
var listItem:ListItemElement=currentListElement.getChildAt(j) as ListItemElement
trace("listItem======="+listItem)
var sourceIdx:int=currentListElement.getChildIndex(listItem)
trace("sourceIdx===="+sourceIdx)
var target:FlowGroupElement=listItem.parent.parent;
var targetIndex:int=target.getChildIndex(listItem.parent);
trace("targetIndex----=="+targetIndex);
//if I set arg2 is sourceIdx,I will get an error;
em.moveChildren(listItem,0,listItem.numChildren,target,targetIndex);
trace("loopNumber======="+j);
//why null?
trace("listItem.parent==="+listItem.parent)
}
}
when I select one para , and create it into list, then I lick it, and remove it , everything is OK, but when I select two paras or more, and create them into the list,and remove. there will be always one or more ListItemElement that can't be removed.
Now, I change the idea, not use listitem, but use list:
Example Two:
public function delList(currentListElement:ListElement):void
{
var em:IEditManager=IEditManager(_Manager.textflow.interactionManager);
trace(currentListElement.numChildren);
var target:FlowGroupElement=currentListElement.parent;
var targetIndex:int=target.getChildIndex(currentListElement);
em.moveChildren(currentListElement,targetIndex,currentListElement.numChildren,target,targetIndex);
}
If I do it like this, no matter I choose one or two or many paras , there will be always one ListItemElement left. And throw an error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at flashx.textLayout.edit::ElementMark()
at MoveElementMemento$/perform()
at flashx.textLayout.edit::ModelEdit$/moveElement()
at flashx.textLayout.operations::MoveChildrenOperation/doOperation()
at flashx.textLayout.edit::EditManager/doInternal()
at flashx.textLayout.edit::EditManager/doOperation()
at flashx.textLayout.edit::EditManager/moveChildren()[C:\Vellum\dev\output\openSource\textLayout\src\flashx\textLayout\edit\EditManager.as:1148
In fact , I'm surely that my selected listElement is correct(according to trace(currentListElement.numChildren);).But why two functions ,there are two results.Especially ,for e.g.2.When IEditManager moveChildren, why always remains one ListItemElement that can't be removed, up to it,otheres can be removed.(e.g. If I select 18 paras, create them into the list, use function 2, now 17 listitems can be removed, only the last one can't be removed, what's more,and throw an error.)
Confused.
Thinking...
-Diding
Copy link to clipboard
Copied
The problem is solved,
Change arg2 is zero,
em.moveChildren(currentListElement,0,currentListElement.numChildren,target,targetIndex);
//list is great!
BTW,how to custom my unordered list? like office word.
Hope your help!
Thanks
Copy link to clipboard
Copied
Thanks for this post from a long time ago. Am just getting around to TLF now and was struggling with lists. Thanks!