Generated reference › API — ICoreEssentials/UI/Graphics
kind: generated#api#icoreessentials-ui-graphics

API — ICoreEssentials/UI/Graphics

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

HeaderDefinesDeclarationsBases
ICoreAnyGraphicsItem.h0
ICoreGraphicsBoxedText.hICoreGraphicsBoxedText27public ICoreGraphicsText
ICoreGraphicsButton.hICoreGraphicsButton36public ICoreGraphicsObject
ICoreGraphicsComboBox.hICoreGraphicsComboBox13public ICoreGraphicsBoxedText
ICoreGraphicsComboBoxDialog.hICoreGraphicsComboBoxDialog13public ICoreGraphicsObject
ICoreGraphicsComboBox_ComboOption.hICoreGraphicsComboBox_ComboOption7public ICoreGraphicsButton
ICoreGraphicsCommands.hICoreGraphicsCommands7
ICoreGraphicsInfoLabel.hICoreGraphicsInfoLabel8public ICoreGraphicsObject
ICoreGraphicsItem.hICoreGraphicsItem20public ICoreNativeItem
ICoreGraphicsObject.h0
ICoreGraphicsPixmap.hICoreGraphicsPixmap8public ICoreNativeItem
ICoreGraphicsProxyWidget.h0
ICoreGraphicsRect.hICoreGraphicsRect17public ICoreNativeItem
ICoreGraphicsRecycler.hICoreGraphicsRecycler5
ICoreGraphicsScene.hICoreGraphicsScene12public ICoreNativeScene
ICoreGraphicsScrollPane.h0
ICoreGraphicsScrollPaneScrollBar.hICoreGraphicsScrollPaneScrollBar10public ICoreGraphicsObject
ICoreGraphicsScrollPaneScrollableArea.hICoreGraphicsScrollPaneScrollableArea16public ICoreGraphicsObject
ICoreGraphicsTable.hICoreGraphicsTable15public ICoreGraphicsObject
ICoreGraphicsTableEntryRow.hICoreGraphicsTableEntryRow12public ICoreGraphicsObject
ICoreGraphicsTableTitleRowSplitter.hICoreGraphicsTableTitleRowSplitter13public ICoreGraphicsObject
ICoreGraphicsTableTitlesRow.hICoreGraphicsTableTitlesRow11public ICoreGraphicsObject
ICoreGraphicsText.hICoreGraphicsText62public ICoreNativeItem
ICoreGraphicsView.hICoreGraphicsView42public ICoreNativeWidget

ICoreAnyGraphicsItem.h#

src/ICoreEssentials/UI/Graphics/ICoreAnyGraphicsItem.h

A scene item of no particular kind: the parent-pointer type every graphics object takes.

This is the scene tier's ICoreAnyWidget, and it exists for the same reason. SoftwareLayout/README.md S11 already records that the toolkit's item type in its PARENT-POINTER shape is not adoptable debt -- it is how the scene graph is spelled, on every item, by the toolkit's own API. Naming it ICore lets code outside the wrapper zone pass a parent through without spelling a Qt type, which is all those call sites ever do with it.

File-scope declarations#

// A scene item of no particular kind: the parent-pointer type every graphics
// object takes.
// 
// This is the scene tier's ICoreAnyWidget, and it exists for the same reason.
// SoftwareLayout/README.md S11 already records that the toolkit's item type in
// its PARENT-POINTER shape is not adoptable debt -- it is how the scene graph
using ICoreAnyGraphicsItem = QGraphicsItem;

// The same, one rung up: a scene item that is also a toolkit object, which is
// what a parent parameter means when the callee will connect to it.
using ICoreAnyGraphicsObject = QGraphicsObject;

// A toolkit object of no particular kind, for parameters that accept anything
// with a toolkit lifetime -- the widest of the three.
using ICoreAnyObject = QObject;

ICoreGraphicsBoxedText.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsBoxedText.h

Its ink is its own (applyThemeColors picks between two field tokens on a themeChanged of its own), so the base's Ink stands down the first time this class sets a colour -- that is the sticky-override rule doing its job, not a conflict.

ICoreGraphicsBoxedText#

ICoreGraphicsBoxedText.h:17 · class · bases public ICoreGraphicsText · pImpl · 27 declaration(s)

class ICoreGraphicsBoxedText : public ICoreGraphicsText {
public:
    // ⚠ REPLACED, NOT OVERLOADED (P2.10b-3b), and the distinction is the whole
    // reason this took its own commit. The warning that stood here still holds
    // and is kept verbatim below: adding an ICoreNativeItem* overload BESIDE
    // the QGraphicsItem* one is R4-ambiguous, because every ICoreGraphicsObject
    // subclass is BOTH -- and ICoreGraphicsTableEntryRow is exactly such a
    // caller. Replacing the parameter has no such problem: that same `this`
    // converts to the one remaining overload unambiguously, and the callers
    // that were unwrapping with icoreNativeItem() stop needing to.
    //
    // *(The superseded warning, preserved because the overload is still wrong:)*
    // ⚠ Do NOT add an ICoreNativeItem* overload beside this. It was tried in
    // P2.5 and it is R4: every ICoreGraphicsObject subclass is BOTH a
    // QGraphicsItem and an ICoreNativeItem, so the two constructors are
    // ambiguous for the arguments most call sites already pass --
    // ICoreGraphicsTableEntryRow.cpp:25 fails to compile immediately. A caller
    // holding a converted (non-Qt) parent unwraps with icoreNativeItem() at the
    // call site instead.
    explicit ICoreGraphicsBoxedText(ICoreNativeItem* parent = nullptr);

    // WAS `QRectF boundingRect() const override` returning the same rectangle.
    // The box states its size explicitly rather than measuring its document,
    // which is exactly what contentBounds() is for; boundingRect() is derived
    // from this on the base now, so the toolkit still sees the same rectangle.
    [[nodiscard]] ICoreRect contentBounds() const override;

    void autoCalcHeight();

    virtual void setWidth(const double& width);
    virtual void setHeight(const double& height);

    void setBackgroundColor(const ICoreColor& color);

    void setBoldText(bool isBold);

    void setManualFocus(bool isFocus);

    void setBorderColor(ICoreColor color);

    // Keep the border invisible, and keep it that way across theme switches. A
    // bare setBorderColor(Qt::transparent) is caller-owned and never refreshed,
    // so the next theme re-derivation restored field.border — which is what drew
    // a hairline box around the chart's axis labels under Light.
    void hideBorder();

    void setUserEditable(const bool& userEditable);

    // Read-only boxes otherwise fill with field.background — the same colour the
    // editable ones wear, so a value the user cannot type in looks exactly like
    // one they can. This opts a box into the treatment the variables space gives
    // its derived column: field.readOnlyBackground plus secondary text. Both
    // themes carry that token, so the split holds on light as well as dark.
    void useRaisedReadOnlyStyle();

    // Wear field.background, and keep wearing it across theme switches. This is
    // what an editable box in a themed dialog wants: a bare setBackgroundColor
    // is caller-owned and never refreshed, so a box painted white under Light
    // stayed white after a switch to Dark.
    void useFieldFill();
    void setFocusable_DisableUserEdit();
    // ⚠ WAS `const`, AND THAT WAS ALWAYS WRONG -- it mutates the item's text
    // layout. It only compiled because QGraphicsTextItem::document() is a
    // const member returning a NON-const QTextDocument*, so the body mutated
    // straight through the const. Routing it via setTextAlignment (P2.10b-1)
    // is what surfaced it; both call sites hold a non-const pointer, so
    // dropping const costs nothing.
    void centerTextHorizontally();

    double predictTextWidthPx(const ICoreString& text) const;
    virtual double getPredictedTextWidthPx() const;  // This is separate because virtual

    double getWidth() const;
    double getHeight() const;

    void resetToInitialState(ICoreNativeItem* parent = nullptr);
    // The recycler's liveness bookkeeping -- see ICoreGraphicsRecycler.
    void kill();
    void setAlive();
    [[nodiscard]] bool isAlive() const;

    // Out of line: Impl is incomplete here, so the unique_ptr's deleter cannot
    // be instantiated in this header. It was an empty inline body before H5.2.
    ~ICoreGraphicsBoxedText() override;

protected:
    // All of this class's focus-out work ran before the toolkit base, so it
    // is focusLosing. See the .cpp.
    void focusLosing(const ICoreFocusEvent& event) override;
    bool keyPressed(const ICoreKeyEvent& event) override;

    // WAS one paint() override, split at the base call the way P2.10a/P2.11b
    // split the focus and key handlers: the fill ran BEFORE
    // ICoreGraphicsText::paint and the border and focus ring ran AFTER it, and
    // those are exactly the two points the base calls these hooks from.
    void paintBackground(ICorePainter& painter) override;
    void paintContent(ICorePainter& painter) override;

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

ICoreGraphicsButton.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsButton.h

The Q_PROPERTY(backgroundOpacity) that stood here is GONE (P2.9d-5d): the fade drives setBackgroundOpacity() through ICoreValueAnimation::onValueChanged now, so nothing resolves the name through the metaobject. The Q_OBJECT that outlived it left with the flip (P2.9d-5e): the base is not a QObject any more, so the macro stopped being removable-with-care and became a compile error.

ICoreGraphicsButton#

ICoreGraphicsButton.h:16 · class · bases public ICoreGraphicsObject · pImpl · 36 declaration(s)

class ICoreGraphicsButton : public ICoreGraphicsObject {
public:
    // The graphics-scene twin of ICoreButton::Variant, remembered for the same
    // reason: the fill, the opacities AND the opaque canvas-coloured backdrop
    // under the glass are all theme tokens, and a button configured under one
    // theme used to keep every one of them after a switch — leaving a light
    // rectangle sitting on the dark canvas.
    enum class Variant { None, Primary };

