Generated reference › API — ICoreSDK/ICoreModel
kind: generated#api#icoresdk-icoremodel

API — ICoreSDK/ICoreModel

The public contract of 16 header(s) under src/ICoreSDK/ICoreModel — 15 class/struct definition(s), 509 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.

ICoreBlockFactory.h#

src/ICoreSDK/ICoreModel/ICoreBlockFactory.h

ICoreBlockFactory#

ICoreBlockFactory.h:7 · class · nested InitialPorts · 12 declaration(s)

class ICoreBlockFactory {
public:

    // ====================[ Solver Environments ]======================
    using SolverEnvCreator = std::function<std::unique_ptr<ICoreBlockSolverEnvironment>(ICoreBlock*)>;
    static void registerBlockSolvEnv(const std::string& type, SolverEnvCreator creator);
    static std::unique_ptr<ICoreBlockSolverEnvironment> createBlockSolverEnvironment(const std::string& type, ICoreBlock* block);
    static std::unordered_map<std::string, SolverEnvCreator>& getSolverEnvRegistry();

    // ====================[ Manager ]======================
    static void setBlockUp(ICoreBlock* blockToSetUp);
    static bool isBlockTypeValidSubsystem(const std::string &blockType);

    // ====================[ Block Icons ]======================
    static void registerIconSVG(const std::string &type, const char *svg);
    static const char *getBlockIconSVG(const std::string &type);

    // All registered block type strings (the keys of the icon catalog). The icon
    // registry is populated by every block TU's static initializer, so this is the
    // authoritative list of valid types. Used to validate a requested type and to
    // resolve a leaf name (e.g. "Gain") to its full hierarchical type path.
    static std::vector<std::string> getAllRegisteredTypes();

    // ====================[ Block Descriptions ]======================
    // The block's user-facing description, as HTML (see ADDING_NEW_BLOCKS.md).
    // Registered by each block TU next to its icon, and handed to the block's
    // configurator by its solver-environment constructor — which needs a live
    // ICoreBlock. The library navigator has none: it lists TYPES, so it reads the
    // description from here, exactly as it reads the icon and the port counts.
    static void registerDescriptionHTML(const std::string& type, const std::string& html);

    // Empty for an unregistered type, so a caller shows nothing rather than a
    // placeholder. Returns a reference into the registry — valid for the process's
    // lifetime, since nothing ever erases from it.
    static const std::string& getBlockDescriptionHTML(const std::string& type);

    // ====================[ Initial Ports ]======================
    // How many ports a freshly created block of a type comes up with. Registered by
    // each block TU next to its icon, and it must mirror the createNewPort() calls in
    // that block's solver-environment constructor — which is where the real ports are
    // born, and which needs a live ICoreBlock on a canvas inside a subsystem tree.
    // A library preview has none of that, so it reads the counts from here instead.
    struct InitialPorts {
        int inputCount = 0;
        int outputCount = 0;
    };
    static void registerInitialPorts(const std::string& type, int inputCount, int outputCount);

    // Zeroed for an unregistered type, so a caller draws nothing rather than guessing.
    static InitialPorts getInitialPorts(const std::string& type);

};
};

ICoreSubsystemTreeNode.h#

src/ICoreSDK/ICoreModel/ICoreSubsystemTreeNode.h

ICoreSubsystemTreeNode#

ICoreSubsystemTreeNode.h:17 · class · pImpl · 73 declaration(s)

class ICoreSubsystemTreeNode {
public:
    // How getTreeWidgetItems() orders the entries it builds for one level of the
    // navigator. The enum lives here rather than in the view because the ordering
    // is applied while the items are built, and the builder is this class -- the
    // view is L8 and this is L3, so the mode travels DOWN as an argument.
    //
    //   Name          -- every entry, subsystems and blocks alike, by name (A-Z).
    //   Kind          -- subsystems first, then blocks; by name within each group.
    //   LastModified  -- most recently modified first (see markModified()).
    //   DateCreated   -- most recently created first.
    //
    // Blocks carry no timestamps of their own, so under the two date modes they
    // sort after every subsystem, among themselves by name. Ties in every mode
    // break on name, so the order is total and a rebuild never reshuffles.
    enum class SortMode { Name, Kind, LastModified, DateCreated };

    explicit ICoreSubsystemTreeNode(ICoreSubsystemTreeNode* parent = nullptr, const std::string& initName = "~auto");

    ICoreBlock* createNewBlock(const std::string &type);
    ICoreLink* createNewLink(std::string type);
    ICoreCanvasArea* createNewCanvasArea();
    ICoreCanvasTextBox* createNewTextbox();
    ICoreImage* createNewImage();

    void deleteBlock(ICoreBlock* block);
    void deleteLink(ICoreLink* link);
    void deleteCanvasArea(ICoreCanvasArea* area);
    void deleteTextbox(ICoreCanvasTextBox* textbox);
    void deleteImage(ICoreImage* image);

    void giveOwnershipUp_Block(ICoreBlock* block);
    void giveOwnershipUp_Link(ICoreLink* link);
    void giveOwnershipUp_CanvasArea(ICoreCanvasArea* area);
    void giveOwnershipUp_Textbox(ICoreCanvasTextBox* textbox);
    void giveOwnershipUp_Image(ICoreImage* image);

    void acquireOwnership_Block(ICoreBlock* block);
    void acquireOwnership_Link(ICoreLink* link);
    void acquireOwnership_CanvasArea(ICoreCanvasArea* area);
    void acquireOwnership_Textbox(ICoreCanvasTextBox* textbox);
    void acquireOwnership_Image(ICoreImage* image);
    void moveLinksFromAllDescendentsToTrash() const;

    void deleteLinksFromAllDescendentsPermanently() const;

    bool isBlockNameAvailable(const std::string& newName, ICoreBlock* blockToExclude);
    bool isLinkNameAvailable(const std::string& newName, const ICoreLink* linkToExclude) const;
    bool isCanvasAreaNameAvailable(const std::string& newName, ICoreCanvasArea* areaToExclude) const;
    bool isTextBoxNameAvailable(const std::string& newName, ICoreCanvasTextBox* noteToExclude);
    bool isImageNameAvailable(const std::string& newName, const ICoreImage* imageToExclude) const;

    void runLinkPathOptimizerToAllBlocks() const;

    void deleteChildTreeNode(ICoreSubsystemTreeNode* nodeToDelete);

    void permanentlyDeleteAllChildren();

    void reArrangeAllChildrenZOrder() const;

    ICoreRect calculateReqAreaOnCanvas() const;

    ICoreSubsystemTreeNode* findTreeNodeByPath(const std::string& fullPath);

    // This node as ONE navigator row, as the cells of that row left to right:
    //   [0] the name, with the subsystem icon and the entry-type / entry-path
    //       roles the view reads back -- the cell that owns the children;
    //   [1] last modified, formatted for display;
    //   [2] date created, likewise.
    //
    // Always three cells, even for a caller showing one column: a tree whose
    // rows disagree about their cell count is a Qt model bug waiting to happen,
    // and hiding a column is the view's job (ICoreTreeView::setColumnSizing),
    // not the model's. Blocks appear as rows here too and have no timestamps of
    // their own, so their detail cells are empty rather than invented.
    //
    // Ownership transfers to whatever the cells are appended to -- see
    // ICoreStandardItem's Group B note.
    [[nodiscard]] std::vector<ICoreStandardItem*> getTreeWidgetItems(SortMode sortMode = SortMode::Name) const;

