Changeset 310:a6d1b7898871 in finroc_tools_gui-java


Ignore:
Timestamp:
08.06.2017 03:29:16 (22 months ago)
Author:
Max Reichardt <mreichardt@…>
Branch:
17.03
Phase:
public
Message:

Adapts to changes in Finroc 17 dependencies. In particular, improves connection panel and changes mechanism for custom type widget outputs

Files:
1 deleted
11 edited

Legend:

Unmodified
Added
Removed
  • ConnectionPanel.java

    r299 r310  
    4444import java.awt.event.MouseEvent; 
    4545import java.util.ArrayList; 
    46 import java.util.HashSet; 
     46import java.util.HashMap; 
    4747import java.util.List; 
    4848import java.util.Set; 
     
    5656import javax.swing.JScrollPane; 
    5757import javax.swing.JTree; 
     58import javax.swing.SwingUtilities; 
    5859import javax.swing.Timer; 
    5960import javax.swing.UIDefaults; 
     
    6768import org.finroc.core.FrameworkElementFlags; 
    6869import org.finroc.core.port.AbstractPort; 
    69 import org.finroc.core.portdatabase.FinrocTypeInfo; 
     70import org.finroc.core.remote.Definitions; 
    7071import org.finroc.core.remote.HasUid; 
     72import org.finroc.core.remote.ModelNode; 
    7173import org.finroc.core.remote.PortWrapper; 
    7274import org.finroc.core.remote.RemoteFrameworkElement; 
     
    7880import org.finroc.tools.gui.util.ElementFilter; 
    7981import org.finroc.tools.gui.util.gui.MJTree; 
     82import org.rrlib.serialization.rtti.DataTypeBase; 
    8083 
    8184 
     
    121124    private MJTree<Object> startPointTree = null; 
    122125    private Point lastMousePos; 
     126    protected final HashMap<Object, Definitions.TypeConversionRating> highlightedElementRatings = new HashMap<Object, Definitions.TypeConversionRating>(); 
    123127 
    124128    /** Tree node that mouse cursor is currently over - NULL if somewhere else */ 
     
    133137    public static int HEIGHT = 0; 
    134138 
    135     /** Temporary object always returned by getNodeAppearance (allocated here to avoid object allocation whenever getNodeAppearance is called) */ 
     139    /** Temporary object always returned by getNodeAppearance (allocated here to avoid object allocation whenever getNodeAppearance is called; may only be accessed by AWT Thread) */ 
    136140    protected final NodeRenderingStyle tempRenderingStyle = new NodeRenderingStyle(); 
     141 
     142    /** Temporary object always returned by checkConnect (allocated here to avoid object allocation whenever getNodeAppearance is called; may only be accessed by AWT Thread) */ 
     143    protected final CheckConnectResult tempCheckConnectResult = new CheckConnectResult(); 
    137144 
    138145    /** Constant for text color in NodeRenderingStyle that signals that background color should be used */ 
     
    140147 
    141148    static boolean NIMBUS_LOOK_AND_FEEL = Themes.nimbusLookAndFeel(); 
     149 
     150    /** Show hidden elements? */ 
     151    private boolean showHiddenElements = false; 
    142152 
    143153    public ConnectionPanel(Owner win, Font treeFont) { 
     
    163173 
    164174        leftScrollPane = new JScrollPane(leftTree); 
     175        leftScrollPane.getVerticalScrollBar().setUnitIncrement(40); 
    165176        rightScrollPane = new JScrollPane(rightTree); 
     177        rightScrollPane.getVerticalScrollBar().setUnitIncrement(40); 
    166178        leftScrollPane.setPreferredSize(new Dimension(Math.min(1920, Toolkit.getDefaultToolkit().getScreenSize().width) / 4, 0)); 
    167179        rightScrollPane.setPreferredSize(new Dimension(Math.min(1920, Toolkit.getDefaultToolkit().getScreenSize().width) / 4, 0)); 
     
    363375 
    364376        // Which matches exist? 
    365         Set<Object> highlight = new HashSet<Object>(); 
    366         for (Object tn : otherTree.getVisibleObjects()) { 
    367             List<Object> connections = hypotheticalConnection(tn); 
    368             if (connections != null) { 
    369                 highlight.addAll(connections); 
     377        highlightedElementRatings.clear(); 
     378        for (Object otherNode : otherTree.getVisibleObjects()) { 
     379            CheckConnectResult connections = checkConnect(otherNode); 
     380            if (connections.impossibleHint.length() == 0) { 
     381                highlightedElementRatings.put(otherNode, connections.minScore); 
    370382            } 
    371383        } 
    372384 
    373385        // Mark all matches in other tree 
    374         if (highlight.size() > 0) { 
    375             otherTree.setSelectedObjects(new ArrayList<Object>(highlight), false); 
     386        if (highlightedElementRatings.size() > 0) { 
     387            otherTree.setSelectedObjects(new ArrayList<Object>(highlightedElementRatings.keySet()), false); 
    376388            ((GuiTreeCellRenderer)otherTree.getCellRenderer()).showSelectionAfter(400); 
    377389        } else { 
     
    382394        startPoints.clear(); 
    383395        startPointTree = selTree; 
    384         if (highlight.size() > 0) { 
     396        if (highlightedElementRatings.size() > 0) { 
    385397            startPoints.addAll(selTree.getSelectedObjects()); 
    386398        } 
     
    408420     * @return Start point of connection line 
    409421     */ 
    410     private Point getLineStartPoint(MJTree<Object> tree, Object p, ConnectorIcon.LineStart lineStart) { 
     422    protected Point getLineStartPoint(MJTree<Object> tree, Object p, ConnectorIcon.LineStart lineStart) { 
    411423        Rectangle r2 = tree.getObjectBounds(p, true);  // Bounds of tree node 
    412424        Rectangle r = tree.getObjectBounds(p, false);  // Bounds of tree node 
     
    508520 
    509521        saveLastMousePos(e); 
    510         List<Object> hypo = null; 
     522        CheckConnectResult newConnections = null; 
    511523        MJTree<Object> otherTree = selectionFromRight ? leftTree : rightTree; 
    512524        if (startPoints.size() > 0) { 
    513             hypo = hypotheticalConnection(getTreeNodeFromPos(otherTree)); 
    514         } 
    515  
    516         if (hypo == null) { 
     525            newConnections = checkConnect(getTreeNodeFromPos(otherTree)); 
     526        } 
     527 
     528        if (newConnections == null || (newConnections.impossibleHint != null && newConnections.impossibleHint.length() > 0)) { 
    517529            if (otherTree.getSelectionCount() > 0) { 
    518530                otherTree.clearSelection(); 
     
    521533        } else { 
    522534            // connect 
    523             MJTree<Object> selTree = selectionFromRight ? rightTree : leftTree; 
    524             List<Object> srcNodes = selTree.getSelectedObjects(); 
    525             connect(srcNodes, hypo); 
     535            MJTree<Object> selectionTree = selectionFromRight ? rightTree : leftTree; 
     536            List<Object> sourceNodes = selectionTree.getSelectedObjects(); 
     537            connect(sourceNodes, newConnections.partnerNodes); 
    526538            leftTree.setSelectedObjects(null, true); 
    527539            rightTree.setSelectedObjects(null, true); 
     
    585597        if (startPoints.size() > 0 && lastMousePos != null) { 
    586598            MJTree<Object> otherTree = selectionFromRight ? leftTree : rightTree; 
    587             List<Object> drawFat = hypotheticalConnection(getTreeNodeFromPos(otherTree)); 
    588             if (drawFat == null) { 
     599            CheckConnectResult drawFat = checkConnect(getTreeNodeFromPos(otherTree)); 
     600            if (drawFat.partnerNodes.size() == 0) { 
    589601                for (Object p : startPoints) { 
    590602                    drawLine(g, getLineStartPoint(startPointTree, p, ConnectorIcon.LineStart.Default), lastMousePos, Color.BLACK, false, false); 
     
    593605                //((GuiTreeCellRenderer)otherTree.getCellRenderer()).showSelectionAfter(0); 
    594606                for (int i = 0; i < startPoints.size(); i++) { 
    595                     if (drawFat.get(i) != null) { 
    596                         Point p1 = getLineStartPoint(startPointTree, startPoints.get(i), getLineStartPosition(startPoints.get(i), drawFat.get(i))); 
    597                         Point p2 = getLineStartPoint(otherTree, drawFat.get(i), getLineStartPosition(drawFat.get(i), startPoints.get(i))); 
     607                    if (i < drawFat.partnerNodes.size()) { 
     608                        Point p1 = getLineStartPoint(startPointTree, startPoints.get(i), getLineStartPosition(startPoints.get(i), drawFat.partnerNodes.get(i))); 
     609                        Point p2 = getLineStartPoint(otherTree, drawFat.partnerNodes.get(i), getLineStartPosition(drawFat.partnerNodes.get(i), startPoints.get(i))); 
    598610                        drawLine(g, p1, p2, selectedColor, true, false); 
    599611                    } 
     
    681693    } 
    682694 
    683     private void drawLine(Graphics g, Point p1, Point p2, Color c, boolean fat, boolean transparency) { 
     695    protected void drawLine(Graphics g, Point p1, Point p2, Color c, boolean fat, boolean transparency) { 
    684696        Graphics2D g2d = (Graphics2D)g; 
    685697        g.setColor(c); 
     
    703715 
    704716    /** 
     717     * Result of checkConnect() method 
     718     * Used like a struct -> public fields. 
     719     */ 
     720    public static class CheckConnectResult { 
     721 
     722        /** Partner nodes that source nodes (with same index) could/would be connected to */ 
     723        public final ArrayList<Object> partnerNodes = new ArrayList<Object>(); 
     724 
     725        /** Scores for connection from source node #index to partner node #index (-> list has the same size as partnerNodes) */ 
     726        public final ArrayList<Definitions.TypeConversionRating> connectionScores = new ArrayList<Definitions.TypeConversionRating>(); 
     727 
     728        /** Minimum score in connectionScores */ 
     729        public Definitions.TypeConversionRating minScore; 
     730 
     731        /** If there is no suitable combination to connect source nodes to partner nodes: contains hint/reason why not (as may be displayed as tool tip atop tree node) */ 
     732        public String impossibleHint; 
     733    } 
     734 
     735    /** 
    705736     * Get hypothetical connections for selected objects in current tree with visible nodes in other tree 
    706737     * 
    707      * @param tn Tree node in other tree to connect to 
     738     * @param other Tree node in other tree to connect to 
     739     * @param resultBuffer Buffer to write result to (optional). Is returned if provided - otherwise a new object is created. 
    708740     * @return List of nodes to connect to. null if there is no suitable combination. 
    709741     */ 
    710     @SuppressWarnings("unchecked") 
    711     protected List<Object> hypotheticalConnection(Object tn) { 
    712         if (tn == null) { 
    713             return null; 
    714         } 
    715         Object result = hypotheticalConnectionImplementation(tn); 
    716         return result != null && result.getClass().equals(ArrayList.class) ? (ArrayList<Object>)result : null; 
    717     } 
    718  
    719     /** 
    720      * Implementation of hypotheticalConnection() 
    721      * 
    722      * @param tn Tree node in other tree to connect to 
    723      * @return ArrayList<Object> of nodes to connect to. String or null if there is no suitable combination (String contains hint/reason as may be displayed as tool tip atop tn). 
    724      */ 
    725     protected Object hypotheticalConnectionImplementation(Object tn) { 
    726  
    727         MJTree<Object> selTree = selectionFromRight ? rightTree : leftTree; 
     742    protected CheckConnectResult checkConnect(Object other) { 
     743        assert(SwingUtilities.isEventDispatchThread()); 
     744        return checkConnect(other, tempCheckConnectResult); 
     745    } 
     746 
     747    /** 
     748     * Get hypothetical connections for selected objects in current tree with visible nodes in other tree 
     749     * 
     750     * @param other Tree node in other tree to connect to 
     751     * @param Buffer to write result to 
     752     * @return List of nodes to connect to. null if there is no suitable combination. 
     753     */ 
     754    protected CheckConnectResult checkConnect(Object other, CheckConnectResult resultBuffer) { 
     755 
     756        // Init objects 
     757        resultBuffer.partnerNodes.clear(); 
     758        resultBuffer.connectionScores.clear(); 
     759        resultBuffer.minScore = Definitions.TypeConversionRating.IMPOSSIBLE; 
     760        resultBuffer.impossibleHint = ""; 
     761        if (other == null) { 
     762            resultBuffer.impossibleHint = "Partner object is null"; 
     763            return resultBuffer; 
     764        } 
     765 
     766        MJTree<Object> selectionTree = selectionFromRight ? rightTree : leftTree; 
    728767        MJTree<Object> otherTree = selectionFromRight ? leftTree : rightTree; 
    729768 
    730         // can connect to this node? 
    731         List<Object> nodesToConnect = selTree.getSelectedObjects(); 
     769        // Can connect to this node? 
     770        List<Object> nodesToConnect = selectionTree.getSelectedObjects(); 
    732771        boolean canConnect = false; 
    733772        for (Object srcNode : nodesToConnect) { 
    734             canConnect |= canConnect(tn, srcNode); 
     773            canConnect |= canConnect(other, srcNode); 
    735774            if (canConnect) { 
    736775                break; 
     
    738777        } 
    739778        if (!canConnect) { 
    740             return "No selected element in other tree can connect to this one"; 
     779            resultBuffer.impossibleHint = "No selected element in other tree can connect to this one"; 
     780            return resultBuffer; 
    741781        } 
    742782 
    743783        // Find "best" connection 
    744784        List<Object> potentialPartners = otherTree.getVisibleObjects(); 
    745         int startElement = potentialPartners.indexOf(tn); 
     785        int startElement = potentialPartners.indexOf(other); 
    746786        assert(startElement >= 0); 
    747         List<Object> result = new ArrayList<Object>(); 
    748787        for (Object srcNode : nodesToConnect) { 
    749788            int i = startElement; 
     
    752791                Object potentialPartner = potentialPartners.get(i); 
    753792                if (canConnect(srcNode, potentialPartner)) { 
    754                     if (!result.contains(potentialPartner)) { 
     793                    if (!resultBuffer.partnerNodes.contains(potentialPartner)) { 
    755794                        partner = potentialPartners.get(i); 
    756795                        break; 
     
    760799            } while (i != startElement); 
    761800            if (partner == null) { 
    762                 return "No connection partner for '" + srcNode.toString(); 
    763             } 
    764             result.add(partner); 
    765         } 
    766         return result; 
     801                resultBuffer.impossibleHint = "No connection partner for '" + srcNode.toString(); 
     802                resultBuffer.partnerNodes.clear(); 
     803                resultBuffer.connectionScores.clear(); 
     804                return resultBuffer; 
     805            } 
     806            resultBuffer.partnerNodes.add(partner); 
     807            resultBuffer.connectionScores.add(Definitions.TypeConversionRating.NO_CONVERSION); 
     808        } 
     809        resultBuffer.minScore = Definitions.TypeConversionRating.NO_CONVERSION; 
     810        resultBuffer.impossibleHint = ""; 
     811        return resultBuffer; 
    767812    } 
    768813 
     
    935980 
    936981    /** 
     982     * @param show Whether to show hidden elements 
     983     */ 
     984    public void setShowHiddenElements(boolean show) { 
     985        showHiddenElements = show; 
     986    } 
     987 
     988    /** 
    937989     * Rendering style for node in tree 
    938990     */ 
     
    9851037     */ 
    9861038    protected NodeRenderingStyle getNodeAppearance(Object node, MJTree<Object> tree, boolean selected) { 
     1039        assert(SwingUtilities.isEventDispatchThread()); 
    9871040        NodeRenderingStyle result = tempRenderingStyle; 
    9881041        result.reset(); 
     
    9901043            AbstractPort port = ((PortWrapper)node).getPort(); 
    9911044            result.textColor = tree.getBackground(); 
    992             boolean rpc = FinrocTypeInfo.isMethodType(port.getDataType(), true); 
     1045            boolean rpc = (port.getDataType().getTypeTraits() & DataTypeBase.IS_RPC_TYPE) != 0; //FinrocTypeInfo.isMethodType(port.getDataType(), true); 
    9931046            boolean leftTreeRPCServerPort = rpc && port.getFlag(FrameworkElementFlags.ACCEPTS_DATA); 
    9941047            boolean mouseOverFlag = (mouseOver instanceof PortWrapper) && (port == ((PortWrapper)mouseOver).getPort() || port.isConnectedTo(((PortWrapper)mouseOver).getPort())); 
     
    10371090        private final MJTree<Object> parent; 
    10381091 
    1039         /** Default renderer for JTree */ 
    1040         private final DefaultTreeCellRenderer defaultRenderer; 
     1092        /** Default renderer for JTree - and one for invisible nodes */ 
     1093        private final DefaultTreeCellRenderer defaultRenderer, invisibleRenderer; 
    10411094 
    10421095        /** Color for contour */ 
     
    10501103            defaultRenderer = new DefaultTreeCellRenderer(); 
    10511104            defaultRenderer.setBackgroundNonSelectionColor(backgroundColor); 
     1105            invisibleRenderer = new DefaultTreeCellRenderer(); 
     1106            invisibleRenderer.setPreferredSize(new Dimension(1, 0)); 
    10521107            this.rightTree = rightTree; 
    10531108            this.parent = parent; 
     
    10581113        @Override 
    10591114        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { 
     1115            if ((!showHiddenElements) && (value instanceof ModelNode) && ((ModelNode)value).isHidden(true)) { 
     1116                return invisibleRenderer; 
     1117            } 
    10601118            NodeRenderingStyle style = getNodeAppearance(value, parent, !timer.isRunning() && sel); 
    10611119            if (style.nodeColor == null || style.nodeColor.getClass().equals(Color.class)) { 
  • ConnectorIcon.java

    r294 r310  
    6464 
    6565    /** Maximum index for icon cache (see calculation in Type.indexInCache()) */ 
    66     private static final int MAX_INDEX = 1 << 10; 
     66    private static final int MAX_INDEX = 1 << 11; 
    6767 
    6868    /** Available cached icons */ 
     
    114114     */ 
    115115    public static ConnectorIcon getIcon(int iconType, IconColor color, BackgroundColor background, int height) { 
    116         int indexInCache = iconType | color.index << 5 | background.index << 8; // 10 bit: [background color 2 bit][color 3 bit][flags 5 bit] 
     116        int indexInCache = iconType | color.index << 5 | background.index << 9; // 11 bit: [background color 2 bit][color 4 bit][flags 5 bit] 
    117117        ConnectorIcon icon = iconCache[indexInCache]; 
    118118        if (icon == null) { 
  • WidgetOutput.java

    r301 r310  
    2727 
    2828import org.finroc.core.datatype.CoreNumber; 
    29 import org.finroc.core.datatype.DataTypeReference; 
    30 import org.rrlib.logging.Log; 
    31 import org.rrlib.logging.LogLevel; 
    3229import org.rrlib.serialization.BinarySerializable; 
    3330import org.rrlib.serialization.StringInputStream; 
     31import org.rrlib.serialization.StringSerializable; 
     32import org.finroc.core.port.AbstractPort; 
    3433import org.finroc.core.port.Port; 
    3534import org.finroc.core.port.PortCreationInfo; 
    3635import org.finroc.core.port.PortListener; 
    3736import org.finroc.core.port.ThreadLocalCache; 
    38 import org.finroc.core.port.cc.CCPortDataManagerTL; 
    3937import org.finroc.core.port.cc.PortNumeric; 
     38import org.finroc.core.port.std.PortBase; 
    4039import org.finroc.core.port.std.PortDataManager; 
    41 import org.finroc.core.remote.RemoteType; 
    4240 
    4341/** 
     
    140138    public static class Blackboard<T> { /*extends WidgetOutputPort<RawBlackboardClient.WritePort>*/ 
    141139 
    142         /** UID */ 
    143         private static final long serialVersionUID = 2712886077657464267L; 
    144  
     140//        /** UID */ 
     141//        private static final long serialVersionUID = 2712886077657464267L; 
     142// 
    145143//        private transient BlackboardClient<T> c; 
    146144// 
     
    169167    } 
    170168 
     169    /** Custom string serialiazable output */ 
    171170    @SuppressWarnings("rawtypes") 
    172     public static class Custom extends WidgetOutputPort<Port<BinarySerializable>> implements RemoteType.Listener { 
     171    public static class Custom extends WidgetOutputPort<Port<BinarySerializable>> { 
    173172 
    174173        /** UID */ 
    175174        private static final long serialVersionUID = -3991768387448158703L; 
    176175 
    177         /** Port's data type (can be changed) */ 
    178         private DataTypeReference type = new DataTypeReference(); 
    179  
    180         /** List of change listeners - stored in case port is recreated */ 
    181         private transient ArrayList<PortListener> changeListeners; 
    182  
    183176        @Override 
    184177        protected Port createPort() { 
    185             if (type != null && type.get() == null) { 
    186                 RemoteType.addRemoteTypeListener(this); 
    187             } 
    188             PortCreationInfo pci = getPci(); 
    189             if (type == null && pci.dataType != null) { 
    190                 type = new DataTypeReference(pci.dataType); 
    191             } 
    192             return new Port(pci.derive((type == null || type.get() == null) ? CoreNumber.TYPE : type.get())); 
    193         } 
    194  
    195         public void changeDataType(DataTypeReference type) { 
    196             if (frameworkElement != null) { 
    197                 frameworkElement.managedDelete(); 
    198             } 
    199             frameworkElement = null; 
    200             port = null; 
    201             this.type = type; 
    202             restore(getParent()); 
    203             if (changeListeners != null) { 
    204                 for (PortListener listener : changeListeners) { 
    205                     EventRouter.addListener(getPort(), "addPortListenerRaw", listener); 
     178            return Port.wrap(new CustomPort(getPci())); 
     179        } 
     180 
     181        @SuppressWarnings("unchecked") 
     182        public synchronized void publishFromString(String s) throws Exception { 
     183            ArrayList<AbstractPort> result = new ArrayList<>(); 
     184            getPort().getConnectionPartners(result, true, false, false); 
     185            for (AbstractPort destination : result) { 
     186                Port destinationPort = Port.wrap(destination); 
     187                StringSerializable buffer = (StringSerializable)destinationPort.getUnusedBuffer(); 
     188                StringInputStream stream = new StringInputStream(s); 
     189                try { 
     190                    buffer.deserialize(stream); 
     191                    destinationPort.publish((BinarySerializable)buffer); 
     192                } catch (Exception ex) { 
     193                    ((PortDataManager)PortDataManager.getManager(buffer)).recycleUnused(); 
     194                    throw ex; 
    206195                } 
    207196            } 
    208197        } 
    209198 
    210         public synchronized void publishFromString(String s) throws Exception { 
    211             BinarySerializable buffer = asPort().getUnusedBuffer(); 
    212             StringInputStream sis = new StringInputStream(s); 
    213             try { 
    214                 buffer = (BinarySerializable)sis.readObject(buffer, buffer.getClass()); 
    215                 asPort().publish(buffer); 
    216                 buffer = null; 
    217             } catch (Exception ex) { 
    218                 if (asPort().hasCCType()) { 
    219                     ((CCPortDataManagerTL)CCPortDataManagerTL.getManager(buffer)).recycleUnused(); 
    220                 } else { 
    221                     ((PortDataManager)PortDataManager.getManager(buffer)).recycleUnused(); 
    222                 } 
    223                 throw ex; 
    224             } 
    225         } 
    226  
    227         /** 
    228          * @return Port's data type 
    229          */ 
    230         public DataTypeReference getType() { 
    231             return type; 
     199        public StringSerializable getAutoLocked() { 
     200            return (StringSerializable)asPort().getAutoLocked(); 
    232201        } 
    233202 
    234203        public synchronized void addChangeListener(PortListener l) { 
    235204            EventRouter.addListener(getPort(), "addPortListenerRaw", l); 
    236             if (changeListeners == null) { 
    237                 changeListeners = new ArrayList<PortListener>(); 
     205        } 
     206    } 
     207 
     208 
     209    private static class CustomPort extends PortBase { 
     210 
     211        @Override 
     212        public boolean mayConnectTo(AbstractPort target, boolean warnIfImpossible) { 
     213            if (StringSerializable.class.isAssignableFrom(target.getDataType().getJavaClass())) { 
     214                return true; 
    238215            } 
    239             changeListeners.add(l); 
    240         } 
    241  
    242         @Override 
    243         public void remoteTypeAdded(RemoteType t) { 
    244             if (t == type.get()) { 
    245                 changeDataType(type); 
    246             } 
    247         } 
    248  
    249         @Override 
    250         public void dispose() { 
    251             super.dispose(); 
    252             changeListeners = null; 
    253             RemoteType.removeUnknownTypeListener(this); 
    254         } 
    255     } 
     216            return super.mayConnectTo(target, warnIfImpossible); 
     217        } 
     218 
     219        public CustomPort(PortCreationInfo pci) { 
     220            super(adjustPci(pci)); 
     221        } 
     222 
     223        private static PortCreationInfo adjustPci(PortCreationInfo pci) { 
     224            pci.dataType = StringSerializable.TYPE; 
     225            return pci; 
     226        } 
     227    } 
     228 
     229 
    256230 
    257231//  public static class Strings extends WidgetOutputPort<ContainsStrings> { 
  • WidgetPropertiesDialog.java

    r206 r310  
    3232import org.finroc.tools.gui.abstractbase.DataModelListener; 
    3333import org.finroc.tools.gui.util.embeddedfiles.FileManager; 
    34 import org.finroc.tools.gui.util.propertyeditor.FieldAccessor; 
    3534import org.finroc.tools.gui.util.propertyeditor.FieldAccessorFactory; 
    3635import org.finroc.tools.gui.util.propertyeditor.PropertyAccessor; 
    37 import org.finroc.tools.gui.util.propertyeditor.gui.CustomTypePortAccessor; 
    3836import org.finroc.tools.gui.util.propertyeditor.gui.PropertiesDialog; 
    3937 
     
    8381        } 
    8482 
    85         @Override 
    86         protected FieldAccessor customFieldHandling(Field f, Object x) { 
    87             if (f.getType() == WidgetOutput.Custom.class) { 
    88                 return new CustomTypePortAccessor(f, x); 
    89             } 
    90             return null; 
    91         } 
     83//        @Override 
     84//        protected FieldAccessor customFieldHandling(Field f, Object x) { 
     85//            if (f.getType() == WidgetOutput.Custom.class) { 
     86//                return new CustomTypePortAccessor(f, x); 
     87//            } 
     88//            return null; 
     89//        } 
    9290    } 
    9391 
  • util/propertyeditor/gui/DataTypeEditor.java

    r306 r310  
    3636 
    3737import org.finroc.core.datatype.DataTypeReference; 
     38import org.finroc.core.remote.RemoteType; 
    3839import org.finroc.tools.gui.util.propertyeditor.PropertiesPanel; 
    3940import org.finroc.tools.gui.util.propertyeditor.PropertyEditComponent; 
     
    5758        String namespace; 
    5859        String shortName; 
    59         DataTypeReference plainType; 
    60         DataTypeReference listType; 
     60        Object plainType; 
     61        Object listType; 
    6162 
    6263        @Override 
     
    7879    private JCheckBox listTypeSelector; 
    7980 
    80     public DataTypeEditor(DataTypeReference[] values, EnumConstantsImporter importer, PropertiesPanel propPanel) { 
     81    public DataTypeEditor(Object[] values, EnumConstantsImporter importer, PropertiesPanel propPanel) { 
    8182        this.importer = importer; 
    8283        this.propPanel = propPanel; 
    8384 
    8485        // Process types 
    85         for (DataTypeReference value : values) { 
     86        for (Object value : values) { 
     87            if (value.toString().equals(DataTypeBase.NULL_TYPE)) { 
     88                continue; 
     89            } 
     90 
    8691            String longName = value.toString(); 
    8792            boolean listType = longName.startsWith("List<"); 
     
    181186        } 
    182187        TypeEntry entry = (TypeEntry)selectedType; 
    183         return listTypeSelector.isSelected() ? entry.listType : entry.plainType; 
     188        return new DataTypeReference((listTypeSelector.isSelected() ? entry.listType : entry.plainType).toString()); 
    184189    } 
    185190 
     
    218223        } 
    219224        if (importEnumConstants != null) { 
    220             importEnumConstants.setEnabled(getCurEditorValue().get().getEnumConstants() != null); 
    221         } 
     225            TypeEntry entry = (TypeEntry)typeSelector.getSelectedItem(); 
     226            importEnumConstants.setEnabled(entry != null && getEnumConstants(listTypeSelector.isSelected() ? entry.listType : entry.plainType) != null); 
     227        } 
     228    } 
     229 
     230    private Object[] getEnumConstants(Object type) { 
     231        if (type instanceof DataTypeBase) { 
     232            return ((DataTypeBase)type).getEnumConstants(); 
     233        } else if (type instanceof RemoteType) { 
     234            return ((RemoteType)type).getEnumConstants(); 
     235        } 
     236        return null; 
    222237    } 
    223238 
     
    247262                    pec.applyChanges(); 
    248263                } 
    249                 importer.importEnumConstants(getCurEditorValue()); 
     264                TypeEntry entry = (TypeEntry)typeSelector.getSelectedItem(); 
     265                Object type = listTypeSelector.isSelected() ? entry.listType : entry.plainType; 
     266                importer.importEnumConstants(getEnumConstants(type), (type instanceof RemoteType) ? ((RemoteType)type).getEnumValues() : null); 
    250267                for (PropertyEditComponent<?> pec : propPanel.getComponentList()) { 
    251268                    pec.updateValue(); 
  • util/propertyeditor/gui/EnumConstantsImporter.java

    r206 r310  
    2222package org.finroc.tools.gui.util.propertyeditor.gui; 
    2323 
    24 import org.finroc.core.datatype.DataTypeReference; 
    2524 
    2625/** 
     
    3433     * Import enum constants of specified enum class. 
    3534     * 
    36      * @param enumType Enum type to import constants from. 
     35     * @param enumStrings Enum strings 
     36     * @param enumValues Enum values. null if they are the default values. 
    3737     */ 
    38     public void importEnumConstants(DataTypeReference enumType); 
     38    public void importEnumConstants(Object[] enumStrings, long[] enumValues); 
    3939 
    4040    /** 
  • util/propertyeditor/gui/GuiComponentFactory.java

    r214 r310  
    2222package org.finroc.tools.gui.util.propertyeditor.gui; 
    2323 
    24 import java.util.Arrays; 
    2524import java.util.Comparator; 
    2625 
     
    3837import org.finroc.core.datatype.Unit; 
    3938import org.finroc.plugins.data_types.StringList; 
    40 import org.rrlib.serialization.rtti.DataTypeBase; 
    4139 
    4240/** 
     
    7775            wpec = new StringEditor(-1); 
    7876            acc = new StringListAdapter((PropertyAccessor<StringList>)acc); 
    79         } else if (DataTypeReference.class.isAssignableFrom(acc.getType())) { 
    80             DataTypeReference[] types = new DataTypeReference[DataTypeBase.getTypeCount()]; 
    81             for (short i = 0; i < types.length; i++) { 
    82                 types[i] = new DataTypeReference(DataTypeBase.getType(i)); 
    83             } 
    84             Arrays.sort(types, this); 
    85             wpec = new DataTypeEditor(types, (acc instanceof EnumConstantsImporter) ? (EnumConstantsImporter)acc : null, panel); 
    8677        } else if (Unit.class.equals(type)) { 
    8778            wpec = new UnitEditor(); 
  • util/treemodel/InterfaceTreeModel.java

    r300 r310  
    3838import org.finroc.core.RuntimeEnvironment; 
    3939import org.finroc.core.plugin.ExternalConnection; 
     40import org.finroc.core.remote.BufferedModelChanges; 
    4041import org.finroc.core.remote.ModelHandler; 
    4142import org.finroc.core.remote.ModelNode; 
     43import org.finroc.core.remote.ModelOperations; 
    4244import org.finroc.core.remote.RemoteFrameworkElement; 
    4345import org.finroc.core.remote.RemoteRuntime; 
     
    7375    private final ArrayList<ElementToShowInitially> elementsToShowInitially = new ArrayList<ElementToShowInitially>(); 
    7476 
    75     /** Show hidden elements in finstruct (not necessary and confusing for application developers; Finroc developers can be interested) */ 
    76     public final boolean SHOW_HIDDEN_ELEMENTS = false; 
    77  
    7877    public InterfaceTreeModel() { 
    7978        externalConnectionParent.init(); 
     
    107106            } 
    108107            if (qualifiedName.charAt(rootString.length()) == separator) { 
    109                 return root.getChildByQualifiedName(qualifiedName, rootString.length() + 1, separator); 
     108                return root.getChildByQualifiedName(qualifiedName, rootString.length() + 1, separator, false); 
     109            } 
     110        } 
     111        return null; 
     112    } 
     113 
     114    /** 
     115     * Returns a child with the specified qualified name 
     116     * 
     117     * @param qualifiedName Qualified name (Names of elements separated with separator char) 
     118     * @param separator Separator 
     119     * @param returnDeepestAncestorElement If element with specified link is not in tree, return element whose link has the longest match with qualified name 
     120     * @return Child with the specified qualified name. Null if no such child exists. 
     121     */ 
     122    public ModelNode getChildByQualifiedName(String qualifiedName, char separator, boolean returnDeepestAncestorElement) { 
     123        String rootString = root.toString(); 
     124        if (qualifiedName.startsWith(rootString)) { 
     125            if (qualifiedName.length() == rootString.length()) { 
     126                return root; 
     127            } 
     128            if (qualifiedName.charAt(rootString.length()) == separator) { 
     129                return root.getChildByQualifiedName(qualifiedName, rootString.length() + 1, separator, returnDeepestAncestorElement); 
    110130            } 
    111131        } 
     
    165185    } 
    166186 
    167     /** Helper enum for ModelHandler implementation below: Opcodes */ 
    168     private enum Operation { ADD, CHANGE, REMOVE, REPLACE, SETMODEL } 
    169  
    170187    /** Helper enum for ModelHandler implementation below: Remote framework element classes in sorting order */ 
    171     private enum ElementClass { SENSOR_INTERFACE, CONTROLLER_INTERFACE, INTERFACE, PARAMETER_INTERFACE, NONPORT, PORT, HIDDEN } 
     188    private enum ElementClass { SENSOR_INTERFACE, CONTROLLER_INTERFACE, INTERFACE, PARAMETER_INTERFACE, NONPORT, PORT } 
    172189 
    173190    /** 
     
    189206     * Model handler for single external connection 
    190207     */ 
    191     class SingleInterfaceHandler implements ModelHandler, Comparator<ModelNode> { 
     208    class SingleInterfaceHandler implements ModelHandler, Comparator<ModelNode>, ModelOperations { 
    192209 
    193210        /** Root node for this interface */ 
     
    195212 
    196213        @Override 
     214        public void applyModelChanges(BufferedModelChanges bufferedChanges) { 
     215            if (bufferedChanges.empty()) { 
     216                return; 
     217            } 
     218            if (SwingUtilities.isEventDispatchThread()) { 
     219                bufferedChanges.executeOperations(this); 
     220            } else { 
     221                bufferedChanges.setModelOperationsForRun(this); 
     222                SwingUtilities.invokeLater(bufferedChanges); 
     223            } 
     224        } 
     225 
     226        @Override 
    197227        public void addNode(ModelNode parent, ModelNode newChild) { 
    198             callOperation(Operation.ADD, parent, newChild, null); 
     228            markHiddenElements(newChild); 
     229            sortNewTreeNode(newChild); 
     230            checkForElementsToShow(newChild); 
     231 
     232            if (newChild.getParent() == parent) { 
     233                return; 
     234            } 
     235 
     236            // use alphabetic sorting for framework elements (with interfaces at the front) 
     237            if (parent instanceof RemoteFrameworkElement) { 
     238                for (int i = 0; i < parent.getChildCount(); i++) { 
     239                    ModelNode child = parent.getChildAt(i); 
     240                    if (compare(newChild, child) < 0) { 
     241 
     242                        //InterfaceTreeModel.this.insertNodeInto(newChild, parent, i); 
     243                        parent.insertChild(i, newChild); 
     244                        TreeModelEvent event = new TreeModelEvent(InterfaceTreeModel.this, getTreePath(parent), new int[] {i}, new Object[] {newChild}); 
     245                        for (int j = listener.size() - 1; j >= 0; j--) { 
     246                            listener.get(j).treeNodesInserted(event); 
     247                        } 
     248                        return; 
     249                    } 
     250                } 
     251            } 
     252 
     253 
     254            int index = parent.getChildCount(); 
     255 
     256            //InterfaceTreeModel.this.insertNodeInto(newChild, parent, index); 
     257            parent.add(newChild); 
     258            TreeModelEvent event = new TreeModelEvent(InterfaceTreeModel.this, getTreePath(parent), new int[] {index}, new Object[] {newChild}); 
     259            for (int j = listener.size() - 1; j >= 0; j--) { 
     260                listener.get(j).treeNodesInserted(event); 
     261            } 
    199262        } 
    200263 
    201264        @Override 
    202265        public void changeNodeName(ModelNode node, String newName) { 
    203             callOperation(Operation.CHANGE, node, null, newName); 
     266            node.setName(newName); 
     267 
     268            //InterfaceTreeModel.this.nodeChanged(node1); 
     269            TreeModelEvent event = new TreeModelEvent(InterfaceTreeModel.this, getTreePath(node.getParent()), new int[] {node.getParent().indexOf(node)}, new Object[] {node}); 
     270            for (int j = listener.size() - 1; j >= 0; j--) { 
     271                listener.get(j).treeNodesChanged(event); 
     272            } 
    204273        } 
    205274 
     
    207276        public void removeNode(ModelNode childToRemove) { 
    208277            assert(childToRemove != null); 
    209             callOperation(Operation.REMOVE, childToRemove, null, null); 
     278            ModelNode parent = childToRemove.getParent(); 
     279            if (parent != null) { 
     280                parent.remove(childToRemove); 
     281                /*index = parent.getIndex(node1); 
     282                parent.remove(index);*/ 
     283                //modelHandler.getTreeModel().nodesWereRemoved(this, new int[]{index}, new TreeNode[]{child});   // doesn't work :-( => occasional NullPointerExceptions 
     284 
     285                //InterfaceTreeModel.this.nodeStructureChanged(parent); 
     286                TreeModelEvent event = new TreeModelEvent(InterfaceTreeModel.this, getTreePath(parent)); 
     287                for (int j = listener.size() - 1; j >= 0; j--) { 
     288                    if (j < listener.size()) { 
     289                        listener.get(j).treeStructureChanged(event); 
     290                    } 
     291                } 
     292            } 
    210293        } 
    211294 
     
    213296        public void replaceNode(ModelNode oldNode, ModelNode newNode) { 
    214297            assert(oldNode != null && newNode != null); 
    215             callOperation(Operation.REPLACE, oldNode, newNode, null); 
     298            ModelNode parent = oldNode.getParent(); 
     299            if (parent != null) { 
     300                markHiddenElements(newNode); 
     301                sortNewTreeNode(newNode); 
     302                checkForElementsToShow(newNode); 
     303                parent.replace(oldNode, newNode); 
     304                /*index = parent.getIndex(node1); 
     305                assert(index >= 0); 
     306                parent.remove(node1); 
     307                parent.insert(node2, index);*/ 
     308 
     309                //InterfaceTreeModel.this.nodeStructureChanged(parent); 
     310                TreeModelEvent event = new TreeModelEvent(InterfaceTreeModel.this, getTreePath(parent)); 
     311                for (int j = listener.size() - 1; j >= 0; j--) { 
     312                    listener.get(j).treeStructureChanged(event); 
     313                } 
     314            } 
    216315        } 
    217316 
    218317        @Override 
    219318        public void setModelRoot(final ModelNode newRoot) { 
    220             callOperation(Operation.SETMODEL, newRoot, null, null); 
     319            if (this.root != null) { 
     320                replaceNode(this.root, newRoot); 
     321            } else { 
     322                addNode(InterfaceTreeModel.this.root, newRoot); 
     323            } 
    221324        } 
    222325 
     
    227330            } else { 
    228331                SwingUtilities.invokeLater(updateTask); 
    229             } 
    230         } 
    231  
    232         /** 
    233          * We forward all operations to this method to avoid having many inner classes. 
    234          * 
    235          * @param operation Operation to perform 
    236          * @param node1 First node 
    237          * @param node2 Second node (optional) 
    238          * @param name Name (optional) 
    239          */ 
    240         private void callOperation(final Operation operation, final ModelNode node1, final ModelNode node2, final String name) { 
    241             if (SwingUtilities.isEventDispatchThread()) { 
    242                 callOperationImplementation(operation, node1, node2, name); 
    243             } 
    244             SwingUtilities.invokeLater(new Runnable() { 
    245                 @Override 
    246                 public void run() { 
    247                     callOperationImplementation(operation, node1, node2, name); 
    248                 } 
    249             }); 
    250         } 
    251  
    252         /** 
    253          * Implementation of all operations. 
    254          * 
    255          * @param operation Operation to perform 
    256          * @param node1 First node 
    257          * @param node2 Second node (optional) 
    258          * @param name Name (optional) 
    259          */ 
    260         private void callOperationImplementation(Operation operation, ModelNode node1, ModelNode node2, String name) { 
    261             switch (operation) { 
    262             case ADD: 
    263                 ModelNode parent = node1; 
    264                 ModelNode newChild = node2; 
    265                 markHiddenElements(newChild); 
    266                 sortNewTreeNode(newChild); 
    267                 checkForElementsToShow(newChild); 
    268  
    269                 if (newChild.getParent() == parent) { 
    270                     return; 
    271                 } 
    272  
    273                 // use alphabetic sorting for framework elements (with interfaces at the front) 
    274                 if (parent instanceof RemoteFrameworkElement) { 
    275                     for (int i = 0; i < parent.getChildCount(); i++) { 
    276                         ModelNode child = parent.getChildAt(i); 
    277                         if (compare(newChild, child) < 0) { 
    278  
    279                             //InterfaceTreeModel.this.insertNodeInto(newChild, parent, i); 
    280                             parent.insertChild(i, newChild); 
    281                             TreeModelEvent event = new TreeModelEvent(InterfaceTreeModel.this, getTreePath(parent), new int[] {i}, new Object[] {newChild}); 
    282                             for (int j = listener.size() - 1; j >= 0; j--) { 
    283                                 listener.get(j).treeNodesInserted(event); 
    284                             } 
    285                             return; 
    286                         } 
    287                     } 
    288                 } 
    289  
    290  
    291                 int index = parent.getChildCount(); 
    292  
    293                 //InterfaceTreeModel.this.insertNodeInto(newChild, parent, index); 
    294                 parent.add(newChild); 
    295                 TreeModelEvent event = new TreeModelEvent(InterfaceTreeModel.this, getTreePath(parent), new int[] {index}, new Object[] {newChild}); 
    296                 for (int j = listener.size() - 1; j >= 0; j--) { 
    297                     listener.get(j).treeNodesInserted(event); 
    298                 } 
    299                 break; 
    300             case CHANGE: 
    301                 node1.setName(name); 
    302  
    303                 //InterfaceTreeModel.this.nodeChanged(node1); 
    304                 event = new TreeModelEvent(InterfaceTreeModel.this, getTreePath(node1.getParent()), new int[] {node1.getParent().indexOf(node1)}, new Object[] {node1}); 
    305                 for (int j = listener.size() - 1; j >= 0; j--) { 
    306                     listener.get(j).treeNodesChanged(event); 
    307                 } 
    308                 break; 
    309             case REMOVE: 
    310                 parent = node1.getParent(); 
    311                 if (parent != null) { 
    312                     parent.remove(node1); 
    313                     /*index = parent.getIndex(node1); 
    314                     parent.remove(index);*/ 
    315                     //modelHandler.getTreeModel().nodesWereRemoved(this, new int[]{index}, new TreeNode[]{child});   // doesn't work :-( => occasional NullPointerExceptions 
    316  
    317                     //InterfaceTreeModel.this.nodeStructureChanged(parent); 
    318                     event = new TreeModelEvent(InterfaceTreeModel.this, getTreePath(parent)); 
    319                     for (int j = listener.size() - 1; j >= 0; j--) { 
    320                         if (j < listener.size()) { 
    321                             listener.get(j).treeStructureChanged(event); 
    322                         } 
    323                     } 
    324                 } 
    325                 break; 
    326             case REPLACE: 
    327                 parent = node1.getParent(); 
    328                 if (parent != null) { 
    329                     markHiddenElements(node2); 
    330                     sortNewTreeNode(node2); 
    331                     checkForElementsToShow(node2); 
    332                     parent.replace(node1, node2); 
    333                     /*index = parent.getIndex(node1); 
    334                     assert(index >= 0); 
    335                     parent.remove(node1); 
    336                     parent.insert(node2, index);*/ 
    337  
    338                     //InterfaceTreeModel.this.nodeStructureChanged(parent); 
    339                     event = new TreeModelEvent(InterfaceTreeModel.this, getTreePath(parent)); 
    340                     for (int j = listener.size() - 1; j >= 0; j--) { 
    341                         listener.get(j).treeStructureChanged(event); 
    342                     } 
    343                 } 
    344                 break; 
    345             case SETMODEL: 
    346                 if (this.root != null) { 
    347                     callOperationImplementation(Operation.REPLACE, this.root, node1, null); 
    348                 } else { 
    349                     callOperationImplementation(Operation.ADD, InterfaceTreeModel.this.root, node1, null); 
    350                 } 
    351                 this.root = node1; 
    352                 break; 
    353332            } 
    354333        } 
     
    360339        private ElementClass getNodeClass(ModelNode node) { 
    361340            if (node instanceof RemoteFrameworkElement) { 
    362                 if (node.isHidden(false)) { 
    363                     return ElementClass.HIDDEN; 
    364                 } 
    365341                RemoteFrameworkElement element = (RemoteFrameworkElement)node; 
    366342                if (element.getFlag(FrameworkElementFlags.PORT)) { 
     
    386362         */ 
    387363        private void markHiddenElements(ModelNode node) { 
    388             if (SHOW_HIDDEN_ELEMENTS) { 
    389                 return; 
    390             } 
    391364            if (node instanceof RemoteFrameworkElement && ((RemoteFrameworkElement)node).isTagged(FrameworkElementTags.HIDDEN_IN_TOOLS)) { 
    392365                node.setHidden(true); 
     
    463436    } 
    464437 
     438//    /** 
     439//     * (may only be called by AWT thread) 
     440//     * @return All remote runtimes in this tree model 
     441//     */ 
     442//    public ArrayList<RemoteRuntime> getAllRemoteRuntimes() { 
     443//        ArrayList<RemoteRuntime> result = new ArrayList<>(); 
     444//        getAllRemoteRuntimes(result, getRoot(), 3); 
     445//        return result; 
     446//    } 
     447// 
     448//    /** 
     449//     * Helper for getAllRemoteRuntimes() 
     450//     * 
     451//     * @param result Result list 
     452//     * @param currentNode Node to process 
     453//     * @param remainingLevels Remaining levels (depth) to process 
     454//     */ 
     455//    private void getAllRemoteRuntimes(ArrayList<RemoteRuntime> result, ModelNode currentNode, int remainingLevels) { 
     456//        for (int i = 0; i < currentNode.getChildCount(); i++) { 
     457//            ModelNode child = currentNode.getChildAt(i); 
     458//            if (child instanceof RemoteRuntime) { 
     459//                result.add((RemoteRuntime)child); 
     460//            } 
     461//            if (remainingLevels >= 1) { 
     462//                getAllRemoteRuntimes(result, child, remainingLevels - 1); 
     463//            } 
     464//        } 
     465//    } 
     466 
     467 
    465468    @Override 
    466469    public Object getChild(Object parent, int index) { 
     
    470473    @Override 
    471474    public int getChildCount(Object parent) { 
    472         if (parent instanceof RemoteRuntime) { 
    473             // only return number of non-hidden elements 
    474             for (int i = 0; i < ((ModelNode)parent).getChildCount(); i++) { 
    475                 ModelNode child = ((ModelNode)parent).getChildAt(i); 
    476                 if (child.isHidden(false)) { 
    477                     return i; 
    478                 } 
    479             } 
    480         } 
    481475        return ((ModelNode)parent).getChildCount(); 
    482476    } 
  • util/treemodel/RemoteRemoteRuntime.java

    r293 r310  
    2222package org.finroc.tools.gui.util.treemodel; 
    2323 
    24 import java.util.ArrayList; 
    2524import java.util.HashMap; 
    26 import java.util.List; 
    2725 
    2826import javax.swing.event.TreeModelEvent; 
     
    3230import org.finroc.core.FrameworkElementFlags; 
    3331import org.finroc.core.RuntimeEnvironment; 
    34 import org.finroc.core.FrameworkElement.Flag; 
    3532import org.finroc.core.admin.AdminClient; 
    36 import org.finroc.core.datatype.FrameworkElementInfo; 
     33import org.finroc.core.net.generic_protocol.RemoteRuntime; 
    3734import org.finroc.core.port.AbstractPort; 
    3835import org.finroc.core.port.Port; 
    3936import org.finroc.core.port.PortCreationInfo; 
    4037import org.finroc.core.port.PortListener; 
    41 import org.finroc.core.port.net.NetPort; 
     38import org.finroc.core.remote.BufferedModelChanges; 
     39import org.finroc.core.remote.FrameworkElementInfo; 
    4240import org.finroc.core.remote.ModelHandler; 
    4341import org.finroc.core.remote.ModelNode; 
     42import org.finroc.core.remote.RemoteConnector; 
    4443import org.finroc.core.remote.RemoteFrameworkElement; 
    4544import org.finroc.core.remote.RemotePort; 
    46 import org.finroc.core.remote.RemoteRuntime; 
    47 import org.finroc.core.remote.RemoteTypes; 
    4845import org.rrlib.logging.Log; 
    4946import org.rrlib.logging.LogLevel; 
    5047import org.rrlib.serialization.BinaryInputStream; 
    5148import org.rrlib.serialization.MemoryBuffer; 
     49import org.rrlib.serialization.SerializationInfo; 
    5250 
    5351/** 
     
    8078    private final ModelHandler handler; 
    8179 
    82     /** Framework element that contains all global links - possibly NULL */ 
    83     private FrameworkElement globalLinks; 
    84  
    8580    /** Id of protocol that this runtime is connected by */ 
    8681    private final String protocolId; 
     
    9388     * (should only be accessed by reader thread of management connection) 
    9489     */ 
    95     private HashMap<Integer, NetPort> remotePortRegister = new HashMap<Integer, NetPort>(); 
     90    //private HashMap<Integer, NetPort> remotePortRegister = new HashMap<Integer, NetPort>(); 
    9691 
    9792    public RemoteRemoteRuntime(String name, String uuid, AdminClient adminClient, String protocolId, ModelNode nodeInParentInterface, InterfaceTreeModel treeModel, ModelHandler handler) { 
    98         super(name, uuid, adminClient != null ? adminClient : new AdminClient("AdminClient", getFrameworkElementForThisRuntime(uuid)), new RemoteTypes()); 
     93        super(getCommonParent(), uuid, adminClient == null, 12); 
     94        if (adminClient != null) { 
     95            this.adminInterface = adminClient; 
     96        } 
    9997        this.frameworkElement = this.getAdminInterface().getParent(); 
    10098        this.nodeInParentInterface = nodeInParentInterface; 
     
    107105 
    108106    public void delete() { 
     107        super.delete(); 
    109108        treeModel.removeTreeModelListener(this); 
    110         if (this.getParent() != null) { 
    111             handler.removeNode(this); 
     109        if (currentModelNode != null && currentModelNode.getParent() != null) { 
     110            BufferedModelChanges changes = new BufferedModelChanges(); 
     111            changes.removeNode(currentModelNode); 
     112            getModelHandler().applyModelChanges(changes); 
    112113        } 
    113114    } 
     
    134135     * (only to be called in constructor) 
    135136     * 
    136      * @param uuid Uuid (passed as super constructor has not been called yet) 
    137      * @return Framework element that contains all elements for managing and accessing this runtime 
    138      */ 
    139     private static synchronized FrameworkElement getFrameworkElementForThisRuntime(String uuid) { 
     137     * @return Framework element that contains all elements for managing and accessing this remote runtimes 
     138     */ 
     139    private static synchronized FrameworkElement getCommonParent() { 
    140140        if (accessPortParent == null) { 
    141141            accessPortParent = new FrameworkElement(RuntimeEnvironment.getInstance(), "Remote Runtime Access"); 
    142142            accessPortParent.init(); 
    143143        } 
    144         FrameworkElement frameworkElement = new FrameworkElement(accessPortParent, uuid); 
    145         frameworkElement.init(); 
    146         return frameworkElement; 
     144        return accessPortParent; 
    147145    } 
    148146 
     
    194192            parent = new ModelNode(protocolId); 
    195193            protocolParentNodeRegister.put(protocolId, parent); 
    196             handler.addNode(treeModelRootNode, parent); 
     194 
     195            BufferedModelChanges changes = new BufferedModelChanges(); 
     196            changes.addNode(treeModelRootNode, parent); 
     197            handler.applyModelChanges(changes); 
    197198        } 
    198199        return parent; 
     
    204205            // Interpret remote structure 
    205206            boolean initial = (this.getParent() == null); 
    206             processStructurePacket(value); 
    207  
    208             if (initial) { 
    209                 ModelNode parent = getProtocolParentNode(handler, treeModel.getRoot(), protocolId); 
    210                 handler.addNode(parent, this); 
     207            try { 
     208                processStructurePacket(value); 
     209 
     210                if (initial) { 
     211                    ModelNode parent = getProtocolParentNode(handler, treeModel.getRoot(), protocolId); 
     212                    BufferedModelChanges changes = new BufferedModelChanges(); 
     213                    changes.addNode(parent, currentModelNode); 
     214                    getModelHandler().applyModelChanges(changes); 
     215                } 
     216            } catch (Exception e) { 
     217                e.printStackTrace(); 
    211218            } 
    212219        } 
     
    219226     * @param structureBufferToProcess Buffer containing serialized structure changes 
    220227     */ 
    221     public void processStructurePacket(MemoryBuffer structureBufferToProcess) { 
     228    public void processStructurePacket(MemoryBuffer structureBufferToProcess) throws Exception { 
    222229        FrameworkElementInfo info = new FrameworkElementInfo(); 
    223         BinaryInputStream stream = new BinaryInputStream(structureBufferToProcess, BinaryInputStream.TypeEncoding.Names); 
     230        BinaryInputStream stream = new BinaryInputStream(structureBufferToProcess, new SerializationInfo()); 
    224231        while (stream.moreDataAvailable()) { 
    225232            byte opcode = stream.readByte(); 
    226233            if (opcode == 0) { 
    227                 info.deserialize(stream, FrameworkElementInfo.StructureExchange.FINSTRUCT); 
     234                info.deserialize(stream, true); 
    228235                //Log.log(LogLevel.DEBUG, info.getLink(0).name); 
    229                 addRemoteStructure(info, this.getParent() == null); 
     236                addRemoteStructure(info); 
    230237                int x = stream.readInt(); 
    231238                if (x != 0x58585858) { 
     
    298305    } 
    299306 
    300     /** 
    301      * @return Framework element that contains all global links (possibly created by call to this) 
    302      */ 
    303     public FrameworkElement getGlobalLinkElement() { 
    304         if (globalLinks == null) { 
    305             globalLinks = new FrameworkElement(frameworkElement, "global", Flag.NETWORK_ELEMENT | Flag.GLOBALLY_UNIQUE_LINK | Flag.ALTERNATIVE_LINK_ROOT, -1); 
    306         } 
    307         return globalLinks; 
    308     } 
    309  
    310307    final char SEPARATOR = 1; 
    311  
    312     /** Extra edge provider implementation for this remote runtime */ 
    313     class ExtraEdgeProvider implements NetPort.ExtraEdgeProvider { 
    314  
    315         private final ArrayList<FrameworkElementInfo.ConnectionInfo> destinations; 
    316  
    317         public ExtraEdgeProvider(ArrayList<FrameworkElementInfo.ConnectionInfo> destinations) { 
    318             this.destinations = destinations; 
    319         } 
    320  
    321         @Override 
    322         public int getRemoteEdgeDestinations(List<AbstractPort> resultList) { 
    323             for (int i = 0; i < destinations.size(); i++) { 
    324                 NetPort pp = remotePortRegister.get(destinations.get(i).handle); 
    325                 if (pp != null) { 
    326                     resultList.add(pp.getPort()); 
    327                 } 
    328             } 
    329             return 0; 
    330         } 
    331     } 
    332308 
    333309    /** 
     
    335311     * 
    336312     * @param info Info on another remote framework element 
    337      * @param initalStructure Is this call originating from initial structure exchange? 
    338      * @param remoteRuntime Remote runtime object to add structure to 
    339      */ 
    340     void addRemoteStructure(FrameworkElementInfo info, boolean initalStructureExchange) { 
     313     */ 
     314    public void addRemoteStructure(FrameworkElementInfo info) { 
    341315        Log.log(LogLevel.DEBUG_VERBOSE_1, this, "Adding element: " + info.toString()); 
     316        org.finroc.core.remote.RemoteRuntime remoteRuntime = newModelNode; 
    342317        if (info.isPort()) { 
    343318            ModelNode portNode = nodeInParentInterface.getChildByQualifiedName("Internal Ports" + SEPARATOR + (((long)info.getHandle()) & 0xFFFFFFFFL), SEPARATOR); 
     
    346321            } 
    347322            if (portNode instanceof RemotePort) { 
    348                 NetPort netport = ((RemotePort)portNode).getPort().asNetPort(); 
    349                 remotePortRegister.put(info.getHandle(), netport); 
    350                 // add edges 
    351                 netport.setExtraEdgeProvider(new ExtraEdgeProvider(info.copyConnections())); 
     323                //NetPort netport = ((RemotePort)portNode).getPort().asNetPort(); 
     324                //remotePortRegister.put(info.getHandle(), netport); 
    352325                //ProxyPort port = new ProxyPort(info); 
     326 
    353327                for (int i = 0; i < info.getLinkCount(); i++) { 
    354                     RemoteFrameworkElement remoteElement = new RemotePort(info.getHandle(), info.getLink(i).name, ((RemotePort)portNode).getPort(), i); 
     328                    RemoteFrameworkElement remoteElement = new RemotePort(info.getHandle(), info.getLink(i).name, ((RemotePort)portNode).getPort(), i, info.getDataType()); 
    355329                    if (i == 0) { 
    356                         this.elementLookup.put(info.getHandle(), remoteElement); 
     330                        remoteRuntime.setElementLookupEntry(info.getHandle(), remoteElement); 
    357331                    } 
    358332                    remoteElement.setName(info.getLink(i).name); 
     
    360334                    remoteElement.setFlags(info.getFlags()); 
    361335                    ModelNode parent = getFrameworkElement(info.getLink(0).parent); 
    362                     if (initalStructureExchange) { 
    363                         parent.add(remoteElement); 
    364                     } else { 
    365                         //handler.addNode(parent, remoteElement); 
    366                         //uninitializedRemotePorts.add(port); 
    367                     } 
     336                    parent.add(remoteElement); 
    368337                } 
    369338                Log.log(LogLevel.DEBUG, this, "Found port for: " + info.toString()); 
     339 
     340                // add edges 
     341                if (info.getOwnedConnectors() != null) { 
     342                    for (RemoteConnector connector : info.getOwnedConnectors()) { 
     343                        remoteRuntime.addConnector(connector); 
     344                    } 
     345                } 
    370346            } else { 
    371347                Log.log(LogLevel.WARNING, this, "Could not find the port for: " + info.toString()); 
    372348            } 
    373349        } else { 
    374             RemoteFrameworkElement remoteElement = getFrameworkElement(info.getHandle()); 
    375             remoteElement.setName(info.getLink(0).name); 
    376             remoteElement.setTags(info.getTags()); 
    377             remoteElement.setFlags(info.getFlags()); 
    378             ModelNode parent = getFrameworkElement(info.getLink(0).parent); 
    379             if (initalStructureExchange) { 
    380                 parent.add(remoteElement); 
    381             } else { 
    382                 handler.addNode(parent, remoteElement); 
    383             } 
     350            super.addRemoteStructure(info, true, null); 
    384351        } 
    385352    } 
     
    394361     */ 
    395362    public RemoteFrameworkElement getFrameworkElement(int handle) { 
    396         RemoteFrameworkElement remoteElement = this.elementLookup.get(handle); 
    397         if (remoteElement == null) { 
    398             remoteElement = new RemoteFrameworkElement(handle, "(unknown)"); 
    399             this.elementLookup.put(handle, remoteElement); 
    400         } 
    401         return remoteElement; 
     363        return currentModelNode.obtainFrameworkElement(handle); 
     364    } 
     365 
     366    @Override 
     367    public void createNewModel() { 
     368        // TODO Auto-generated method stub 
     369 
     370    } 
     371 
     372    @Override 
     373    public void disconnect() { 
     374        // TODO Auto-generated method stub 
     375 
     376    } 
     377 
     378    @Override 
     379    public ModelHandler getModelHandler() { 
     380        // TODO 
     381        return handler; 
    402382    } 
    403383 
  • widgets/ComboBox.java

    r301 r310  
    2626import java.awt.event.ActionListener; 
    2727import java.io.Serializable; 
     28import java.util.ArrayList; 
    2829 
    2930import javax.swing.JComboBox; 
     
    3839 
    3940import org.finroc.core.FrameworkElementFlags; 
    40 import org.finroc.core.datatype.DataTypeReference; 
    4141import org.finroc.core.port.AbstractPort; 
    4242import org.finroc.core.port.PortCreationInfo; 
    4343import org.finroc.core.port.PortListener; 
     44import org.finroc.core.remote.RemotePort; 
     45import org.finroc.core.remote.RemoteType; 
    4446import org.rrlib.logging.Log; 
    4547import org.rrlib.logging.LogLevel; 
     
    7678 
    7779    @Override 
    78     public void importEnumConstants(DataTypeReference enumType) { 
     80    public void importEnumConstants(Object[] enumStrings, long[] enumValues) { 
     81 
     82        // Check whether anything needs to be changed 
     83        if (choices.size() == enumStrings.length) { 
     84            int i = 0; 
     85            boolean equal = true; 
     86            for (Object o : enumStrings) { 
     87                long value = enumValues == null ? i : enumValues[i]; 
     88                String customOutput = (o instanceof Enum<?>) ? Serialization.serialize((Enum<?>)o) : (o.toString() + " (" + value + ")"); 
     89                equal |= customOutput.equals(choices.get(i).name); 
     90                i++; 
     91            } 
     92            if (equal) { 
     93                return; 
     94            } 
     95        } 
     96 
    7997        choices.clear(); 
    8098        int i = 0; 
    81         for (Object o : enumType.get().getEnumConstants()) { 
    82             String customOutput = (o instanceof Enum<?>) ? Serialization.serialize((Enum<?>)o) : (o.toString() + " (" + i + ")"); 
    83             choices.add(new ComboBoxElement(o.toString(), i, i, i, customOutput)); 
     99        for (Object o : enumStrings) { 
     100            long value = enumValues == null ? i : enumValues[i]; 
     101            String customOutput = (o instanceof Enum<?>) ? Serialization.serialize((Enum<?>)o) : (o.toString() + " (" + value + ")"); 
     102            choices.add(new ComboBoxElement(o.toString(), value, value, value, customOutput)); 
    84103            i++; 
    85104        } 
     
    121140        private static final long serialVersionUID = -8663762048760660960L; 
    122141 
    123         JComboBox comboBox = new JComboBox(); 
     142        JComboBox<ComboBoxElement> comboBox = new JComboBox<>(); 
    124143        boolean updatingFromReversePush = true; 
    125144 
     
    171190        public void run() { 
    172191            for (ComboBoxElement cbe : choices) { 
     192 
     193                // Auto-import enum constants on reverse push 
     194                if (customOutput.getPort().isConnected()) { 
     195                    ArrayList<AbstractPort> result = new ArrayList<>(); 
     196                    customOutput.getPort().getConnectionPartners(result, true, false, false); 
     197                    for (AbstractPort destination : result) { 
     198                        RemotePort[] remotePorts = RemotePort.get(destination); 
     199                        if (remotePorts != null) { 
     200                            RemoteType type = remotePorts[0].getDataType(); 
     201                            if (type.isEnum()) { 
     202                                importEnumConstants(type.getEnumConstants(), type.getEnumValues()); 
     203                                break; 
     204                            } 
     205                        } 
     206                    } 
     207                } 
     208 
    173209                if ((output1.getDouble() == cbe.output1 || !output1.getPort().isConnected()) && 
    174210                        (output2.getDouble() == cbe.output2 || !output2.getPort().isConnected()) && 
     
    178214                    comboBox.setSelectedItem(cbe); 
    179215                    updatingFromReversePush = false; 
     216                    releaseAllLocks(); 
    180217                    return; 
    181218                } 
  • widgets/ValueInputField.java

    r302 r310  
    3232import javax.swing.event.CaretListener; 
    3333 
    34 import org.finroc.tools.gui.GUIPanel; 
    3534import org.finroc.tools.gui.Widget; 
    3635import org.finroc.tools.gui.WidgetOutput; 
     
    3938 
    4039import org.finroc.core.FrameworkElementFlags; 
    41 import org.finroc.core.datatype.CoreNumber; 
    42 import org.finroc.core.datatype.DataTypeReference; 
    4340import org.finroc.core.port.AbstractPort; 
    4441import org.finroc.core.port.PortCreationInfo; 
     
    6966    @Override 
    7067    protected PortCreationInfo getPortCreationInfo(PortCreationInfo suggestion, WidgetPort<?> forPort) { 
    71         return suggestion.derive(suggestion.flags | FrameworkElementFlags.PUSH_STRATEGY_REVERSE).derive(value.getType() == null ? CoreNumber.TYPE : null); 
     68        return suggestion.derive(suggestion.flags | FrameworkElementFlags.PUSH_STRATEGY_REVERSE); 
    7269    } 
    7370 
Note: See TracChangeset for help on using the changeset viewer.