    explicit ICoreGraphicsButton(ICoreNativeItem* parent = nullptr, const ICoreString& initialText = "");

    // Wear a variant, now and after every theme switch. Prefer
    // setVariant(Variant::Primary), called directly by the port buttons.
    void setVariant(Variant variant);

    // contentBounds(), not boundingRect() (P2.9d-2). Same value, same members:
    // the base derives boundingRect() from this, so nothing about the geometry
    // changes -- what goes away is an override of a Qt virtual that would stop
    // being called at all once this tier drops its Qt base.
    [[nodiscard]] ICoreRect contentBounds() const override;

    void reconstructDescendents();

    void animateShow();
    void animateHide();

    void setHoldHoveredStyle(bool newValue);
    void setHoverColor(ICoreColor newHoverColor);

    // Wear the app's nav-row hover treatment — the ICoreNavItemStyle wash,
    // hairline and accent edge that an ICoreMenu row and every plain
    // ICoreButton light with — instead of the flat hover pill.
    //
    // ⚠ OFF BY DEFAULT, and deliberately so. Turning it on for every graphics
    // button would restyle the canvas context menu's own rows, the combo box
    // options and the auto-inserter along with whatever asked for it; a button
    // that wants the treatment says so. A glass finish still wins over it —
    // setGlassFinish paints the whole body itself, so the two cannot both draw.
    void setNavItemStyle(bool on);

    // The hover wash a plain (non-glass) graphics button wears under `theme`.
    // On dark that is ICoreButton's hover, so a canvas button and a panel button
    // answer the pointer the same way; on light it stays the royal-tinted pill.
    // Public so the few buttons that re-apply a hover colour of their own can
    // ask for the default rather than hardcoding a token.
    static ICoreColor resolveHoverFill(const ICoreTheme& theme);

    // ⚠ applyVariant() and m_variant MOVED INTO Impl (H5.1). applyVariant
    // re-derives the variant's backdrop, fill and opacities from the active
    // theme and runs from the constructor's theme subscription.

    // Forgets that the pointer is over the button. A button that is hidden (or moved
    // out from under the pointer) never receives its hoverLeaveEvent, so without this
    // it comes back still wearing the hover wash.
    void clearHoverState();
    void setFillColor(ICoreColor newFillColor);
    void setBorderColor(ICoreColor newBorderColor);

    // Wear the app's tinted variant finish in `fill` — the graphics-scene twin of
    // ICoreButton::setGlassFinish, so a purple button looks the same on the canvas
    // as it does in a panel. Since 2026-08-15 that finish is a SOLID, unbordered
    // plate: `fill` lands at full alpha in every state, and `restOpacity` /
    // setHoverOpacity() name the ends of the hover animation whose travel the
    // painter spends lightening the plate by theme.button.tintedHoverLighter.
    // (The name is the widget button's and is kept so the twins still match.)
    void setGlassFinish(const ICoreColor& fill, const double& restOpacity);
    void setHoverOpacity(const double& newOpacity);

    [[nodiscard]] double backgroundOpacity() const;
    void setBackgroundOpacity(double newOpacity);

    void setText(const ICoreString& newText);

    // The label rests in the theme's primary text color; a button that fills itself
    // with a strong color on selection needs to repaint its text to match.
    void setLabelColor(const ICoreColor& color);
    void setWidth(double width) override;
    void setHeight(double height);

    void setIcon(const ICoreIcon& icon);
    void setIconPos(const ICorePoint& newIconPos);
    void setIconSize(const ICoreSizeF& newIconSize);

    void setLabelXPos(const double& newXPos);

    // Centers the caption in the button instead of leaving it pinned to the left
    // edge, which is what a text button (rather than an icon one with a padded
    // caption) needs. Call it once the text AND the width are both set.
    void centerLabel();

    [[nodiscard]] double getWidth() const;
    [[nodiscard]] double getHeight() const;

    [[nodiscard]] ICoreString getText() const;

    void resetToInitialState_GraphicsButton(ICoreNativeItem* parent, const ICoreString& initialText = "");

    // ⚠ Declared here and DEFINED OUT OF LINE, which it did not used to be:
    // m_backgroundFade is a unique_ptr to a forward-declared ICoreAnimation, and
    // its deleter has to be instantiated where that type is complete. An empty
    // inline body compiles here and then fails in every TU that includes this
    // header without ICoreAnimation.h -- four of them, none of them this class's
    // own. (P4.2 hit the same rule; it is the third wrapper to grow an owning
    // member and the third to need this.)
    ~ICoreGraphicsButton() override;

protected:
    // The old paint() override, split at the base's own seam (P2.9d-2b) -- the
    // last Qt virtual this tier had. paintBody() draws the button's own rounded
    // body, paintContent() the icon on top of it, and the base calls them in
    // that order, so the painted sequence is unchanged.
    //
    // ⚠ paintBody() TURNS ON ANTIALIASING ITSELF, and dropping that line is a
    // silent regression rather than a compile error. The old paint() set
    // Antialiasing AND SmoothPixmapTransform; the base's paint() sets only
    // Antialiasing, deliberately (see its note). ICorePainter::setAntialiasing
    // sets both, so this class -- which draws a pixmap in paintContent() -- has
    // to ask for the pair the way the other pixmap-drawing subclasses do.
    void paintBody(ICorePainter& painter) override;
    void paintContent(ICorePainter& painter) override;

    void pointerEntered(const ICoreMouseEvent& event) override;
    void pointerLeft() override;

    void visibilityChanged(bool visible) override;

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

ICoreGraphicsComboBox.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsComboBox.h

Retyped with its base in P2.10b-3b. Still no ICoreNativeItem* OVERLOAD -- R4, see the note on ICoreGraphicsBoxedText, which explains why replacing the parameter is safe where adding a second one is not.

ICoreGraphicsComboBox#

ICoreGraphicsComboBox.h:14 · class · bases public ICoreGraphicsBoxedText · pImpl · 13 declaration(s)

class ICoreGraphicsComboBox : public ICoreGraphicsBoxedText {
public:
    // Retyped with its base in P2.10b-3b. Still no ICoreNativeItem* OVERLOAD --
    // R4, see the note on ICoreGraphicsBoxedText, which explains why replacing
    // the parameter is safe where adding a second one is not.
    explicit ICoreGraphicsComboBox(ICoreNativeItem* parent);

    void populate(const std::pair<std::vector<std::string>, std::string>& options);

    void setWidth(const double& width) override;
    void setHeight(const double& height) override;

    virtual void setChosenOption(const std::string& newChosenOption);

    virtual void animateComboDialogHide();
    virtual void animateComboDialogShow();

    double getPredictedTextWidthPx() const override;

    ICoreGraphicsComboBoxDialog* getOptionsDialog() const;

    void resetToInitialState_GraphicsComboBox(ICoreNativeItem* parent);

    // Out of line: Impl is incomplete here, so the unique_ptr's deleter cannot
    // be instantiated in this header. It was an empty inline body before H5.14.
    ~ICoreGraphicsComboBox() override;

protected:
    // Returns true: the old body accepted and never reached the toolkit
    // base. P2.8's press rule -- false here would hand the press to
    // QGraphicsTextItem as well and cost the item its grab.
    bool mousePressed(const ICoreMouseEvent& event) override;
    void focusLosing(const ICoreFocusEvent& event) override;

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

ICoreGraphicsComboBoxDialog.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsComboBoxDialog.h

⚠⚠ THE ONE SIGNATURE P2.9c COULD NOT RETYPE, AND IT IS P2.9d'S GATE. parent here is always an ICoreGraphicsComboBox, which is TEXT tier (ICoreGraphicsBoxedText -> ICoreGraphicsText -> QGraphicsTextItem) -- a SEPARATE hierarchy that implements no ICoreNativeItem, so there is no handle to narrow this to. It stays QGraphicsObject* until P2.10 gives ICoreGraphicsText the interface (2 additive lines, the shape P6.4 used for ICoreLabel). P2.9d cannot flip while this is raw, because after the flip a QGraphicsObject* is not something a converted item can be parented to at all. ✅ NARROWED BY P2.10b-6, which is the event the note above was waiting for: the text tier is converted, so parent is an ICoreNativeItem and is no longer a QGraphicsObject at all.

ICoreGraphicsComboBoxDialog#

ICoreGraphicsComboBoxDialog.h:12 · class · bases public ICoreGraphicsObject · pImpl · 13 declaration(s)

class ICoreGraphicsComboBoxDialog : public ICoreGraphicsObject {
public:
    // ⚠⚠ THE ONE SIGNATURE P2.9c COULD NOT RETYPE, AND IT IS P2.9d'S GATE.
    // `parent` here is always an ICoreGraphicsComboBox, which is TEXT tier
    // (ICoreGraphicsBoxedText -> ICoreGraphicsText -> QGraphicsTextItem) -- a
    // SEPARATE hierarchy that implements no ICoreNativeItem, so there is no
    // handle to narrow this to. It stays QGraphicsObject* until P2.10 gives
    // ICoreGraphicsText the interface (2 additive lines, the shape P6.4 used
    // for ICoreLabel). **P2.9d cannot flip while this is raw**, because after
    // the flip a QGraphicsObject* is not something a converted item can be
    // parented to at all.
    // ✅ NARROWED BY P2.10b-6, which is the event the note above was waiting
    // for: the text tier is converted, so `parent` is an ICoreNativeItem and
    // is no longer a QGraphicsObject at all.
    explicit ICoreGraphicsComboBoxDialog(ICoreNativeItem* parent, ICoreGraphicsComboBox* parentComboBox);

