TraversalEngine abstract class utilisation - javafx

Firstly, i am sorry but i don't speak english very well. Secondly, i have a problem with nodes which are put in a gridpane. In fact, if the focus is taken by the first one wich is located on the top left side, when i push the tab key, the focus is not taken by the other which is located on the right.
People ask me to use the traversalEngine abstract class in order to solve this problem. Nevertheless, when i try to implement an engine object, it doesn't work if i put the parameters which are shown everywhere on the web:
TraversalEngine engine = new TraversalEngine(gridPane, false) {
It ask me to remove the parameters. If i do it, i don't have access to the trav method. In fact, it is the getRoot method which appears and can be implemented :
TraversalEngine engine = new TraversalEngine() {
#Override
protected Parent getRoot() {
// TODO Auto-generated method stub
return null;
}
}
Is there something which can be make in order to solve this problem ?
Thanks you for your help
Vinz

The traversal order for focusing nodes in a parent is the order in which they occur in the child list. Assuming every child contains at most one focusable node you could simply add the children line by line or reorder the children.
This could be done programmatically of course, but adding the children in the correct order in the first place would be more efficient...
public static int getColumnIndex(Node n) {
Integer i = GridPane.getColumnIndex(n);
return i == null ? 0 : i;
}
public static int getRowIndex(Node n) {
Integer i = GridPane.getRowIndex(n);
return i == null ? 0 : i;
}
grid.getChildren().sort(Comparator.comparingInt(ContainingClass::getRowIndex).thenComparingInt(ContainingClass::getColumnIndex));

Related

In Inorder traversal of BST, how could pointer go back to the parent node?

I am sorry this question could be ignorant,but I am so confused.
public static void InOrderRecur(TreeNode<char> treeNode)
{
if (treeNode == null)
{
return;
}
InOrderRecur(treeNode.LChild);
Console.Write(treeNode.Data);
InOrderRecur(treeNode.RChild);
}
After some recursive steps, the pointer went to the leftmost node.
Check the leftmost.leftChild, which is null.
Print the leftmost node.
Check the leftmost.rightChild, which is null.
Then we need to go back to the parent node. But I don't know which line of code could accomplish this function?
For example, which code could make pointer go back to 18 from 12?
Thank you very much.

Preventing the caret from positioning itself between the line start and the first VisualLineElement (at VisualColumn == 0)

I'm working on a project that has taken a dependency on AvalonEdit to manage a document. Certain lines in this document are flagged to use a specific indentation which cannot be modified from within AvalonEdit.
I've managed to achieve this with VisualLineElements that are injected at the start of these flagged lines. The visual elements have a DocumentLength of 0 and a VisualLength the size of the indentation. I also overrode the GetNextCaretPosition method to "push" the caret either to the left of the VisualLineElement (in the case of backwards movement) or to the right (in the case of forward movement).
Here's a version of my VisualLineElement with reduced formatting (note that the element is always injected at VisualColumn == 0) :
public class MyLineFormatElement : VisualLineElement
{
private readonly string _elementText;
public MyLineFormatElement (string elementText)
: base(elementText.Length, 0)
{
_elementText = elementText;
}
public override bool CanSplit
{
get
{
return false;
}
}
public override int GetNextCaretPosition(int visualColumn, System.Windows.Documents.LogicalDirection direction, ICSharpCode.AvalonEdit.Document.CaretPositioningMode mode)
{
if (visualColumn >= VisualColumn && visualColumn <= VisualColumn + VisualLength)
{
return direction == LogicalDirection.Forward ? VisualColumn + VisualLength : VisualColumn;
}
return base.GetNextCaretPosition(visualColumn, direction, mode);
}
public override TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context)
{
return new TextCharacters(_elementText, TextRunProperties);
}
}
This works great except for one issue I'm having: I can still place the caret at the start of the line. From a user standpoint, this is very confusing. What's worse, pressing "delete" when at the start of the line, or pressing "backspace" when at the end of the indentation simply moves the caret without making any modification. As I understand it, the delete/backspace problem would be resolved if the caret couldn't be placed at the line start (based on the code in CaretNavigationCommandHandler.OnMoveCaret).
My best guess as to how to fix this is to override the HandlesLineBorders property so it returns true and then modify GetNextCaretPosition so that:
1. When moving forward over the element, return VisualColumn + VisualLength (this is already the case)
2. When moving backwards over the element, return the previous line's last visual column (I don't know how to do this)
Is the last part of #2 possible? If so, how do I do that? If not, are there any other approaches I should try? I'd really like to stick with VisualLineElements to keep a clean separation between the actual content of the document and the way it's rendered.
Just return -1; that signifies that there are no more caret stops within your VisualLineElement (in the search direction).
The NewLineTextElement (the symbol signifying the end of a line) in AvalonEdit 4.1 was implemented using the same approach (but the implementation was changed in 4.2 when virtual space was implemented).
You should also override IsWhitespace and return true. This is important when AvalonEdit tries to detect the indentation (when word-wrap and options.InheritWordWrapIndentation is enabled).

