flex-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Hugo Ferreira (JIRA)" <j...@apache.org>
Subject [jira] [Created] (FLEX-35373) TLF - Leader dots/dash/underscore
Date Sun, 24 Dec 2017 00:37:00 GMT
Hugo Ferreira created FLEX-35373:
------------------------------------

             Summary: TLF - Leader dots/dash/underscore
                 Key: FLEX-35373
                 URL: https://issues.apache.org/jira/browse/FLEX-35373
             Project: Apache Flex
          Issue Type: New Feature
          Components: TLF
    Affects Versions: Apache Flex 4.14.1
         Environment: Flex + AIR + TLF
            Reporter: Hugo Ferreira
            Priority: Critical


Flex TLF it's a great text framework under the FTE (the engine), however the FTE does not
provide a way for a feature called leader tabs in ms word (see https://support.office.com/en-us/article/Show-dots-or-leaders-between-tabs-c80b62d0-2244-4078-95bd-8c82f91440ba?ui=en-US&rs=en-US&ad=US).
This is a critical/blocker feature for many types of letters and after a deep search, I didn't
find anyone that had implemented and provided this feature, so I decided implement it my self
in TLF layer and share with Flex community (may be not perfect and you are free to adjust
or improve but the base is there and works for me).

This is the new LeaderOperation main class:
{code:java}
package flashx.textLayout.operations
{
	import flash.text.engine.TextLine;

	import flashx.textLayout.edit.EditManager;
	import flashx.textLayout.edit.SelectionState;
	import flashx.textLayout.operations.FlowTextOperation;
	import flashx.textLayout.operations.InsertTextOperation;

	import mx.utils.StringUtil;

	public class LeaderOperation extends FlowTextOperation
	{
		private var insertEndLeaderOperation:InsertTextOperation = null;

		public var leaderType:String;
		public var linePosition:int;

		public function LeaderOperation(operationState:SelectionState)
		{
			super(operationState);
		}

		public static function getLeader(text:String):Leader
		{
			var index:int = text.indexOf(StringUtil.repeat(Leader.TYPE_DOT, 4));
			if (index > -1)
				return new Leader(Leader.TYPE_DOT, index);

			index = text.indexOf(StringUtil.repeat(Leader.TYPE_DASH, 4));
			if (index > -1)
				return new Leader(Leader.TYPE_DASH, index);

			index = text.indexOf(StringUtil.repeat(Leader.TYPE_UNDERSCORE, 4));
			if (index > -1)
				return new Leader(Leader.TYPE_UNDERSCORE, index);

			return null;
		}

		public function createLeader(leaderType:String, linePosition:int):void
		{
			if (textFlow.interactionManager is EditManager)
			{
				var operationState:SelectionState = originalSelectionState;
				var editManager:EditManager = textFlow.interactionManager as EditManager;

				if (operationState != null)
				{
					var numLines:int = textFlow.flowComposer.numLines;
					var line:TextLine = textFlow.flowComposer.findLineAtPosition(linePosition).getTextLine();

					while (numLines == textFlow.flowComposer.numLines)
					{
						var leader:LeaderOperation = new LeaderOperation(operationState);
						leader.leaderType = leaderType;
						leader.linePosition = linePosition;
						editManager.doOperation(leader);
					}

					editManager.undo();
				}
			}
		}
		
		public override function doOperation():Boolean
		{
			insertEndLeaderOperation = new InsertTextOperation(new SelectionState(textFlow, linePosition
+ 1, linePosition + 1), leaderType);
			insertEndLeaderOperation.doOperation();

			return true;
		}
		
		public override function undo():SelectionState
		{
			insertEndLeaderOperation.undo();
			return originalSelectionState;
		}
	}
}
{code}

And this is the new Leader model class:
{code:java}
package flashx.textLayout.operations
{
	public class Leader
	{
		public static const TYPE_DOT:String = ".";
		public static const TYPE_DASH:String = "-";
		public static const TYPE_UNDERSCORE:String = "_";

		public var type:String;
		public var index:int;

		public function Leader(type:String, index:int)
		{
			this.type = type;
			this.index = index;
		}
	}
}
{code}

In EditManager class, replace the keyUpHandler function by this new version:
{code:java}
public override function keyUpHandler(event:KeyboardEvent):void
		{
			if (!hasSelection() || event.isDefaultPrevented())
				return;
				
			super.keyUpHandler(event);

			var leader:Leader = LeaderOperation.getLeader(textFlow.getText(getSelectionState().absoluteStart));
			if (leader != null)
			{
				var operationState:SelectionState = (textFlow.interactionManager as EditManager).defaultOperationState();
				new LeaderOperation(operationState).createLeader(leader.type, getSelectionState().absoluteStart
+ leader.index);
			}
			
			if ((textFlow.configuration.manageEnterKey && event.charCode == Keyboard.ENTER)
|| (textFlow.configuration.manageTabKey && event.charCode == Keyboard.TAB)) {
				event.stopImmediatePropagation();
			}
		}
{code}

In InsertTextOperation class, replace the doOperation function by this new version:
{code:java}
		public override function doOperation():Boolean
		{
			doInternal();

			if (_text != "" && _text != Leader.TYPE_DOT && _text != Leader.TYPE_DASH
&& _text != Leader.TYPE_UNDERSCORE)
			{
				var leader:Leader = LeaderOperation.getLeader(textFlow.getText(originalSelectionState.absoluteStart));
				if (leader != null)
					new InsertTextOperation(new SelectionState(textFlow, originalSelectionState.absoluteStart
+ leader.index,
						originalSelectionState.absoluteStart + leader.index + 2), "").doOperation();
			}

			return true;
		}
{code}

If the developer final project, if he want to start a dot leader in the selected line, this
is the method do to that:

{code:java}
		public function createDotLeader():void
		{
			var editManager:EditManager = textFlow.interactionManager as EditManager;
			var lineIndex:int = textFlow.flowComposer.findLineIndexAtPosition(editManager.defaultOperationState().absoluteEnd);
			var totalChars:int = textFlow.flowComposer.findLineAtPosition(editManager.defaultOperationState().absoluteEnd).getTextLine().atomCount;

			for (var i:int = 0; i < lineIndex; i++)
			{
				totalChars += textFlow.flowComposer.getLineAt(i).getTextLine().atomCount;
			}

			new LeaderOperation(editManager.defaultOperationState()).createLeader(Leader.TYPE_DOT,
totalChars - 2);
		}
{code}

Final thoughts:
- The leader is started by defined a specific line with 3 possibilities (dot, dash, underscore);
- When the user change the line (add text or delete text) or even the paragraph, the leader
is automatically adjusted to fit on the line !
- This works even after save and reload the tlf data however a better approach could be a
new type of format to not depend on the numbers of .... or ---- or ____ (works for me and
it's a very good first version but it's not bullet proof).



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Mime
View raw message