    // How the two detail cells above are rendered, and the ONE place that
    // decision lives -- the navigator's column titles are written against it.
    // Local time, seconds dropped: a diagram edit is not a stopwatch reading,
    // and the narrow columns these sit in have no room for them.
    [[nodiscard]] static std::string formatTimestampForDisplay(long long msSinceEpoch);

    void pushBackChildTreeNode(ICoreSubsystemTreeNode *newChild);

    void eraseChildTreeNode(const ICoreSubsystemTreeNode *childToErase);

    void checkOutCanvasPointersBeforeDeletion(ICoreCanvas* canvasToCheckOut);

    // ======================= Setters ==============================

    void setParent(ICoreSubsystemTreeNode* parent);
    void setName(const std::string& newName) const;
    void reconstructPath();
    void setLoadedToCanvas(ICoreCanvas* canvas);

    // ---------------- The two timestamps every subsystem carries
    //
    // Milliseconds since the Unix epoch, in the same units ICoreDateTime takes
    // (fromMSecsSinceEpoch), so a caller that wants to SHOW one hands it straight
    // over. A plain integer rather than a formatted string on purpose: it sorts,
    // it round-trips through the recipe without a parser, and it carries no
    // locale.
    //
    // Both are stamped with "now" by the constructor and by resetToInitialState,
    // so a node always has a real pair -- there is no invalid/zero state to guard
    // at the call sites. The setters exist for ONE caller each: the recipe
    // interpreter, restoring what ICoreRecipeSerializer wrote (`h.setTimes(...)`
    // / `subsystemTimes(...)`). Everything else uses markModified().
    void setCreatedTimeMs(long long msSinceEpoch);
    void setLastModifiedTimeMs(long long msSinceEpoch);

    // Stamps THIS node's last-modified with now, and every ancestor up to the
    // root with it -- a change inside a subsystem is a change to each diagram
    // that contains it.
    //
    // ⚠ What it does NOT cover: this is called from the structural edits that go
    // through a tree node (an object created, deleted, renamed, or moved in or
    // out of the level). Editing a block's own config or dragging it a few pixels
    // never reaches this class and so does not stamp anything. That is the
    // documented meaning of the property -- "when the contents of this subsystem
    // last changed shape" -- not an oversight.
    void markModified();

    // ======================= Getters ==============================

    ICoreSubsystemTreeNode* getParent() const;
    std::string getPath() const;
    std::string getName() const;
    [[nodiscard]] long long getCreatedTimeMs() const;
    [[nodiscard]] long long getLastModifiedTimeMs() const;
    // int getMaxSolverOrder() const;
    ICoreCanvasOriginAnchor* getCanvasOriginAnchor() const;

    std::vector<ICoreSubsystemTreeNode*> getChildrenTreeNodes() const;
    std::vector<ICoreBlock*> getChildrenBlocks() const;
    std::vector<ICoreLink*> getChildrenLinks() const;
    std::vector<ICoreCanvasArea*> getChildrenCanvasAreas() const;
    std::vector<ICoreCanvasTextBox*> getChildrenTextBoxes() const;
    std::vector<ICoreImage*> getChildrenImages() const;
    ICoreCanvas* getCanvasLoadedTo() const;
    ICoreBlock* getAssociatedSubsystemBlock() const;
    std::vector<ICoreBlock*> getAllGateBlocks() const;
    // std::unordered_map<int, std::vector<ICoreBlock*>> getBlocksToSolveMap() const;
    // std::vector<ICoreBlock *> getMatchingOrderBlocksToSolveList(const int &order) const;
     ICoreTreeNodeSolverEnvironment* getSolverEnvironment() const;

    bool isHomeNode() const;
    bool isRootNode() const;

    bool isHomeDescendantsNode() const;

    void printTree(const std::string& prefix) const;

    void printLinksReport() const;

    void moveAllChildrenToTrash();

    void resetToInitialState(ICoreSubsystemTreeNode* parent = nullptr, const std::string& initName = "~auto");
    void kill();
    void setAlive();
    bool isAlive() const;

    ~ICoreSubsystemTreeNode();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreSubsystemTreeNodeRegistry.h#

src/ICoreSDK/ICoreModel/ICoreSubsystemTreeNodeRegistry.h

======================= Path forms =========================== Tree paths are canonically rooted at the app name ("ICoreBlocks/Home/Motor"), but that first segment is noise to the user -- and hidden altogether while navigation-root access is off. These convert between the canonical form the lookups need and the form the UI shows and accepts. Every find*ByPath() below normalises through toCanonicalPath(), so callers may hand them either form.

ICoreSubsystemTreeNodeRegistry#

ICoreSubsystemTreeNodeRegistry.h:11 · class · 20 declaration(s)

class ICoreSubsystemTreeNodeRegistry {
public:

    static long initializeSubsystemTreeNodeRegistry();

    static ICoreSubsystemTreeNode* findTreeNodeByPath(const std::string& path);
    static ICoreVariablesSpace* findVariablesSpaceByPath(const std::string& path);
    static ICoreBlock* findBlockByPath(const std::string &path);
    static ICorePort* findPortByPath(const std::string &path);

    static const ICoreVariable* scanVariableSpacesForVariable(const ICoreBlock* parentBlock, const ICoreBlockConfigVariable *var);

    // ======================= Path forms ===========================
    // Tree paths are canonically rooted at the app name ("ICoreBlocks/Home/Motor"), but that
    // first segment is noise to the user -- and hidden altogether while navigation-root access
    // is off. These convert between the canonical form the lookups need and the form the UI
    // shows and accepts. Every find*ByPath() below normalises through toCanonicalPath(), so
    // callers may hand them either form.

    // Adds the "<AppName>/" root segment when it is missing and trims stray outer slashes:
    // "Home/Motor", "/Home/Motor" and "ICoreBlocks/Home/Motor" all canonicalise to the same
    // path. An empty input stays empty, which resolves to nothing.
    static std::string toCanonicalPath(const std::string& path);

    // Drops the root segment while navigation-root access is off, so the user reads
    // "Home/Motor". The Root node itself has no user-facing form and yields an empty string.
    // With access on the canonical path is handed back untouched.
    static std::string toDisplayPath(const std::string& path);

    // ================= Navigation root access =====================
    // Gates every user-facing route into the part of the tree that sits above Home: the Root
    // node itself and its non-Home children (Temp / ClipBoard / Trash), which are internal
    // staging areas for the clipboard and the recycle bin. Off by default, so the user only
    // ever sees Home and its descendants. Switch it on to expose the full tree unchanged.
    //
    // These forward to ICoreUserPreferences, which is what stores the setting: it is reachable
    // from Settings -> Advanced and from the console, and it survives a restart.
    static bool isNavigationRootAccessAllowed();
    static void setNavigationRootAccessAllowed(bool allowed);

    // The node the navigation surfaces present as their top level: the Root node when access
    // is allowed, Home otherwise.
    static ICoreSubsystemTreeNode* getNavigationRootTreeNode();

    // True when the node may be shown to, or navigated to by, the user. A null node is never
    // visible, so callers can pass an unresolved lookup straight through.
    static bool isTreeNodeUserVisible(const ICoreSubsystemTreeNode* node);
    static bool isTreeNodePathUserVisible(const std::string& path);

    // ======================= Getters ==============================
    static ICoreSubsystemTreeNode* getRootTreeNode();
    static ICoreSubsystemTreeNode* getHomeTreeNode();
    static ICoreSubsystemTreeNode* getTempTreeNode();
    static ICoreSubsystemTreeNode* getClipBoardTreeNode();
    static ICoreSubsystemTreeNode* getTrashTreeNode();