Forcing vertical scrollbar re-calcuation in a hierarchical tree class derived from mx.controls.Tree

I'm working (for my sins) on a Flex 3.3 project, which unfortunately cannot be upgraded to a newer SDK version at this stage, and have hit an issue with the custom hierarchical tree class (subclassing mx.controls.Tree) we're using. Excuse the spelling; the previous developer had a fear of dictionaries...
public class HierachyTree extends Tree
public function HierachyTree()
{
super();
iconFunction = itemIconFunc;
// etc.
}
I'm using a solution somewhere between these two methods (basically, implementing ITreeDataDescriptor) in order to add live text filtering to the component, and it's working so far:
public class HierachyTreeFilteredDataDescriptor implements ITreeDataDescriptor
{
private var filter:Function
public function HierachyTreeFilteredDataDescriptor(filterFunction:Function)
{
this.filter = filterFunction;
}
public function getChildren(node:Object, model:Object=null):ICollectionView
{
var children:ArrayCollection = new ArrayCollection([]);
// Filter the children...
return children;
}
public function hasChildren(node:Object, model:Object=null):Boolean
{
var treeItem:Object = node as Object;
if (! (treeItem is ScenarioMeta)) return (treeItem as Object).children.length > 0;
else return false;
}
The issue is that (with tree:HierachyTree) neither tree.maxVerticalScrollPosition nor the protected property tree.verticalScrollBar.maxScrollPosition updates when the search string is changed.
I've tried calling invalidateList() and invalidateDisplayList() on tree — and calling invalidateDisplayList() and invalidateSize() on tree.verticalScrollBar — to no avail.
Any ideas?
I have completely the same situation. I have a need to filter the whole tree, and I did use the solution from those 2 blogs.
Tried to validateList(), validateDisplayList(), tried to return a new collection(not filtered) on getChildren in data descriptor, but that caused other issues.
The following was the easiest and worked for me the best:
treeDataProvider.dispatchEvent(new
CollectionEvent(CollectionEvent.COLLECTION_CHANGE, false, false,
CollectionEventKind.RESET));
So, let me get this straight, what you're trying to accomplish is filter the data as per a search string inserted which should then refresh the tree?
If that's the case, it's fairly simple as long as you're using ArrayCollection as the data provider for the tree:
// Check if data is ArrayCollection
var ac:ArrayCollection;
if(tree.dataProvider is ArrayCollection)
{
ac = ArrayCollection(tree.dataProvider);
}
else if(tree.dataProvider is HierarchicalData) // Check if it's hierarchical data
{
ac = HierarchicalData(tree.dataProvider).source as ArrayCollection;
}
// filter - specify custom filter function somewhere, look at docs on how to implement
ac.filterFunction = someFilterFunction;
ac.refresh(); // Does the filtering and lets the tree know that it should redraw all nodes
I think you get the idea. Much easier to do this based on the data.

Dynamic list constraint on Alfresco

I'm trying to follow the examples provided in this post, to create a dynamic list constraint in Alfresco 3.3.
So, I've created my own class extending ListOfValuesConstraint:
public class MyConstraint extends ListOfValuesConstraint {
private static ServiceRegistry registry;
#Override
public void initialize() {
loadData();
}
#Override
public List getAllowedValues() {
//loadData();
return super.getAllowedValues();
}
#Override
public void setAllowedValues(List allowedValues) {
}
protected void loadData() {
List<String> values = new LinkedList<String>();
String query = "+TYPE:\"cm:category\" +#cm\\:description:\"" + tipo + "\"";
StoreRef storeRef = new StoreRef("workspace://SpacesStore");
ResultSet resultSet = registry.getSearchService().query(storeRef, SearchService.LANGUAGE_LUCENE, query);
// ... values.add(data obtained using searchService and nodeService) ...
if (values.isEmpty()) {
values.add("-");
}
super.setAllowedValues(values);
}
}
ServiceRegistry reference is injected by Spring, and it's working fine. If I only call loadData() from initialize(), it executes the Lucene query, gets the data, and the dropdown displays it correctly. Only that it's not dynamic: data doesn't get refreshed unless I restart the Alfresco server.
getAllowedValues() is called each time the UI has to display a property having this constraint. The idea on the referred post is to call loadData() from getAllowedValues() too, so the values will be actually dynamic. But when I do this, I don't get any data. The Lucene query is the same, but returns 0 results, so my dropdown only displays -.
BTW, the query I'm doing is: +TYPE:"cm:category" +#cm\:description:"something here", and it's the same on each case. It works from initialize, but doesn't from getAllowedValues.
Any ideas on why is this happening, or how can I solve it?
Thanks
Edit: we upgraded to Alfresco 3.3.0g Community yesterday, but we're still having the same issues.
This dynamic-list-of-values-constraint is a bad idea and I tell you why:
The Alfresco repository should be in a valid state all the time. Your (dynamic) list of constraints will change (that's why you want it to be dynamic). Adding items would not be a problem, but editing and removing items are. If you would remove an item from your option-list, the nodes in the repository with this property value will be invalid.
You will not be able to fix this easily. The standard UI will fail on invalid-state-nodes. Simply editing this value and setting it to something valid will not work. You have been warned.
Because the default UI widget for a ListConstraint is a dropdown, not every dropdown should be a ListConstraint. ListConstraints are designed for something like a Status property: { Draft, Waiting Approval, Approved }. Not for a list of customer-names.
I have seen this same topic come up again and again over the last few years. What you actually want is let the user choose a value from a dynamic list of options (combo box). This is a UI problem, not a dictionary-model-issue. You should setup something like this with the web-config-context.xml (Alfresco web UI) or in Alfresco Share. The last one is more flexible and I would recommend taking that path.

AS3: removing objects by array item reference

I am trying to add some Sprite objects as the contents of an array, and I would like to be able to "clear" them from the stage. I would assume that if there are loaders involved, I need to do
_imgArray[i].close();
_imgArray[i].unload();
And if I am using a sprite, I can do:
removeChild(_imgArray[i]);
None of the above work. WHY???
For an example and/or description of how I am setting this up, see Joel's post here
...but note that he hasn't included a reference for deleting them from view.
Currently I try:
for(i = 0; i < _localXML.length(); i++)
{
var tmp:BMLink = new BMLink(_localXML[i], _bw, _bh, i);
_imgArray[i] = tmp;
_imgArray[i].x = (_bw + _mainpad) * i;
_base.addChild(_imgArray[i]);
}
But this doesn't work.
I would love it if someone could explain to me why this wouldn't be proper syntax.
The class instances that are populating the array are all extending sprite, but they have their own individual loaders inside w/ progress events etc.
jml
OK; I finally figured it out through a bunch of trial and error.
It seems that I was attempting to remove the child of my main class sprite (this) rather than the sub-sprite that I had added the children to.
Sorry for the noise, but for the record, if you find that you can't do
this.removeChild(_imgArray[i]);
it's not because you don't have the correct syntax, but because you might not have an
_imgArray[i]
at that particular point of your display list hierarchy... so...
_base.removeChild(_imgArray[i]);
...worked in this case.
jml
You can make an Interface IDestroy for example with a destroy method who will manage all cleaning/removing stuff :
public interface IDestroy{
function destroy():void;
}
public class MySprite extends Sprite implements IDestroy {
..
public function destroy():void{
// remove events
..
// remove loader
..
//remove from parent
if (parent!==null){
parent.removeChild(this);
}
// etc.. more cleaning
}
}
then when you have an object who is an instance of IDestroy you can call the destroy method
if (myObject is IDestroy){
IDestroy(myObject).destroy();
}
or another way
var id:IDestroy=myObject as IDestroy;
if (id!==null)
id.destroy();
Edit:
I don't understand why any of the method i gave you in the comment will not work but _base.removeChild(_imgArray[i]) will :
addChild and removeChild accept only a DisplayObject as a parameter, so if you can do _base.addChild(_imgArray[i]) it means that _imgArray[i] inherits from DisplayObject and _imgArray[i] has a parent.
So var myDisplayObject:DisplayObject=_imgArray[i] as DisplayObject; will not return null and you will be able todo myDisplayObject.parent.removeChild(myDisplayObject); which is a general approach to your problem without relying on your _base DisplayObjectContainer (MovieClip/Sprite/...)

Resources