    void populateList(const std::vector<std::string> &options);

    void clearAllComboOptions();

    void autoCalculateComboOptionsSizes();

    void setWidth(double width) override;
    void setOptionHeight(double newOptionHeight);
    void setPadding(double newPadding);

    void setChosenOptionCheckIcon(const std::string&  newChosenOption) const;

    double getCachedHeight() const;

    // Same gate as the constructor above.
    void resetToInitialState(ICoreNativeItem* parent, ICoreGraphicsComboBox* parentComboBox);
    // The recycler's liveness bookkeeping -- see ICoreGraphicsRecycler. This
    // class has no isAlive(); only kill() and setAlive() were ever called.
    void kill();
    void setAlive();

    // Out of line: Impl is incomplete here, so the unique_ptr's deleter cannot
    // be instantiated in this header. It was an empty inline body before H5.8.
    ~ICoreGraphicsComboBoxDialog() override;

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

ICoreGraphicsComboBox_ComboOption.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsComboBox_ComboOption.h

Out of line: Impl is incomplete here, so the unique_ptr's deleter cannot be instantiated in this header.

ICoreGraphicsComboBox_ComboOption#

ICoreGraphicsComboBox_ComboOption.h:10 · class · bases public ICoreGraphicsButton · pImpl · 7 declaration(s)

class ICoreGraphicsComboBox_ComboOption : public ICoreGraphicsButton {
public:
    explicit ICoreGraphicsComboBox_ComboOption(ICoreNativeItem* parent, ICoreGraphicsComboBox* grandParentComboBox, const ICoreString& initialText);

    // Out of line: Impl is incomplete here, so the unique_ptr's deleter cannot
    // be instantiated in this header.
    ~ICoreGraphicsComboBox_ComboOption() override;

    void resetToInitialState(ICoreNativeItem* parent, ICoreGraphicsComboBox* grandParentComboBox, const ICoreString& initialText);

    // The recycler's liveness bookkeeping: collect_ComboOption() kill()s an
    // option before pooling it and request_ComboOption() setAlive()s it on the
    // way back out, so a handle held across a recycle reports itself dead.
    void kill();
    void setAlive();
    [[nodiscard]] bool isAlive() const;

protected:
    bool mousePressed(const ICoreMouseEvent& event) override;

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

ICoreGraphicsCommands.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsCommands.h

ICoreGraphicsCommands#

ICoreGraphicsCommands.h:22 · class · 7 declaration(s)

Scene-side helpers callable from OUTSIDE the wrapper zone without naming a Qt type: the parameter is only ever a pointer a wrapper API handed the caller, so the call site spells nothing but its own...

class ICoreGraphicsCommands {
public:
    ICoreGraphicsCommands() = delete;

    // Release the scene's mouse grab if (and only if) `item` holds it.
    static void ungrabMouseSafely(ICoreNativeItem* item);

    // Detach `item` from whatever scene currently owns it; no-op when none.
    static void removeFromScene(ICoreNativeItem* item);

    // removeFromScene, then repaint the scene the item just left.
    static void removeFromSceneAndRefresh(ICoreNativeItem* item);

    // Stop every animation parented to `owner`; no-op when null or childless.
    //
    // Deliberately reaches ALL animations, not only the ICore-wrapped ones: a
    // recycled object may own a plain toolkit animation as well, and one left
    // running would keep writing to an object that has been handed back.
    //
    // ⚠ Q1.7 REPLACED THE SINGLE `QObject*` ENTRY POINT WITH THREE NAMED ONES,
    // one per wrapper interface, and the names are NOT interchangeable
    // overloads. The comment that stood here said this "takes the widest owner
    // type" -- but post-conversion there is no widest ICore type: a widget
    // wrapper implements ICoreNativeWidget, a scene item ICoreNativeItem, a
    // model ICoreNativeObject, and none of the three derives from another. An
    // overload set would have been fine, but stopChildAnimationsOfItem was
    // already a distinct NAME for exactly this reason (see its own note), so
    // the other two follow it rather than splitting the file's convention.
    static void stopChildAnimationsOfWidget(ICoreNativeWidget* widget);
    static void stopChildAnimationsOfObject(ICoreNativeObject* object);

    // The same walk for an ITEM wrapper (P2.9d-5c). A different NAME, not an
    // overload of the above: until P2.9d-5e a scene item converts to QObject*
    // through its Qt base AND to ICoreNativeItem* through its seam base, so an
    // overload pair would be R4-ambiguous at every graphics-tier call site --
    // the same reason ICoreThemeBinding grew subscribeNative rather than a
    // subscribe overload. Widgets and pre-unwrapped handles keep the QObject*
    // spelling above.
    //
    // No-op for a null wrapper AND for a wrapper whose item is not a
    // QGraphicsObject (a bare-QGraphicsItem wrapper has no object tree to
    // walk, hence nothing parented to it to stop).
    static void stopChildAnimationsOfItem(ICoreNativeItem* item);

    // ⚠ stopChildAnimations(QObject*) -- what all three of the above forward
    // to once each has resolved its own wrapper -- MOVED TO THE .cpp as a
    // file-local function by the header surface rule (H5.15). It was private
    // since Q1.7 because it is the shared body rather than an entry point,
    // which is exactly why it does not belong on the class at all. It was also
    // this header's last mention of QObject.
};
};

ICoreGraphicsInfoLabel.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsInfoLabel.h

Complete type, not a forward declaration: the unique_ptr<ICoreValueAnimation> member needs sizeof(ICoreValueAnimation) wherever a label is destroyed. The destructor is ALSO out of line (belt and braces from two concurrent fixes of the same incomplete-type error; either alone would do).

ICoreGraphicsInfoLabel#

ICoreGraphicsInfoLabel.h:19 · class · bases public ICoreGraphicsObject · pImpl · 8 declaration(s)

class ICoreGraphicsInfoLabel : public ICoreGraphicsObject {
public:
    explicit ICoreGraphicsInfoLabel(ICoreNativeItem* parentToolBar = nullptr);

    // contentBounds(), not boundingRect() (P2.9d-2). Same value, same members:
    // the base derives boundingRect() from this, so nothing about the geometry
    // changes -- what goes away is an override of a Qt virtual that would stop
    // being called at all once this tier drops its Qt base.
    [[nodiscard]] ICoreRect contentBounds() const override;

    void paintBody(ICorePainter& painter) override;
    void paintContent(ICorePainter& painter) override;

    // Seam-typed since P2.9d-5c: both callers (the two ToolBarButton classes)
    // pass themselves, and a wrapper upcasts to ICoreNativeItem* by itself --
    // the QGraphicsObject* this took would have needed a conversion that stops
    // existing at the flip.
    void showInfoLabel(const ICoreString& title, ICoreNativeItem* objectUnderCursor, const ICoreString& technique, double delayDuration);
    void hideInfoLabel();

    void setText(const ICoreString& text);

    // Out of line: the unique_ptr member below is over a forward-declared
    // type, so the destructor must live where ICoreValueAnimation is complete.
    ~ICoreGraphicsInfoLabel() override;

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

ICoreGraphicsItem.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsItem.h

ICoreGraphicsItem#

ICoreGraphicsItem.h:31 · class · bases public ICoreNativeItem · pImpl · 20 declaration(s)

ICoreGraphicsItem -- the non-QObject half of the scene tier: a rounded body with a fill and a border that a subclass draws on top of.

class ICoreGraphicsItem : public ICoreNativeItem {
public:
    explicit ICoreGraphicsItem(ICoreNativeItem* parent = nullptr);
    ~ICoreGraphicsItem() override;

    ICoreGraphicsItem(const ICoreGraphicsItem&) = delete;
    ICoreGraphicsItem& operator=(const ICoreGraphicsItem&) = delete;

    // This item's own area, origin at (0,0). Overriding it is how a subclass
    // states its size; the toolkit's boundingRect() is derived from it.
    virtual ICoreRect contentBounds() const;

    virtual void setWidth(double newWidth);
    void setHeight(double newHeight);
    void setFillColor(ICoreColor newColor);
    void setBorderColor(ICoreColor newColor);

    double getWidth() const;
    double getHeight() const;

    // --- Scene-tree placement. Forwarders, discovered from call sites: under
    // --- pImpl nothing is inherited, so each one exists because something asks
    // --- for it (§9).

    void setPos(const ICorePoint& position);
    void setPos(double x, double y);

    // A null parent detaches the item from the scene tree.
    void setParentItem(ICoreNativeItem* parent);

    void setZValue(double z);

    void setVisible(bool visible);
    void show();
    void hide();

    ICoreNativeHandle nativeItemHandle() const override;

protected:
    // Called on every repaint, after the rounded body has been drawn. The same
    // hook ICoreGraphicsObject carries; this base is the non-QObject half of
    // the scene tier and needs the identical surface.
    virtual void paintContent(ICorePainter& painter);

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

ICoreGraphicsObject.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsObject.h

Declares no class of its own — see the file.

ICoreGraphicsPixmap.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsPixmap.h

ICoreGraphicsPixmap#

ICoreGraphicsPixmap.h:41 · class · final · bases public ICoreNativeItem · pImpl · 8 declaration(s)

ICoreGraphicsPixmap -- a raster image sitting on a graphics scene.

class ICoreGraphicsPixmap final : public ICoreNativeItem {
public:
    explicit ICoreGraphicsPixmap(ICoreNativeItem* parent = nullptr);
    ~ICoreGraphicsPixmap() override;

    ICoreGraphicsPixmap(const ICoreGraphicsPixmap&) = delete;
    ICoreGraphicsPixmap& operator=(const ICoreGraphicsPixmap&) = delete;