    static bool isDebugMode();

    static void printGlobalTree();
};
};

ICoreBlock.h#

src/ICoreSDK/ICoreModel/Block/ICoreBlock.h

ICoreBlock#

ICoreBlock.h:15 · class · pImpl · 72 declaration(s)

class ICoreBlock {
public:
    explicit ICoreBlock(ICoreSubsystemTreeNode* parent, const std::string &fullType);

    std::string generateUniqueName(const std::string& prefix) const;

    ICorePort* createNewPort(const std::string& portType, const std::string& initialPortDescription,
                                bool isOutputPort, const std::string& preferredFacing = "West");
    void deletePort(ICorePort* port);
    void deleteAllPorts();
    void acquirePortOwnership(ICorePort* port);
    void givePortOwnership(ICorePort* port);

    ICoreCanvasObjectState* getState() const;
    void updateToState(const ICoreCanvasObjectState* desiredState);

    void assignClonedProperties(ICoreBlock* originalBlock, bool clonePorts);

    void select();
    void deSelect();

    ICorePort* getPortByName(const std::string& portName) const;

    // ======================= Helpers ==============================

    bool checkNameValid(const std::string& nameToCheck);
    // bool isNameAvailable(const std::string& newName);

    // ======================= UI Manager ==============================

    void addToCanvas(ICoreCanvas* canvas);
    void freeFromCanvas();

    // Layer 4: canonical "remove me from the live model graph" — detach from parent container +
    // canvas/selection. Idempotent. Called by collectGarbage_Block so collection is self-sufficient.
    void detachFromModel();

    // ======================= Setters ==============================

    // Interactive rename: validates, and reports a rejected name to the user in a modal dialog.
    // Never call it for a name the code generated itself -- see setName_Raw_NoVerification.
    bool setName(const std::string& name);
    // Machine-set rename: no validation, no dialog. For names the code produced itself
    // (generateUniqueName, a captured state) where a modal error would stall a load, an undo or a
    // paste on a name the user never typed.
    void setName_Raw_NoVerification(const std::string& newName);
    void setCommentedOut(bool commentedOut);
    // The name label under the block is per-block state, not a view setting: it is
    // captured in the block's state and written to the recipe, so hiding it survives
    // undo/redo and a save/reload.
    void setNameLabelVisible(bool visible);
    void setParent(ICoreSubsystemTreeNode* newParent);
    void setAssociatedTreeNode(ICoreSubsystemTreeNode* ICoreSubsystemTreeNode);

    // ======================= Appearance ==============================
    //
    // A block type's default look: how big it is, what shape its frame is, and
    // whether the user may retype its port description labels. Every one of
    // these is declared once, per type, from the block's solver-environment
    // constructor in ICoreBlockLibrary.
    //
    // THEY LIVE HERE SO THE BLOCK LIBRARY DOES NOT HAVE TO NAME ICoreBlockView.
    // That library is ~113k lines across 302 files that contain no Qt
    // whatsoever -- until these calls, which reached through getBlockUI() into
    // a toolkit scene object and dragged the whole widget stack in behind them, in
    // 146 of those files, to say things as view-free as "a Terminator is 50x50".
    // Routed through the model instead, the statement stays where it belongs
    // and the dependency collapses to the one forwarding site in ICoreBlock.cpp.
    //
    // Forwarding, deliberately, not storage: setWidth() on the view also
    // resizes the frame and re-attaches the config UI, so these have to reach
    // it. What changed is who says the words, not what happens.
    //
    // double rather than the toolkit's real type because this header is
    // toolkit-free and stays that way; the forwarding site converts.
    void setWidth(double width);
    void setHeight(double height);
    void setRotation(double angleDegrees);
    void setAllowUserEditingPortDescLabels(bool allow);
    void setCircleFrame();
    void setTriangleFrame();
    void setFrameBackgroundColor(int red, int green, int blue);
    void setFrameMinimumWidth(double width);
    // Whether the block type's registered art is painted on this block's face.
    // Turn it off when the face carries something else -- a live readout. The
    // art stays REGISTERED either way: the library palette, the auto-inserter
    // button and ICoreRecipeInterpreter's block-type check all read it from
    // the factory, and a block type with no icon registered is not a valid
    // block type as far as a recipe is concerned.
    void setFaceIconVisible(bool visible);
    // Whether this block carries a readout PLATE on its face -- the bordered
    // ground setFaceText() writes into. Off by default: without this every
    // block on the canvas would wear an empty one. A block type that shows a
    // value turns it on once, and the plate then stays up for the block's whole
    // life, EMPTY between runs rather than vanishing. An empty readout is still
    // a readout; a block that loses its face looks broken.
    void setFaceReadoutVisible(bool visible);

    // ======================= Live face readout ==============================
    //
    // The text a block shows ON ITS OWN FACE, centred in the frame. Display is
    // what wanted it -- Simulink paints the value on the block, and this tree
    // had nowhere but the run log to put one -- and any block with a per-sample
    // value to show reaches it the same way.
    //
    // ⚠ SAFE TO CALL FROM THE SOLVER THREAD, and that is the whole point of it
    // being here rather than on the view. compute_h() runs on
    // ICoreModelSimulator's worker thread and the label is a scene item, so the
    // call stores the text and hops it to the GUI thread.
    //
    // Consecutive values COALESCE: at most one hop is ever in flight, and it
    // delivers whatever the latest text is when it lands. A solver stepping
    // thousands of times a second therefore costs the event loop a bounded
    // number of updates instead of one per sample, and the label still settles
    // on the final value of the run.
    void setFaceText(const std::string& text);
    // Hides the readout. Call it at the start of a run so a block does not open
    // one showing the last sample of the previous one.
    void clearFaceText();

    // ======================= Getters ==============================

    ICoreSubsystemTreeNode* getParent() const;
    std::string getName() const;
    std::string getType();
    std::string getFullType();
    std::string getPath() const;

    ICoreBlockView* getBlockUI() const;

    std::vector<ICorePort*> getPorts() const;

    std::vector<ICorePort*> getInputPorts() const;
    std::vector<ICorePort*> getOutputPorts() const;

    void setGateBlock();
    void setSubsystemBlock();
    void setScopeBlock();
    // A sink that consumes signals without charting them (Signal Recorder). Kept
    // apart from setScopeBlock() because that one attaches a chart; what the two
    // share is being a terminal the verifier has to record at "Output Gates and
    // Sink Blocks", which is what isSinkBlock() answers for.
    void setSinkBlock();
    bool isGateBlock() const;
    bool isSubsystemBlock() const;
    bool isScopeBlock() const;
    bool isSinkBlock() const;

    bool isSelected() const;
    bool isCommentedOut() const;
    bool isNameLabelVisible() const;
    bool isDebugActive() const;

    std::string getClassID() const;

    ICoreSubsystemTreeNode* getAssociatedTreeNode() const;

    ICoreBlockSubsystemGate* getAssociatedSubsystemGate() const;
    ICoreChart* getAttachedChart() const;

    ICoreCanvas* getLoadedToCanvas() const;

    ICoreBlockConfigurator* getBlockConfigurator() const;
    ICoreBlockSolverEnvironment* getSolverEnvironment() const;

    void assignSolverEnvironment(std::unique_ptr<ICoreBlockSolverEnvironment> newEnvironment);

    void setTrashOrder(const int newTrashOrder);
    int getTrashOrder() const;
    void increaseTrashOrder();
    void decreaseTrashOrder();

