Generated reference › API — ICoreBlocks/ICoreStudio/StudioObjects/Chart
kind: generated#api#icoreblocks-icorestudio-studioobjects-chart

API — ICoreBlocks/ICoreStudio/StudioObjects/Chart

The public contract of 12 header(s) under src/ICoreBlocks/ICoreStudio/StudioObjects/Chart — 12 class/struct definition(s), 167 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.

ICoreChart.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/ICoreChart.h

ICoreChart#

ICoreChart.h:37 · class · bases public ICoreChartBase · pImpl · nested SubChartOf · 76 declaration(s)

A plot, and - when it is not itself a sub chart - the window around it.

class ICoreChart : public ICoreChartBase {
public:
    explicit ICoreChart(ICoreBlock* parentBlock = nullptr);

    // ---- Sub charts
    ICoreChart* addSubChart();
    void removeAllSubCharts();
    [[nodiscard]] std::vector<ICoreChart*> getSubCharts() const;
    [[nodiscard]] bool isSubChart() const;

    // The chart that owns the window. Returns this when there is no host.
    [[nodiscard]] ICoreChart* getHostChart();
    [[nodiscard]] const ICoreChart* getHostChart() const;

    // Host first, then every sub chart in stacking order. Always non-empty.
    [[nodiscard]] std::vector<ICoreChart*> getChartStack();

    // Splits the viewport evenly over the stack. Driven by the view. One
    // column by default; a grid once setSubChartGrid() has been called.
    void layoutChartsInScene(double viewportWidth, double viewportHeight);

    // The stack laid out as a GRID rather than a single column -- MATLAB's
    // subplot(m, n, p) and tiledlayout(m, n) (the core-MATLAB board, C13.5).
    // rows x cols tiles, the stack filling them row by row with the host in
    // the first tile, which is exactly how MATLAB numbers p. 0 x 0, the
    // default, is the one-column stack every scope and Bode pair has always
    // used. A stack longer than rows*cols wraps into further rows rather
    // than being clipped. Forwarded to the host from a sub chart.
    void setSubChartGrid(int rows, int cols);
    [[nodiscard]] int subChartGridRows() const;
    [[nodiscard]] int subChartGridCols() const;

    // The title bar of the window this chart (or its host) owns. `figure`
    // names its windows the way MATLAB does ("Figure 2").
    void setWindowTitle(const ICoreString& title);

    void showInWindow();
    void hideWindow() const;

    void triggerZoom(const double &delta);
    void resetZoomAndPan();
    void resetZoomAndPanAllCharts();

    void plot(const ICoreMatrix& matrix);
    void clearAndPlot(const ICoreMatrix& matrix);

    // --- Chart Export ---
    bool exportAsImage(const ICoreString& filePath) const;   // png/jpg (auto by extension)
    bool exportAsPDF(const ICoreString& filePath);
    bool exportAsSVG(const ICoreString& filePath);
    bool exportAsEPS(const ICoreString& filePath);   // A10.55

    // --- Data Export --- (covers every sub chart in the window)
    bool exportDataCSV(const ICoreString& filePath);

    void enableFlushingTimer();
    void disableFlushingTimer();

    ICoreChartLinePath* createNewLinePath();
    void clearAllLinePaths();
    [[nodiscard]] ICoreChartLinePath* getLinePathByIndex(const int& index) const;

    // Tops the chart up to the given number of line paths, creating the missing
    // ones. Restoring state needs it: styles are captured per path, but the
    // paths themselves are only created when the model runs, so they have to be
    // put back before a style has anything to be applied to.
    void ensureLinePathCount(int requiredCount);
    void ensureSubChartCount(int requiredCount);

    void updateAllChildrenPositions() const;

    void getState(ICoreCanvasObjectState* stateToPopulate) const;
    void updateToState(const std::unordered_map<std::string, std::string>& desiredProperties);

    void loadSerializedPathStyles(const std::unordered_map<std::string, std::string> &allPaths);

    void cacheDrawnPathStyles(const bool &clearOldCachedStyles);

    std::unordered_map<std::string, std::string> popOldestPathStyle();
    // Forget the styles clearAllLinePaths() cached. That cache is what lets a
    // scope re-plot without losing the colours and names its user picked; a
    // MATLAB-style redraw (hold off) must NOT inherit them -- `legend("a")`
    // on one plot would name the first line of every plot after it.
    void discardCachedPathStyles();

