View Javadoc
1   package org.opentrafficsim.editor.extensions.map;
2   
3   import java.rmi.RemoteException;
4   
5   import org.djunits.value.vdouble.scalar.Direction;
6   import org.djutils.draw.point.OrientedPoint2d;
7   import org.djutils.draw.point.Point2d;
8   import org.djutils.event.Event;
9   import org.djutils.event.EventListener;
10  import org.djutils.event.reference.ReferenceType;
11  import org.opentrafficsim.base.geometry.BoundingCircle;
12  import org.opentrafficsim.base.geometry.OtsBounds2d;
13  import org.opentrafficsim.draw.network.NodeAnimation.NodeData;
14  import org.opentrafficsim.editor.OtsEditor;
15  import org.opentrafficsim.editor.XsdTreeNode;
16  import org.opentrafficsim.editor.extensions.Adapters;
17  
18  /**
19   * NodeData for the editor Map.
20   * <p>
21   * Copyright (c) 2023-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
22   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
23   * </p>
24   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
25   */
26  public class MapNodeData extends MapData implements NodeData, EventListener
27  {
28  
29      /** */
30      private static final long serialVersionUID = 20231003L;
31  
32      /** Bounds. */
33      private static final OtsBounds2d BOUNDS = new BoundingCircle(1.0);
34  
35      /** String attribute. */
36      private String id = "";
37  
38      /** Coordinate attribute. */
39      private Point2d coordinate = null;
40  
41      /** Direction attribute. */
42      private Direction direction = null;
43  
44      /** Location. */
45      private OrientedPoint2d location = new OrientedPoint2d(0.0, 0.0);
46  
47      /**
48       * Constructor.
49       * @param map Map; map.
50       * @param nodeNode XsdTreeNode; node Ots.Network.Node.
51       * @param editor OtsEditor; editor.
52       */
53      public MapNodeData(final EditorMap map, final XsdTreeNode nodeNode, final OtsEditor editor)
54      {
55          super(map, nodeNode, editor);
56          getNode().addListener(this, XsdTreeNode.ATTRIBUTE_CHANGED, ReferenceType.WEAK);
57          // for when node is duplicated, set data immediately
58          try
59          {
60              if (getNode().isActive())
61              {
62                  notify(new Event(XsdTreeNode.ATTRIBUTE_CHANGED, new Object[] {getNode(), "Id", null}));
63                  notify(new Event(XsdTreeNode.ATTRIBUTE_CHANGED, new Object[] {getNode(), "Coordinate", null}));
64                  notify(new Event(XsdTreeNode.ATTRIBUTE_CHANGED, new Object[] {getNode(), "Direction", null}));
65              }
66          }
67          catch (RemoteException e)
68          {
69              throw new RuntimeException(e);
70          }
71      }
72  
73      /** {@inheritDoc} */
74      @Override
75      public OtsBounds2d getBounds()
76      {
77          return BOUNDS;
78      }
79  
80      /** {@inheritDoc} */
81      @Override
82      public String getId()
83      {
84          return this.id;
85      }
86      
87      /** {@inheritDoc} */
88      @Override
89      public void destroy()
90      {
91          super.destroy();
92          getNode().removeListener(this, XsdTreeNode.ATTRIBUTE_CHANGED);
93      }
94  
95      /** {@inheritDoc} */
96      @Override
97      public OrientedPoint2d getLocation()
98      {
99          return this.location;
100     }
101 
102     /** {@inheritDoc} */
103     @Override
104     public void notify(final Event event) throws RemoteException
105     {
106         String attribute = (String) ((Object[]) event.getContent())[1];
107         String value = getNode().getAttributeValue(attribute);
108         if ("Id".equals(attribute))
109         {
110             this.id = value == null ? "" : value;
111             return;
112         }
113         else if ("Coordinate".equals(attribute))
114         {
115             setValue((v) -> this.coordinate = v, Adapters.get(Point2d.class), getNode(), "Coordinate");
116         }
117         else if ("Direction".equals(attribute))
118         {
119             setValue((v) -> this.direction = v, Adapters.get(Direction.class), getNode(), "Direction");
120         }
121         else
122         {
123             return;
124         }
125         setLocation();
126     }
127 
128     /** {@inheritDoc} */
129     @Override
130     public void evalChanged()
131     {
132         this.id = getNode().getId() == null ? "" : getNode().getId();
133         setValue((v) -> this.coordinate = v, Adapters.get(Point2d.class), getNode(), "Coordinate");
134         setValue((v) -> this.direction = v, Adapters.get(Direction.class), getNode(), "Direction");
135         setLocation();
136     }
137 
138     /**
139      * Set the location from the coordinate and direction. Notify when invalid or valid.
140      */
141     private void setLocation()
142     {
143         if (this.coordinate == null)
144         {
145             setInvalid();
146             return;
147         }
148         this.location = new OrientedPoint2d(this.coordinate, this.direction == null ? 0.0 : this.direction.si);
149         setValid();
150     }
151 
152     /** {@inheritDoc} */
153     @Override
154     public String toString()
155     {
156         return "Node " + this.id;
157     }
158 
159 }