    void resetToInitialState(ICoreSubsystemTreeNode* parent, const std::string &type);
    void kill();
    void setAlive();
    bool isAlive() const;

    ~ICoreBlock();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreBlockConfigVariable.h#

src/ICoreSDK/ICoreModel/Block/BlockConfig/ICoreBlockConfigVariable.h

ICoreBlockConfigVariable deepCopy() const;

void linkToVariablesSpace(ICoreVariablesSpaceVariable* variablesSpaceVariable); void unlinkFromVariablesSpace();

ICoreVariablesSpaceVariable* getLinkedVariablesSpaceVariable() const;

Declares no class of its own — see the file.

ICoreBlockConfigurator.h#

src/ICoreSDK/ICoreModel/Block/BlockConfig/ICoreBlockConfigurator.h

Designates one (private) config variable as user-editable source code: the config dialog toolbar shows an "Edit Code" button bound to it, and the recipe serializer persists it (base64) despite it being private.

ICoreBlockConfigurator#

ICoreBlockConfigurator.h:7 · class · pImpl · 31 declaration(s)

class ICoreBlockConfigurator {
public:
    explicit ICoreBlockConfigurator(ICoreBlock* parentBlock);

    ICoreBlockConfigVariable* createNewVariable(const std::string& initName, const std::string& initValue, const bool& isPrivate = false);
    bool isVarNameUnique(const std::string& nameToCheck) const;

    void clearAllVariables_WithoutUIEntries();

    void requestToShowConfigUI();

    void hideConfigUI();
    void deleteConfigUI();

    void assignClonedProperties(ICoreBlockConfigurator* originalBlockConfigurator) const;

    void setIsPinnedToCanvas(bool newIsPinned) const;

    void setBlockDescription(const std::string& newBlockDescription);

    void setAllowUserEditingNumberOfInputPorts(const bool& newProperty);
    void setAllowUserEditingNumberOfOutputPorts(const bool& newProperty);

    ICoreBlockConfigView* getConfigUI() const;

    bool getIsInputPortsNumberPrivate() const;
    bool getIsOutputPortsNumberPrivate() const;

    void setDefaultOutputPortDescText(const std::string &newValue);
    void setDefaultInputPortDescText(const std::string &newValue);

    std::string getDefaultOutputPortDescText() const;

    std::string getDefaultInputPortDescText() const;

    // Designates one (private) config variable as user-editable source code:
    // the config dialog toolbar shows an "Edit Code" button bound to it, and
    // the recipe serializer persists it (base64) despite it being private.
    void setCodeEditorVariableName(const std::string& configVarName);
    std::string getCodeEditorVariableName() const;  // "" = block has no code editor

    // Which language the code editor window opens the variable in (editor
    // widget + highlighter + window title). Python unless the block says so.
    enum class CodeEditorLanguage { Python, C };
    void setCodeEditorLanguage(CodeEditorLanguage newLanguage);
    CodeEditorLanguage getCodeEditorLanguage() const;

    std::string getDescriptionText() const;
    std::vector<ICoreBlockConfigVariable*> getAllVariables();
    ICoreBlock* getParentBlock() const;

    ICoreBlockConfigVariable* getConfigVariable(const std::string& name) const;

    void resetToInitialState(ICoreBlock* parentBlock);
    void kill();
    void setAlive();
    bool isAlive() const;

    ~ICoreBlockConfigurator();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreBlockSubsystemGate.h#

src/ICoreSDK/ICoreModel/Block/GateBlock/ICoreBlockSubsystemGate.h

ICoreBlockSubsystemGate#

ICoreBlockSubsystemGate.h:8 · class · pImpl · 11 declaration(s)

class ICoreBlockSubsystemGate {
public:
    explicit ICoreBlockSubsystemGate(ICoreBlock* parentBlock);

    void deleteParentSubsystemLinkedPort(ICorePort* gateBlockPort);
    void createParentSubsystemLinkedPort(ICorePort* gateBlockPort);

    std::string getUniquePortDescLabelText(const bool& isOutputPort) const;

    void regenerateAllParentSubsystemPortsAfterGateBlockMigration();

    void deleteAllPortsAtBothBlocks();

    void resetToInitialState(ICoreBlock* parentBlock);
    void kill();
    void setAlive();
    bool isAlive() const;

    ~ICoreBlockSubsystemGate();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICorePort.h#

src/ICoreSDK/ICoreModel/Block/Port/ICorePort.h

ICorePort#

ICorePort.h:14 · class · pImpl · 37 declaration(s)

class ICorePort {
public:

    // preferredPortFacing is not guaranteed. ICorePortsPosAligner will determine if possible! Default alignment follow rules sat in ICorePortsPosAligner
    explicit ICorePort(ICoreBlock* parentBlock = nullptr, const std::string &type = "ICoreDouble",
            const std::string &initialPortDescription = "", const bool isOutputPort = false, const std::string& preferredFacing = "West");

    void setParentItem(ICoreBlockViewFrame* blockFrame) const;

    void setWirelessPortPairedTo(ICorePort* pairingPort);
    void clearWirelessPairing();
    ICorePort* getWirelessPortPairedTo() const;

    std::string getDescriptionLabelText() const;
    void setDescriptionLabelText(const std::string& newDescText) const;

    [[nodiscard]] std::string capturePortState() const;

    void assignClonedProperties(const ICorePort* originalPort) const;

    std::string getName();

    [[nodiscard]] bool isOutputPort() const;
    [[nodiscard]] int getSerializationNumber() const;

    ICoreBlock* getParentBlock() const;

    [[nodiscard]] std::string getType() const;

    void enforceSettingPortSerializationNumber(const int& newSerializationNumber);

    void overwriteSignalValue(const ICoreMatrix& newVal) const;

    [[nodiscard]] ICorePortView* getPortUI() const;

    // The two things the model bridge needed from the port's view, said by the
    // port instead. Same reasoning as the appearance block in ICoreBlock.h:
    // reaching through getPortUI() made ICorePortSolverEnvironment and
    // ICoreModelVerification -- neither of which draws anything -- compile
    // against the editor's widget stack to resize a label and read a position.
    //
    // ICorePoint rather than the view's own point type, so this header stays
    // free of raw toolkit names; the forwarding site converts, and the one call
    // site already assigned the result to an ICorePoint anyway.
    void setSignalSizeLabel(int numOfRows, int numOfColumns) const;
    [[nodiscard]] ICorePoint getCanvasBaseCoordinates() const;

    std::string getPath() const;

    void setIsConnected(bool newIsConnected);
    void setConnectionLinkBranch(ICoreLinkBranch* newLinkBranch);
    [[nodiscard]] bool getIsConnected() const;
    [[nodiscard]] ICoreLinkBranch* getConnectionLinkBranch() const;
    ICorePort* getConnectionSource() const;
    bool isConnectedToAnyInputPort() const;
    ICorePortSolverEnvironment* getSolverEnvironment() const;

    ICorePort* isConnectedToValidOutputPort() const;

    //const std::string& getConnectionThread() const;
    //ICorePort* getConnectedToPort() const;

    ICoreMatrix* getSignal() const;

    // Layer 4: canonical "remove me from the live model graph" — sever the cross-references a port
    // can dangle (link-branch connection + wireless gate pairing). Idempotent. Called by
    // collectGarbage_Port. NOTE: ports-vector removal + gate-mirror teardown stay in
    // ICoreBlock::givePortOwnership (single-shot, not idempotent), so detachFromModel does NOT route
    // through it.
    void detachFromModel();