    // Fills exactly `width` x `height`, ignoring the source aspect ratio and
    // smoothing the result. Ignoring the ratio is deliberate and is what the
    // canvas image object has always done: the frame is resized by its own
    // handles, and letterboxing inside a frame the user just dragged reads as
    // the drag not having worked.
    //
    // A null source clears the item rather than scaling nothing, so a caller
    // does not need the isNull() guard the sites used to carry.
    void setStretchedPixmap(const ICorePixmap& source, int width, int height);

    // Drops the raster and shows nothing. This is the ICore spelling of the one
    // call site that set a deliberately-null pixmap to mean "empty"; it is the
    // same operation setStretchedPixmap() performs for a null source, named.
    void clearPixmap();

    // A null parent detaches the item from the scene tree, which the image
    // object's clear path relies on -- so null is forwarded, not rejected.
    void setParentItem(ICoreNativeItem* parent);

    ICoreNativeHandle nativeItemHandle() const override;

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

ICoreGraphicsProxyWidget.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsProxyWidget.h

Declares no class of its own — see the file.

ICoreGraphicsRect.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsRect.h

ICoreGraphicsRect#

ICoreGraphicsRect.h:35 · class · bases public ICoreNativeItem · pImpl · 17 declaration(s)

ICoreGraphicsRect -- a themed rectangle on a graphics scene.

class ICoreGraphicsRect : public ICoreNativeItem {
public:
    enum class Style {
        None,          // pen and brush untouched -- the default
        Marquee,       // solid 1px selection border at 150 alpha, selection fill
        MarqueeDashed  // dashed selection border at full alpha, selection fill
    };

    explicit ICoreGraphicsRect(ICoreNativeItem* parent = nullptr);
    explicit ICoreGraphicsRect(Style style, ICoreNativeItem* parent = nullptr);
    ~ICoreGraphicsRect() override;

    ICoreGraphicsRect(const ICoreGraphicsRect&) = delete;
    ICoreGraphicsRect& operator=(const ICoreGraphicsRect&) = delete;

    void setRectStyle(Style style);
    Style rectStyle() const;

    // The band itself, in the item's own coordinates.
    void setRect(const ICoreRect& rect);
    ICoreRect rect() const;

    // The band in SCENE coordinates -- what every hit test against it actually
    // wants. This replaces `mapToScene(rect()).boundingRect()`, which
    // ICoreCanvasSelectionRectangle spelled out FIVE times, once per kind of
    // thing it scans. One expression, one place, and the mapping can no longer
    // drift between the five.
    ICoreRect sceneBounds() const;

    void setVisible(bool visible);
    bool isVisible() const;

    void setZValue(double z);

    void setPos(const ICorePoint& position);
    ICorePoint scenePos() const;

    void setParentItem(ICoreNativeItem* parent);

    ICoreNativeHandle nativeItemHandle() const override;

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

ICoreGraphicsRecycler.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsRecycler.h

ICoreGraphicsRecycler#

ICoreGraphicsRecycler.h:34 · class · 5 declaration(s)

ICoreGraphicsRecycler -- pools for the high-churn graphics items Essentials itself builds tables and combo dialogs out of (ESSENTIALS_INDEPENDENCE D5).

class ICoreGraphicsRecycler {
public:
    static ICoreGraphicsTableEntryRow* request_TableEntryRow(
        ICoreGraphicsTable* parentTable, const std::vector<std::string>& columns);
    static void collect_TableEntryRow(ICoreGraphicsTableEntryRow* entry);

    static ICoreGraphicsBoxedText* request_BoxedText(ICoreNativeItem* parent);
    static void collect_BoxedText(ICoreGraphicsBoxedText* box);

    static ICoreGraphicsTableTitleRowSplitter* request_TableTitleRowSplitter(
        ICoreGraphicsTableTitlesRow* parent, ICoreGraphicsTable* grandParentTable);
    static void collect_TableTitleRowSplitter(ICoreGraphicsTableTitleRowSplitter* splitter);

    static ICoreGraphicsComboBox_ComboOption* request_ComboOption(
        ICoreNativeItem* parent, ICoreGraphicsComboBox* grandParentComboBox,
        const ICoreString& initialText);
    static void collect_ComboOption(ICoreGraphicsComboBox_ComboOption* option);
};
};

ICoreGraphicsScene.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsScene.h

ICoreGraphicsScene -- the scene every canvas, chart and floating-panel view runs on.

⚠ THIS CLASS CARRIES NO APPEARANCE, AND THAT IS THE POINT OF ITS HISTORY.

It used to own a Backdrop enum (None/Canvas/Panel) and a theme subscription that re-derived the background brush on every Light <-> Dark switch. Every one of those parts is gone, because the whole mechanism was unreachable: all three construction sites in the tree (ICoreCanvasParent, ICoreChart, ICoreFloatingPanelsGraphicsView) used the parent-only constructor, which meant Backdrop::None, which made applyTheme() return before touching the brush. The component had exactly one reachable state and it was "do nothing".

ICoreGraphicsScene#

ICoreGraphicsScene.h:41 · class · final · bases public ICoreNativeScene · pImpl · 12 declaration(s)

class ICoreGraphicsScene final : public ICoreNativeScene {
public:
    // The parent owns the scene's lifetime, exactly as the QObject parent did.
    // Two of the three construction sites pass nothing and keep the scene in a
    // member instead.
    explicit ICoreGraphicsScene(ICoreNativeWidget* parent = nullptr);
    ~ICoreGraphicsScene() override;

    ICoreGraphicsScene(const ICoreGraphicsScene&) = delete;
    ICoreGraphicsScene& operator=(const ICoreGraphicsScene&) = delete;

    void setSceneRect(const ICoreRect& rect);

    void addItem(ICoreNativeItem* item);
    void removeItem(ICoreNativeItem* item);

    // Empties the scene, releasing the mouse grab first if the item being
    // removed is holding it.
    //
    // This replaces an items() getter, and the ordering is why it is a method
    // rather than a loop at the call site: removing the grabber without
    // ungrabbing leaves Qt dispatching moves to a detached item. The one caller
    // (ICoreCanvasParent::loadCanvas) had that dance written out by hand, and
    // it is the kind of thing the second caller gets wrong.
    void removeAllItems();

    // Releases the scene's mouse grab, if the grab is both held and still
    // valid. A grabber whose scene() is no longer this one is stale and is
    // skipped -- ICoreStudioSurfaceRegistry paid for that check and it moved
    // here with the rest of the operation.
    void ungrabMouse();

    // Whether the item is currently in THIS scene. Replaces the two sites that
    // compared a raw item->scene() against the scene pointer, which the pImpl
    // boundary no longer lets them spell.
    bool contains(const ICoreNativeItem* item) const;

    // Draws `source` (in scene coordinates) onto `target` (in the painter's
    // coordinates). Added for P2.9d-4, whose survey found this to be the ONE
    // site in the whole scene tier that wants the scene object back rather than
    // a bool -- ICoreCanvasPrinter, printing the diagram onto a page.
    //
    // ⚠ THE SOURCE IS STRETCHED TO FILL THE TARGET EXACTLY -- no letterbox,
    // i.e. Qt's IgnoreAspectRatio and not its KeepAspectRatio default. That is
    // what the one caller wants (it sizes `target` to the diagram's own
    // proportions first, so a second fit would only round it), and it is spelled
    // into the operation rather than exposed as a mode: an aspect-ratio enum at
    // a consumer site is the re-export hole P6.4 records neither guard seeing.
    // A caller that genuinely wants a letterbox should scale its own target.
    //
    // ⚠ It takes an ICorePainter& rather than growing a Qt parameter, following
    // ICoreChartBase::renderSceneToPainter, which P7.1 gave this exact shape.
    // QGraphicsScene::render is the only route a scene has onto a painter and it
    // takes a QPainter*, so the body composes with the toolkit through
    // ICorePainter::qt() -- the seam working, not an escape from it.
    void renderTo(ICorePainter& painter, const ICoreRect& target, const ICoreRect& source);

    ICoreNativeHandle nativeSceneHandle() const override;

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

ICoreGraphicsScrollPane.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsScrollPane.h

Q_OBJECT removed (P2.9d-3): this class declares no signal, slot, Q_PROPERTY or Q_INVOKABLE of its own, and nothing qobject_casts to it, holds a QPointer to it, animates it by name or reaches its metaObject(). It therefore had a meta-object nobody consulted -- and it could not keep one past P2.9d-5, when the base stops being a QObject.

Declares no class of its own — see the file.

ICoreGraphicsScrollPaneScrollBar.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsScrollPaneScrollBar.h

ICoreGraphicsScrollPaneScrollBar#

ICoreGraphicsScrollPaneScrollBar.h:14 · class · bases public ICoreGraphicsObject · pImpl · 10 declaration(s)

Draggable vertical scroll bar for ICoreGraphicsScrollPane.

class ICoreGraphicsScrollPaneScrollBar : public ICoreGraphicsObject {
public:
    explicit ICoreGraphicsScrollPaneScrollBar(ICoreGraphicsScrollPaneScrollableArea* scrollableArea,
                                              ICoreNativeItem* parent = nullptr);

    // contentBounds(), not boundingRect() (P2.9d-2). Same value, same members:
    // the base derives boundingRect() from this, so nothing about the geometry
    // changes -- what goes away is an override of a Qt virtual that would stop
    // being called at all once this tier drops its Qt base.
    [[nodiscard]] ICoreRect contentBounds() const override;

    void paintBody(ICorePainter& painter) override;

    void setWidth(double width) override;
    void setTrackHeight(double height);

