Generated reference › API — ICoreSDK/ICoreBlockLibrary
kind: generated#api#icoresdk-icoreblocklibrary

API — ICoreSDK/ICoreBlockLibrary

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

ICoreUserBlockDefinition.h#

src/ICoreSDK/ICoreBlockLibrary/UserBlocks/ICoreUserBlockDefinition.h

ICoreUserBlockDefinition#

ICoreUserBlockDefinition.h:33 · class · 7 declaration(s)

One parsed .iblock file — a USER-DEFINED block definition, the unit the Block Wizard writes and the user block library (ICoreUserBlockLibrary) scans.

class ICoreUserBlockDefinition {
public:
    enum class Kind {
        Composite,   // body = recipe text (ICoreRecipeSerializer output)
        Python       // body = Python source with a compute(t, u, state)
    };

    // ---- identity ---------------------------------------------------------
    ICoreString uuid;       // v4; identity across renames — never regenerate on edit
    ICoreString name;       // leaf segment, identifier-safe [A-Za-z0-9_]
    ICoreString family;     // middle segment, identifier-safe
    ICoreString summary;    // one line, shown by the navigator entry
    ICoreString created;    // "YYYY-MM-DD"; informational, not validated
    ICoreString modified;
    Kind kind = Kind::Composite;

    // ---- ports ------------------------------------------------------------
    // Counts are what the navigator preview draws (the analogue of
    // registerInitialPorts). Labels are empty or exactly count-sized; a side
    // with 2+ ports MUST carry labels — same rule as ADDING_NEW_BLOCKS.md §3,
    // and validate() enforces it. Labels may not contain commas (they are
    // comma-separated in the header).
    int inputCount = 0;
    int outputCount = 0;
    ICoreStringList inputLabels;
    ICoreStringList outputLabels;

    // ---- payloads ---------------------------------------------------------
    ICoreString iconSvg;          // may be empty: navigator falls back to a monogram
    ICoreString descriptionHtml;  // may be empty: hover card shows the summary
    ICoreString body;             // must be non-empty for Kind::Python

    // ---- file text <-> definition -----------------------------------------
    // False leaves `err` explaining which line or section refused, in words a
    // user can act on ("line 4: ...", "missing section ...ICON...").
    // `out` is reset first and is only trustworthy when parse returns true.
    static bool parse(const ICoreString& fileText, ICoreUserBlockDefinition& out,
                      ICoreString& err);

    // The exact text parse() accepts. Assumes validate() passed — serialize
    // does not re-check.
    ICoreString serialize() const;

    // The rules a definition must satisfy before it is written or listed:
    // uuid present, identifier-safe name/family, non-negative counts, label
    // count/mandatory-label rules, non-empty Python body. parse() runs this
    // last, so a parsed definition is always a valid one.
    bool validate(ICoreString& err) const;

    // ---- naming -----------------------------------------------------------
    // "My_Blocks/<family>/<name>" — the navigator address. A pseudo-type: it
    // is never registered anywhere, and the grand family is reserved for us
    // (USER_BLOCK_WIZARD.md §8).
    ICoreString pseudoType() const;
    static const char* grandFamily();

    // ---- helpers ----------------------------------------------------------
    static bool isIdentifierSafe(const ICoreString& s);   // non-empty, [A-Za-z0-9_]
    static ICoreString generateUuid();                    // random v4, lowercase
    static ICoreString kindName(Kind kind);               // "composite" / "python"
    static bool kindFromName(const ICoreString& text, Kind& out);

    static constexpr int formatMajorVersion = 1;

    bool operator==(const ICoreUserBlockDefinition& other) const;
    bool operator!=(const ICoreUserBlockDefinition& other) const;
};
};

ICoreUserBlockLibrary.h#

src/ICoreSDK/ICoreBlockLibrary/UserBlocks/ICoreUserBlockLibrary.h

ICoreUserBlockLibrary#

ICoreUserBlockLibrary.h:37 · class · nested SkippedFile · 13 declaration(s)

The user's per-app library of .iblock definitions: one folder tree under the application home, scanned off disk, never cached across calls.

class ICoreUserBlockLibrary {
public:
    // One unreadable file from the last scan, and why. The navigator's manage
    // dialog lists these — a silently absent block reads as "the app lost my
    // work", which is worse than any error message.
    struct SkippedFile {
        ICoreString path;
        ICoreString reason;
    };

    // Every definition on disk right now, family folders in name order, files
    // in name order inside each. Rescans on every call (the set is small, and
    // a cache would go stale the moment a user drops a file in with the app
    // running — the same reasoning as ICoreTemplateLibrary::all()).
    static ICoreList<ICoreUserBlockDefinition> all();