    // --- Clear connection ---
    void clearConnection();
    //void removeOtherSidePortConnectionProperty(ICorePort* otherSidePort);
    void removePortConnection(ICorePort* portToRemove, ICoreLink* connectionLink);

    ICoreSubsystemTreeNode* getGrandParentTreeNode() const;
    void printConnectionDetails() const;

    void resetToInitialState(ICoreBlock* parentBlock, const std::string &type, const std::string &initialPortDescription,
                const bool isOutputPort, const std::string& preferredFacing);
    void kill();
    void setAlive();
    bool isAlive() const;

    ~ICorePort();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreEditorHost.h#

src/ICoreSDK/ICoreModel/Host/ICoreEditorHost.h

ICoreEditorHost#

ICoreEditorHost.h:40 · class · nested ConsoleResult · 21 declaration(s)

ICoreEditorHost -- what the simulation kernel needs FROM whatever is hosting it, expressed as something the kernel owns.

class ICoreEditorHost {
public:
    virtual ~ICoreEditorHost() = default;

    // Matches the levels the run-diagnosis panel already understood, so the
    // meaning of a level is unchanged by the move -- only who names it.
    enum class DiagnosticLevel {
        Log     = 0,
        Warning = 1,
        Error   = 2,
    };

    // Outcome of evaluating one console line. A plain value type so the kernel
    // is not handed a widget's result struct.
    struct ConsoleResult {
        bool ok = false;
        std::string output;
    };

    // --- run diagnostics ---------------------------------------------------
    virtual void diagnosticLogged(const std::string& message, DiagnosticLevel level);
    virtual void diagnosticsCleared();

    // --- user-facing notifications -----------------------------------------
    virtual void notifyFriendly(const std::string& title, const std::string& message);
    virtual void notifyWarning(const std::string& title, const std::string& message);
    virtual void notifyError(const std::string& title, const std::string& message);

    // --- simulator lifecycle -----------------------------------------------
    virtual void solverStarted();
    virtual void solverPaused();
    virtual void solverStopped(bool wasAborted);
    virtual void debugModeStarted();
    virtual void progressReset();

    // A run that ends BEFORE the solver starts -- the build failed, or the canvas has
    // nothing on it. NOT solverStopped: no solver ran, so there is no outcome to
    // announce, and whoever aborted has already said why (a "Nothing to Simulate"
    // notification, a build failure in the diagnostics). A host still has to hear it,
    // because a run's controls go inert the moment the build starts and this is the
    // only thing left that can put them back.
    virtual void solverStartupAborted();

    // --- model configuration ------------------------------------------------
    virtual void startTimeChanged();
    virtual void stopTimeChanged();

    // --- model build lifecycle ----------------------------------------------
    //
    // modelBuildFinished is raised for BOTH outcomes, from the one place the build
    // returns from. modelBuildFailed stays what it always was -- the failure-only
    // hook the port signal-type tags key off -- so a host that wants "the build is
    // over, whatever it did" has something to hang a busy indicator off, and one
    // that only cares about failure is unchanged.
    virtual void modelBuildStarted();
    virtual void modelBuildFinished(bool succeeded);
    virtual void modelBuildFailed();

    // --- navigation policy ---------------------------------------------------
    virtual void navigationAccessChanged();

    // --- the one REQUEST rather than notification ----------------------------
    //
    // Everything above tells the host something happened. This asks it to do
    // something and hands back the answer, because the console grammar the
    // script runner needs lives in the panel that implements it. The default
    // returns a failed result rather than pretending to have run the line: a
    // host with no console genuinely cannot evaluate one, and silently
    // reporting success would make a script look like it had worked.
    virtual ConsoleResult evaluateConsoleLine(const std::string& line);

    // The host in force. Never null -- with none registered this is a shared
    // do-nothing instance, which is exactly right for a headless process.
    static ICoreEditorHost& instance();

    // Registers the host. Pass nullptr to go back to the do-nothing default,
    // which is what a teardown should do rather than leave a dangling host
    // behind for late kernel activity to call into.
    static void setInstance(ICoreEditorHost* host);
};
};

ICoreLink.h#

src/ICoreSDK/ICoreModel/Link/ICoreLink.h

Layer 4: canonical "remove me from the live model graph" — detach from parent container + canvas/selection. Idempotent. Called by collectGarbage_Link so collection is self-sufficient.

ICoreLink.h:11 · class · pImpl · 38 declaration(s)

class ICoreLink {
public:
    explicit ICoreLink(ICoreSubsystemTreeNode* parent, std::string type);

    std::string generateUniqueName(const std::string& prefix) const;

    ICoreLinkBranch* createNewBranch();
    void giveBranchOwnershipUp(ICoreLinkBranch* branchToGiveUp, bool forceRootBranchRemoval);
    void acquireBranchOwnership(ICoreLinkBranch* branchToAcquire);
    void deleteBranch(ICoreLinkBranch* branchToDelete);

    void clearAllBranches_IncludingRoot();

    void addToCanvas(ICoreCanvas* canvas);
    void freeFromCanvas();

    // Layer 4: canonical "remove me from the live model graph" — detach from parent container +
    // canvas/selection. Idempotent. Called by collectGarbage_Link so collection is self-sufficient.
    void detachFromModel();

    std::string parseRootBranchState() const;

    static std::string parseNoneRootBranchState(const ICoreLinkBranch* branchToCaptureState);
    ICoreCanvasObjectState* getState() const;
    void updateToState(ICoreCanvasObjectState* desiredState);
    void updateRootBranchToState(const ICoreCanvasObjectState* fullLinkDesiredState) const;
    void updateNoneRootBranchesToState(const ICoreCanvasObjectState* fullLinkDesiredState);
    static std::vector<std::string> splitByDollarSign(const std::string& input);
    static std::vector<ICorePoint> parsePoints(const std::string& str);

    void ensureAllBranchesSplitFromLinkRoot() const;

    void setParent(ICoreSubsystemTreeNode* newParent);

    void setName(const std::string& newName);

    ICoreSubsystemTreeNode* getParent() const;
    std::string getName();
    std::string getType();
    std::string getPath() const;

    ICoreCanvas* getDrawnToCanvas() const;
    std::string getClassID() const;

    ICoreLinkBranch* getRootBranch() const;
    std::vector<ICoreLinkBranch*> getAllBranches() const;

    void setTrashOrder(const int newTrashOrder);
    int getTrashOrder() const;
    void increaseTrashOrder();
    void decreaseTrashOrder();

    void resetToInitialState(ICoreSubsystemTreeNode* parent, std::string type);
    void kill();
    void setAlive();
    bool isAlive() const;

    ~ICoreLink();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreLinkBranch.h#

src/ICoreSDK/ICoreModel/Link/ICoreLinkBranch.h

Corners are MODEL coordinates. There used to be two overloads here -- one taking the toolkit's point vector and one taking ICorePoint -- because a std::vector does not convert between value types even when its elements do. Now that the branch stores ICorePoint, the two collapsed into this one; it does NOT touch the sign of y (these coordinates are already in the +y-down sense, same contract as ICoreRecipeStudioBridge's).

Taken BY VALUE because optimize_unusedPath rewrites the path in place.

ICoreLinkBranch#

ICoreLinkBranch.h:12 · class · pImpl · 81 declaration(s)

class ICoreLinkBranch {
public:
    explicit ICoreLinkBranch(ICoreLink* parentLink = nullptr);

