Xcos MVC: implement model.sim and anticipating on future model properties. 60/14960/8
Paul Bignier [Tue, 29 Jul 2014 09:59:50 +0000 (11:59 +0200)]
Change-Id: I5abcc4e3ef69118c5f90fcb9a417839e4b0367da

14 files changed:
scilab/modules/scicos/Makefile.am
scilab/modules/scicos/includes/utilities.hxx
scilab/modules/scicos/macros/scicos_scicos/scicos_model.sci
scilab/modules/scicos/src/c/scicos.vcxproj
scilab/modules/scicos/src/c/scicos.vcxproj.filters
scilab/modules/scicos/src/cpp/LoggerView.cpp
scilab/modules/scicos/src/cpp/Model_getObjectProperties.cpp
scilab/modules/scicos/src/cpp/Model_setObjectProperties.cpp
scilab/modules/scicos/src/cpp/model/BaseObject.hxx
scilab/modules/scicos/src/cpp/model/Block.hxx
scilab/modules/scicos/src/cpp/model/Port.hxx
scilab/modules/scicos/src/cpp/view_scilab/ModelAdapter.cpp
scilab/modules/scicos/src/cpp/view_scilab/ports_management.cpp [deleted file]
scilab/modules/scicos/src/cpp/view_scilab/ports_management.hxx

index cd00a8e..0fd4a6e 100644 (file)
@@ -29,8 +29,7 @@ src/cpp/view_scilab/ModelAdapter.cpp \
 src/cpp/view_scilab/ParamsAdapter.cpp \
 src/cpp/view_scilab/ScsAdapter.cpp \
 src/cpp/view_scilab/StateAdapter.cpp \
-src/cpp/view_scilab/TextAdapter.cpp \
-src/cpp/view_scilab/ports_management.cpp
+src/cpp/view_scilab/TextAdapter.cpp
 
 
 SCICOS_C_SOURCES = \
index 842debd..c0530ed 100644 (file)
@@ -102,6 +102,9 @@ enum object_properties_t
     PORT_KIND,          //!< model::Port::kind value
     IMPLICIT,           //!< model::Port::implicit value
     PORT_NUMBER,        //!< model::Port::portNumber value
+    DATATYPE_ROWS,      //!< model::Port::in value
+    DATATYPE_COLS,      //!< model::Port::in2 value
+    DATATYPE_TYPE,      //!< model::Port::intyp value
     CONNECTED_SIGNALS,  //!< model::Port::connectedSignals value
 };
 