    void setWidth(double newWidth);
    void setHeight(double newHeight);

    // Swaps a linear axis for a base-10 logarithmic one (the toolkit cannot
    // convert one in place, so the axis is replaced and the series reattached).
    // No-ops if the axis is already logarithmic, or if any plotted value on
    // that axis is <= 0 -- reported through ICoreRunDiagnosis rather than
    // silently. Call after plot(), which is what establishes the range being
    // carried over. The chart toolbar's "Set log ruler" menu entries call these
    // across the whole chart stack; a caller building a plot that is
    // conventionally logarithmic (a Bode magnitude, say) can call them directly
    // instead.
    void setLogarithmicX();
    void setLogarithmicY();

    void setAxisLabelText_X(const std::string& newText) const;
    void setAxisLabelText_Y(const std::string& newText) const;
    void setAxisFont_X(const ICoreFont& newFont) const;
    void setAxisFont_Y(const ICoreFont& newFont) const;

    [[nodiscard]] std::vector<ICoreChartLinePath*> getAllLinePaths() const;
    [[nodiscard]] ICoreChartRightPanel* getRightSidePanel() const;

    // Show or fold away the side panel, as its caption toggle does -- and move
    // the toggle's arrow with it, which setPanelShown() on the panel alone does
    // not. A tool that embeds a chart and wants the plot at full width from the
    // start calls this with false (the FFT Analysis panel does). A sub chart
    // shares its host's panel and forwards there.
    void setSidePanelShown(bool shown);

    // Paint the chart's ground in surface.panel, the step under panelRaised,
    // instead of panelRaised itself. For a chart embedded in a page that sits on
    // a raised card (the FFT Analysis panel): on the card's own colour the
    // chart's area does not read as an area at all. Survives theme switches; a
    // sub chart forwards to its host.
    void setSunkenGround(bool sunken);

    [[nodiscard]] ICoreChartAxisLabel* getXAxisLabel() const;
    [[nodiscard]] ICoreChartAxisLabel* getYAxisLabel() const;

    // Deliberately hides the base's axis builder. The toolkit's version
    // destroys the existing axes and builds new ones carrying its own built-in
    // light theme, so tick labels come back near-black whatever theme is
    // active. Every axis a chart ever gets is born here or in
    // setLogarithmicX/Y(), and painting them in this one place is what keeps a
    // caller from having to remember to.
    void createDefaultAxes();

    // ---- Previous runs: the faded traces a scope keeps of the runs before
    // the current one.
    //
    // A sink hands the traces on the plot to archiveCurrentRun() right before
    // it clears them for a new run, and the chart redraws the last
    // previousRunsKept() runs underneath the current one, fainter with age.
    // They are DECORATIVE paths (ICoreChartLinePathBase::setDecorative): not
    // in getAllLinePaths(), the legend, the side panel, the CSV export or the
    // saved styles, and not in resetZoomAndPan() -- so the auto fit frames the
    // current run whether the old ones are shown or not.
    //
    // The two settings belong to the chart owning the window and are saved
    // with its state; a sub chart forwards them there. Turning the traces off
    // hides them and keeps recording, so turning them back on shows the runs
    // made meanwhile.
    void setShowPreviousRuns(bool show);
    [[nodiscard]] bool showsPreviousRuns() const;
    void setPreviousRunsKept(int count);          // clamped to 1..10
    [[nodiscard]] int previousRunsKept() const;
    void archiveCurrentRun();
    void clearPreviousRuns();
    // How many earlier runs this plot holds, shown or not.
    [[nodiscard]] int previousRunCount() const;

    void setInfiniteStreaming(const bool& newInfiniteStreaming);
    bool isInfiniteStreaming() const;
    void setMovingWindowWidth(const int& newMovingWindowWidth);
    int getBufferWidth() const;

    ICoreBlock *getParentBlock() const;
    ICoreGraphicsView* getView() const;
    ICoreWidget* getRootWidget() const;

    void resetToInitialState();
    void kill();
    void setAlive();
    bool isAlive() const;