    // What the most recent scan could not read. Refreshed by all() and by the
    // mutating calls below (each rescans to validate its inputs).
    static ICoreList<SkippedFile> skippedInLastScan();

    // Lookups over a fresh scan. False leaves `out` untouched.
    static bool findByUuid(const ICoreString& uuid, ICoreUserBlockDefinition& out);
    static bool findByPseudoType(const ICoreString& pseudoType, ICoreUserBlockDefinition& out);

    // Family folder names (sorted, may include empty families) — the wizard's
    // family combo lists these.
    static ICoreStringList families();

    // Write `def` into the library at pathFor(def). Collisions:
    //   * target file exists with the SAME uuid    -> update in place;
    //   * target file exists with a DIFFERENT uuid -> refused unless
    //     `overwrite` (the wizard asks the user first);
    //   * same uuid already lives at a DIFFERENT path -> treated as a
    //     rename/move: the old file is removed after the new one is written.
    // False leaves `err` filled and the library unchanged.
    static bool save(const ICoreUserBlockDefinition& def, bool overwrite, ICoreString& err);

    // Bring an external .iblock into the library: parse + validate `source`,
    // then save() it where its own header says it belongs. `imported` receives
    // the definition on success (the caller wants the name for its "Imported
    // <block>" message). The source file is never modified.
    static bool importFile(const std::filesystem::path& source, bool overwrite,
                           ICoreUserBlockDefinition& imported, ICoreString& err);

    // Copy the block's library file to `destination`, byte for byte. Refuses
    // to overwrite an existing destination — the caller's file dialog owns
    // that conversation.
    static bool exportTo(const ICoreString& uuid, const std::filesystem::path& destination,
                         ICoreString& err);

    // Delete the block's file; prunes its family folder if that leaves it
    // empty. False when no such uuid or the delete failed.
    static bool remove(const ICoreString& uuid, ICoreString& err);

    // "<application home>/Blocks". Created on first look, like the user
    // templates folder, so there is always somewhere to drop a file.
    static std::filesystem::path userBlocksFolderPath();

    // TEST SEAM. The regression sandbox repoints the DOCUMENTS folder but the
    // application home is deliberately assigned once and never moves — so a
    // sandboxed case points this library at a scratch tree instead. An empty
    // path restores the real app home. Never called outside the test suite.
    static void setRootOverrideForTests(const std::filesystem::path& root);

    // "<root>/<family>/<name>.iblock" for this definition.
    static std::filesystem::path pathFor(const ICoreUserBlockDefinition& def);

    // Change notification, toolkit-free: save/import/remove fire every
    // subscriber after the library has changed on disk. The navigator's
    // rebuild hangs off this. Subscribers run on the caller's thread.
    static int subscribeToChanges(std::function<void()> onChanged);
    static void unsubscribeFromChanges(int token);

    // The drag-and-drop format a user-block navigator entry carries and the
    // canvas accepts; the payload is a definition's uuid. Declared here next
    // to the uuids it quotes, for the same no-drift reason as
    // ICoreTemplateLibrary::dragMimeType().
    static const char* dragMimeType();
};
};

ICoreUserBlockMaterializer.h#

src/ICoreSDK/ICoreBlockLibrary/UserBlocks/ICoreUserBlockMaterializer.h

ICoreUserBlockMaterializer#

ICoreUserBlockMaterializer.h:33 · class · 0 declaration(s)

Stamps a user block definition into a live diagram (USER_BLOCK_WIZARD.md §7).

class ICoreUserBlockMaterializer {
public:
    // Stamp `def` into `parent` at `position` (origin-anchor coordinates,
    // +y up, exactly like move()). `createdName` receives the name the
    // instance actually got — a sibling clash gets a numbered name instead.
    static ICoreRecipeFileTransfer::Result stamp(ICoreSubsystemTreeNode* parent,
                                                 const ICoreUserBlockDefinition& def,
                                                 const ICorePoint& position,
                                                 ICoreString* createdName = nullptr);

    // The drop handler's form: resolve `uuid` in ICoreUserBlockLibrary, then
    // stamp. Fails with a user-readable reason when the uuid is not in the
    // library (e.g. the file was deleted while the navigator still showed it).
    static ICoreRecipeFileTransfer::Result stampByUuid(ICoreSubsystemTreeNode* parent,
                                                       const ICoreString& uuid,
                                                       const ICorePoint& position,
                                                       ICoreString* createdName = nullptr);
};
};