index a0c4d87..37dd574 100644 (file)
@@ -26,10 +26,10 @@ function model=scicos_model(v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15,v
     if exists("sim","local")==0 then sim="",end
     if exists("in","local")==0 then in=[],end
     if exists("in2","local")==0 then in2=[],end
-    if exists("intyp","local")==0 then intyp=1,end
+    if exists("intyp","local")==0 then intyp=[],end
     if exists("out","local")==0 then out=[],end
     if exists("out2","local")==0 then out2=[],end
-    if exists("outtyp","local")==0 then outtyp=1,end
+    if exists("outtyp","local")==0 then outtyp=[],end
     if exists("evtin","local")==0 then evtin=[],end
     if exists("evtout","local")==0 then evtout=[],end
     if exists("state","local")==0 then state=[],end
index baa2f62..02c682e 100644 (file)
@@ -267,7 +267,6 @@ lib /DEF:"$(ProjectDir)differential_equations_f_Import.def" /SUBSYSTEM:WINDOWS /
     <ClCompile Include="..\cpp\view_scilab\ScsAdapter.cpp" />
     <ClCompile Include="..\cpp\view_scilab\StateAdapter.cpp" />
     <ClCompile Include="..\cpp\view_scilab\TextAdapter.cpp" />
-    <ClCompile Include="..\cpp\view_scilab\ports_management.cpp" />
     <ClCompile Include="copyvarfromlistentry.c" />
     <ClCompile Include="createblklist.c" />
     <ClCompile Include="DllmainScicos.c" />
index a926a99..7b43603 100644 (file)
     <ClCompile Include="..\cpp\view_scilab\BlockAdapter.cpp">
       <Filter>Source Files\MVC\view_scilab</Filter>
     </ClCompile>
-    <ClCompile Include="..\cpp\view_scilab\ports_management.cpp">
-      <Filter>Source Files\MVC\view_scilab</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\sci_gateway\cpp\sci_scicos_new.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
index 22bd132..8a626f6 100644 (file)
@@ -158,6 +158,15 @@ static std::ostream& operator<<(std::ostream& os, object_properties_t p)
         case PORT_NUMBER:
             os << "PORT_NUMBER";
             break;
+        case DATATYPE_ROWS:
+            os << "DATATYPE_ROWS";
+            break;
+        case DATATYPE_COLS:
+            os << "DATATYPE_COLS";
+            break;
+        case DATATYPE_TYPE:
+            os << "DATATYPE_TYPE";
+            break;
         case CONNECTED_SIGNALS:
             os << "CONNECTED_SIGNALS";
             break;
index 4bb2e78..d86ce29 100644 (file)
@@ -94,6 +94,9 @@ bool Model::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, int
         model::Block* o = static_cast<model::Block*>(getObject(uid));
         switch (p)
         {
+            case SIM_FUNCTION_API:
+                o->getSimFunctionApi(v);
+                return true;
             default:
                 break;
         }
@@ -199,6 +202,9 @@ bool Model::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std
         model::Block* o = static_cast<model::Block*>(getObject(uid));
         switch (p)
         {
+            case SIM_FUNCTION_NAME:
+                o->getSimFunctionName(v);
+                return true;
             case STYLE:
                 o->getStyle(v);
                 return true;
@@ -415,7 +421,7 @@ bool Model::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std
     return false;
 }
 
-bool Model::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector< std::string >& v)
+bool Model::getObjectProperty(ScicosID uid, kind_t k, object_properties_t p, std::vector<std::string>& v)
 {
 
     if (k == ANNOTATION)
index 8332edc..de6f5de 100644 (file)
@@ -91,6 +91,10 @@ update_status_t Model::setObjectProperty(ScicosID uid, kind_t k, object_properti
         model::Block* o = static_cast<model::Block*>(getObject(uid));
         switch (p)
         {
+            case SIM_FUNCTION_API:
+            {
+                return o->setSimFunctionApi(v);
+            }
             default:
                 break;
         }
@@ -248,6 +252,8 @@ update_status_t Model::setObjectProperty(ScicosID uid, kind_t k, object_properti
         model::Block* o = static_cast<model::Block*>(getObject(uid));
         switch (p)
         {
+            case SIM_FUNCTION_NAME:
+                return o->setSimFunctionName(v);
             case STYLE:
                 return o->setStyle(v);
             case LABEL:
index cba3389..68a98bc 100644 (file)
@@ -110,14 +110,18 @@ struct Datatype
 {
 public:
     Datatype(unsigned int datatype, unsigned int r, unsigned c) :
-        datatype_id(datatype), rows(r), collumns(c)
+        datatype_id(datatype), rows(r), columns(c)
     {
     }
 
-    const unsigned int datatype_id;
-    const unsigned int rows;
-    const unsigned int collumns;
+    const int datatype_id;
+    const int rows;
+    const int columns;
 
+    bool operator==(const Datatype& d) const
+    {
+        return datatype_id == d.datatype_id && rows == d.rows && columns == d.columns;
+    }
 };
 
 /** @}*/
index 9d0561f..a1dce6d 100644 (file)
@@ -77,14 +77,14 @@ enum blocktype_t
     BLOCKTYPE_H = 'h', //!< N/A ; used to represent blocks composed by blocks
     BLOCKTYPE_L = 'l', //!< synchronization block ; ifthenelse and eselect
     BLOCKTYPE_M = 'm', //!< memorization block ; see the Scicos original paper
-    BLOCKTYPE_X = 'x', //!< derivable block without state ; these blocks will be treated as if they contains a state.
+    BLOCKTYPE_X = 'x', //!< derivable block without state ; these blocks will be treated as if they contain a state.
     BLOCKTYPE_Z = 'z', //!< zero-crossing block ; see the Scicos original paper.
 };
 
 struct Descriptor
 {
     std::string functionName;
-    char functionApi;
+    int functionApi;
 
     char dep_ut;            //!< dep_ut_t masked value
     char blocktype;         //!< one of blocktype_t value
@@ -350,6 +350,38 @@ private:
         return SUCCESS;
     }
 
+    void getSimFunctionName(std::string& data) const
+    {
+        data = sim.functionName;
+    }
+
+    update_status_t setSimFunctionName(const std::string& data)
+    {
+        if (data == sim.functionName)
+        {
+            return NO_CHANGES;
+        }
+
+        sim.functionName = data;
+        return SUCCESS;
+    }
+
+    void getSimFunctionApi(int& data) const
+    {
+        data = sim.functionApi;
+    }
+
+    update_status_t setSimFunctionApi(const int data)
+    {
+        if (data == sim.functionApi)
+        {
+            return NO_CHANGES;
+        }
+
+        sim.functionApi = data;
+        return SUCCESS;
+    }
+
 private:
     ScicosID parentDiagram;
     std::string interfaceFunction;
index 72d2e76..e6cf3f5 100644 (file)
@@ -33,9 +33,10 @@ class Port: public BaseObject
     friend class ::org_scilab_modules_scicos::Model;
 
 private:
-    Port() : BaseObject(PORT), dataType(0), sourceBlock(0), kind(UNDEF), implicit(false), style(), label(), connectedSignals() {};
-    Port(const Port& o) : BaseObject(PORT), dataType(o.dataType), sourceBlock(o.sourceBlock),
-        kind(o.kind), implicit(o.implicit), style(o.style), label(o.label), connectedSignals(o.connectedSignals) {};
+    Port() : BaseObject(PORT), dataType(0), sourceBlock(0), kind(UNDEF), implicit(false),
+        style(), label(), connectedSignals() {};
+    Port(const Port& o) : BaseObject(PORT), dataType(o.dataType), sourceBlock(o.sourceBlock), kind(o.kind), implicit(o.implicit),
+        style(o.style), label(o.label), connectedSignals(o.connectedSignals) {};
     ~Port() {};
 
     const std::vector<ScicosID>& getConnectedSignals() const
index 1ccc2da..f2dc0e9 100644 (file)
  *
  */
 
+#include "list.hxx"
+#include "double.hxx"
+#include "string.hxx"
+
+#include "Controller.hxx"
 #include "ModelAdapter.hxx"
+#include "ports_management.hxx"
 
 namespace org_scilab_modules_scicos
 {
 namespace view_scilab
 {
 
+struct sim
+{
+
+    static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
+    {
+        model::Block* adaptee = adaptor.getAdaptee();
+
+        // First, extact the function Name
+        std::string name;
+        controller.getObjectProperty(adaptee->id(), adaptee->kind(), SIM_FUNCTION_NAME, name);
+        types::String* Name = new types::String(1, 1);
+        Name->set(0, name.data());
+
+        // Then the Api. If it is zero, then just return the Name. Otherwise, return a list containing both.
+        int api;
+        controller.getObjectProperty(adaptee->id(), adaptee->kind(), SIM_FUNCTION_API, api);
+
+        if (api == 0)
+        {
+            return Name;
+        }
+        else
+        {
+            types::Double* Api = new types::Double(1, 1, (double) api);
+            types::List* o = new types::List();
+            o->set(0, Name);
+            o->set(1, Api);
+            return o;
+        }
+    }
+
+    static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
+    {
+        model::Block* adaptee = adaptor.getAdaptee();
+
+        if (v->getType() == types::InternalType::ScilabString)
+        {
+            types::String* current = v->getAs<types::String>();
+            if (current->getSize() != 1)
+            {
+                return false;
+            }
+
+            char* c_str = wide_string_to_UTF8(current->get(0));
+            std::string name = std::string(c_str);
+            FREE(c_str);
+
+            // If the input is a scalar string, then the functionApi is 0.
+            int api = 0;
+
+            controller.setObjectProperty(adaptee->id(), adaptee->kind(), SIM_FUNCTION_NAME, name);
+            controller.setObjectProperty(adaptee->id(), adaptee->kind(), SIM_FUNCTION_API, api);
+        }
+        else if (v->getType() == types::InternalType::ScilabList)
+        {
+            // If the input is a 2-sized list, then it must be string and positive integer.
+            types::List* current = v->getAs<types::List>();
+            if (current->getSize() != 2)
+            {
+                return false;
+            }
+            if (current->get(0)->getType() != types::InternalType::ScilabString || current->get(1)->getType() != types::InternalType::ScilabDouble)
+            {
+                return false;
+            }
+
+            types::String* Name = current->get(0)->getAs<types::String>();
+            if (Name->getSize() != 1)
+            {
+                return false;
+            }
+            char* c_str = wide_string_to_UTF8(Name->get(0));
+            std::string name = std::string(c_str);
+            FREE(c_str);
+
+            types::Double* Api = current->get(1)->getAs<types::Double>();
+            if (Api->getSize() != 1)
+            {
+                return false;
+            }
+            double api = Api->get(0);
+            if (floor(api) != api)
+            {
+                return false;
+            }
+            int api_int = (int) api;
 
+            controller.setObjectProperty(adaptee->id(), adaptee->kind(), SIM_FUNCTION_NAME, name);
+            controller.setObjectProperty(adaptee->id(), adaptee->kind(), SIM_FUNCTION_API, api_int);
+        }
+        else
+        {
+            return false;
+        }
+        return true;
+    }
+};
 
 template<> property<ModelAdapter>::props_t property<ModelAdapter>::fields = property<ModelAdapter>::props_t();
 
@@ -27,6 +129,11 @@ ModelAdapter::ModelAdapter(const ModelAdapter& o) :
 ModelAdapter::ModelAdapter(org_scilab_modules_scicos::model::Block* o) :
     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(o)
 {
+    if (property<ModelAdapter>::properties_has_not_been_set())
+    {
+        property<ModelAdapter>::fields.reserve(1);
+        property<ModelAdapter>::add_property(L"sim", &sim::get, &sim::set);
+    }
 }
 
 ModelAdapter::~ModelAdapter()
diff --git a/scilab/modules/scicos/src/cpp/view_scilab/ports_management.cpp b/scilab/modules/scicos/src/cpp/view_scilab/ports_management.cpp
deleted file mode 100644 (file)
index f11463d..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- *  Copyright (C) 2014 - Scilab Enterprises - Paul Bignier
- *  Copyright (C) 2014 - Scilab Enterprises - Clement DAVID
- *
- *  This file must be used under the terms of the CeCILL.
- *  This source file is licensed as described in the file COPYING, which
- *  you should have received as part of this distribution.  The terms
- *  are also available at
- *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
- *
- */
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "internal.hxx"
-#include "double.hxx"
-#include "string.hxx"
-
-#include "ports_management.hxx"
-
-namespace org_scilab_modules_scicos
-{
-namespace view_scilab
-{
-
-static const wchar_t E[] = L"E";
-static const wchar_t I[] = L"I";
-
-types::InternalType* get_ports_property(const GraphicsAdapter& adaptor, object_properties_t port_kind, const Controller& controller, object_properties_t p)
-{
-    model::Block* adaptee = adaptor.getAdaptee();
-
-    // Retrieve the identifiers
-    std::vector<ScicosID> ids;
-    controller.getObjectProperty(adaptee->id(), adaptee->kind(), p, ids);
-
-    // Translate identifiers to return values
-    int i = 0;
-    switch (p)
-    {
-        case CONNECTED_SIGNALS:
-        {
-            double* v;
-            types::Double* o = new types::Double(ids.size(), 1, &v);
-
-            ScicosID diagram;
-            controller.getObjectProperty(adaptee->id(), adaptee->kind(), PARENT_DIAGRAM, diagram);
-
-            std::vector<ScicosID> children;
-            controller.getObjectProperty(diagram, DIAGRAM, CHILDREN, children);
-
-            for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
-            {
-                ScicosID id;
-                controller.getObjectProperty(*it, PORT, p, id);
-
-                std::vector<ScicosID>::iterator found = std::find(children.begin(), children.end(), id);
-
-                if (found != children.end())
-                {
-                    v[i] = std::distance(found, children.begin());
-                }
-                else
-                {
-                    v[i] = 0;
-                }
-            }
-            return o;
-        }
-        case STYLE:
-        case LABEL:
-        {
-            types::String* o = new types::String(ids.size(), 1);
-            for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
-            {
-                std::string s;
-                controller.getObjectProperty(*it, PORT, p, s);
-                o->set(i, s.data());
-            }
-            return o;
-        }
-        case IMPLICIT:
-        {
-            types::String* o = new types::String(ids.size(), 1);
-            for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
-            {
-                bool v;
-                controller.getObjectProperty(*it, PORT, p, v);
-                o->set(i, (v == false) ? E : I);
-            }
-            return o;
-        }
-        default:
-            return 0;
-    }
-}
-
-bool set_ports_property(const GraphicsAdapter& adaptor, object_properties_t port_kind, Controller& controller, object_properties_t p, types::InternalType* v)
-{
-    model::Block* adaptee = adaptor.getAdaptee();
-
-    // Retrieve the ports identifiers
-    std::vector<ScicosID> ids;
-    controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, ids);
-
-    if (v->getType() == types::InternalType::ScilabString)
-    {
-        types::String* current = v->getAs<types::String>();
-        if (current->getCols() != 0 && current->getCols() != 1)
-        {
-            return false;
-        }
-
-        size_t rows = current->getRows();
-        if (rows != ids.size())
-        {
-            return false;
-        }
-
-        int i = 0;
-        switch (p)
-        {
-            case IMPLICIT:
-            {
-                for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
-                {
-                    if (current->get(i) == I)
-                    {
-                        controller.setObjectProperty(*it, PORT, p, true);
-                    }
-                    else if (current->get(i) == E)
-                    {
-                        controller.setObjectProperty(*it, PORT, p, false);
-                    }
-                    else
-                    {
-                        return false;
-                    }
-                }
-                return true;
-            }
-            case STYLE:
-            case LABEL:
-            {
-                std::vector<std::string> style = std::vector<std::string>(current->getSize());
-                for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
-                {
-                    char* c_str = wide_string_to_UTF8(current->get(i));
-                    style[i] = std::string(c_str);
-                    FREE(c_str);
-                    controller.setObjectProperty(*it, PORT, p, style[i]);
-                }
-                return true;
-            }
-            default:
-                return false;
-        }
-    }
-    else if (v->getType() == types::InternalType::ScilabDouble)
-    {
-        types::Double* current = v->getAs<types::Double>();
-        if (current->getRows() != 0 || current->getCols() != 0)
-        {
-            return false;
-        }
-        if (ids.size() != 0)
-        {
-            return false;
-        }
-        // Do nothing, because if the sizes match, then there are already zero concerned ports, so no ports to update
-        return true;
-    }
-    return false;
-}
-
-bool update_ports_with_property(const GraphicsAdapter& adaptor, object_properties_t port_kind, Controller& controller, object_properties_t p, types::InternalType* v)
-{
-    model::Block* adaptee = adaptor.getAdaptee();
-
-    if (v->getType() != types::InternalType::ScilabDouble)
-    {
-        return false;
-    }
-    types::Double* value = v->getAs<types::Double>();
-
-    ScicosID parentDiagram;
-    controller.getObjectProperty(adaptee->id(), BLOCK, PARENT_DIAGRAM, parentDiagram);
-
-    std::vector<ScicosID> children;
-    if (parentDiagram != 0)
-    {
-        controller.getObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
-    }
-
-    std::vector<int> newPorts = std::vector<int>(value->getSize());
-    double* d = value->getReal();
-    for (std::vector<int>::iterator it = newPorts.begin(); it != newPorts.end(); ++it, ++d)
-    {
-        if (0 > *d && *d >= children.size())
-        {
-            return false;
-        }
-
-        *it = (int) * d;
-    }
-    std::vector<ScicosID> deletedObjects;
-
-    // retrieve old data
-    std::vector<ScicosID> oldPorts;
-    controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, oldPorts);
-    std::vector<ScicosID> previousPorts = oldPorts;
-
-    if (p != CONNECTED_SIGNALS)
-    {
-        // FIXME: implement port creation for the blk.model
-        return false;
-    }
-
-    // updated ports
-    while (!oldPorts.empty() || !newPorts.empty())
-    {
-        ScicosID oldPort = oldPorts.back();
-        oldPorts.pop_back();
-        int newPort = newPorts.back();
-        newPorts.pop_back();
-
-        ScicosID oldSignal;
-        controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, oldSignal);
-        ScicosID newSignal = children[newPort];
-
-        if (oldSignal != newSignal)
-        {
-            // disconnect the old link
-            ScicosID oldSignalSrc;
-            controller.getObjectProperty(oldSignal, LINK, SOURCE_PORT, oldSignalSrc);
-            ScicosID oldSignalDst;
-            controller.getObjectProperty(oldSignal, LINK, DESTINATION_PORT, oldSignalDst);
-
-            ScicosID unconnected = 0;
-            if (oldSignalSrc == oldPort)
-            {
-                controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected);
-            }
-            else // oldSignalDst == oldPort
-            {
-                controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected);
-            }
-            // Link de-association is not performed as the link will be removed
-
-            // connect the new link
-            controller.setObjectProperty(newSignal, LINK, SOURCE_PORT, 0);
-            controller.setObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, newSignal);
-
-            children.erase(std::find(children.begin(), children.end(), oldSignal));
-            deletedObjects.push_back(oldSignal);
-        }
-    }
-
-    // removed ports
-    if (!oldPorts.empty())
-    {
-        previousPorts.erase(previousPorts.begin() + oldPorts.size(), previousPorts.end());
-
-        while (!oldPorts.empty())
-        {
-            ScicosID oldPort = oldPorts.back();
-            oldPorts.pop_back();
-
-            ScicosID signal;
-            controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, signal);
-            if (signal != 0)
-            {
-                // the link is connected, disconnect the other side
-                ScicosID oldSignalSrc;
-                controller.getObjectProperty(signal, LINK, SOURCE_PORT, oldSignalSrc);
-                ScicosID oldSignalDst;
-                controller.getObjectProperty(signal, LINK, DESTINATION_PORT, oldSignalDst);
-
-                ScicosID unconnected = 0;
-                if (oldSignalSrc == oldPort)
-                {
-                    controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected);
-                }
-                else     // oldSignalDst == oldPort
-                {
-                    controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected);
-                }
-
-                children.erase(std::find(children.begin(), children.end(), signal));
-                deletedObjects.push_back(signal);
-            }
-
-            deletedObjects.push_back(oldPort);
-        }
-
-        controller.setObjectProperty(adaptee->id(), BLOCK, port_kind, previousPorts);
-    }
-
-    // added ports
-    if (!newPorts.empty())
-    {
-        while (!newPorts.empty())
-        {
-            int newPort = newPorts.back();
-            oldPorts.pop_back();
-
-            ScicosID id = controller.createObject(PORT);
-            controller.setObjectProperty(id, PORT, SOURCE_BLOCK, adaptee->id());
-            // set the connected signal if applicable
-            if (newPort != 0)
-            {
-                ScicosID signal = children[newPort];
-                controller.setObjectProperty(id, PORT, CONNECTED_SIGNALS, signal);
-            }
-
-            previousPorts.push_back(id);
-        }
-
-        controller.setObjectProperty(adaptee->id(), BLOCK, port_kind, previousPorts);
-    }
-
-    // remove objects from the model after de-association
-    if (parentDiagram != 0)
-    {
-        controller.setObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
-    }
-    for (std::vector<ScicosID>::iterator it = deletedObjects.begin(); it != deletedObjects.end(); ++it)
-    {
-        controller.deleteObject(*it);
-    }
-
-    return true;
-}
-
-} /* view_scilab */
-} /* namespace org_scilab_modules_scicos */
index 492be05..23f9ffe 100644 (file)
 
 #include <string>
 #include <vector>
