API — ICoreEssentials/UI/Graphics
The public contract of 23 header(s) under ICoreEssentials/UI/Graphics — 20 class/struct definition(s), 414 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.
ICoreGraphicsBoxedText.h#
ICoreEssentials/UI/Graphics/ICoreGraphicsBoxedText.h
ICoreGraphicsBoxedText#
ICoreGraphicsBoxedText.h:71 · class · bases public ICoreGraphicsText · pImpl · 46 declaration(s)
ICoreGraphicsBoxedText -- a text field that lives on a graphics scene.
class ICoreGraphicsBoxedText : public ICoreGraphicsText {
public:
// What the user may do with the value.
//
// ⚠ THREE STATES, WHERE THE OLD SURFACE HAD A BOOL AND THREE INDEPENDENT
// STYLE FLAGS THAT COULD DISAGREE WITH IT. setUserEditable(false) plus
// useFieldFill() produced a box that looked editable and was not;
// setFocusable_DisableUserEdit() produced a fourth state neither of the
// other two could express. A role says what the box IS, and the fill
// follows from it unless a caller overrides the fill deliberately.
enum class Role {
// Typing changes the value. A press mounts the editor.
Editable,
// The value may be read, SELECTED and copied -- with the platform's own
// context menu -- but not changed. A press still mounts the editor,
// read-only, which is what makes the selection and the menu real rather
// than approximated.
ReadOnly,
// A label that happens to have a box around it. Takes no focus, mounts
// nothing, and does not answer a press at all.
Display
};
// The ground the box wears. Defaults to whatever the role implies.
enum class Fill {
None, // transparent -- a box that is only a border
Field, // field.background: "you may type here"
RaisedReadOnly // field.readOnlyBackground: "a value, not a field"
};
explicit ICoreGraphicsBoxedText(ICoreNativeItem* parent = nullptr);
~ICoreGraphicsBoxedText() override;
// -- what it is ---------------------------------------------------------
void setRole(Role role);
[[nodiscard]] Role role() const;
// ⚠ STICKY, AND ONLY WHEN A CALLER SETS IT. setRole picks a fill to match
// unless this has been called, after which the caller's choice survives
// both a role change and a theme switch. Same sticky-override rule
// ICoreGraphicsText applies to its ink.
void setFill(Fill fill);
[[nodiscard]] Fill fill() const;
void setBorderVisible(bool visible);
[[nodiscard]] bool isBorderVisible() const;
// Drawn in place of the value while the value is empty, in the tertiary
// ink. It is NOT the value: toPlainText() stays empty, and committing an
// empty edit leaves it empty.
void setPlaceholder(const ICoreString& text);
[[nodiscard]] ICoreString placeholder() const;
// -- the editing session ------------------------------------------------
// Mount the editor over this box and give it the focus. False when the role
// forbids it, when a session is already open, or when the box is in no
// scene -- an unparented box has nowhere to mount a control.
bool beginEditing();
// Take what the editor holds, put it in the box, and unmount. Fires
// onTextCommitted only when the value actually changed.
void commitEditing();
// Unmount, and keep the value the box had before the session opened.
void cancelEditing();
[[nodiscard]] bool isEditing() const;
// Whether mounting selects the whole value. True by default, which is what
// a user replacing a field's contents expects; false for a box they are
// more likely to be amending than replacing.
void setSelectsAllOnEdit(bool selects);
[[nodiscard]] bool selectsAllOnEdit() const;
// ⚠ COMMITTED, NOT EDITED, and the distinction is the one ICoreLineEdit
// already draws between onTextEdited and onEditingFinished. This fires once,
// when a session ends with a changed value -- never on a keystroke. A caller
// that wants keystrokes is reaching for the wrong object: subscribe here and
// keep the scene's value the thing you read.
ICoreSignal<ICoreString> onTextCommitted;
ICoreSignal<> onEditingBegan;
ICoreSignal<> onEditingCancelled;
// -- geometry and measurement -------------------------------------------
[[nodiscard]] ICoreRect contentBounds() const override;
virtual void setWidth(const double& width);
virtual void setHeight(const double& height);
[[nodiscard]] double getWidth() const;
[[nodiscard]] double getHeight() const;
// Fit the height to the text currently in the box.
void autoCalcHeight();
[[nodiscard]] double predictTextWidthPx(const ICoreString& text) const;
[[nodiscard]] virtual double getPredictedTextWidthPx() const;
// -- appearance ---------------------------------------------------------
void setBoldText(bool isBold);
void centerTextHorizontally();
// ⚠ CALLER-OWNED AND NOT REFRESHED, which is the whole difference between
// this and setFill(). A colour set here survives a theme switch untouched,
// because the caller asked for a COLOUR rather than for a role. That is
// right for a highlight and wrong for a field's ground -- which is what
// setFill is for, and why the two are separate methods rather than one.
void setBackgroundColor(const ICoreColor& color);
void setBorderColor(ICoreColor color);
// -- lifecycle ----------------------------------------------------------
void resetToInitialState(ICoreNativeItem* parent = nullptr);
// The recycler's liveness bookkeeping -- see ICoreGraphicsRecycler.
void kill();
void setAlive();
[[nodiscard]] bool isAlive() const;
// -----------------------------------------------------------------------
// Compatibility. Every one of these is the old spelling of something above
// and is implemented by calling it. Kept because callers outside this
// repository use them.
// -----------------------------------------------------------------------
// -> setRole(Editable) / setRole(ReadOnly)
void setUserEditable(const bool& userEditable);
// -> setRole(ReadOnly) + setFill(RaisedReadOnly)
void useRaisedReadOnlyStyle();
// -> setFill(Field)
void useFieldFill();
// -> setBorderVisible(false)
void hideBorder();
// -> setRole(ReadOnly). The old name says what it disabled rather than what
// it produced, which is why it reads as a fourth state and is not one.
void setFocusable_DisableUserEdit();
// ⚠⚠ DECLARED SINCE THIS CLASS EXISTED AND DEFINED ON NO BACKEND. It had no
// body anywhere and no call site, so a caller reaching for it failed at the
// LINKER, with a name it could do nothing about. Deleting the declaration
// would move that failure to the compiler, which is not an improvement for
// somebody else's build; so it is given the body its name implies -- take
// the focus, or give it up -- and becomes usable rather than a trap.
void setManualFocus(bool isFocus);
protected:
void focusLosing(const ICoreFocusEvent& event) override;
bool keyPressed(const ICoreKeyEvent& event) override;
bool mousePressed(const ICoreMouseEvent& event) override;
bool mouseDoubleClicked(const ICoreMouseEvent& event) override;
void pointerEntered(const ICoreMouseEvent& event) override;
void pointerLeft() override;
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#
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:17 · class · bases public ICoreGraphicsObject · pImpl · 46 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);
// -----------------------------------------------------------------------
// ⚠⚠ THE CLICK. THIS CLASS HAD NONE FOR ITS ENTIRE LIFE, WHICH IS WHY
// EVERY CALLER IN THIS TREE IS A SUBCLASS.
//
// A button is the one control whose whole purpose is to be pressed, and
// this one published no signal for it: `isPressed` was a member that
// NOTHING EVER WROTE -- there was no mousePressed or mouseReleased override
// anywhere in the class -- so it was false for the life of every button and
// no body ever read a pressed state. The only way to be told about a click
// was to derive and override a protected hook, which is what the combo
// box's options, the gallery's scene buttons and every canvas tool button
// each do, separately.
//
// ⚠ AND A PRESS IS NOT A CLICK, which is the reason this is three signals
// and not one. QAbstractButton fires `clicked` on a RELEASE that lands
// inside the button that took the press -- so a user who presses, drags off
// and releases has cancelled, and ~200 call sites in this product are
// written against that. `ICoreButtonInput` is where that rule already
// lives, spelled once for every backend; this class routes through it
// rather than re-deciding it.
// -----------------------------------------------------------------------
// A release that landed inside the button that took the press.
ICoreSignal<> onClicked;
// The raw edges, for a caller that genuinely wants them (a canvas that
// begins a drag on the press). Most callers want onClicked.
ICoreSignal<> onPressed;
ICoreSignal<> onReleased;
// Checkable buttons only; carries the new state.
ICoreSignal<bool> onToggled;
// A checkable button flips on click, BEFORE onClicked fires -- so a handler
// reading isChecked() sees the new value, which is QAbstractButton's order.
void setCheckable(bool checkable);
[[nodiscard]] bool isCheckable() const;
void setChecked(bool checked);
[[nodiscard]] bool isChecked() const;
// ⚠ THE RESTING PLATE, AND IT IS OFF BY DEFAULT HERE WHERE IT IS ON FOR THE
// WIDGET BUTTON. A caption-only widget button wears a surface at rest,
// because a button whose whole content is a word has nothing else to say it
// is a button. On a canvas that is not automatically true -- a scene button
// usually sits on a node that is already a surface -- and turning it on for
// every graphics button would restyle the canvas context menu's rows and
// the combo box's options along with whatever asked for it. Same reasoning,
// and the same default, that setNavItemStyle below already carries.
void setRestPlate(bool on);
[[nodiscard]] bool hasRestPlate() const;
// How far the background travels while the finger is down. Defaults to the
// theme's button.pressedOpacity.
void setPressedOpacity(double opacity);
// 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);
// ⚠ setIcon(icoreThemedIcon(path)) EXCEPT THAT IT FOLLOWS A THEME SWITCH.
// The glyph is drawn through ICoreIconRenderer, which can rebuild the ART
// and not merely its rasterization once it is given the path -- see that
// header, which also records why the version of this that only repainted
// could never have worked on a native seat.
void setThemedIcon(const ICoreString& svgPath);
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;
// ⚠⚠ A SUBCLASS THAT OVERRIDES EITHER OF THESE MUST CALL THE BASE, OR THE
// BUTTON LOSES ITS PRESSED LOOK AND ITS onClicked. They are new -- the
// class had no mouse handlers at all until the click was built -- so every
// existing overrider in this tree and outside it currently replaces them,
// which is exactly the state those subclasses were already in and is why
// adding them breaks nothing. New code should subscribe to onClicked and
// override neither.
//
// `ICoreButtonInput` takes what the override returned as
// `consumedByOverride`, so a subclass that handles the press itself and
// calls the base still gets the chrome without getting a second click.
bool mousePressed(const ICoreMouseEvent& event) override;
bool mouseReleased(const ICoreMouseEvent& event) override;
void visibilityChanged(bool visible) override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreGraphicsComboBox.h#
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:18 · class · bases public ICoreGraphicsBoxedText · pImpl · 22 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);
// -----------------------------------------------------------------------
// ⚠⚠ THE SELECTION, THE POPUP AND THE KEYBOARD -- none of which this class
// published, and the first of which it could not even report.
//
// A combo box exists to tell somebody what was chosen, and this one had no
// signal at all: a caller learned about a change by subclassing and
// overriding setChosenOption, which is the same shape ICoreGraphicsButton
// was in before it grew onClicked.
// -----------------------------------------------------------------------
// Fires when the VALUE changes, whoever changed it -- a click on a row, an
// arrow key, or setChosenOption from a caller. Not fired for a re-selection
// of the value already held.
ICoreSignal<ICoreString> onSelectionChanged;
[[nodiscard]] ICoreString chosenOption() const;
[[nodiscard]] int optionCount() const;
// ⚠ THE POPUP'S STATE IS PUBLIC BECAUSE IT WAS ALREADY REACHABLE AND ONLY
// BY ACCIDENT: animateComboDialogShow/Hide below are the old spelling, they
// are public, and they were the only way to ask -- by calling one and
// seeing what happened. A bool and two named calls say the same thing
// without the side effect.
// ⚠⚠ VIRTUAL SINCE A10.47, AND ITS NOT BEING VIRTUAL IS WHAT MADE A
// SUBCLASS'S POPUP WORK LOOK LIKE DEAD CODE. Everything that opens or
// closes a dropdown in practice -- mousePressed(), keyPressed(),
// focusLosing() -- calls THIS, not the two compatibility spellings below;
// those are reached from exactly one place in the tree. So a subclass that
// customised the popup by overriding animateComboDialogShow/Hide (the only
// hooks that existed) had its bodies skipped by every real gesture, and the
// one combo box in the editor did precisely that: its dropdown is supposed
// to be re-parented onto the canvas's floating layer while it is open, and
// instead it stayed a child of the box, behind every sibling drawn after it.
//
// The compatibility verbs stay virtual too and still forward here, so both
// spellings dispatch to the same override.
virtual void setPopupOpen(bool open);
[[nodiscard]] bool isPopupOpen() const;
void setWidth(const double& width) override;
void setHeight(const double& height) override;
virtual void setChosenOption(const std::string& newChosenOption);
// Compatibility spellings of setPopupOpen(false) / setPopupOpen(true).
//
// ⚠ NEITHER EVER ANIMATED ANYTHING. They set the popup's height to 0 or to
// its cached full height in one step; the names describe an intention
// nobody implemented. Kept because callers outside this repository use
// them, and left virtual because they always were.
virtual void animateComboDialogHide();
virtual void animateComboDialogShow();
double getPredictedTextWidthPx() const override;
// -----------------------------------------------------------------------
// ⚠⚠ WHERE THE LIST GOES, AND IT IS ONE ANSWER FOR TWO PLACERS (A10.45).
//
// This class parents the popup to itself and puts it at `placement.x/.y`.
// ICoreBlockConfigDialogContentPaneEntryComboBox does NOT: its dropdown has
// to escape the config pane, so on open it re-parents the list onto the
// canvas's floating layer and positions that layer in CANVAS coordinates
// instead (A10.38). Two placers, and before this row they carried the same
// rule written out twice -- `icoreComboPopupTop(getHeight())` here and
// `+ ICorePoint(0, this->getHeight())` there. Both must move together or a
// flipped list appears in one of them and not the other, so the rule lives
// here and both ask for it.
//
// In this box's own coordinates. Asks popupBounds() for the room.
// -----------------------------------------------------------------------
[[nodiscard]] ICoreComboPopupPlacement popupPlacement() const;
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:
// ⚠⚠ THE ROOM THE LIST HAS, AND AN EMPTY RECT MEANS "I DO NOT KNOW" RATHER
// THAN "THERE IS NONE" (A10.45). In this box's own coordinates.
//
// The default is empty, and under an empty rect popupPlacement() returns
// exactly what this class did before the flip existed: below the box, at the
// box's own width, never moved. That default is the point of the hook, not a
// placeholder to be filled in later. A10.45 was opened NOT ATTEMPTED with
// its reason written into the row -- *"flipping against the wrong rectangle
// is a popup that jumps upward in the middle of a tall dialog, which is
// worse than one that always opens down"* -- and a box in this tier cannot
// see its container: parentItem() answers an ICoreNativeItem* handle, which
// has no contentBounds(), and the TEXT tier has no scene accessor.
//
// So the question is asked of whoever can answer it. A container that can
// reach its view -- the editor's combo box can, through the canvas -- gives
// the visible area here and gets the flip; one that cannot says nothing and
// keeps today's behaviour. Nothing guesses.
virtual ICoreRect popupBounds() const;
// ⚠ EVERY ONE OF THESE EXISTS TO STOP THE BASE ACTING. A combo box is not
// editable text; it keeps ICoreGraphicsBoxedText for its type and for its
// field chrome, and overrides each hook the base would otherwise have used
// to mount an editor. The .cpp banner says why the inheritance is kept.
bool mousePressed(const ICoreMouseEvent& event) override;
bool mouseDoubleClicked(const ICoreMouseEvent& event) override;
bool keyPressed(const ICoreKeyEvent& event) override;
void focusLosing(const ICoreFocusEvent& event) override;
// The chevron, over the base's field chrome.
void paintContent(ICorePainter& painter) override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreGraphicsComboBoxDialog.h#
ICoreEssentials/UI/Graphics/ICoreGraphicsComboBoxDialog.h
⚠⚠ THE ONE SIGNATURE P2.9c COULD NOT RETYPE, AND IT IS P2.9d'S GATE.
parenthere 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, soparentis an ICoreNativeItem and is no longer a QGraphicsObject at all.
ICoreGraphicsComboBoxDialog#
ICoreGraphicsComboBoxDialog.h:13 · class · bases public ICoreGraphicsObject · pImpl · 22 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;
// -----------------------------------------------------------------------
// The painted lane's own surface.
//
// The rows are drawn from a vector of strings now rather than being a list
// of child scene items, so the questions a keyboard user's combo box asks
// -- how many are there, what is the third one called, light the third one
// -- have nowhere else to go. They were previously answered by walking the
// child items, which is why nothing outside this class could ask them.
// -----------------------------------------------------------------------
[[nodiscard]] int optionCount() const;
[[nodiscard]] std::string optionAt(int index) const;
// ⚠ THE HIGHLIGHT IS THE HOVER, deliberately, rather than a second state
// beside it. A pointer user and a keyboard user are pointing at the same
// row and there is only one row that can be lit; keeping two would let them
// disagree, and the disagreement is invisible until someone hovers one row
// and arrows onto another.
void setHighlightedOption(int index);
[[nodiscard]] int highlightedOption() 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;
protected:
// ⚠ THE POPUP DRAWS ITS OWN ROWS AND HIT-TESTS THEM ITSELF, which is what a
// painted lane means. None of these existed while every option was a child
// button: the scene did the hit-testing and the buttons did the drawing.
void paintContent(ICorePainter& painter) override;
bool mousePressed(const ICoreMouseEvent& event) override;
void pointerEntered(const ICoreMouseEvent& event) override;
void pointerMoved(const ICoreMouseEvent& event) override;
void pointerLeft() override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreGraphicsComboBox_ComboOption.h#
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#
ICoreEssentials/UI/Graphics/ICoreGraphicsCommands.h
⚠
class QObject;RETIRED BY A9.4 (2026-08-21) -- dead. The banner below says these helpers are callable from outside the wrapper zone "without naming a Qt type"; the declaration was the one place this header still did.
ICoreGraphicsCommands#
ICoreGraphicsCommands.h:24 · class · 10 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.
// -- item geometry, for callers outside the wrapper zone ----------------
//
// ⚠ THESE EXIST SO A PORTABLE BODY CAN ASK AN ITEM WHERE IT IS. A file that
// holds an `ICoreNativeItem*` has no way to read its position or its bounds
// without unwrapping the handle, which only a backend may do -- so a body
// that needs them is trapped in whichever backend it was written in, for no
// reason but that (§0.31's "location accident"). `ICoreGraphicsInfoLabel` is
// the worked example: 300 lines of otherwise toolkit-free code that could
// not leave `Backends/Qt/` because of two calls.
//
// Position is in the item's PARENT's coordinates and bounds is its own
// content box at the origin -- the same pair `pos()` and `boundingRect()`
// mean on the other toolkit, so a caller moved across needs no rethink.
// Both answer zero for a null wrapper.
// ⚠ OUT-PARAMS OF DOUBLES RATHER THAN ICorePoint / ICoreRect, AND THAT IS
// TO KEEP THIS HEADER AS LIGHT AS IT IS. It carries FORWARD DECLARATIONS
// AND NOTHING ELSE -- no include at all -- which is what lets it be
// included from outside the wrapper zone without dragging anything behind
// it. Returning an ICorePoint needs the complete type, and ICorePoint.h
// includes <QPoint>: one convenience signature here would put the toolkit
// into every caller of a header whose whole point is that it does not.
// The same trade A4.3 got wrong once and paid for in eleven lab recipes.
static void itemPosition(const ICoreNativeItem* item, double& x, double& y);
static void itemBounds(const ICoreNativeItem* item,
double& x, double& y, double& width, double& height);
// The two MUTATORS the same argument justifies -- move an item within its
// parent, and re-parent one -- for a caller outside the wrapper zone that
// holds only handles.
//
// ⚠ THEY EXIST FOR EXACTLY ONE READER, AND IT IS THE ONE THAT PROVES THE
// POINT: `ICoreGraphicsScrollPaneScrollableArea` held its scrolled content
// as a raw `QGraphicsItem*` purely to call `setPos` and `setParentItem` on
// it, and that single member was the whole of what kept a 193-line,
// otherwise-portable body inside `Backends/Qt/` (§0.31). The capability
// goes INTO the wrapper rather than the call site going around it.
//
// Both are no-ops for a null wrapper. `setItemParent(item, nullptr)`
// detaches: on both backends that makes the item TOP-LEVEL in the scene it
// is in rather than removing it, which is what QGraphicsItem::setParentItem
// does and what every seat in this tier reproduces.
static void setItemPosition(ICoreNativeItem* item, double x, double y);
static void setItemParent(ICoreNativeItem* item, ICoreNativeItem* parent);
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`, and every one parented
// beneath it; no-op when null or when there is nothing running.
//
// ⚠ WHAT "PARENTED TO" MEANS CHANGED UNDER THIS SURFACE AND THE CONTRACT
// DID NOT (A0.6). It used to mean "a QAbstractAnimation in the toolkit's
// object tree beneath `owner`", found with findChildren(). The Motion tier
// holds no toolkit animation any more -- both backends run on the portable
// clock -- so the Qt seat keeps the association in a registry and answers
// the same question from it. Same set of animations, same recursion into
// descendants, no call site changed.
//
// ⚠ AND THE OLD NOTE'S PROMISE IS RETIRED RATHER THAN QUIETLY BROKEN: it
// said this "deliberately reaches ALL animations, not only the
// ICore-wrapped ones", because a recycled object might own a plain toolkit
// animation too. Measured at A0.6: the tree constructs no toolkit
// animation anywhere -- `new QPropertyAnimation` / `new QVariantAnimation`
// appear in comments and nowhere else -- so the wider set is empty, and a
// walk kept alive to cover it would find only what this already finds.
//
// ⚠ 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#
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#
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#
ICoreEssentials/UI/Graphics/ICoreGraphicsObject.h
Declares no class of its own — see the file.
ICoreGraphicsPixmap.h#
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#
ICoreEssentials/UI/Graphics/ICoreGraphicsProxyWidget.h
Declares no class of its own — see the file.
ICoreGraphicsRect.h#
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#
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#
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
Backdropenum (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#
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#
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#
ICoreEssentials/UI/Graphics/ICoreGraphicsScrollPaneScrollableArea.h
⚠ ELEVEN DEAD Qt INCLUDES RETIRED HERE (A9.4, 2026-08-21): <QColor>, <QGraphicsItem>, <QGraphicsSceneWheelEvent>, <QObject>, <QPainter>, <QPainterPath>, <QRectF>, <QStyleOptionGraphicsItem>, <QWidget>, <Qt> and <QtGlobal>. Not one of those types is named anywhere in this file -- counted over the file rather than assumed: eleven Qt references, and all eleven of them were the include lines themselves.
They are the fossil of the conversion the class's own comments narrate: this was a QGraphicsObject with a Q_OBJECT, overriding boundingRect(), shape() and paint() against Qt event and style-option types. Every one of those became an ICore type (contentBounds, contentShape, paintBody over ICorePainter) and the base became ICoreGraphicsObject -- and the include block never moved, because nothing fails when it does not.
ICoreGraphicsScrollPaneScrollableArea#
ICoreGraphicsScrollPaneScrollableArea.h:31 · class · bases public ICoreGraphicsObject · pImpl · 19 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;
// -----------------------------------------------------------------------
// ⚠⚠ THE SCROLL STATE AS ONE VALUE, WHICH IS WHAT THE BAR NEXT DOOR
// USED TO RE-DERIVE. It asked getContentHeight() and getViewportHeight()
// and worked out the maximum, the page step and the thumb's share in its
// own arithmetic -- so two files held the same three numbers and could
// round them differently. They cannot now: there is one model and the bar
// reads it.
//
// ⚠ THE SIGN IS THE CORE'S, NOT getScrollY()'s. `value` is how far the
// viewport has travelled INTO the content -- zero at the top, positive
// going down -- which is what every scroll bar speaks. getScrollY() above
// is the content ITEM's y offset and is the negative of it; it keeps its
// sign because it is published and callers outside this repository use it.
// -----------------------------------------------------------------------
[[nodiscard]] const ICoreScrollModel& scrollModel() const;
void setScrollValue(int value);
[[nodiscard]] int scrollValue() 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#
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:15 · class · bases public ICoreGraphicsObject · pImpl · 17 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);
// ⚠ THE TABLE IS THE ONE PLACE EDGES ARE DERIVED, and everything that
// needs a boundary asks here rather than re-deriving one. The splitter is
// the caller this exists for: it used to read a vector of WIDTHS off the
// titles row and do its own arithmetic on them.
[[nodiscard]] std::vector<int> columnEdges() const;
[[nodiscard]] const std::vector<double>& columnRatios() const;
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#
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 · 13 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;
// ⚠⚠ THE COLUMN BOUNDARIES, WHICH ARE WHAT A CELL, A HAIRLINE AND A
// SPLITTER ALL ACTUALLY WANT. This used to be a vector of WIDTHS and every
// consumer accumulated it back into boundaries with its own padding
// arithmetic -- three call sites, three chances to be off by two pixels.
// `edges` has size N+1, starts at 0 and ends at the content width exactly.
void setColumnEdges(const std::vector<int>& edges);
// Compatibility: widths, converted to edges and forwarded.
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#
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#
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:15 · class · bases public ICoreGraphicsObject · pImpl · 12 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;
// ⚠⚠ THE COLUMN BOUNDARIES, WHICH ARE WHAT A CELL, A HAIRLINE AND A
// SPLITTER ALL ACTUALLY WANT. This used to be a vector of WIDTHS and every
// consumer accumulated it back into boundaries with its own padding
// arithmetic -- three call sites, three chances to be off by two pixels.
// `edges` has size N+1, starts at 0 and ends at the content width exactly.
void setColumnEdges(const std::vector<int>& edges);
// Compatibility: widths, converted to edges and forwarded.
void setColumnsWidths(std::vector<double> newColumnsWidths);
void setHeight(double height);
std::vector<ICoreGraphicsBoxedText*> getAllTextItems() const;
std::vector<double> getColumnsWidths() const;
// ⚠ `std::ptrdiff_t` where the lowercase Qt typedef `qsizetype` once sat --
// a TOOLKIT NAME in a wrapper-zone public header, which is what this zone
// exists to prevent. It survived because a lowercase Qt typedef matches no
// scan written for `Q`-prefixed names, and because `ICorePoint.h` still
// reached <QPoint>, so it resolved on both backends and nothing ever went
// red. (§0.136 later measured the two as the same WIDTH but different
// TYPES -- long long vs long -- so callers convert implicitly.)
std::ptrdiff_t 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#
ICoreEssentials/UI/Graphics/ICoreGraphicsText.h
ICoreGraphicsText#
ICoreGraphicsText.h:66 · class · bases public ICoreNativeItem · pImpl · 64 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.)
// * 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.
//
// ✅ setZValue/zValue WERE ON THAT LIST AND HAVE COME OFF IT, which is
// the rule above working rather than an exception to it: something
// asked. ICoreGraphicsComboBox is TEXT tier and its popup is its own
// child, so a sibling of the BOX painted over the whole dropdown --
// the owner's *"Popup appears behind the siblings of the combobox"* --
// and raising the box for as long as its list is open is the fix. There
// is no way to spell that without a z on this tier: the combo box is
// not an ICoreGraphicsObject and never will be (see the class banner on
// the two hierarchies).
// ------------------------------------------------------------------
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);
// Stacking among SIBLINGS -- items that share a parent, plus their whole
// subtrees. It cannot order an item against its own parent or child.
void setZValue(double z);
[[nodiscard]] double zValue() const;
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#
ICoreEssentials/UI/Graphics/ICoreGraphicsView.h
ICoreGraphicsView#
ICoreGraphicsView.h:36 · class · bases public ICoreNativeWidget · pImpl · 43 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;
// Where the pointer is, in VIEWPORT coordinates, as this view last saw it.
// Answers false when the pointer is not over this view at all, which is a
// real state and not a failure: a caller asking "how far is the pointer
// from this item" should read false as "further than any distance you
// care about".
//
// ⚠⚠ IT EXISTS BECAUSE `mapViewportToGlobal` MEANS THREE DIFFERENT THINGS
// (`W10.108`, 2026-09-21). Its own comment above says *"to screen
// coordinates"*, and only the AppKit seat delivers that: WinUI answers in
// WINDOW-CLIENT coordinates because `screenOrigin` is still (0,0)
// tree-wide, and the GTK4 seat answers in TOPLEVEL coordinates and says so
// outright -- *"the name is the only thing that overstates it"*, because
// Wayland does not let a client know where its toplevel is.
//
// So a caller that combined it with `ICoreCursor::pos()` -- which IS true
// screen coordinates, from GetCursorPos -- was subtracting two different
// spaces on two of the three seats. The editor canvas's root item did exactly
// that to decide whether the pointer had left a block's hover margin, and
// the error is the window's position on the desktop: hundreds of points, so
// the pointer read as instantly far away and the affordances vanished the
// moment you left the block. The owner reported it as *"when mouse hovers
// away they hide right away"*.
//
// ⚠ VIEWPORT COORDINATES, NOT SCENE, for the reason the portable core's own
// pointer fields give: only the view coordinate is unchanged across a zoom,
// so a caller that wants the scene point maps it itself and gets the right
// answer at the current zoom.
//
// 📌 *A mapping whose name promises one space and whose three
// implementations deliver three is worse than no mapping at all -- every
// consumer is correct on the seat it was written against.*
bool pointerViewportPos(ICorePoint& out) 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;
};