I'm having problems copying a graph in jgraphX. The example given by the author doesnt appear to clone recursively the children of the default parent:
graph2.addCells(graph1.cloneCells(graph1.getChildCells(graph1.getDefaultParent())));
There is a method: mxGraphModel.cloneCells(vertexList, true) which claims to clone recursively, but it doesnt seem to work for me. I've tracked down the unexpected behaviour, and it seems to be coming from restoreClone. My cloned cells are not having their edges restored. The following code from mxGraphModel.java illustrates the problem:
protected void restoreClone(Object clone, Object cell, Map mapping)
{
if (clone instanceof mxICell)
{
mxICell mxc = (mxICell) clone;
Object source = getTerminal(cell, true);
.getTerminal() is expecting an edge, and behaves accordingly, but the way restoreClone uses "cell" means that it is a vertex in this instance. So the terminal is null, and so "source" becomes null. Is this a bug? I'm wondering if the problem is that cloneCell() is recursive, while restoreClone is not recursive, and only restores the first level of cells?
Is there an easier way to just simply copy the whole graph in one go?
Related
Some context :
In Godot, one is constantly working with nodes and those nodes' children.
Godot has made the design choice of letting the dev manipulate nodes with some sort of querying language that often relies on the full path (starting from the root of the current scene).
For example if the scene is structured like this :
MyRootNode
|
|-- MyChild1
| |
| |-- MySubChild1
|
|
|-- Mychild2
...then the devs are encouraged to access "MySubChild1" with a path :
node = get_node("MyRootNode/MyChild1/MySubChild1")
(note: I''m using the verbose "get_node" syntax rather than $ syntax for readability to C# devs)
Because of that ease of use, I can see that GDScript devs have a tendency to do this :
root = get_node("MyRootNode")
child1 = get_node("MyRootNode/MyChild1")
subchild1 = get_node("MyRootNode/MyChild1/MySubChild1")
...rather than this (pseudo-code) :
root = get_node("MyRootNode")
child1 = root.get_child("MyChild1")
subchild1 = child1 .get_child("MySubChild1")
It makes perfect sense to write queries in a weakly-typed scripting language : all the queryable items have more or less the same type.
The named version of get_child() doesn't even exist. In reality you would need to do this :
root = get_node("MyRootNode")
child1 = root.get_child(0) // first child
subchild1 = child1 .get_child(0) // first child
=================
This is all very awkward for a C# developer. Because of the typing. It's like we're given safety but then it's instantly taken away.
Imagine this :
public class MyRootNode : Node
{
private Control MyChild1 = null; // initialized in _Ready once and for all
public override void _Ready()
{
MyChild1 = GetNode<Control>("MyChild1");
}
public override void _Process(float delta)
{
// Not possible!!!
var mySubChild1 = MyChild1.GetChild<TextureRect>("MySubChild1");
}
}
My question : Is there a way of getting a child in a safe way? It seems to me that none of the solutions seem natural (as developed below), and I mean "safe" in contrast to that.
If I do this :
var mySubChild1 = GetNode<TextureRect>("MyRootNode/MyChild1/MySubChild1");
...then it's extremely unsafe in case of nodes renaming or if I decide to change the tree structure.
If I do this :
var mySubChild1 = MyChild1.GetChild<TextureRect>(0);
....then it's still horrendously unreadable (accessing named items by index? No thanks)
As a C# dev, how do you do it?
My question : It seems to me that there's no way of getting a child in a safe way. None of the solutions seem natural.
That is not a question. That is an statement of opinion.
If I do this:
var mySubChild1 = GetNode<TextureRect>("MyRootNode/MyChild1/MySubChild1");
…then it's extremely unsafe in case of nodes renaming or if I decide to change the tree structure.
This is more unsafe that just a matter of changing the code. The problem is that the scene tree can change independently of the code. In my own terms: the scene tree is external to the code. And thus, the scene tree changing is a reason of change for the code. In other words, the scene tree changing is a responsibility of the code.
Remember single responsibility principle? That is how the software architects would suggest you deal with potential external changes. Make a piece of your code that is the only part that needs to change when the external change happens, so the change does not propagate across your code. I would relax it and say that it does not have to be a separate class, it just has to be self-contained.
In that order of ideas, this makes sense:
onready var root = get_node("MyRootNode")
onready var child1 = get_node("MyRootNode/MyChild1")
onready var subchild1 = get_node("MyRootNode/MyChild1/MySubChild1")
If you use these kind of declarations and initialization on top of your file, that is the only place where you would have to change the code to fix it. Granted, you don't have onready in C#, instead you have to do it on _Ready.
If I do this:
var mySubChild1 = MyChild1.GetChild<TextureRect>(0);
… then it's still horrendously unreadable (accessing named items by index? No thanks)
Agreed. Then don't do it.
As a C# dev, how do you do it?
I don't know what C# developers do. Because I'm not actively using C# at the time.
Now, I did bring up a few other things in comments.
First, if you are in control of the project, you can make sure your code does not fail. That of course might means changing the paths… However, if you use Scene Unique Nodes you can minimize it.
This code:
onready var root = get_node("MyRootNode")
onready var child1 = get_node("MyRootNode/MyChild1")
onready var subchild1 = get_node("MyRootNode/MyChild1/MySubChild1")
Would turn into this:
onready var root = get_node("%MyRootNode")
onready var child1 = get_node("%MyChild1")
onready var subchild1 = get_node("%MySubChild1")
That is, the scene tree hierarchy is no longer relevant. And given that you give good names to your Nodes, you should be able to move them around in your scene tree without further issue. And to be clear, this is implemented in the get_node function so other languages such as C# can use (and GDScript gets some syntactic sugar on top, which I'm not using here).
So yes, you can do that in C#:
private Control MyChild1 = null;
public override void _Ready()
{
MyChild1 = GetNode<Control>("%MyChild1");
}
Second, you can use get_node_or_null (GetNodeOrNull in C#). So your code does not throw when there isn't a node. Instead you can handle the null.
Speaking of nulls. When a Node is freed (e.g. by calling queue_free, which is QueueFree in C#) it does not make the references to it null. And no, Godot does not override the equality operators in C#. Which is why we also have is_instance_valid (Object.IsInstanceValid in C#).
Third, the idea of getting a child by name is not needed in Godot because get_node et.al. can do it.
To be clear, get_node does not work from the root of the current scene, it works from the Node on which you call it. So you can do this:
public class MyRootNode : Node
{
private Control MyChild1 = null; // initialized in _Ready once and for all
public override void _Ready()
{
MyChild1 = GetNode<Control>("MyChild1");
}
public override void _Process(float delta)
{
// Notice I'm using GetNode here
var mySubChild1 = MyChild1.GetNode<TextureRect>("MySubChild1");
}
}
I don't know if that is satisfactory for you, and I don't know if that is a common practice.
Someone else posted this answer in a different discussion channel : It provides extra elements, more centered around C#'s possibilities.
if it’s exported nodepaths I highly recommend
https://github.com/31/GodotOnReady it cuts down on a lot of
boilerplate code.
Otherwise parentNode.GetNode(“path”) has been working great.
Using % in combination with "Access as Scene Unique Name" is
cool with stuff that you will tweak and move around a lot, I use
it with UI mostly.
For additional safety, you can rock parentNode.GetNodeOrNull(path).
Unlike GetNode, GetNodeOrNull with a type won’t raise an Exception if
something doesn't match (type or name), it just returns null.
So at least it won’t silently burn you.
Best practice I found is to only use these methods in node setup
methods.
Otherwise I do regular dependency injection, and groups to
find what I need.
That being said, I always advocate failing loudly and failing fast,
so I only use GetNode and existing references. If it explodes
it means I messed up.
No matter what anyone does there are ways for it to break. Some of the responsibility simply must fall on developers changing code to test their work. If you wish to access something by name, then changing that name on the object but not at the point of access is going to cause failure. That said, you can avoid the risk of reorganization of your object breaking your code by using the less-efficient
Node : find_node ( String mask, bool recursive=true, bool owned=true ) const
so
root = get_node("MyRootNode")
child1 = get_node("MyRootNode/MyChild1")
subchild1 = get_node("MyRootNode/MyChild1/MySubChild1")
can become
root = find_node("MyRootNode")
child1 = find_node("MyChild1")
subchild1 = find_node("MySubChild1")
It requires you to name your nodes of interest uniquely within this object. But the structure to traverse to reach said nodes can change.
Guys how can I fix the error java.util.ConcurrentModificationException: null
experiments.forEach {
if(NAME_VARIANT == it.variantName) {
for (i in (0..Math.min(result.size - 1, Constants.MAX_METHODS_APPLIED))) {
if (response.paymentMethods[i].scoring.rules!!.none { it.ruleName == NAME_RULE}) {
response.appliedExperiments.clear()
}
}
}
}
This exception ConcurrentModificationException is thrown when you're trying to modify a collection at the same time as iterating over it.
In the piece of code you provided, you're iterating over experiments, and you're modifying response.appliedExperiments (by calling clear() on it). If those 2 variables actually point to the same collection, calling clear() is expected to throw.
In order to do what you want, you probably want those lists to start off as copies of each other, but still be different. When you create response.appliedExperiments, make sure it's a new list and not the same list.
EDIT: in the code you provided, you are passing experiments directly to the constructor of SortingServiceResponse, and I'm guessing this constructor uses the list as-is as the appliedExperiments property of reponse. Instead, you should pass a copy of the list, for instance using toMutableList():
val response = SortingServiceResponse(experiments.toMutableList(), result)
An even better approach would be to use read-only List instead of MutableList for experiments to avoid making this kind of mistakes in the first place. Only use mutable collections when you really need to. Most of the time, you can use operators (like filter or map) that create new read-only lists instead of working with mutable lists directly.
My Dev setup:
Qt version : Qt 5.15.0
OS: Embedded Linux
I have a list of information.
Assume I have a structure called MyStruct
My model class is having a member variable of QList of above structure, to hold data for my view. Whenever I am opening the view, I am updating the QList (Note: There may or may not be a change). Updating here is something like assigning a new QList to existing one. before assignment, I am calling beginResetModel and after assignment I am calling endResetModel,
void MyModelClass::SomeInsertMethod(const QList<MyStruct>& aNewData)
{
beginResetModel();
m_lstData = aNewData;
endResetModel();
}
One thing I believe can be improved, is putting a check, if the new data is different than the existing data and then doing the above. Something like this:
void MyModelClass::SomeInsertMethod(const QList<MyStruct>& aNewData)
{
if (m_lstData != aNewData)
{
beginResetModel();
m_lstData = aNewData;
endResetModel();
}
}
Apart from that, is there any possibilities of getting a performance issue for calling beginResetModel/endResetModel? I m seeing a very small delay in the view coming up in my application.
I checked the documentation of QAbstractItemModel for above methods. Didn't get anything specific to the performance issue.
The other way, which this can be done, is by individually comparing the elements of the lists and triggering a dataChanged signal with appropriate model index and roles. But I feel, this will unnecessarily introduce some additional loops and comparisons, which again may cause some other performance issue. Correct me if I am wrong.
Is there any advantage of using dataChanged over beginResetModel/EndResetModel?
Please let me know your views on the above.
class FilterCriteria {
#observable filter = new Map();
}
let criteria = new FilterCriteria ();
// setting up a reaction when something in the filter changes
// (property added, removed, or changed)
reaction(()=>criteria.filter, data => console.log(data.toJSON()));
criteria.filter.set('name', 'John'); // setting a new property.
I would expect the above code to print out { 'name': 'John' }, but it seems that the reaction is not running.
I suspect that I set up the reaction in the wrong way. I want to react whenever a new key is added, an existing key is removed or a key value is changed. I don't know the keys or values at compile time.
How am I supposed to do that?
UPDATE
I changed my code to
class FilterCriteria {
#observable filter = new Map();
#computed get json(){ return this.filter.toJSON(); }
}
...
reaction(()=>criteria.json, data => console.log(data));
and now it seems to work properly. The reaction sideffect is executed whenever I add, remove or change a value in the Map.
So the question is why the reaction did execute in the second but not in the first example?
UPDATE 2
I changed my code again for a second time. I reverted to almost the first version but this time instead of reacting on criteria.filter and logging data.toJSON(), i react on criteria.filter.toJSON() and I log data (toJSON is moved from the sideffect to the value being watched). This time the reaction runs normally.
class FilterCriteria {
#observable filter = new Map();
}
reaction(()=>criteria.filter.toJSON(), data => console.log(data));
Again, I don't understand why. If criteria.filter is not an observable in itself then how does the watched expression is reevaluated when something inside criteria.filter is changed?
UPDATE 4 (hope the final one) SOLUTION
According to MobX documentation, mobx reacts to any existing observable property that is read during the execution of a tracked function.
reaction side-effect executes when the observable property changes. In my example, when reacting to criteria.filter , the observable property that is read here is filter, but the filter itself never changes. It is the same map always. It is the properties of filter that change. So the reaction is never run for criteria.filter.
But when I react on criteria.filter.toJSON() or mobx.toJS(criteria.filter), the reaction is executed correctly.
So why is that? criteria.filter doesn't change, and toJSON is not an observable property. It is a function. same for mobx.toJS. It seems no properties are read here. But this is not correct. As the documentation states (but not so emphatically), the properties of criteria.filter are indeed read when toJSON or mobx.toJS is executed, because both functions create a deep clone of the map (thus iterating over every property).
Now, in the beginning, the Map did not contain any property. So how is it that newly added properties are tracked, since they did not exist (to be read) when tracking begun? This is a map's feature. Maps provide observability for not yet existing properties too.
In MobX 5 you can track not existing properties of observable objects (not class instances) too, provided that they were instatiated with observable or observable.object. Class instances don't support this.
In mobx you have two options when you want to observe changes to something that is observable. reaction and observe. Reaction allows you to specify when you want some function to be called when a specific aspect of the observable changes. This could be changes to an array length, keys, properties, really anything. observe will trigger some function any time that the observable has changed.
I suspect the reason that your reaction hasn't been triggered is because of the first function. () => criteria.filter. This will not be triggered when a key is added/removed or a value changed. Instead, it will be triggered when filter actually changes. And since filter is really a reference to the Map, it will never change, even when the Map itself changes.
Here are some examples to illustrate my point:
If you want to trigger a reaction when a key has been added or removed, you may want your function to be:
() => criteria.filter.keys()
The result of this function will be different when a key has been added or removed. Similarly, if you want to trigger a reaction for when a value has been modified, something like this should work:
() => criteria.filter.values()
So some combination of those two should be what you need to listen to changes to keys/values. Alternatively, you could use observe, which will trigger on every change and require you to check what has changed to ensure that your specific conditions have been met to warrant calling a function (ie. key/value change)
UPDATE: Here is an example that illustrates the problem
#observable map = new Map();
Lets say that the value of map in memory is 5. So when you check map === map, it is equivalent to 5 === 5 and will evaluate to true.
Now, looking at the first code snippet you posted:
reaction(() => map, data => console.log(map.toJSON()));
Every time you add/remove a key or change a value, that first function will run. And the result will be 5, since that is what we said the value in memory is for this example. It will say: the old value is 5, and the new value is 5, so there is no change. Therefore, the reaction will not run the second function.
Now the second snippet:
reaction(() => map.toJSON(), data => console.log(data));
At first the result of the function will be: {} because the Map is empty. Now lets add a key:
map.set(1, 'some value');
Now, the result of the first function will be:
{"1": "some value"}
Clearly, this value is different than {}, so something has changed, and the second function of the reaction is called.
My Redux store is normalized, i.e. it's quite flat and each entity type has it's own slice.
Here is a simplified example of my Redux store:
drawings
1: {name:'D1', thumbnailId: 33}
2: {name:'D2', thumbnailId: 34}
thumbnails
33: {filePath: 'path to local file'}
34: {filePath: null (i.e. needs to be downloaded)}
The listview that shows the drawings whith respective thumbnail needs to be re-rendered when:
Changes in drawings-slice occurs, i.e. new, removed or updated drawings
Changes in any of the referenced thumbnails occurs, i.e. thumbnail 34 eventually gets downloaded (download is handled async by a Redux-Saga)
My current mapStateToProps is obviously flawed, as it does excessive selections from the Redux store. This happens before the actual view gets hold of its new props, so I cannot control this from shouldComponentUpdate.
There are several places in my app where I need a better solution for this.
Here is my flawed mapStateToProps (I'm using Immutable.js):
(state, ownProps) => {
const drawings = selectProjectDrawings(state, ownProps.projectId).map(drawing => {
const thumbnailFileGuid = drawing.get('thumbnailFileGuid');
if (!thumbnailFileGuid) return drawing;
const filePath = selectFile(state, thumbnailFileGuid).get(THUMBNAIL_FILE_PATH_FIELD);
return filePath ? drawing.set('_thumbnailFilePath', filePath) : drawing;
});
return {
drawings: drawings
};
}
Edit:
A really bad thing with my current solution is that I'm creating new drawing object by augmenting them with _thumbnailPath. This means that I cannot compare the object references in shouldComponentUpdate, as the reference is always altered.
Being able to compare object references is one of the main argument for not mutating the objects, but I have thrown away this opportunity with my flawed solution.
I would suggest placing this logic behind a selector. reselect is a selector memoization library which means that it will do a deep compare of the values for you and if the returned object and all the properties within stay the same, (including deep tree like structures) then it will return the original object.
React then will notice this is the same object instance (not a new one) and not re-render. It is OK if you recreate the drawing object within the selector, since you are not capturing this in any persistent state.
Side note: As your app grows, you will notice that all connected components will get mapStateToProps called even if it has nothing to do with it, therefore using a memoized selector really helps here. Otherwise your componentShouldUpdate gets complex real quick.