    // ⚠ Deliberately HIDES ICoreGraphicsObject::getWidth() and always did;
    // moving the body out of line does not change that.
    [[nodiscard]] double getWidth() const;

    // Recomputes the thumb size/position and visibility from the current
    // scrollable-area state. Called whenever the scroll offset or content
    // height changes.
    void refresh();

    // Out of line: Impl is incomplete here, so the unique_ptr's deleter cannot
    // be instantiated in this header. It was an empty inline body before H5.5.
    ~ICoreGraphicsScrollPaneScrollBar() override;

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

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

ICoreGraphicsScrollPaneScrollableArea.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsScrollPaneScrollableArea.h

Q_OBJECT removed (P2.9d-3): this class declares no signal, slot, Q_PROPERTY or Q_INVOKABLE of its own, and nothing qobject_casts to it, holds a QPointer to it, animates it by name or reaches its metaObject(). It therefore had a meta-object nobody consulted -- and it could not keep one past P2.9d-5, when the base stops being a QObject.

ICoreGraphicsScrollPaneScrollableArea#

ICoreGraphicsScrollPaneScrollableArea.h:23 · class · bases public ICoreGraphicsObject · pImpl · 16 declaration(s)

class ICoreGraphicsScrollPaneScrollableArea : public ICoreGraphicsObject {
public:
    explicit ICoreGraphicsScrollPaneScrollableArea(ICoreNativeItem* parent = nullptr);

    // contentBounds(), not boundingRect() (P2.9d-2). Same value, same members:
    // the base derives boundingRect() from this, so nothing about the geometry
    // changes -- what goes away is an override of a Qt virtual that would stop
    // being called at all once this tier drops its Qt base.
    [[nodiscard]] ICoreRect contentBounds() const override;

    [[nodiscard]] ICorePainterPath contentShape() const override;

    void paintBody(ICorePainter& painter) override;

    // Seam-typed since P2.9d-5c (see ICoreGraphicsScrollPane::setContentItem).
    void setContentItem(ICoreNativeItem* content);

    void setWidth(double width) override;
    void setHeight(double height);

    void setFillColor(ICoreColor fillColor);
    void setBorderColor(ICoreColor borderColor);

    void scroll(double scrollValue);

    // Scroll-bar support.
    void setScrollBar(ICoreGraphicsScrollPaneScrollBar* scrollBar);
    void setScrollY(double scrollY);     // absolute offset; clamped + applied
    [[nodiscard]] double getScrollY() const;
    [[nodiscard]] double getViewportHeight() const;
    double getContentHeight() const;

    // Out of line: Impl is incomplete here, so the unique_ptr's deleter cannot
    // be instantiated in this header. It was an empty inline body before H5.7.
    ~ICoreGraphicsScrollPaneScrollableArea() override;

protected:
    bool wheelScrolled(const ICoreWheelEvent& event) override;

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

ICoreGraphicsTable.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsTable.h

Q_OBJECT removed (P2.9d-3): this class declares no signal, slot, Q_PROPERTY or Q_INVOKABLE of its own, and nothing qobject_casts to it, holds a QPointer to it, animates it by name or reaches its metaObject(). It therefore had a meta-object nobody consulted -- and it could not keep one past P2.9d-5, when the base stops being a QObject.

ICoreGraphicsTable#

ICoreGraphicsTable.h:14 · class · bases public ICoreGraphicsObject · pImpl · 15 declaration(s)

class ICoreGraphicsTable : public ICoreGraphicsObject {
public:
    explicit ICoreGraphicsTable(ICoreNativeItem* parent = nullptr, const std::vector<std::string>& initialColumnsNames = {});

    // contentBounds(), not boundingRect() (P2.9d-2). Same value, same members:
    // the base derives boundingRect() from this, so nothing about the geometry
    // changes -- what goes away is an override of a Qt virtual that would stop
    // being called at all once this tier drops its Qt base.
    [[nodiscard]] ICoreRect contentBounds() const override;

    void paintBody(ICorePainter& painter) override;
    void setInitialEntryRowTexts(const std::vector<std::string>& entryDefaultInitialTexts_Candidate);
    ICoreGraphicsTableEntryRow* createNewEntryRow(const std::vector<std::string>& entryInitialTexts);
    void deleteEntryRow(ICoreGraphicsTableEntryRow *entryToDelete);
    void setWidth(double width) override;
    void setHeight(double height);
    void setColumnEditable(const int& columnIndex, const bool& enabled);
    void setColumnsWidthRatios(const std::vector<double>& newSpaces);
    void autoCalculateEntriesYPos();
    void reconstructDescendents();
    void clearAllEntries();
    void resetToInitialState(ICoreNativeItem* parent = nullptr, const std::vector<std::string>& initialColumnsNames = {});

    ~ICoreGraphicsTable() override;

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

ICoreGraphicsTableEntryRow.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsTableEntryRow.h

Q_OBJECT removed (P2.9d-3): this class declares no signal, slot, Q_PROPERTY or Q_INVOKABLE of its own, and nothing qobject_casts to it, holds a QPointer to it, animates it by name or reaches its metaObject(). It therefore had a meta-object nobody consulted -- and it could not keep one past P2.9d-5, when the base stops being a QObject.

ICoreGraphicsTableEntryRow#

ICoreGraphicsTableEntryRow.h:13 · class · bases public ICoreGraphicsObject · pImpl · 12 declaration(s)

class ICoreGraphicsTableEntryRow : public ICoreGraphicsObject {
public:
    explicit ICoreGraphicsTableEntryRow(ICoreGraphicsTable* parentTable, const std::vector<std::string>& columns);

    // contentBounds(), not boundingRect() (P2.9d-2). Same value, same members:
    // the base derives boundingRect() from this, so nothing about the geometry
    // changes -- what goes away is an override of a Qt virtual that would stop
    // being called at all once this tier drops its Qt base.
    [[nodiscard]] ICoreRect contentBounds() const override;

    void paintBody(ICorePainter& painter) override;

    void setColumnsWidths(std::vector<double> columnsWidths);

    void setHeight(double height);

    std::vector<ICoreGraphicsBoxedText*> getAllTextItems() const;

    void reconstructDescendents();

    void resetToInitialState(ICoreGraphicsTable* parentTable, const std::vector<std::string>& columns);
    // The recycler's liveness bookkeeping -- see ICoreGraphicsRecycler.
    void kill();
    void setAlive();
    [[nodiscard]] bool isAlive() const;

    ~ICoreGraphicsTableEntryRow() override;

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

ICoreGraphicsTableTitleRowSplitter.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsTableTitleRowSplitter.h

Q_OBJECT removed (P2.9d-3): this class declares no signal, slot, Q_PROPERTY or Q_INVOKABLE of its own, and nothing qobject_casts to it, holds a QPointer to it, animates it by name or reaches its metaObject(). It therefore had a meta-object nobody consulted -- and it could not keep one past P2.9d-5, when the base stops being a QObject.

ICoreGraphicsTableTitleRowSplitter#

ICoreGraphicsTableTitleRowSplitter.h:14 · class · bases public ICoreGraphicsObject · pImpl · 13 declaration(s)

class ICoreGraphicsTableTitleRowSplitter : public ICoreGraphicsObject {
public:
    explicit ICoreGraphicsTableTitleRowSplitter(ICoreGraphicsTableTitlesRow* parentTitlesRow, ICoreGraphicsTable* grandParentTable);

    // contentBounds(), not boundingRect() (P2.9d-2). Same value, same members:
    // the base derives boundingRect() from this, so nothing about the geometry
    // changes -- what goes away is an override of a Qt virtual that would stop
    // being called at all once this tier drops its Qt base.
    [[nodiscard]] ICoreRect contentBounds() const override;

    void paintBody(ICorePainter& painter) override;

    void resetToInitialState(ICoreGraphicsTableTitlesRow* parentTitlesRow, ICoreGraphicsTable* grandParentTable);

    // The recycler's liveness bookkeeping -- see ICoreGraphicsRecycler.
    void kill();
    void setAlive();
    [[nodiscard]] bool isAlive() const;

    ~ICoreGraphicsTableTitleRowSplitter() override;

protected:
    void pointerEntered(const ICoreMouseEvent& event) override;
    void pointerLeft() override;
    bool mousePressed(const ICoreMouseEvent& event) override;
    bool mouseMoved(const ICoreMouseEvent& event) override;
    bool mouseReleased(const ICoreMouseEvent& event) override;

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

ICoreGraphicsTableTitlesRow.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsTableTitlesRow.h

Q_OBJECT removed (P2.9d-3): this class declares no signal, slot, Q_PROPERTY or Q_INVOKABLE of its own, and nothing qobject_casts to it, holds a QPointer to it, animates it by name or reaches its metaObject(). It therefore had a meta-object nobody consulted -- and it could not keep one past P2.9d-5, when the base stops being a QObject.

ICoreGraphicsTableTitlesRow#

ICoreGraphicsTableTitlesRow.h:14 · class · bases public ICoreGraphicsObject · pImpl · 11 declaration(s)

class ICoreGraphicsTableTitlesRow : public ICoreGraphicsObject {
public:
    explicit ICoreGraphicsTableTitlesRow(ICoreGraphicsTable* parentTable, const std::vector<std::string>& columns);

    // contentBounds(), not boundingRect() (P2.9d-2). Same value, same members:
    // the base derives boundingRect() from this, so nothing about the geometry
    // changes -- what goes away is an override of a Qt virtual that would stop
    // being called at all once this tier drops its Qt base.
    [[nodiscard]] ICoreRect contentBounds() const override;

    void paintBody(ICorePainter& painter) override;