    ~ICoreChart() override;

protected:
    bool wheelScrolled(const ICoreWheelEvent& event) override;
    bool mousePressed(const ICoreMouseEvent& event) override;
    bool mouseMoved(const ICoreMouseEvent& event) override;
    bool mouseReleased(const ICoreMouseEvent& event) override;
    bool mouseDoubleClicked(const ICoreMouseEvent& event) override;

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

ICoreChartAxisLabel.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/ICoreChartAxisLabel.h

ICoreChartAxisLabel#

ICoreChartAxisLabel.h:20 · class · bases public ICoreGraphicsBoxedText · pImpl · 6 declaration(s)

The title drawn beside one of a chart's two axes.

class ICoreChartAxisLabel : public ICoreGraphicsBoxedText {
public:
    explicit ICoreChartAxisLabel(ICoreChart* parent);

    void autoUpdateSize();

    ~ICoreChartAxisLabel() override;

protected:
    // ⚠⚠ THE HOOK THIS CLASS ACTUALLY RESIZES ON. Raised by
    // ICoreGraphicsText::setPlainText()/setHtml() themselves, once per real
    // change -- so it covers the editing session, a programmatic set and a
    // cancel alike, where the two hooks below cover none of them any more. The
    // .cpp says why at length.
    void textChanged() override;

    // ⚠ focusLost, NOT focusLosing, and the difference is load-bearing.
    // autoUpdateSize() measures the CURRENT text, so it has to run AFTER
    // the toolkit base has committed the edit -- which is exactly what the
    // old body did by calling its parent first. focusLosing would size the
    // label against the pre-edit text.
    void focusLost(const ICoreFocusEvent& event) override;
    // ⚠ keyPressHandled, NOT keyPressed -- same reason as focusLost above.
    // autoUpdateSize() measures the current text, so it must run after the
    // toolkit has inserted the character; the old override got that by
    // calling its parent first. Sizing before the insert lags the label one
    // keystroke behind, visibly, while typing.
    void keyPressHandled(const ICoreKeyEvent& event) override;

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

ICoreChartLinePath.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/ICoreChartLinePath.h

How the path's points are drawn. Scatter suits data that is a set of points rather than a signal -- a pole-zero map, say -- where connecting consecutive entries with a line would draw a shape that means nothing.

The shapes themselves live on the wrapper base; this alias is what call sites already spell (ICoreChartLinePath::MarkerShape::Cross) and keeps them unchanged.

ICoreChartLinePath#

ICoreChartLinePath.h:10 · class · final · bases public ICoreChartLinePathBase · pImpl · 14 declaration(s)

class ICoreChartLinePath final : public ICoreChartLinePathBase {
public:
    // How the path's points are drawn. Scatter suits data that is a set of
    // points rather than a signal -- a pole-zero map, say -- where connecting
    // consecutive entries with a line would draw a shape that means nothing.
    //
    // The shapes themselves live on the wrapper base; this alias is what call
    // sites already spell (ICoreChartLinePath::MarkerShape::Cross) and keeps
    // them unchanged.
    using MarkerShape = ICoreChartMarkerShape;

    explicit ICoreChartLinePath(ICoreChart* parentChart);

    ICoreRect getPathBounds() const;
    void pushPoint(const double& x, const double& y);
    // True when points arrived since the last flush of either kind. A tick
    // with nothing new must not refit the view: the flush timer outlives a run
    // whose blocks were never finished, and a refit per tick is what pinned
    // the user's zoom and pan in place.
    bool updateMovingWindow();
    void flushEntireDataVectorToSeries();

    std::unordered_map<std::string, std::string> captureStyle(const std::string& prefix) const;
    void applyStyle(const std::unordered_map<std::string, std::string> &desiredState);

    void setPathName(const ICoreString &name);
    void setPathColor(const ICoreColor &color);

    // Point labels are text drawn onto the plot, so their color has to follow
    // the theme or they vanish into a dark plot area. But it is also a
    // user-settable, saved property, and a theme switch must not overwrite a
    // color someone picked. These two are the split: anything that represents
    // a choice — the properties panel, a restored state — goes through
    // setPointLabelsColorCustom(), which latches the path out of theming;
    // applyThemeToPointLabels() then only touches paths still on the default.
    void setPointLabelsColorCustom(const ICoreColor& color);
    void applyThemeToPointLabels();

