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
RevLine 
[99]1package com.framsticks.gui.tree;
2
3import java.lang.ref.WeakReference;
4import java.util.Iterator;
5import java.util.LinkedList;
6
[100]7import org.apache.logging.log4j.LogManager;
8import org.apache.logging.log4j.Logger;
[99]9
10import com.framsticks.gui.Frame;
11import com.framsticks.gui.ImageProvider;
12import com.framsticks.gui.TreeAtFrame;
[100]13import com.framsticks.gui.TreePanel;
14import com.framsticks.params.Access;
[99]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;
[105]21import com.framsticks.structure.Node;
22import com.framsticks.structure.Path;
23import com.framsticks.structure.SideNoteKey;
24import com.framsticks.structure.Tree;
[99]25import com.framsticks.util.FramsticksException;
[105]26import com.framsticks.util.dispatching.Future;
[99]27import com.framsticks.util.lang.Casting;
28import com.framsticks.util.lang.Containers;
29import com.framsticks.util.swing.TooltipConstructor;
[100]30
[105]31import static com.framsticks.structure.TreeOperations.*;
[99]32
33public class TreeNode extends AbstractNode {
34
[100]35        private static final Logger log = LogManager.getLogger(TreeNode.class);
[99]36
37        protected final WeakReference<Object> reference;
[100]38        protected final int hashCode;
39        protected final TreeAtFrame treeAtFrame;
40        protected final String textual;
[99]41        protected final CompositeParam param;
[100]42        protected TreePanel panel;
[99]43
[100]44        public TreeModel getTreeModel() {
45                return treeAtFrame.getFrame().getTreeModel();
46        }
[99]47
[100]48        /**
49         * @param reference
50         */
[99]51        public TreeNode(TreeAtFrame treeAtFrame, Path path) {
52                path.assureResolved();
[100]53
54                this.reference = new WeakReference<Object>(path.getTopObject());
55                this.textual = path.getTextual();
56                this.treeAtFrame = treeAtFrame;
[99]57                this.param = path.getTop().getParam();
[100]58                hashCode = System.identityHashCode(path.getTopObject());
[99]59
[101]60                if (isMarked(path.getTree(), path.getTopObject(), getTreeModel().createdTag, false)) {
[100]61                        return;
62                }
[99]63
[100]64                // path.getTree().putSideNote(path.getTopObject(), Textual.class, path.getTextual());
[101]65                mark(path.getTree(), path.getTopObject(), getTreeModel().createdTag, true);
[100]66
[99]67                /** Iterate over all EventParams and for matching ValueParams register listeners. */
[100]68                if (path.getTop().getParam() instanceof ObjectParam) {
69                        Access access = bindAccess(path);
[105]70                        for (EventParam eventParam : Containers.filterInstanceof(access.getParams(), EventParam.class)) {
[99]71                                if (!eventParam.getId().endsWith("_changed")) {
72                                        continue;
73                                }
74                                String valueId = eventParam.getId().substring(0, eventParam.getId().length() - 8);
[105]75                                final ValueParam valueParam = Casting.tryCast(ValueParam.class, access.getParam(valueId));
[99]76                                if (valueParam == null) {
77                                        continue;
78                                }
[100]79                                getTreeModel().registerForEventParam(this, path, eventParam, valueParam);
[99]80                        }
81                }
82        }
83
[100]84        @Override
85        public int hashCode() {
86                return hashCode;
[99]87        }
88
89        @Override
[100]90        public boolean equals(Object obj) {
91                if (obj instanceof TreeNode) {
92                        return lock() == ((TreeNode) obj).lock();
[99]93                }
[100]94                return false;
[99]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                }
[100]103                Tree tree = getTree();
104                Access access = bindAccessForTreeObject(referent);
[99]105
106                final int count = access.getCompositeParamCount();
107                if (number >= count) {
108                        throw new FramsticksException().msg("invalid state - no child");
109                }
110
[100]111                /** textual path may be not valid anymore*/
[99]112                CompositeParam childParam = access.getCompositeParam(number);
113
[100]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) {
[99]121                }
[100]122                return new EmptyNode(getFrame(), childParam);
[99]123
[100]124        }
[99]125
[100]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);
[99]140        }
141
142        public Object lock() {
143                return reference.get();
144        }
145
146        @Override
[100]147        public int getIndexOfChild(Object child) {
[99]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                }
[100]157                final Access access = bindAccessForTreeObject(parentObject);
[99]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                }
[100]166                log.debug("{} not found in {}", child, this);
[99]167                return -1;
168        }
169
[100]170        public Frame getFrame() {
171                return getTreeAtFrame().getFrame();
[99]172        }
173
[100]174        public TreeAtFrame getTreeAtFrame() {
175                return treeAtFrame;
176        }
177
[99]178        public Tree getTree() {
[100]179                return getTreeAtFrame().getTree();
[99]180        }
181
[100]182        protected Path assurePath() {
183                return Path.to(getTree(), getTextual()).assureResolved();
184        }
[99]185
186        @Override
187        public String toString() {
[100]188                return getTextual();
[99]189        }
190
[100]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;
[99]202        }
203
204        @Override
[100]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
[99]216        public boolean isLeaf() {
217                Object referent = lock();
218                if (referent == null) {
219                        return true;
220                }
[100]221                return bindAccessForTreeObject(referent).getCompositeParamCount() == 0;
[99]222        }
223
[100]224        protected Access bindAccessForTreeObject(Object child) {
225                return bindAccessFromSideNote(getTree(), child);
[99]226        }
227
228        @Override
229        public void render(TreeCellRenderer renderer) {
230
231                Object child = lock();
[100]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);
[101]239                CompositeParam param = getTree().getSideNote(child, Path.OBJECT_PARAM_KEY);
[100]240                String name = param.getId();
[99]241
[100]242                StringParam nameParam = Casting.tryCast(StringParam.class, access.getParam("name"));
[99]243
[100]244                if (nameParam != null) {
245                        name = access.get(nameParam, String.class);
246                }
[99]247
[100]248                renderer.setToolTipText(new TooltipConstructor()
[105]249                                .append("frams", access.getTypeId())
[99]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)))
[100]255                                .append("size", access.getCompositeParamCount())
[99]256                                .build());
[100]257
258                renderer.setIcon(ImageProvider.loadImage(TreeCellRenderer.findIconName(param)));
[99]259                renderer.setText(name);
[100]260        }
[99]261
[100]262
263        public String getTextual() {
264                return textual;
[99]265        }
266
[101]267        @SuppressWarnings("rawtypes")
268        protected final SideNoteKey<LinkedList> listenersTag = SideNoteKey.make(LinkedList.class);
[100]269
270        protected <A> void tryAddListener(final Path path, final EventParam eventParam, Class<A> argumentType, final EventListener<A> listener) {
[105]271                addListener(path, eventParam, listener, argumentType, new Future<Void>(getFrame()) {
[101]272                        @SuppressWarnings("unchecked")
[100]273                        @Override
274                        protected void result(Void result) {
275                                assert getFrame().isActive();
276                                log.debug("registered gui listener for {} at {}", eventParam, path);
[101]277                                getOrCreateSideNote(getTree(), lock(), listenersTag).add(listener);
[100]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
[99]291}
Note: See TracBrowser for help on using the repository browser.