    void setColumnsWidths(std::vector<double> newColumnsWidths);

    void setHeight(double height);

    std::vector<ICoreGraphicsBoxedText*> getAllTextItems() const;
    std::vector<double> getColumnsWidths() const;

    qsizetype getSplitterIndex(ICoreGraphicsTableTitleRowSplitter* splitter);
    // [[nodiscard]] std::vector<double> getAllSplitters() const;

    void reconstructDescendents();

    void resetToInitialState(ICoreGraphicsTable* parentTable, const std::vector<std::string>& columns);

    ~ICoreGraphicsTableTitlesRow() override;

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

ICoreGraphicsText.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsText.h

ICoreGraphicsText#

ICoreGraphicsText.h:66 · class · bases public ICoreNativeItem · pImpl · 62 declaration(s)

⚠ IMPLEMENTS ICoreNativeItem, added by P2.10 at P2.9's request.

class ICoreGraphicsText : public ICoreNativeItem {
public:
    // The Impl's QGraphicsTextItem, not `this`. R2 still applies inside:
    // QGraphicsTextItem reaches QGraphicsItem through QGraphicsObject, so the
    // cast is written out in the .cpp where Impl is complete.
    ICoreNativeHandle nativeItemHandle() const override;

    // ⚠ Takes ICoreFont, and deliberately does NOT re-export the inherited
    // QGraphicsTextItem::setFont(const QFont&) with a `using`. P7.6 converted ICoreFont, so
    // it no longer converts to QFont and every call site passing one needs a
    // sink that speaks the wrapper. A `using` here would reopen exactly the
    // re-export hole §9 records neither guard being able to see, since the Qt
    // name would appear only at the call site. Hiding the base overload is
    // safe: QGraphicsTextItem::setFont is not virtual, and a caller still holding a raw
    // QFont converts through ICoreFont's implicit inbound constructor.
    void setFont(const ICoreFont& font);

    // The getter setFont has always implied, added by P2.10b-6a because the
    // flip needs it: 9 sites read the item's font and today reach
    // QGraphicsTextItem::font() through the base, which stops existing at
    // P2.10b-6.
    //
    // Returns ICoreFont, not QFont, and that costs those 9 sites NOTHING today:
    // every sink already speaks the wrapper -- serializeFont(const ICoreFont&),
    // ICoreNativeDialogs::getFont(const ICoreFont&, ...) -- and four of them
    // already write `ICoreFont f = ...->font()`, which was converting from QFont
    // through ICoreFont's implicit inbound constructor on the way in.
    //
    // ⚠ Shadows the base's non-virtual font() rather than `using`-ing it, for
    // exactly the reason setFont above spells out: a `using` would re-export a
    // QFont-returning overload that neither guard can see at the call site.
    [[nodiscard]] ICoreFont font() const;

    // The item's own area, origin at (0,0) -- the ICore spelling of
    // boundingRect(). The default computes it from the document; overriding
    // THIS is how a subclass states its own size, exactly as it is on
    // ICoreGraphicsObject.
    //
    // ⚠ THE DEFAULT MUST CALL QGraphicsTextItem::boundingRect() QUALIFIED, AND
    // THAT IS NOT A STYLE CHOICE. boundingRect() below is now derived from
    // this, so an unqualified boundingRect() here is INFINITE RECURSION -- it
    // would re-enter the override that just called us. The .cpp says so again
    // at the body.
    [[nodiscard]] virtual ICoreRect contentBounds() const;

    // ⚠ boundingRect() IS GONE FROM THIS TYPE, as this comment promised it
    // would be. It lives on Impl and is derived from contentBounds() there, so
    // a subclass still states its size by overriding contentBounds() and the
    // toolkit still sees the same rectangle. A caller that wants the rectangle
    // asks contentBounds().

    // ------------------------------------------------------------------
    // P2.10b-1 -- THE TEXT/DOCUMENT FACADE. Additive; the toolkit base is
    // still here, so nothing below changes behaviour yet. It exists so the
    // flip (P2.10b-6) changes these BODIES and not the ~114 call sites that
    // reach QGraphicsTextItem's own surface through this type.
    //
    // ⚠ THIS HALF BREAKS NOTHING, AND THAT IS A PROPERTY OF ICoreString
    // RATHER THAN OF THE DESIGN. ICoreString converts to and from QString
    // IMPLICITLY BOTH WAYS (its header says so at the conversion block), so a
    // caller passing a QString or a literal, or assigning the result to a
    // QString, keeps compiling untouched. Do NOT generalise that to the item
    // half in P2.10b-2: ICorePoint and ICoreRect convert IN implicitly and
    // OUT only by a named call, which is why P2.9d-1 broke 12 TUs on purpose.
    //
    // ⚠ Deliberately absent, each because reading the call sites said so:
    //   * document()      -- 15 sites, and NOT ONE of them wants a document.
    //                        They want the four operations below. Exposing a
    //                        QTextDocument* would put a raw Qt type through
    //                        the seam to serve nobody.
    //   * textCursor()/setTextCursor() -- 4 sites, all four BYTE-IDENTICAL:
    //                        get cursor, clearSelection, set it back. That is
    //                        clearTextSelection(), and QTextCursor never has
    //                        to cross. (Fifth and sixth copies of the same
    //                        duplication P2.11a and P2.9d-1 each removed.)
    //   * textInteractionFlags() -- 1 site, and it only asks "is this
    //                        editable". A flags getter would hand out
    //                        Qt::TextInteractionFlags for a bool question.
    // ------------------------------------------------------------------

    // Content. These SHADOW the non-virtual base methods, exactly as setFont
    // and setDefaultTextColor above already do.
    void setPlainText(const ICoreString& text);
    [[nodiscard]] ICoreString toPlainText() const;
    void setHtml(const ICoreString& html);

    // Layout. setTextWidth is a pure forwarder today and costs its 14 call
    // sites nothing -- it is here because at the flip there is no base to
    // inherit it from, not because anything needs rewriting.
    void setTextWidth(double width);
    [[nodiscard]] double textWidth() const;

    // document()->setDocumentMargin(). Four sites, all of them margin 0.
    void setDocumentMargin(double margin);

    // document()->setDefaultTextOption() with an alignment. Five sites, all
    // of them ICoreAlignment::Center. The enum is already pinned 1:1 to
    // Qt::Alignment in ICoreInputEnumsVerify.cpp, so the seam is a cast.
    void setTextAlignment(ICoreAlignment alignment);

    // document()->adjustSize(), then the laid-out size. Split in two because
    // the one site that needs the size mutates first and then reads, and
    // folding a mutation into a getter would hide that.
    void adjustTextSize();

    // The DOCUMENT's laid-out size as a rect at origin (0,0) -- the same
    // convention contentBounds() documents above. ⚠ NOT a synonym for
    // contentBounds(): that one is boundingRect(), which is the ITEM's area.
    // The two are close and are not defined to be equal, so they stay two
    // methods mapping to two toolkit calls rather than one guess.
    [[nodiscard]] ICoreRect textBounds() const;

    // Interaction. Four values because four are used; the pairing with Qt is
    // in the .cpp. TextBrowserInteraction and the widget tier's combinations
    // are deliberately absent -- no site in this tier asks for them.
    enum class TextInteraction {
        None,                          // Qt::NoTextInteraction
        SelectableByMouse,             // Qt::TextSelectableByMouse
        SelectableByMouseAndKeyboard,  // ... | Qt::TextSelectableByKeyboard
        Editable                       // Qt::TextEditorInteraction
    };
    void setTextInteraction(TextInteraction interaction);

    // The one question the single flags reader actually asks.
    [[nodiscard]] bool isTextEditable() const;

    // The four-line block that was copy-pasted into four classes.
    void clearTextSelection();

    // ------------------------------------------------------------------
    // P2.10b-2 -- THE ITEM FACADE. The plain-QGraphicsItem half, and unlike
    // b-1 above it is mostly a COPY: ICoreGraphicsObject already spells all
    // of this (P2.9a + P2.9d-1), and the text tier gets the SAME names so one
    // concept does not end up with two spellings across two tiers.
    //
    // ⚠ THIS HALF DOES BREAK CALL SITES, AND THAT IS THE MECHANISM WORKING.
    // Two reasons, both inherited from P2.9a's write-ups:
    //   * Name hiding in C++ is per-NAME, not per-signature, so declaring
    //     setPos here hides the base's whole overload set. That is what makes
    //     a leftover Qt spelling a compile error rather than a silent
    //     survivor. Do NOT "fix" it with `using QGraphicsTextItem::setPos;`.
    //   * pos() returns ICorePoint, and ICorePoint converts IN from QPointF
    //     implicitly but OUT only through the named toQPointF(). So a site
    //     feeding the result to a Qt sink must move, and the compiler names
    //     each one.
    // The sites the compiler named are fixed in this same commit -- a facade
    // that leaves the tree red is not a landable step.
    //
    // ⚠ Deliberately absent:
    //   * boundingRect() -- 16 call sites, and contentBounds() has answered
    //     them since before b-1. Adding a second spelling of the item's own
    //     area is what §9 forbids. (The 16 sites move in b-3; the VIRTUAL
    //     override on ICoreGraphicsBoxedText is b-4's, not this row's.)
    //   * setZValue, sceneBounds, mapToScene/mapFromScene, setOpacity,
    //     setEnabled, setAcceptDrops -- on ICoreGraphicsObject because the
    //     scene tier calls them. This tier calls none of them. A forwarder
    //     exists because something asks for it.
    // ------------------------------------------------------------------

    void setPos(const ICorePoint& position);
    void setPos(double x, double y);
    [[nodiscard]] ICorePoint pos() const;