    // Draws each point as a marker of the given shape and size (in pixels).
    // `keepConnectingLine` false -- the default -- hides the line so the result
    // is a pure scatter; true overlays markers on a normal line plot.
    void setScatterStyle(const MarkerShape& shape, const ICoreColor& color,
                         const double& markerSizePx = 11.0,
                         const bool& keepConnectingLine = false);

    // True once setScatterStyle() has been applied.
    [[nodiscard]] bool isScatter() const;

    // Declared here and DEFINED in the .cpp -- unique_ptr<Impl> needs Impl
    // complete to destroy it, and it is incomplete in this header.
    ~ICoreChartLinePath() override;

protected:
    void pointClicked(const ICorePoint& point) override;

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

ICoreChartLinePathRef.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/ICoreChartLinePathRef.h

ICoreChartLinePathRef#

ICoreChartLinePathRef.h:43 · class · pImpl · 11 declaration(s)

A weak, self-nulling handle to one ICoreChartLinePath.

class ICoreChartLinePathRef {
public:
    ICoreChartLinePathRef();

    // Implicit on purpose: binding a handle reads `map.insert(name, path)` with
    // a plain ICoreChartLinePath* on the right, exactly as it did when the map
    // held the guarded pointer directly.
    ICoreChartLinePathRef(ICoreChartLinePath* path);

    ~ICoreChartLinePathRef();

    // This is a VALUE -- ICoreRecipeInterpreter keeps a whole map of them, so it
    // is copied and rehashed. The residue below deletes the implicit copy, so
    // all four are written by hand in the .cpp; the moves are noexcept, or a
    // growing container silently goes back to copying.
    ICoreChartLinePathRef(const ICoreChartLinePathRef& other);
    ICoreChartLinePathRef& operator=(const ICoreChartLinePathRef& other);
    ICoreChartLinePathRef(ICoreChartLinePathRef&& other) noexcept;
    ICoreChartLinePathRef& operator=(ICoreChartLinePathRef&& other) noexcept;

    // The live path, or nullptr if it has been destroyed since it was bound.
    ICoreChartLinePath* get() const;

    // True while the path is still alive.
    explicit operator bool() const;

    bool operator==(const ICoreChartLinePathRef& other) const;
    bool operator!=(const ICoreChartLinePathRef& other) const;

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

ICoreChartMenuStrip.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/ICoreChartMenuStrip.h

The chart window's own menu strip: "X Label", "Y Label" and "Chart" in the title bar, behaving as the titles of a menu bar -- click one to open its drop-down, click it again to close it, and while one is open, moving the pointer onto another switches to it (owner, 2026-10-03).

⚠ NOT ICoreMenuBar AND NOT ICoreMenu, FOR ONE REASON EACH. ICoreMenuBar hands its menus to the SYSTEM menu bar on macOS and is never shown there; these belong to the chart window's title bar on every desktop. ICoreMenu PAINTS its rows and hosts no widget, and the owner asked for the controls themselves inside the menu -- "the text LineEdit itself to enter the value. No need to open a separate popup for them." So a drop-down here is a popup window of its own that holds real controls, drawn with ICoreMenu's own geometry and ink (ICoreMenuCore / ICoreMenuChrome), so it reads as one of the app's menus.

ICoreChartDropDown#

ICoreChartMenuStrip.h:29 · class · final · bases public ICoreWidget · pImpl · 12 declaration(s)

One drop-down: plain menu rows and caption-and-control rows, on ICoreMenu's rounded, framed surface.

class ICoreChartDropDown final : public ICoreWidget {
public:
    explicit ICoreChartDropDown(ICoreNativeWidget* parent = nullptr);
    ~ICoreChartDropDown() override;

    // A plain menu row. Activating it closes the drop-down, then runs.
    void addItem(const ICoreString& text, std::function<void()> onActivated);

    // A caption on the left and `control` on the right; the drop-down takes
    // the control over. It stays open while the control is used.
    void addField(const ICoreString& caption, ICoreNativeWidget* control);

    void addSeparator();

    // Run just before the drop-down shows -- where the controls re-read what
    // they show, so it never opens on stale values.
    void setAboutToShowHook(std::function<void()> hook);

