source: java/main/src/main/java/com/framsticks/gui/tree/TreeNode.java @ 101

Last change on this file since 101 was 101, checked in by psniegowski, 11 years ago

HIGHLIGHTS:

  • improve tree side notes
  • improve GUI layout
  • add foldable list of occured events to EventControl?
  • improve automatic type conversion in proxy listeners
  • implement several Access functionalities as algorithms independent of Access type
  • introduce draft base classes for distributed experiments
  • automatically register dependant Java classes to FramsClass? registry
  • add testing prime experiment and configuration
  • simplify and improve task dispatching

CHANGELOG:
Improve task dispatching in RemoteTree?.

GUI no longer hangs on connection problems.

Make all dispatchers joinables.

Refactorize Thread dispatcher.

Remove Task and PeriodicTask?.

Use Java utilities in those situations.

Reworking tasks dispatching.

Fix bug in EventControl? listener dispatching.

Minor improvements.

Add testing configuration for ExternalProcess? in GUI.

More improvement to prime.

Support for USERREADONLY in GUI.

Add that flag to various params in Java classes.

Remove redundant register clauses from several FramsClassAnnotations?.

Automatically gather and register dependant classes.

Add configuration for prime.

Improve Simulator class.

Add prime.xml configuration.

Introduce draft Experiment and Simulator classes.

Add prime experiment tests.

Enclose typical map with listeners into SimpleUniqueList?.

Needfile works in GUI.

Improve needfile handling in Browser.

More improvement with NeedFile?.

Implementing needfile.

Update test.

Rename ChangeEvent? to TestChangeEvent?.

Automatic argument type search in RemoteTree? listeners.

MultiParamLoader? uses AccessProvider?. By default old implementation
enclosed in AccessStash? or Registry.

Minor changes.

Rename SourceInterface? to Source.

Also improve toString of File and ListSource?.

Remove unused SimpleSource? class.

Add clearing in HistoryControl?.

Show entries in table at EventControl?.

Improve EventControl?.

Add listeners registration to EventControl?.

Add foldable table to HistoryControl?.

Add control row to Procedure and Event controls.

Improve layout of controls.

Another minor change to gui layout.

Minor improvement in the SliderControl?.

Minor changes.

Move ReflectionAccess?.Backend to separate file.

It was to cluttered.

Cleanup in ReflectionAccess?.

Move setMin, setMax, setDef to AccessOperations?.

Extract loading operation into AccessOperations?.

Append Framsticks to name of UnsupportedOperationException?.

The java.lang.UnsupportedOperationException? was shadowing this class.

Rename params.Util to params.ParamsUtil?.

Several improvements.

Minor changes.

Implement revert functionality.

Improve local changes management.

Minor improvement.

Remove methods rendered superfluous after SideNoteKey? improvement.

Improve SideNoteKey?.

It is now generic type, so explicit type specification at
call site is no more needed.

Introduce SideNoteKey? interface.

Only Objects implementing that key may be used as side note keys.

Minor improvements.

Use strings instead of ValueControls? in several gui mappings.