    // Corners are MODEL coordinates. There used to be two overloads here -- one
    // taking the toolkit's point vector and one taking ICorePoint -- because a
    // std::vector does not convert between value types even when its elements
    // do. Now that the branch stores ICorePoint, the two collapsed into this
    // one; it does NOT touch the sign of y (these coordinates are already in
    // the +y-down sense, same contract as ICoreRecipeStudioBridge's).
    //
    // Taken BY VALUE because optimize_unusedPath rewrites the path in place.
    void setBranchCorners(std::vector<ICorePoint> newBranchCorners, bool allowUpdateUI);

    void setBranchCorners_RelativeToCanvasOriginAnchor(const std::vector<ICorePoint> &newBranchCorners, bool allowUpdateUI);
    void reRunPathPlannerOverUnusedPath(std::vector<ICorePoint>& pathToRecreate);
    void updateCornerCoordinates(const int& index, const ICorePoint& newCorner);
    void translateCorner(const int& index, const double& dx, double& dy);
    void translateBranch(ICorePoint delta);
    void offsetPosition(ICorePoint delta);
    void ungrabMouse() const;
    void assignBranchConnection(ICorePort* tailPortToAssign, ICoreLinkBranch* branchSplittingFrom,
                                ICorePort* headPortToAssign, bool moveBranchOwnership);

    // Add new branch segments. Call from here
    ICoreLinkBranchSegment* addSegmentAtStart();
    ICoreLinkBranchSegment* addSegmentAtEnd();
    ICoreLinkBranchSegment* addSegmentAtIndex(int index);

    // ====== These three don't add the new segments to the corners list (Raw). Call them from addSegmentAt...
    ICoreLinkBranchSegment* createNewSegment_insertAtBranchStart(ICorePoint startCorner, ICorePoint endCorner);
    ICoreLinkBranchSegment* createNewSegment_insertAtBranchEnd(ICorePoint startCorner, ICorePoint endCorner);
    ICoreLinkBranchSegment* createNewSegmentAtIndex(int index);

    static double computeDirectionalCost(
        const ICorePoint& point,
        const ICorePoint& closestOnSegment,
        const ICorePoint& segmentStart,
        const ICorePoint& segmentEnd);

    static ICorePoint computeVector(const ICorePoint& from, const ICorePoint& to);

    void addCornerAtEnd(ICorePoint newCorner);

    void clearAllSegments();
    // void resetAllBranchSegment() const;
    // void adjustNumberOfSegment(const int& newNumberOfSegment);

    void assignClonedProperties(const ICoreLinkBranch* originalBranch);

    void setTailPort(ICorePort* newTailPort);
    void setHeadPort(ICorePort* newHeadPort);
    ICorePort* getTailPort() const;
    ICorePort* getHeadPort() const;

    ICoreLinkBranchTail* getBranchTail() const;
    ICoreLinkBranchHead* getBranchHead() const;

    void addToCanvas(ICoreCanvas* canvas);
    void freeFromCanvas();

    ICorePoint getClosestPointOnBranch(const ICorePoint& PointToCheckTo) const;
    ICoreLinkBranchSegment* getClosestSegmentToPoint(const ICorePoint& targetPoint) const;

    void updateUI();

    void updateHeadAndTailPosOrientation() const;

    void setConnectedStyle() const;
    void setUnconnectedStyle() const;

    void optimize_unusedPath(std::vector<ICorePoint>& newBranchCorners);
    void optimize_usedPath();

    static int countCorners(const std::vector<ICorePoint>& pathToCount);
    bool doesPointLayOnBranch(const ICorePoint& pointToCheck) const;
    void minimizeCorners(std::vector<ICorePoint> &originalPath) const;
    static ICorePoint tryUpdatingPerpendicularCorner(const ICorePoint& previousCorner, const ICorePoint& thisCorner, const ICorePoint& nextCorner);
    std::vector<ICorePoint> getBranchCorners_RelativeToCanvasOriginAnchor() const;
    static void printDirections(const std::vector<ICorePoint>& path);
    bool isRootBranch() const;

    void shiftBranchCorners_X(double delta_x);
    void shiftBranchCorners_Y(double delta_y);
    void shiftBranchToTailCoords(ICorePoint newTailCoords);

    void select();
    void deSelect();
    bool isSelected() const;

    void setSegUnderCursor(ICoreLinkBranchSegment* segment);

    std::vector<ICoreLinkBranch*> getSplitToBranches() const;
    std::vector<ICorePoint> getBranchCorners() const;
    std::vector<ICoreLinkBranchSegment*>& getBranchUISegments();
    ICoreLink* getParentLink() const;
    ICorePoint getTailCoordinates() const;
    ICorePoint getHeadCoordinates() const;

    void setZValue(int minZOrder);

    bool getIsSplittingFromAnotherBranch() const;
    ICoreLinkBranch* getSplittingFromBranch() const;

    ICoreLinkBranchSegment* getSegUnderCursor() const;
    ICoreLinkBranchSegmentMover* getBranchSegmentMover() const;
    void ensureBranchTailLaysOnBranchingLink();

    static void mergeCollinear_pathUnusedYet(std::vector<ICorePoint>& path);
    void mergeCollinear_currentUsedPath();

    static bool isCollinear(const ICorePoint& a, const ICorePoint& b, const ICorePoint& c, double eps = 1e-8);
    static bool segmentsIntersect(const ICorePoint& p1, const ICorePoint& p2,
                                  const ICorePoint& q1, const ICorePoint& q2,
                                  ICorePoint& intersection);
    static void removeLoops(std::vector<ICorePoint>& path);
    static void normalizeRadAngle(double& angle);

    void setAllowOptimizationAtPortMove(const bool& newAllow);
    bool isOptimizationAllowedAtPortMove() const;

    void setIsBranchDirectPath(bool newIsBranchDirectPath);
    void setParentLink(ICoreLink* newParentLink);

    void resetBranchMigrationOrder();
    void incrementBranchMigrationOrder();
    int getMigrationOrder() const;

    bool isPathFreeOfObstacles(const std::vector<ICorePoint>& originalPath) const;
    static bool lineIntersectsRect(const ICoreRect& rect, const ICorePoint& p1, const ICorePoint& p2);

    void printConnectionDetails() const;

    void resetToInitialState(ICoreLink* parentLink = nullptr);
    void kill();
    void setAlive();
    bool isAlive() const;

    ~ICoreLinkBranch();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreBlockSolverEnvironment.h#

src/ICoreSDK/ICoreModel/SolverEnvironments/ICoreBlockSolverEnvironment.h

ICoreBlockSolverEnvironment#

ICoreBlockSolverEnvironment.h:11 · class · pImpl · 59 declaration(s)

class ICoreBlockSolverEnvironment {
public:

    // ------------------------------------------------------
    // Constructor
    // ------------------------------------------------------
    explicit ICoreBlockSolverEnvironment(ICoreBlock* parentBlock);

    // DECLARED here, DEFINED in the .cpp: the residue below is a unique_ptr to an
    // incomplete Impl, and every one of the 286 derived blocks destroys this base.
    virtual ~ICoreBlockSolverEnvironment();

    // ------------------------------------------------------
    // Solver Order Assignment (Recursive)
    // ------------------------------------------------------
    int assignSolverOrder();