+#include <algorithm>
 
 #include "internal.hxx"
+#include "double.hxx"
+#include "string.hxx"
 
 #include "Controller.hxx"
-#include "GraphicsAdapter.hxx"
 
 namespace org_scilab_modules_scicos
 {
@@ -30,21 +32,370 @@ namespace view_scilab
 /*
  * Return a Scilab encoded value for a property.
  */
-types::InternalType* get_ports_property(const GraphicsAdapter& adaptor, object_properties_t port_kind, const Controller& controller, object_properties_t p);
+template<typename Adaptor>
+types::InternalType* get_ports_property(const Adaptor& adaptor, object_properties_t port_kind, const Controller& controller, object_properties_t p)
+{
+    static const wchar_t E[] = L"E";
+    static const wchar_t I[] = L"I";
+    model::Block* adaptee = adaptor.getAdaptee();
+
+    // Retrieve the identifiers
+    std::vector<ScicosID> ids;
+    controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, ids);
+
+    // Translate identifiers to return values
+    int i = 0;
+    switch (p)
+    {
+        case CONNECTED_SIGNALS:
+        {
+            double* v;
+            types::Double* o = new types::Double(ids.size(), 1, &v);
+
+            ScicosID diagram;
+            controller.getObjectProperty(adaptee->id(), adaptee->kind(), PARENT_DIAGRAM, diagram);
+
+            std::vector<ScicosID> children;
+            controller.getObjectProperty(diagram, DIAGRAM, CHILDREN, children);
+
+            for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
+            {
+                ScicosID id;
+                controller.getObjectProperty(*it, PORT, p, id);
+
+                std::vector<ScicosID>::iterator found = std::find(children.begin(), children.end(), id);
+
+                if (found != children.end())
+                {
+                    v[i] = std::distance(found, children.begin());
+                }
+                else
+                {
+                    v[i] = 0;
+                }
+            }
+            return o;
+        }
+        case STYLE:
+        case LABEL:
+        {
+            types::String* o = new types::String(ids.size(), 1);
+            for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
+            {
+                std::string s;
+                controller.getObjectProperty(*it, PORT, p, s);
+                o->set(i, s.data());
+            }
+            return o;
+        }
+        case IMPLICIT:
+        {
+            types::String* o = new types::String(ids.size(), 1);
+            for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
+            {
+                bool v;
+                controller.getObjectProperty(*it, PORT, p, v);
+                o->set(i, (v == false) ? E : I);
+            }
+            return o;
+        }
+        case DATATYPE_ROWS:
+        case DATATYPE_COLS:
+        case DATATYPE_TYPE:
+        {
+            types::Double* o = new types::Double(ids.size(), 1);
+            for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
+            {
+                double v;
+                controller.getObjectProperty(*it, PORT, p, v);
+                o[i] = v;
+            }
+            return o;
+        }
+        default:
+            return 0;
+    }
+}
 
 /*
  * Set a Scilab encoded values as a property.
  *
  * \note this method will return false if one of the ports does not exist
  */
