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

Last change on this file since 193 was 193, checked in by Maciej Komosinski, 10 years ago

Set svn:eol-style native for all textual files

  • Property svn:eol-style set to native
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.