    void popupUnder(ICoreWidget* anchor);
    void closeDropDown();
    [[nodiscard]] bool isOpen() const;

    // Closed, however it was closed.
    ICoreSignal<> onClosed;

protected:
    bool keyPressed(const ICoreKeyEvent& event) override;
    void pointerPressedOutside() override;
    void hidden() override;

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

ICoreChartMenuStrip#

ICoreChartMenuStrip.h:65 · class · final · bases public ICoreWidget · pImpl · 5 declaration(s)

The row of titles that opens them.

class ICoreChartMenuStrip final : public ICoreWidget {
public:
    ICoreChartMenuStrip();
    ~ICoreChartMenuStrip() override;

    // A title on the strip and the drop-down it opens, owned by the strip.
    ICoreChartDropDown* addMenu(const ICoreString& title);

    void closeOpenMenu();

protected:
    // Watches the pointer while a drop-down is open, so sliding along the
    // strip switches drop-downs -- the open popup has the pointer, so the
    // titles cannot see those moves themselves. Armed only while one is open.
    void applicationPointerMoved(const ICorePoint& globalPos) override;

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

ICoreChartRightPanel.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/ICoreChartRightPanel.h

---- Collapsing. The state is held rather than read back off the widget: the tool bar asks for it while the chart window is still being assembled, and until a widget has a shown parent Qt reports it as hidden either way.

ICoreChartRightPanel#

ICoreChartRightPanel.h:18 · class · final · bases public ICoreWidget · pImpl · 14 declaration(s)

class ICoreChartRightPanel final : public ICoreWidget {
public:
    explicit ICoreChartRightPanel(ICoreChart* parentChart);

    void addPath(ICoreChartLinePath *newPath);
    void selectPath(ICoreChartLinePath *path);
    void refreshPathEntry(const ICoreChartLinePath *path);
    void populatePropertiesPanelWithLinePath(ICoreChartLinePath *path);
    void showPropertiesForCurrentSelection();
    void clearAllPaths();
    void resetPropertiesMap();

    // ---- Collapsing. The state is held rather than read back off the widget:
    // the tool bar asks for it while the chart window is still being assembled,
    // and until a widget has a shown parent Qt reports it as hidden either way.
    void setPanelShown(bool shown);
    [[nodiscard]] bool isPanelShown() const;

    // Told after every setPanelShown(), with the new state -- the chart window
    // re-draws the rail's join to its caption from it (A10.86).
    void setPanelShownChangedHook(std::function<void(bool)> hook);

    // ⚠ THE PANEL IS ON THE LEFT SINCE A10.86, AND IN ITS OWN WINDOW IT IS THE
    // WINDOW'S RAIL: square, flush against the window's left edge, the caption
    // and the bottom, in the editor rail's gradient and rim (ICoreRailChrome.h),
    // with the caption continuing it. The chart dresses it so when it shows the
    // chart in its OWN window; a chart embedded in another window's layout
    // (the FFT tool, the verification view) keeps the floating panel.
    void dressAsRail();

    ~ICoreChartRightPanel() override;

protected:
    // The rail's rim once dressAsRail() has run, so the panel's edge matches
    // the fillet and the rim that continue it; the default before.
    ICoreColor borderColor() const override;

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

ICoreChartRightPanelPropertiesPanel.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/ICoreChartRightPanelPropertiesPanel.h

A full-width caption naming the group of rows under it. A10.52: without one, every row in the second group had to repeat "Point Labels …" in a column too narrow to show it, and the titles elided instead.

ICoreChartRightPanelPropertiesPanel#

ICoreChartRightPanelPropertiesPanel.h:14 · class · final · bases public ICoreWidget · pImpl · 8 declaration(s)

class ICoreChartRightPanelPropertiesPanel final : public ICoreWidget {
public:
    explicit ICoreChartRightPanelPropertiesPanel(ICoreWidget* parent, ICoreChartLinePath* path);

