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

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

HIGHLIGHTS:

  • import refactorization: move Tree, Path, etc.

from core to structure package

  • initial serialization implementation
  • improve PrimeExperiment? test
  • many organizational changes and convenience improvements

CHANGELOG:
Make registry in AbstractTree? final.

Move most classes from core to structure package.

Minor changes.

Switch names of Future and FutureHandler?.

Rename ExceptionResultHandler? to ExceptionHandler?.

Rename ExceptionHandler? to ExceptionDispatcherHandler?.

Fix bug in ParamCandidate? cache.

Add missing synchronization to the BufferedDispatcher?.

Develop @Serialized support.

Rework serialization further.

Add serialization/deserialization interface to ValueParam?.

Move getStorageType and isNumeric from Param down to params hierarchy.

Minor changes.

Improve param type induction.

Add TestSerializedClass? for testing new serialization.

Add info files gor GenePool? and Population.

Add standard.expt exemplary netfile.

Add type name field to PropertiesObject?.

Use PropertiesObject? for PropertiesAccess? instead of ordinary map.

Hide getFramsClass is several more places.

More unification accross FramsClass?, Access and Path.

Add ParamCollection?.

Simplify interface for getting params from FramsClass?, Access
or Path.

Make Access.call() interface variadic.

Add arguments(args) convenience wrapper around new Object[] {args}.

Upgrade to apache.commons.lang version 3.1

Minor improvement with Response constructors.

Develop proper result printing in ClientAtServer?.

Add experimentNetsave to PrimeExperiment?.

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