    // ------------------------------------------------------
    // State Space
    // ------------------------------------------------------
    void initializeStateSpace_Continues(const ICoreMatrix& A, const ICoreMatrix& B, const ICoreMatrix& C, const ICoreMatrix& D);
    void initializeStateSpace_Continues(const ICoreMatrix &A, const ICoreMatrix &Bu, const ICoreMatrix &Bf,
                                        const ICoreMatrix &C, const ICoreMatrix &Du, const ICoreMatrix &Df);
    void initializeStateSpace_Discrete(const ICoreMatrix &A, const ICoreMatrix &B, const ICoreMatrix &C,
                                       const ICoreMatrix &D, const double &Ts);
    void initializeStateSpace_Discrete(const ICoreMatrix &A, const ICoreMatrix &Bu, const ICoreMatrix &Bf,
                                       const ICoreMatrix &C, const ICoreMatrix &Du, const ICoreMatrix &Df,
                                       const double &Ts);
    void discretize();
    // Clears stateSpace_cont back to its default-constructed (empty) value and drops the
    // valid flag. Needed by blocks whose state-space representability depends on a config
    // that can change between runs -- Gain, whose "Multiplication Type" is only expressible
    // as y = D*u in some modes -- because the flag is otherwise sticky: once a suitable
    // config had set it, a later unsuitable one would leave callers merging stale matrices.
    void clearStateSpace_cont();
    // Virtual so a block can refuse to hand out a state space its current config does not
    // actually satisfy (see the Gain override), rather than returning a stale or meaningless one.
    [[nodiscard]] virtual ICoreStateSpace getStateSpace_cont() const;
    [[nodiscard]] ICoreStateSpace getStateSpace_disc() const;
    // True once initializeStateSpace_Continues has been called at least once. Blocks that never
    // model continuous dynamics (Gain, Sum, Mux, ...) leave stateSpace_cont at its default-constructed
    // 1x1 zero matrices, which is shape-valid but mathematically meaningless — callers reasoning about
    // stateSpace_cont (e.g. series/parallel merging) must gate on this rather than inspecting matrix sizes.
    [[nodiscard]] bool hasValidStateSpace_cont() const;

    // ------------------------------------------------------
    // Reset
    // ------------------------------------------------------
    void resetSolverOrder();
    void clearVisitedBlocks();
    void clearInternalStates();
    void assignHomeTreeNodeSampling();

    // ------------------------------------------------------
    // Block Sampling
    // ------------------------------------------------------
    void assignSamplingTime();

    // ------------------------------------------------------
    // Solve Step
    // ------------------------------------------------------
    void setInitialState(const ICoreMatrix& initialState);
    void solve(const double &tn);

    // ------------------------------------------------------
    //      Ports signal size
    // ------------------------------------------------------
    virtual void initializePortSignalSize();
    virtual bool verifyInitializedPortSignals();

    // Port sizing runs as a convergence loop (ICoreModelBuild::initializePortsSignalMatrixSize),
    // so the per-block line initializePortSignalSize() logs would otherwise be repeated once per
    // block per pass. The build turns it off after the first pass and back on when it is done.
    static void setPortSizingLogEnabled(const bool& enabled);

    // For an override that logs its own sizing failures. Anything a block reports from
    // initializePortSignalSize() is reported once per pass unless it asks this first --
    // and a PERMANENT failure (no runtime, code that will not compile) is reported on
    // every one of them, which is how the diagnostics panel came to receive thousands of
    // copies of two lines and take the GUI thread down with it.
    [[nodiscard]] static bool isPortSizingLogEnabled();

    // ------------------------------------------------------
    //      Block Config
    // ------------------------------------------------------
    virtual void loadBlockConfig();

    // ------------------------------------------------------
    //      Block Simulation
    // ------------------------------------------------------
    virtual ICoreMatrix compute_f(const ICoreMatrix& x, const std::vector<ICoreMatrix>& u, const double& t);
    virtual std::vector<ICoreMatrix> compute_h(const ICoreMatrix& x, const std::vector<ICoreMatrix>& u, const double& t);
    virtual ICoreMatrix compute_f_discrete(const ICoreMatrix& x, const std::vector<ICoreMatrix>& u, const double& t);
    virtual std::vector<ICoreMatrix> compute_h_discrete(const ICoreMatrix& x, const std::vector<ICoreMatrix>& u, const double& t);
    virtual void onSolverFinish();

    // ------------------------------------------------------
    //      Coder
    // ------------------------------------------------------
    virtual std::string generateBodyCode_Python();
    virtual std::string generateParamsCode_Python(const std::string& blockFuncName) const;

    virtual std::string generateBodyCode_Matlab();
    virtual std::string generateParamsCode_Matlab(const std::string& blockFuncName) const;
    virtual std::string generateBodyCode_Java();
    virtual std::string generateParamsCode_Java(const std::string& blockFuncName) const;
    virtual std::string generateBodyCode_Rust();
    virtual std::string generateParamsCode_Rust(const std::string& blockFuncName) const;
    virtual std::string generateBodyCode_C();
    virtual std::string generateParamsCode_C(const std::string& blockFuncName) const;
    virtual std::string generateStateCode_C(const std::string& blockFuncName) const;   // persistent C state fields
    virtual std::string generateBodyCode_Cpp();
    virtual std::string generateParamsCode_Cpp(const std::string& blockFuncName) const;

    virtual std::string generateBodyCode_VHDL();
    virtual std::string generateParamsCode_VHDL(const std::string& blockFuncName) const;
    virtual std::string generateStateDeclCode_VHDL(const std::string& blockFuncName) const;    // persistent architecture-scope state signals
    virtual std::string generateStateResetCode_VHDL(const std::string& blockFuncName) const;   // rst-branch seeding for the above
    virtual std::string generateBodyCode_Verilog();
    virtual std::string generateParamsCode_Verilog(const std::string& blockFuncName) const;
    virtual std::string generateStateDeclCode_Verilog(const std::string& blockFuncName) const;    // persistent module-scope state regs
    virtual std::string generateStateResetCode_Verilog(const std::string& blockFuncName) const;   // rst-branch seeding for the above
    virtual std::string generateBodyCode_SystemVerilog();
    virtual std::string generateParamsCode_SystemVerilog(const std::string& blockFuncName) const;
    virtual std::string generateStateDeclCode_SystemVerilog(const std::string& blockFuncName) const;    // persistent module-scope state regs
    virtual std::string generateStateResetCode_SystemVerilog(const std::string& blockFuncName) const;   // rst-branch seeding for the above

    virtual std::string generateDeclCode_PLC_ST();
    virtual std::string generateBodyCode_PLC_ST();
    virtual std::string generateParamsCode_PLC_ST(const std::string& blockFuncName) const;

    // ------------------------------------------------------
    //      Getters
    // ------------------------------------------------------
    void setDiscreteOnlyBlock(const bool& newDiscreteOnlyBlock);
    [[nodiscard]] int getSolverOrder() const;
    [[nodiscard]] double getSamplingTime() const;
    [[nodiscard]] ICoreBlock* getParentBlock() const;
    [[nodiscard]] ICoreMatrix& getConfig_matrix(const std::string& key);
    [[nodiscard]] std::string& getConfig_string(const std::string& key);
    [[nodiscard]] std::vector<ICorePort*> getInputPorts() const;
    [[nodiscard]] std::vector<ICorePort*> getOutputPorts() const;

    [[nodiscard]] double get_tn_1() const;
    [[nodiscard]] double get_dt() const;

    void printConfigMap_double() const;
    void printConfigMap_string() const;