    void addPropertyEntry_MajorSplit() const;
    // A full-width caption naming the group of rows under it. A10.52: without
    // one, every row in the second group had to repeat "Point Labels …" in a
    // column too narrow to show it, and the titles elided instead.
    void addPropertyEntry_SectionHeading(const std::string& title) const;
    void addPropertyEntry_ToggleButton(const std::string &title, ICoreToggleButton *interfaceUI) const;
    void addPropertyEntry_LineEdit(const std::string &title, ICoreLineEdit *interfaceUI) const;
    // Takes the wrapper interface rather than QWidget*, so an already-converted
    // wrapper (ICoreSlider) can be handed over alongside the unconverted ones.
    void addPropertyEntry_Widget(const std::string &title, ICoreNativeWidget *interfaceUI) const;

    ~ICoreChartRightPanelPropertiesPanel() override;

protected:
    // Does nothing -- enforces a fully transparent panel.
    void paintContent(ICorePainter&) override;

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

ICoreChartToolBar.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/ICoreChartToolBar.h

ICoreChartToolBar#

ICoreChartToolBar.h:23 · class · final · bases public ICoreToolBar · pImpl · 6 declaration(s)

The chart window's controls, as one row of caption pills (A10.86): the side panel's toggle on the left, over the panel, and the axis, zoom and export groups on the right.

class ICoreChartToolBar final : public ICoreToolBar {
public:
    // The row's height: one caption pill's -- and 32 on macOS, where the
    // chart's pills are cut to it (owner, 2026-09-25: *"drop the heights of
    // the toolbars at the top bar of ICoreChart as well"*, after the editor's
    // title row went 36 -> 32 there).
#if defined(ICORE_OS_MAC)
    static constexpr int kRowHeight = 32;
#else
    static constexpr int kRowHeight = 36;
#endif

    explicit ICoreChartToolBar(ICoreChart* parentChart);

    // The pills, which take clicks; everything between them is caption.
    [[nodiscard]] std::vector<ICoreWidget*> titleBarControls() const;

    // Re-read the side panel's state into the toggle's arrow and tooltip, after
    // something other than the toggle showed or hid the panel.
    void syncPanelToggle() const;

    ~ICoreChartToolBar() override;

protected:
    void paintContent(ICorePainter& painter) override;

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

ICoreChartView.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/ICoreChartView.h

ICoreGraphicsView's hook, not resizeEvent: this class only ever read viewport()->rect(), which is exactly what the hook is handed.

ICoreChartView#

ICoreChartView.h:12 · class · final · bases public ICoreGraphicsView · pImpl · 3 declaration(s)

class ICoreChartView final : public ICoreGraphicsView {
public:
    explicit ICoreChartView(ICoreGraphicsScene* scene, ICoreChart* chart);

protected:
    // ICoreGraphicsView's hook, not resizeEvent: this class only ever read
    // viewport()->rect(), which is exactly what the hook is handed.
    void resized(const ICoreRect& viewportBounds) override;

public:
    // Declared here and DEFINED in the .cpp: unique_ptr<Impl> needs Impl
    // complete to destroy it, and it is incomplete in this header.
    ~ICoreChartView() override;

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

ICoreChartZoomRect.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/ICoreChartZoomRect.h

⚠ NARROWED, and the old note is kept here because the reason it stopped being true is reusable. It read: "ICoreAnyGraphicsItem, not ICoreGraphicsItem: the only caller parents this to an ICoreChart, which derives from the toolkit's chart and so has no ICoreGraphicsItem subobject to point at. There is no cast that makes the narrow type true."

Correct at the time. P2.2 then gave ICoreChartBase public ICoreNativeItem -- two lines, added for an unrelated reason -- and the chart gained exactly the subobject this parameter needed. The lesson is that "not migrated yet" parameters unblock themselves as the seam spreads; re-check them rather than treating the note as permanent.

Declares no class of its own — see the file.

ICoreSinkChartBridge.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/SinkBlocksBridge/ICoreSinkChartBridge.h

ICoreSinkChartBridge#

ICoreSinkChartBridge.h:49 · class · final · pImpl · 11 declaration(s)

The one seam between a charting sink block and the chart it draws on.

class ICoreSinkChartBridge final {
public:
    // `ownerBlock` is the sink block itself -- the chart is looked up through it
    // on each call rather than cached, because setScopeBlock() may not have
    // attached one yet when the block's constructor builds this bridge.
    explicit ICoreSinkChartBridge(ICoreBlock* ownerBlock);