-bool set_ports_property(const GraphicsAdapter& adaptor, object_properties_t port_kind, Controller& controller, object_properties_t p, types::InternalType* v);
+template<typename Adaptor>
+bool set_ports_property(const Adaptor& adaptor, object_properties_t port_kind, Controller& controller, object_properties_t p, types::InternalType* v)
+{
+    static const wchar_t E[] = L"E";
+    static const wchar_t I[] = L"I";
+    model::Block* adaptee = adaptor.getAdaptee();
+
+    // Retrieve the ports identifiers
+    std::vector<ScicosID> ids;
+    controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, ids);
+
+    if (v->getType() == types::InternalType::ScilabString)
+    {
+        types::String* current = v->getAs<types::String>();
+        if (current->getCols() != 0 && current->getCols() != 1)
+        {
+            return false;
+        }
+
+        size_t rows = current->getRows();
+        if (rows != ids.size())
+        {
+            return false;
+        }
+
+        int i = 0;
+        switch (p)
+        {
+            case IMPLICIT:
+            {
+                for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
+                {
+                    if (current->get(i) == I)
+                    {
+                        controller.setObjectProperty(*it, PORT, p, true);
+                    }
+                    else if (current->get(i) == E)
+                    {
+                        controller.setObjectProperty(*it, PORT, p, false);
+                    }
+                    else
+                    {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            case STYLE:
+            case LABEL:
+            {
+                std::vector<std::string> style = std::vector<std::string>(current->getSize());
+                for (std::vector<ScicosID>::iterator it = ids.begin(); it != ids.end(); ++it, ++i)
+                {
+                    char* c_str = wide_string_to_UTF8(current->get(i));
+                    style[i] = std::string(c_str);
+                    FREE(c_str);
+                    controller.setObjectProperty(*it, PORT, p, style[i]);
+                }
+                return true;
+            }
+            default:
+                return false;
+        }
+    }
+    else if (v->getType() == types::InternalType::ScilabDouble)
+    {
+        types::Double* current = v->getAs<types::Double>();
+        if (current->getRows() != 0 || current->getCols() != 0)
+        {
+            return false;
+        }
+        if (ids.size() != 0)
+        {
+            return false;
+        }
+        // Do nothing, because if the sizes match, then there are already zero concerned ports, so no ports to update
+        return true;
+    }
+    return false;
+}
 
 /**
  * Update the ports with a specific property.
  *
  * Create ports if needed, remove ports if needed and set a default property on each port.
  */
-bool update_ports_with_property(const GraphicsAdapter& adaptor, object_properties_t port_kind, Controller& controller, object_properties_t p, types::InternalType* v);
+template<typename Adaptor>
+bool update_ports_with_property(const Adaptor& adaptor, object_properties_t port_kind, Controller& controller, object_properties_t p, types::InternalType* v)
+{
+    model::Block* adaptee = adaptor.getAdaptee();
+
+    if (v->getType() != types::InternalType::ScilabDouble)
+    {
+        return false;
+    }
+    types::Double* value = v->getAs<types::Double>();
+
+    ScicosID parentDiagram;
+    controller.getObjectProperty(adaptee->id(), BLOCK, PARENT_DIAGRAM, parentDiagram);
+
+    std::vector<ScicosID> children;
+    if (parentDiagram != 0)
+    {
+        controller.getObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
+    }
+
+    std::vector<int> newPorts = std::vector<int>(value->getSize());
+
+    // retrieve old data
+    std::vector<ScicosID> oldPorts;
+    controller.getObjectProperty(adaptee->id(), adaptee->kind(), port_kind, oldPorts);
+    std::vector<ScicosID> previousPorts = oldPorts;
+
+    double* d = value->getReal();
+    if (p == CONNECTED_SIGNALS)
+    {
+        for (std::vector<int>::iterator it = newPorts.begin(); it != newPorts.end(); ++it, ++d)
+        {
+            if (0 > *d && *d >= children.size())
+            {
+                return false;
+            }
+
+            *it = (int) * d;
+        }
+    }
+    else
+    {
+        // Here, we are modyfing either 'in', 'in2' or 'intyp', so the Port ids must remain the same as much as possible (copy the old ones),
+        // and set the new ones to zero (unconnected) if there are any (insert them at the beginning of newPorts).
+        if (newPorts.size() != 0)
+        {
+            //
+            if (newPorts.size() >= oldPorts.size())
+            {
+                std::fill(newPorts.begin(), newPorts.begin() + newPorts.size() - oldPorts.size(), 0);
+                std::copy(oldPorts.begin(), oldPorts.end(), newPorts.begin() + newPorts.size() - oldPorts.size() + 1);
+            }
+            else if (newPorts.size() < oldPorts.size())
+            {
+                std::copy(oldPorts.begin(), oldPorts.begin() + newPorts.size(), newPorts.begin());
+            }
+        }
+    }
+    std::vector<ScicosID> deletedObjects;
+
+    // updated ports
+    while (!oldPorts.empty() && !newPorts.empty())
+    {
+        ScicosID oldPort = oldPorts.back();
+        oldPorts.pop_back();
+        int newPort = newPorts.back();
+        newPorts.pop_back();
+
+        ScicosID oldSignal;
+        controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, oldSignal);
+        ScicosID newSignal = children[newPort];
+
+        if (p == CONNECTED_SIGNALS)
+        {
+            if (oldSignal != newSignal)
+            {
+                // disconnect the old link
+                ScicosID oldSignalSrc;
+                controller.getObjectProperty(oldSignal, LINK, SOURCE_PORT, oldSignalSrc);
+                ScicosID oldSignalDst;
+                controller.getObjectProperty(oldSignal, LINK, DESTINATION_PORT, oldSignalDst);
+
+                ScicosID unconnected = 0;
+                if (oldSignalSrc == oldPort)
+                {
+                    controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected);
+                }
+                else // oldSignalDst == oldPort
+                {
+                    controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected);
+                }
+                // Link de-association is not performed as the link will be removed
+
+                // connect the new link
+                controller.setObjectProperty(newSignal, LINK, SOURCE_PORT, 0);
+                controller.setObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, newSignal);
+
+                children.erase(std::find(children.begin(), children.end(), oldSignal));
+                deletedObjects.push_back(oldSignal);
+            }
+        }
+        else
+        {
+            // The common port ids (CONNECTED_SIGNALS property) remain the same, so just update the p property
+            controller.setObjectProperty(oldPort, PORT, p, d[newPorts.size() - 1]);
+        }
+    }
+
+    // removed ports
+    if (!oldPorts.empty())
+    {
+        previousPorts.erase(previousPorts.begin() + oldPorts.size(), previousPorts.end());
+
+        while (!oldPorts.empty())
+        {
+            ScicosID oldPort = oldPorts.back();
+            oldPorts.pop_back();
+
+            ScicosID signal;
+            controller.getObjectProperty(oldPort, PORT, CONNECTED_SIGNALS, signal);
+            if (signal != 0)
+            {
+                // the link is connected, disconnect the other side
+                ScicosID oldSignalSrc;
+                controller.getObjectProperty(signal, LINK, SOURCE_PORT, oldSignalSrc);
+                ScicosID oldSignalDst;
+                controller.getObjectProperty(signal, LINK, DESTINATION_PORT, oldSignalDst);
+
+                ScicosID unconnected = 0;
+                if (oldSignalSrc == oldPort)
+                {
+                    controller.setObjectProperty(oldSignalDst, PORT, CONNECTED_SIGNALS, unconnected);
+                }
+                else     // oldSignalDst == oldPort
+                {
+                    controller.setObjectProperty(oldSignalSrc, PORT, CONNECTED_SIGNALS, unconnected);
+                }
+
+                children.erase(std::find(children.begin(), children.end(), signal));
+                deletedObjects.push_back(signal);
+            }
+
+            deletedObjects.push_back(oldPort);
+        }
+
+        controller.setObjectProperty(adaptee->id(), BLOCK, port_kind, previousPorts);
+    }
+
+    // added ports
+    if (!newPorts.empty())
+    {
+        while (!newPorts.empty())
+        {
+            int newPort = newPorts.back();
+            oldPorts.pop_back();
+
+            ScicosID id = controller.createObject(PORT);
+            controller.setObjectProperty(id, PORT, SOURCE_BLOCK, adaptee->id());
+            if (p != CONNECTED_SIGNALS)
+            {
+                // In addition to setting the signal to 0 (the 0s at the start of newPorts), set the requested property
+                controller.setObjectProperty(id, PORT, p, d[newPorts.size() - 1]);
+            }
+            // set the connected signal if applicable
+            if (newPort != 0)
+            {
+                ScicosID signal = children[newPort];
+                controller.setObjectProperty(id, PORT, CONNECTED_SIGNALS, signal);
+            }
+
+            previousPorts.push_back(id);
+        }
+
+        controller.setObjectProperty(adaptee->id(), BLOCK, port_kind, previousPorts);
+    }
+
+    // remove objects from the model after de-association
+    if (parentDiagram != 0)
+    {
+        controller.setObjectProperty(parentDiagram, DIAGRAM, CHILDREN, children);
+    }
+    for (std::vector<ScicosID>::iterator it = deletedObjects.begin(); it != deletedObjects.end(); ++it)
+    {
+        controller.deleteObject(*it);
+    }
+
+    return true;
+}
 
 
 } /* view_scilab */