    // The per-block rate config EVERY block carries (created in the constructor).
    // Public because the Simulink bridge maps it onto Simulink's SampleTime for
    // every block type rather than per entry — the two share a convention:
    // <= 0 inherits the surrounding rate, > 0 is an explicit period.
    static const std::string CONFIG_SAMPLING_TIME;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICorePortSolverEnvironment.h#

src/ICoreSDK/ICoreModel/SolverEnvironments/ICorePortSolverEnvironment.h

ICorePortSolverEnvironment#

ICorePortSolverEnvironment.h:8 · class · pImpl · 8 declaration(s)

class ICorePortSolverEnvironment {
public:
    explicit ICorePortSolverEnvironment(ICorePort* parentPort);

    void setPortSignalSize(const size_t& newNumOfRows, const size_t& newNumOfColumns);
    void resetPortSignal();
    size_t getPortSignalNumOfRows() const;
    size_t getPortSignalNumOfColumns() const;

    ICoreMatrix* getSignal() const;
    void resetToInitialState();

    ~ICorePortSolverEnvironment();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTreeNodeSolverEnvironment.h#

src/ICoreSDK/ICoreModel/SolverEnvironments/ICoreTreeNodeSolverEnvironment.h

ICoreTreeNodeSolverEnvironment#

ICoreTreeNodeSolverEnvironment.h:7 · class · pImpl · 8 declaration(s)

class ICoreTreeNodeSolverEnvironment {
public:
    explicit  ICoreTreeNodeSolverEnvironment();

    void setMaxSolverOrder(const int &newMaxSolverOrder);

    void addMatchedOrderBlocks(const int& order, const std::vector<ICoreBlock*>& blocks);

    int getMaxSolverOrder() const;
    std::unordered_map<int, std::vector<ICoreBlock *>> getBlocksToSolveMap() const;
    std::vector<ICoreBlock *> getMatchingOrderBlocksToSolveList(const int &order) const;

    void resetToInitialState();

    ~ ICoreTreeNodeSolverEnvironment();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreVariablesSpace.h#

src/ICoreSDK/ICoreModel/VariablesSpace/ICoreVariablesSpace.h

ICoreVariablesSpace#

ICoreVariablesSpace.h:17 · class · pImpl · 30 declaration(s)

Backend model: a storage of variables.

class ICoreVariablesSpace {
public:
    explicit ICoreVariablesSpace(ICoreSubsystemTreeNode* parent);

    // Layer 4: canonical "remove me from the live model graph". A variables space is held by its
    // parent tree node via a single pointer (no children vector), and its UI now lives in the left
    // fixed panel (not the canvas), so this is just a selection detach. Idempotent.
    void detachFromModel();

    // -------------------------------------------------------------------------------------------
    // View registry. Each ICoreVariablesSpaceView attaches itself on construction and detaches on
    // destruction. refreshAllUIs() tells every attached view to re-read the model.
    // -------------------------------------------------------------------------------------------
    void attachUI(ICoreVariablesSpaceView* ui);
    void detachUI(ICoreVariablesSpaceView* ui);
    void refreshAllUIs();

    // Read access for views to render rows from the model.
    [[nodiscard]] const std::vector<ICoreVariablesSpaceVariable*>& getAllVariables() const;

    // Commit helpers called by a view when a cell loses focus. The model validates/writes the data
    // and then re-syncs all views (so a rejected duplicate name is reverted everywhere). Returns
    // true only when the stored data actually changed (so callers can autosave just on real edits;
    // a no-op re-entry or a rejected duplicate name returns false).
    bool commitVariableName(ICoreVariablesSpaceVariable* var, const std::string& candidate);
    bool commitVariableValue(ICoreVariablesSpaceVariable* var, const std::string& value);

    ICoreVariablesSpaceVariable* createNewVariable();
    bool isVariableNameUnique(const std::string &nameToCheck, const ICoreVariablesSpaceVariable* variableToExclude = nullptr) const;

    // Programmatic declaration (e.g. from the command console, not a table view). Upserts by name:
    // updates the value if the name already exists, otherwise fills the first empty placeholder row
    // or appends a new one. Re-syncs all attached views. Returns false only for an empty name.
    bool declareVariable(const std::string& name, const std::string& value);

    // Programmatic declaration of a recorded signal, the Signal Recorder block's
    // way in. Same upsert-by-name semantics as declareVariable() -- it just
    // serialises the series to its canonical timeseries(...) string first, so
    // the stored entry is an ordinary variable that happens to type as
    // "Time Series". Returns false for an empty name or an invalid series
    // (mismatched time/value lengths), never storing a half-formed one.
    //
    // Not thread safe: it re-syncs the attached views, so it must be called on
    // the GUI thread. A block recording from the solver thread has to marshal
    // (see the Signal Recorder's onSolverFinish).
    bool declareTimeSeries(const std::string& name, const ICoreTimeSeries& series);

    void deleteVariable(ICoreVariablesSpaceVariable* varToDelete);

    void clearAllVariables();

    void autoAdjustNumOfRows();

    // -------------------------------------------------------------------------------------------
    // Read-only access for the rest of the backend.
    //
    // The variables space is a pure "space of variables": it is edited *only* through its views.
    // Other modules must never mutate it; they may only read a variable's value/type by name
    // through this API. Only variables with a non-empty name count as defined (empty placeholder
    // rows are skipped).
    // -------------------------------------------------------------------------------------------
    [[nodiscard]] bool hasVariable(const std::string& name) const;
    [[nodiscard]] std::string getVariableValue(const std::string& name) const;   // "" if not found
    [[nodiscard]] std::string getVariableType(const std::string& name) const;    // "" if not found
    [[nodiscard]] const ICoreVariable* getVariable(const std::string& name) const; // nullptr if not found
    [[nodiscard]] std::vector<std::pair<std::string, std::string>> getAllDefinedVariables() const;

    // Recorded-signal reads. getTimeSeries() returns false when the name is
    // unknown, holds something that is not a time series, or holds one whose
    // stored string no longer parses -- callers get an empty series in every
    // failure case and never a partially filled one.
    [[nodiscard]] bool getTimeSeries(const std::string& name, ICoreTimeSeries& out) const;

    // Names of every entry currently typing as "Time Series", in table order.
    // This is what the math tool windows list as their available signals.
    [[nodiscard]] std::vector<std::string> getAllTimeSeriesNames() const;

    [[nodiscard]] ICoreCanvasObjectState* getState() const;

    void updateToState(ICoreCanvasObjectState *desiredState);

    ICoreSubsystemTreeNode* getParent() const;
    [[nodiscard]] std::string getName() const;
    [[nodiscard]] std::string getPath() const;

    void select();
    void deSelect();

    bool isEmpty() const;

    bool isSelected() const;

    const std::string& getClassID();

    ~ICoreVariablesSpace();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreVariablesSpaceVariable.h#

src/ICoreSDK/ICoreModel/VariablesSpace/ICoreVariablesSpaceVariable.h

ICoreVariablesSpaceVariable#

ICoreVariablesSpaceVariable.h:11 · class · pImpl · 8 declaration(s)

Pure data model for a single variables-space entry.

class ICoreVariablesSpaceVariable {
public:
    explicit ICoreVariablesSpaceVariable(ICoreVariablesSpace* parentSpace);

    // Data-only mutators (no UI). Type is derived from the value by the underlying ICoreVariable.
    std::string setName(const std::string& newName) const;
    std::string setValue(const std::string& newValue);

    ICoreVariable* getSyntraVariable() const;

    [[nodiscard]] std::string getName() const;
    [[nodiscard]] std::string getValue() const;
    [[nodiscard]] std::string getType() const;

    ~ICoreVariablesSpaceVariable();

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};