    // Declared here, DEFINED in the .cpp: the four sink blocks hold this BY
    // VALUE, so their translation units destroy it and would otherwise need
    // Impl complete.
    ~ICoreSinkChartBridge();

    // False when the block has no chart attached. Every method below is a no-op
    // in that case, so a caller only needs this when it wants to skip work of
    // its own (Record, which records into variables whether or not it plots).
    [[nodiscard]] bool hasChart() const;

    // Rolling window instead of the whole history, for a run with no end.
    // Applied directly rather than posted: it sets a plain flag the chart reads,
    // which is what the blocks already did.
    void setInfiniteStreaming(const bool& newInfiniteStreaming) const;

    // ---- Run setup. Called in this order from loadBlockConfig().
    void clearTraces() const;
    void addTrace(const std::string& traceName) const;

    // A trace that draws as STEPS rather than as a straight line between
    // samples (T3.6). A boolean or an integer signal does not pass through the
    // values between two samples -- an int32 going 1 -> 4 was never 2.5 -- and
    // a straight line says it did. Simulink draws these kinds the same way, so
    // a reader who knows one plot reads the other.
    //
    // Implemented HERE rather than in the chart: a step is two points, and
    // inserting the corner is the only difference between the two shapes. The
    // toolkit's series needs nothing new, and neither does the path.
    void addTrace(const std::string& traceName, bool drawAsSteps) const;

    // createDefaultAxes() must run AFTER the traces exist -- the axes are built
    // from the paths -- which is why this is a separate call and not folded into
    // addTrace(). It also starts the flushing timer for the run.
    void finishTraces(const std::string& xAxisLabel) const;
    void finishTraces(const std::string& xAxisLabel, const std::string& yAxisLabel) const;

    // ---- Per sample. `traceIndex` is the position the trace was added in.
    // Out-of-range indices are dropped by the chart, not by the caller.
    void pushPoint(const int& traceIndex, const double& x, const double& y) const;

    // ---- End of run: flush every buffered point into its series and stop the
    // flushing timer.
    void finishRun() const;

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

ICoreSinkRecordingBridge.h#

src/ICoreBlocks/ICoreStudio/StudioObjects/Chart/SinkBlocksBridge/ICoreSinkRecordingBridge.h

ICoreSinkRecordingBridge#

ICoreSinkRecordingBridge.h:29 · class · final · 1 declaration(s)

The seam between a recording sink block and the variables space.

class ICoreSinkRecordingBridge final {
public:
    // Declares `names[k]` = `channels[k]` in the global variables space, on the
    // GUI thread. Pairs are taken up to the shorter of the two vectors.
    //
    // `blockLabel` prefixes the diagnosis logged when there is no variables
    // space to record into -- "Record" or "Signal Recorder" -- so the message
    // still names the block once the call is one frame deeper than it was.
    static void declareTimeSeries(std::vector<std::string> names,
                                  std::vector<ICoreTimeSeries> channels,
                                  const std::string& blockLabel);

    // Declares `name` = `record` in the global variables space, on the GUI thread,
    // as the record's struct(...) storage form: how a run leaves an OBJECT there
    // (an iddata, a linearization result) rather than a signal.
    static void declareRecord(const std::string& name, const ICoreRecord& record, const std::string& blockLabel);

    // MATLAB's time-domain `iddata` as a record: what an Iddata Sink leaves in the
    // space at the end of a run. `outputData` is N x ny and `inputData` N x nu,
    // one row per sample and one column per channel; `ts` is the sample time and
    // `tstart` the first sample's time. The four numeric properties are held --
    // OutputData, InputData, Ts, Tstart, in MATLAB's property order -- and the
    // character ones (Domain 'Time', InterSample 'foh', TimeUnit 'seconds', and the
    // channel names u1.. and y1..) are withheld BY NAME, because a record holds
    // numbers only. false, with `whyNot`, for a row-count mismatch or a sample
    // time that is not a positive finite number, as MATLAB's iddata refuses one.
    static bool iddataRecord(const ICoreMatrix& outputData, const ICoreMatrix& inputData, double ts, double tstart,
                             ICoreRecord& out, std::string* whyNot = nullptr);
};
};