    // A null parent detaches the item from the scene tree.
    void setParentItem(ICoreNativeItem* parent);

    // The ICore spelling of setTransformOriginPoint -- the name
    // ICoreGraphicsObject already gave it. ⚠ A survey that matches on method
    // NAMES reports this one missing from the scene tier's facade; the
    // concept is there under a better name. Check concepts, not spellings.
    void setTransformOrigin(const ICorePoint& origin);
    void setRotation(double angle);

    void setVisible(bool visible);
    [[nodiscard]] bool isVisible() const;
    void show();
    void hide();
    void update();
    void prepareGeometryChange();

    void setAcceptHoverEvents(bool accept);

    // ⚠ The SCOPED enum, with no bitmask sibling -- copied deliberately,
    // including the omission. P2.9a wrote the bitmask overload first and had
    // to delete it: ICoreMouseButtons is a `using = unsigned int` and
    // Qt::MouseButton is unscoped, so every call site spelling Qt::LeftButton
    // bound to it silently and the tree stayed green with the raw Qt name
    // alive inside a wrapper zone. The two sites in this tier still spelling
    // Qt::LeftButton fail loudly under the scoped enum, which is the point.
    void setAcceptedMouseButtons(ICoreMouseButton button);

    // ------------------------------------------------------------------
    // The QGraphicsItem flags this tier sets, as named booleans.
    //
    // ✅ P2.9a LEFT ItemIsFocusable TO THIS TASK BY NAME -- "they are P2.10's
    // to name, and naming them here would put the vocabulary on the wrong
    // base" (ICoreGraphicsObject.h). setFocusable is the answer, spelled to
    // match ICoreWidget::setFocusable rather than invented.
    //
    // ⚠⚠ THE OTHER FLAG P2.9a DELEGATED, ItemUsesExtendedStyleOption, GETS NO
    // NAME AT ALL -- it is dead, and its four sites should be DELETED (b-3).
    // Three separate things say so:
    //   * Qt's docs: the flag governs only how finely exposedRect is filled
    //     in on QStyleOptionGraphicsItem. NOTHING in this entire tree reads
    //     exposedRect or levelOfDetailFromTransform, so it cannot have an
    //     effect either way.
    //   * The comment riding on every one of the four sites -- "This prevents
    //     Qt from drawing the dashed focus rect" -- is simply not what the
    //     flag does. What actually strips Qt's focus decoration is this
    //     class's Chrome (None/FocusRing), added by P2.10a's predecessor.
    //   * ICoreCanvasAreaViewTitleBarLabel already has both lines COMMENTED
    //     OUT and looks and behaves correctly, which is the experiment
    //     already having been run.
    // Naming a flag whose only demonstrated property is a wrong comment
    // would carry the cargo across the seam. Same reading P7.3 made when it
    // declined to add toHexRgbString.
    // ------------------------------------------------------------------
    void setFocusable(bool focusable);
    void setSelectable(bool selectable);
    [[nodiscard]] bool isSelected() const;

    // Focus. ⚠ `takeFocus` rather than `setFocus`, because that is what
    // ICoreWidget already calls it (ICoreWidget.h) -- the scene tier has no
    // focus vocabulary to copy, since scene items did not take keyboard focus
    // and text items do. Same default reason as the widget tier.
    void takeFocus(ICoreFocusReason reason = ICoreFocusReason::Mouse);
    void clearFocus();
    [[nodiscard]] bool hasFocus() const;

    // ✅ "Am I on a scene?" -- and it is a BOOL, not P2.9d-4's reverse
    // lookup. The whole text tier has exactly ONE scene() site and it is
    // `if (!this->scene())`. P6.5's handle-keyed reverse lookup exists for a
    // caller that wants the ICoreGraphicsScene wrapper back; this tier has
    // none, so the expensive decision does not arise here.
    [[nodiscard]] bool isInScene() const;

    // Added by the flip for ICoreCanvasScanner, its single caller. On P0.7's
    // precedent: one caller justifies a forwarder when the alternative is
    // stranding a raw toolkit call that cannot survive the conversion.
    [[nodiscard]] bool isUnderMouse() const;

    // Which content token the text is drawn in.
    enum class Ink { Primary, Secondary, Tertiary, Accent, OnAccent };

    // What paint() does with Qt's own selection/focus decoration.
    enum class Chrome {
        Default,   // leave it to Qt -- the default, and what a plain
                   // QGraphicsTextItem does
        None,      // strip Qt's selected/focused states, draw nothing extra
        FocusRing  // strip them, then draw this application's selection-border
                   // ring while the item has focus
    };

    // ⚠ Retyped off QGraphicsItem* by the flip. ICoreGraphicsBoxedText's
    // constructor was already ICoreNativeItem* (P2.10b-3b) and had to unwrap
    // with icoreNativeItem() to reach these two; that unwrap is now gone, which
    // is the single line b-3b predicted would delete here.
    explicit ICoreGraphicsText(ICoreNativeItem* parent = nullptr);
    explicit ICoreGraphicsText(const ICoreString& text, ICoreNativeItem* parent = nullptr);

    void setInk(Ink ink);
    // Out of line since the flip: the state lives in Impl now.
    [[nodiscard]] Ink ink() const;

    void setChrome(Chrome chrome);
    [[nodiscard]] Chrome chrome() const;

    // Shadows QGraphicsTextItem::setDefaultTextColor -- see the header note.
    void setDefaultTextColor(const ICoreColor& color);

    // Hands the item back to the theme after a custom colour.
    void clearCustomTextColor();

    // Out of line: Impl is incomplete here, so the unique_ptr's deleter
    // cannot be instantiated in this header.
    ~ICoreGraphicsText() override;

protected:
    // Called BEFORE the text is drawn, for a subclass that wants a ground
    // behind its label. Separate from paintContent below and not a substitute
    // for it: anything drawn in paintContent lands ON TOP of the text, so a
    // background painted there would hide the very label it is backing.
    virtual void paintBackground(ICorePainter& painter);

    // Called after the text (and any focus ring) has been drawn, for a subclass
    // that decorates its label.
    virtual void paintContent(ICorePainter& painter);

    // The same hook surface ICoreGraphicsObject carries, for the text tier.
    // Hover requires setAcceptHoverEvents(true) on the item, as in the toolkit.
    virtual void pointerEntered(const ICoreMouseEvent& event);
    virtual void pointerLeft();

    // ------------------------------------------------------------------
    // ⚠ A HOOK, NOT AN ICoreSignal, AND THE CALL SITES ARE WHY.
    // Both tree-wide connections to QTextDocument::contentsChanged name
    // `this` as the receiver (ICoreCanvasTextBoxViewLabel, twice) -- it is an
    // object telling ITSELF its text changed, never a subscriber elsewhere.
    // An ICoreSignal would be exactly the speculative surface P2.10a deleted
    // from ICoreGraphicsBoxedText for having zero connections.
    //
    // Wired once here, in the constructor, so the connection is the base's
    // business and a recycled subclass cannot forget it -- or double it.
    // ⚠ ICoreCanvasTextBoxViewLabel::resetToInitialState currently re-connects
    // on every recycle without disconnecting, so a recycled note re-lays-out
    // once per previous life. Migrating it in P2.10b-3 removes that by
    // construction; it is a real (if cheap) defect, recorded so the fix is
    // not mistaken for a behaviour change.
    // ------------------------------------------------------------------
    virtual void textChanged();

    // ------------------------------------------------------------------
    // The gap P2.10 has to close, added additively ahead of the conversion
    // exactly as P2.7 did for ICoreGraphicsObject: empty bodies, the toolkit
    // handlers still virtual, so an unmigrated subclass keeps working.
    //
    // ⚠ THE RETURN CONVENTION IS ICoreGraphicsObject'S AND SO IS ITS TRAP.
    // false forwards to the toolkit base; true accepts and skips it. For a
    // PRESS that difference is not cosmetic: Qt accepts a reimplemented press
    // by default and makes the item the mouse grabber, while the base ignores
    // it for an item that is neither movable nor selectable -- so a handler
    // that used to return without calling its base must return TRUE, and
    // returning false silently costs it every later move and release. P2.8
    // hit this across 25 classes; the rule is written up under that task.
    // ------------------------------------------------------------------
    virtual bool mousePressed(const ICoreMouseEvent& event);
    virtual bool mouseMoved(const ICoreMouseEvent& event);
    virtual bool mouseReleased(const ICoreMouseEvent& event);
    virtual bool mouseDoubleClicked(const ICoreMouseEvent& event);

    // Matches ICoreGraphicsObject's widened hook (P2.8 batch 11): an
    // ICoreMouseEvent, not a bare point, because a context menu is opened at a
    // screen position, tested at an item position, and may place what it
    // creates at a scene position.
    virtual bool contextMenuRequested(const ICoreMouseEvent& event);

    // ------------------------------------------------------------------
    // ⚠ FOCUS-OUT IS A PAIR HERE, AND IT IS THE ONE TIER WHERE IT HAS TO BE.
    // Decided by the owner, 2026-08-11, after reading all four overriders.
    //
    // `focusLost` means "after the toolkit base" EVERYWHERE ELSE in the tree
    // -- ICoreWidget::focusOutEvent calls QWidget's base and then the hook.
    // But every one of this class's four overriders does its substantive work
    // BEFORE the base: the three labels commit their text (setPlainText,
    // applyDefaultStyle, updatePosition) and ICoreGraphicsBoxedText emits its
    // signal, all ahead of QGraphicsTextItem::focusOutEvent. Folding that into
    // a single after-the-base hook would move a document mutation across the
    // toolkit's own focus-out handling.
    //
    // Reversing this class's forwarder instead was rejected: it would give one
    // name two meanings across two tiers. So the slot splits, and each body
    // maps mechanically with NO order change at all.
    //
    // ⚠ `guiTest`'s 30 cases are theme/shell/render and would NOT catch a
    // focus-ordering regression, so this could not be settled by running the
    // suites -- only by reading the bodies. Keep it that way: if you add a
    // third hook here, read every overrider before you do.
    //
    // Most subclasses want only ONE of the pair. That is expected, not a smell.
    // ------------------------------------------------------------------