File size: 8.1 KB
Line 
1package com.framsticks.gui.tree;
2
3import java.lang.ref.WeakReference;
4import java.util.Iterator;
5import java.util.LinkedList;
6
7import org.apache.logging.log4j.LogManager;
8import org.apache.logging.log4j.Logger;
9
10import com.framsticks.core.Node;
11import com.framsticks.core.Path;
12import com.framsticks.core.SideNoteKey;
13import com.framsticks.core.Tree;
14import com.framsticks.gui.Frame;
15import com.framsticks.gui.ImageProvider;
16import com.framsticks.gui.TreeAtFrame;
17import com.framsticks.gui.TreePanel;
18import com.framsticks.params.Access;
19import com.framsticks.params.CompositeParam;
20import com.framsticks.params.EventListener;
21import com.framsticks.params.FramsClass;
22import com.framsticks.params.ValueParam;
23import com.framsticks.params.types.EventParam;
24import com.framsticks.params.types.ObjectParam;
25import com.framsticks.params.types.StringParam;
26import com.framsticks.util.FramsticksException;
27import com.framsticks.util.dispatching.FutureHandler;
28import com.framsticks.util.lang.Casting;
29import com.framsticks.util.lang.Containers;
30import com.framsticks.util.swing.TooltipConstructor;
31
32import static com.framsticks.core.TreeOperations.*;
33
34public class TreeNode extends AbstractNode {
35
36        private static final Logger log = LogManager.getLogger(TreeNode.class);
37
38        protected final WeakReference<Object> reference;
39        protected final int hashCode;
40        protected final TreeAtFrame treeAtFrame;
41        protected final String textual;
42        protected final CompositeParam param;
43        protected TreePanel panel;
44
45        public TreeModel getTreeModel() {
46                return treeAtFrame.getFrame().getTreeModel();
47        }
48
49        /**
50         * @param reference
51         */
52        public TreeNode(TreeAtFrame treeAtFrame, Path path) {
53                path.assureResolved();
54
55                this.reference = new WeakReference<Object>(path.getTopObject());
56                this.textual = path.getTextual();
57                this.treeAtFrame = treeAtFrame;
58                this.param = path.getTop().getParam();
59                hashCode = System.identityHashCode(path.getTopObject());
60
61                if (isMarked(path.getTree(), path.getTopObject(), getTreeModel().createdTag, false)) {
62                        return;
63                }
64
65                // path.getTree().putSideNote(path.getTopObject(), Textual.class, path.getTextual());
66                mark(path.getTree(), path.getTopObject(), getTreeModel().createdTag, true);
67
68                /** Iterate over all EventParams and for matching ValueParams register listeners. */
69                if (path.getTop().getParam() instanceof ObjectParam) {
70                        Access access = bindAccess(path);
71                        FramsClass framsClass = access.getFramsClass();
72                        for (EventParam eventParam : Containers.filterInstanceof(framsClass.getParamEntries(), EventParam.class)) {
73                                if (!eventParam.getId().endsWith("_changed")) {
74                                        continue;
75                                }
76                                String valueId = eventParam.getId().substring(0, eventParam.getId().length() - 8);
77                                final ValueParam valueParam = Casting.tryCast(ValueParam.class, framsClass.getParam(valueId));
78                                if (valueParam == null) {
79                                        continue;
80                                }
81                                getTreeModel().registerForEventParam(this, path, eventParam, valueParam);
82                        }
83                }
84        }
85
86        @Override
87        public int hashCode() {
88                return hashCode;
89        }
90
91        @Override
92        public boolean equals(Object obj) {
93                if (obj instanceof TreeNode) {
94                        return lock() == ((TreeNode) obj).lock();
95                }
96                return false;
97        }
98
99        @Override
100        public AbstractNode getChild(int number) {
101                Object referent = lock();
102                if (referent == null) {
103                        throw new FramsticksException().msg("invalid state - missing referent");
104                }
105                Tree tree = getTree();
106                Access access = bindAccessForTreeObject(referent);
107
108                final int count = access.getCompositeParamCount();
109                if (number >= count) {
110                        throw new FramsticksException().msg("invalid state - no child");
111                }
112
113                /** textual path may be not valid anymore*/
114                CompositeParam childParam = access.getCompositeParam(number);
115
116                try {
117                        Path path = Path.to(tree, getTextual()).appendParam(childParam).tryFindResolution();
118                        if (!path.isResolved()) {
119                                path = create(path);
120                        }
121                        return prepareTreeNodeForChild(path);
122                } catch (FramsticksException e) {
123                }
124                return new EmptyNode(getFrame(), childParam);
125
126        }
127
128        public TreeNode prepareTreeNodeForChild(Path path) {
129                assert path.getTree() == getTree();
130                Object parent = lock();
131                Iterator<Node> n = path.getNodes().iterator();
132                while (n.hasNext()) {
133                        if (n.next().getObject() == parent) {
134                                break;
135                        }
136                }
137                if (!n.hasNext()) {
138                        return null;
139                        // throw new FramsticksException().msg("tree node is not on path (or is last)").arg("path", path).arg("node", this);
140                }
141                return new TreeNode(treeAtFrame, path);
142        }
143
144        public Object lock() {
145                return reference.get();
146        }
147
148        @Override
149        public int getIndexOfChild(Object child) {
150                final TreeNode treeChild = Casting.tryCast(TreeNode.class, child);
151                if (treeChild == null) {
152                        return -1;
153                }
154                final Object childObject = treeChild.lock();
155                final Object parentObject = lock();
156                if (childObject == null || parentObject == null) {
157                        return -1;
158                }
159                final Access access = bindAccessForTreeObject(parentObject);
160
161                final int count = access.getCompositeParamCount();
162                for (int i = 0; i < count; ++i) {
163                        Object c = access.get(access.getCompositeParam(i), Object.class);
164                        if (c == childObject) {
165                                return i;
166                        }
167                }
168                log.debug("{} not found in {}", child, this);
169                return -1;
170        }
171
172        public Frame getFrame() {
173                return getTreeAtFrame().getFrame();
174        }
175
176        public TreeAtFrame getTreeAtFrame() {
177                return treeAtFrame;
178        }
179
180        public Tree getTree() {
181                return getTreeAtFrame().getTree();
182        }
183
184        protected Path assurePath() {
185                return Path.to(getTree(), getTextual()).assureResolved();
186        }
187
188        @Override
189        public String toString() {
190                return getTextual();
191        }
192
193        public Node tryCreateNode() {
194                Object child = lock();
195                if (child == null) {
196                        return null;
197                }
198                String textual = getTextual();
199                Path path = Path.tryTo(getTree(), textual);
200                if (path.isResolved(textual)) {
201                        return path.getTop();
202                }
203                return null;
204        }
205
206        @Override
207        public int getChildCount() {
208                Object referent = lock();
209                if (referent == null) {
210                        return 0;
211                }
212                Access access = bindAccessForTreeObject(referent);
213                final int count = access.getCompositeParamCount();
214                return count;
215        }
216
217        @Override
218        public boolean isLeaf() {
219                Object referent = lock();
220                if (referent == null) {
221                        return true;
222                }
223                return bindAccessForTreeObject(referent).getCompositeParamCount() == 0;
224        }
225
226        protected Access bindAccessForTreeObject(Object child) {
227                return bindAccessFromSideNote(getTree(), child);
228        }
229
230        @Override
231        public void render(TreeCellRenderer renderer) {
232
233                Object child = lock();
234                if (child == null) {
235                        renderer.setToolTipText("?");
236                        renderer.setText("?");
237                        renderer.setIcon(ImageProvider.loadImage(ImageProvider.FOLDER_CLOSED));
238                        return;
239                }
240                Access access = bindAccessForTreeObject(child);
241                CompositeParam param = getTree().getSideNote(child, Path.OBJECT_PARAM_KEY);
242                String name = param.getId();
243
244                StringParam nameParam = Casting.tryCast(StringParam.class, access.getParam("name"));
245
246                if (nameParam != null) {
247                        name = access.get(nameParam, String.class);
248                }
249
250                renderer.setToolTipText(new TooltipConstructor()
251                                .append("frams", access.getId())
252                                .append("java", child.getClass().getCanonicalName())
253                                .append("access", access.getClass().getSimpleName())
254                                .append("name", name)
255                                .append("id", param.getId())
256                                .append("object", Integer.toHexString(System.identityHashCode(child)))
257                                .append("size", access.getCompositeParamCount())
258                                .build());
259
260                renderer.setIcon(ImageProvider.loadImage(TreeCellRenderer.findIconName(param)));
261                renderer.setText(name);
262        }
263
264
265        public String getTextual() {
266                return textual;
267        }
268
269        @SuppressWarnings("rawtypes")
270        protected final SideNoteKey<LinkedList> listenersTag = SideNoteKey.make(LinkedList.class);
271
272        protected <A> void tryAddListener(final Path path, final EventParam eventParam, Class<A> argumentType, final EventListener<A> listener) {
273                getTree().addListener(path, eventParam, listener, argumentType, new FutureHandler<Void>(getFrame()) {
274                        @SuppressWarnings("unchecked")
275                        @Override
276                        protected void result(Void result) {
277                                assert getFrame().isActive();
278                                log.debug("registered gui listener for {} at {}", eventParam, path);
279                                getOrCreateSideNote(getTree(), lock(), listenersTag).add(listener);
280                        }
281                });
282        }
283
284        @Override
285        public TreePanel getPanel() {
286                if (panel != null) {
287                        return panel;
288                }
289                panel = getTreeAtFrame().preparePanel(param);
290                return panel;
291        }
292
293}
Note: See TracBrowser for help on using the repository browser.