    // ⚠ FOCUS-IN IS A SINGLE VETOING HOOK, NOT A PAIR, AND THE ASYMMETRY WITH
    // FOCUS-OUT ABOVE IS THE POINT (P2.10b-4). Its one overrider,
    // ICorePortViewDescriptionLabel, DECLINES the base outright when the label
    // is not user-editable -- so what it needs is a veto, which is exactly
    // what focus-out's note says a focus LOSS can never have. Nothing in this
    // tier does work after QGraphicsTextItem::focusInEvent, so there is no
    // after-half to name and none is invented (§9).
    //
    // Return true to skip the toolkit base; call event.ignore() to also let
    // the focus event propagate. Two axes, spelled as keyPressed spells them.
    //
    // ⚠ NOT named `focusGained`: ICoreWidget::focusGained is `void` and runs
    // AFTER its base, so reusing that name for a before-the-base bool would be
    // one name meaning two things across two tiers -- the trap P2.10a rejected
    // when it named `focusLosing` and keyPressHandled dodged again below.
    virtual bool focusGaining(const ICoreFocusEvent& event);

    // Before QGraphicsTextItem::focusOutEvent -- commit or normalise the text
    // here, which is what every overrider in this tree actually does.
    virtual void focusLosing(const ICoreFocusEvent& event);

    // After the toolkit base has handled the focus loss. Matches what
    // `focusLost` means on ICoreWidget. In this tier the bodies that landed
    // here are logging, which is why the split was needed rather than a
    // reversal.
    virtual void focusLost(const ICoreFocusEvent& event);

    // ------------------------------------------------------------------
    // KEYS, AND THEY ARE A PAIR FOR THE SAME REASON FOCUS-OUT IS (P2.10b-4).
    //
    // `keyPressed` is the before-the-base, vetoing half, spelled exactly as
    // ICoreWidget::keyPressed so one concept keeps one name across tiers.
    // Return true to skip the toolkit base; call event.ignore() to also let
    // the key propagate to the item above. Two axes, as with the mouse.
    //
    // ⚠ `keyPressHandled` runs AFTER the toolkit base, and it exists because
    // ICoreChartAxisLabel's body does. That class resizes itself to fit its
    // text on every keystroke, and it measures the CURRENT text -- so running
    // it before QGraphicsTextItem inserts the character sizes the label one
    // keystroke behind, visibly, while typing. Its old override called its
    // parent FIRST and then resized, and this pair is the only way to keep
    // that sequence once the Qt virtual is gone.
    //
    // ⚠ It is NOT named `keyPressed` even though "after" is the past tense
    // that would read best: ICoreWidget already uses `keyPressed` for the
    // BEFORE half, and one name meaning two things in two tiers is precisely
    // what P2.10a rejected when it named `focusLosing`.
    //
    // One caller is enough here, on P0.7's precedent (ICoreEasingSpec was
    // added for a single site because the alternative was dropping the
    // behaviour or stranding a raw Qt type). The alternative here is the same:
    // strand a Qt override that cannot survive the flip, or change behaviour.
    // ------------------------------------------------------------------
    virtual bool keyPressed(const ICoreKeyEvent& event);
    virtual void keyPressHandled(const ICoreKeyEvent& event);

    // ⚠ THE 11 TOOLKIT VIRTUALS THAT STOOD HERE (hoverEnter/Leave, the four
    // mouse events, contextMenu, focusIn/Out, keyPress, paint) MOVED INTO Impl
    // WHOLESALE. They are what forwards the toolkit to the hooks above, and
    // they had to move because Impl is the QGraphicsTextItem now. Their bodies
    // are unchanged -- only `QGraphicsTextItem::x(e)` became
    // `QGraphicsTextItem::x(e)` on Impl and `hook(...)` became
    // `m_owner.hook(...)`.

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

ICoreGraphicsView.h#

src/ICoreEssentials/UI/Graphics/ICoreGraphicsView.h

ICoreGraphicsView#

ICoreGraphicsView.h:36 · class · bases public ICoreNativeWidget · pImpl · 42 declaration(s)

class ICoreGraphicsView : public ICoreNativeWidget {
public:
    enum class Backdrop {
        None,        // brush untouched -- the default, see above
        Canvas,      // the block-diagram ground
        Panel,       // content raised above a panel (a chart's plot sheet)
        Transparent  // no brush, and a translucent viewport, so whatever the
                     // view floats over shows through
    };

    explicit ICoreGraphicsView(ICoreNativeWidget* parent = nullptr);
    explicit ICoreGraphicsView(Backdrop backdrop, ICoreNativeWidget* parent = nullptr);
    explicit ICoreGraphicsView(ICoreGraphicsScene* scene, Backdrop backdrop);
    ~ICoreGraphicsView() override;

    ICoreGraphicsView(const ICoreGraphicsView&) = delete;
    ICoreGraphicsView& operator=(const ICoreGraphicsView&) = delete;

    void setScene(ICoreGraphicsScene* scene);

    void setBackdrop(Backdrop backdrop);
    Backdrop backdrop() const;

    // The frame and both scroll bars, off together. Opt-in: a view that says
    // nothing keeps the toolkit's frame and its automatic scroll bars.
    void setChromeHidden(bool hidden);
    bool isChromeHidden() const;

    // Scroll bars only, leaving the frame alone -- what ICoreChartView wants,
    // and the reason this is not folded into setChromeHidden().
    void setScrollBarsVisible(bool visible);

    // Zoom and pan keep the point under the pointer fixed, rather than the
    // view centre. Both views that zoom want this; it is not the default.
    void setZoomAnchoredUnderPointer(bool anchored);

    void setAcceptsDrops(bool accepts);
    void setAntialiased(bool antialiased);
    void setFixedSize(double width, double height);

    // --- Scroll position and viewport geometry.
    //
    // These replace 12 external reaches through `horizontalScrollBar()->value()`
    // and its setter. Every one of them wanted a scroll POSITION; not one
    // wanted a QScrollBar, so handing one out was exporting a toolkit widget to
    // express a number. Doubles because every caller already computes in
    // zoom-scaled doubles; the truncation to the toolkit's integer scrollbar
    // now happens once, here, instead of at each call site.
    double horizontalScroll() const;
    double verticalScroll() const;
    void setHorizontalScroll(double value);
    void setVerticalScroll(double value);

    // ⚠ viewWidth/viewHeight rather than width/height. The short names arrived
    // from QWidget before the conversion, and a call site that kept using them
    // would silently bind to something else rather than fail -- the quiet
    // substitution R1 punishes elsewhere.
    double viewWidth() const;
    double viewHeight() const;

    // The visible area in the view's own coordinates.
    ICoreRect viewportBounds() const;

    ICorePoint mapToScene(const ICorePoint& viewPoint) const;
    ICoreRect mapToScene(const ICoreRect& viewRect) const;
    ICorePoint mapFromScene(const ICorePoint& scenePoint) const;

    // Position and margins within the parent's layout. Both arrive from QWidget
    // today; a chart moves its view to the plot origin and zeroes its margins.
    void setViewPosition(double x, double y);
    void setViewMargins(double left, double top, double right, double bottom);

    void centerViewOn(const ICorePoint& scenePosition);

    // Centres on an ITEM rather than a point -- what "show me this block" means
    // at the one call site, and it saves the caller reaching for the item's
    // scene position through a second API.
    void centerViewOn(ICoreNativeItem* item);

    // Viewport-relative point to screen coordinates. Named on the view because
    // the mapping is the VIEWPORT's, not the widget's, and a caller that used
    // the widget's would be off by the frame.
    ICorePoint mapViewportToGlobal(const ICorePoint& viewportPoint) const;
    void scaleBy(double factor);
    void requestRepaint();

    ICoreNativeHandle nativeWidgetHandle() const override;

protected:
    // ------------------------------------------------------------------
    // The hook surface (P2.11b), mirroring ICoreGraphicsObject's. The names are
    // deliberately the ones already in use one tier down (and ICoreChartBase's
    // `wheelScrolled`), so a reader moving between the item tier and the view
    // tier meets one vocabulary rather than two. Every bool answers "handled?";
    // false forwards to the toolkit base so unhandled gestures behave as before.
    // ------------------------------------------------------------------

    virtual bool wheelScrolled(const ICoreWheelEvent& event);

    virtual bool mousePressed(const ICoreMouseEvent& event);
    virtual bool mouseMoved(const ICoreMouseEvent& event);
    virtual bool mouseReleased(const ICoreMouseEvent& event);

    // Drag and drop onto the view. Qt's contract applies unchanged: a drag not
    // accepted on ENTER never produces the later two.
    virtual bool dragEntered(const ICoreDragEvent& event);
    virtual bool dragMovedOver(const ICoreDragEvent& event);
    virtual bool payloadDropped(const ICoreDragEvent& event);

    // ⚠ Hands over the VIEWPORT bounds, not the widget size, and not the
    // old/new pair the P5.1 gap list sketches for ICoreWidget. Discovered from
    // the call site rather than from what Qt offers (§9): the one overrider,
    // ICoreChartView, ignores the event entirely and reads the viewport rect.
    virtual void resized(const ICoreRect& viewportBounds);

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