API — ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab
The public contract of 20 header(s) under src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab — 24 class/struct definition(s), 332 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.
ICoreTab.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/ICoreTab.h
W0.22, 2026-08-27: this header declares std::deque and std::string in its own public signatures and included neither. It compiled everywhere anyway because ICoreEssentials/pch.h is force-included ahead of it and, on a qt CORE backend, QtCore's headers hand both over transitively -- so the first configuration to reach it without Qt is the first to see it: 17 C2039s on std::deque, and then SEVEN MORE reading "backNavigationHistoryList is not a member of ICoreTab::Impl", because the member in ICoreTab.cpp:37 is a std::deque too and its declaration is what failed to parse. Those seven are the SAME defect and not a stale member.
ICoreTab#
ICoreTab.h:21 · class · pImpl · 23 declaration(s)
class ICoreTab {
public:
explicit ICoreTab(ICoreStudioSurface* parent);
void loadTreeNode(ICoreSubsystemTreeNode* nodeToLoad, bool resetCanvas = true);
// Re-runs loadTreeNode()'s per-load passes (canonical z-order, then the "links
// drifted away from their ports" correction) over whatever this tab currently
// shows. A recipe replay repopulates the node UNDER a tab that is already loaded
// and never calls loadTreeNode() again -- which is how the drift came back, twice.
// ICoreStudioStateMachine::applyRecipeSnapshot() sweeps every tab through this
// once the replay is done. A pass that must run on every load -- project open,
// switch, undo, redo -- goes into runPerLoadPasses() in ICoreTab.cpp, which both
// paths share, and never onto the end of loadTreeNode() alone.
void rerunPerLoadPasses() const;
void navigateBack();
void navigateUp();
// False once the walk up would leave the part of the tree the user is allowed to see,
// so navigateUp() and the Up button's enabled state stay in agreement.
bool canNavigateUp() const;
void refreshLoadedTreeNode();
void refreshLoadedTreeNodeFromLoadedPath();
// Undo/redo rebuilds every nested subsystem, and a rebuilt node's origin anchor
// starts wherever its recycled anchor was reset to -- not where this tab's view was
// looking, so the diagram would land off screen and outside the canvas. Called just
// before the replay; the next refreshLoadedTreeNodeFromLoadedPath() moves the
// rebuilt diagram back under the remembered spot, then lets the canvas grow for
// anything the step brought back past its edge.
void rememberOriginAnchorPosition();
void deleteTabPermanently();
void ensureTabHeadersHaveTheCorrectName() const;
void handleNavigationHistory(ICoreSubsystemTreeNode* nodeToCache);
// Moves this tab into `newParent`'s strip at `tabIndex` among its tabs
// (-1 = the end) -- a tab dropped into another window lands where it was
// dropped, not always last.
void setParent(ICoreStudioSurface* newParent, int tabIndex = -1);
ICoreTabHeader* getTabHeader() const;
ICoreStudioSurface* getParentStudioSurface() const;
ICoreCanvas* getAttachedCanvas() const;
std::string getLoadedTreenodePath() const;
std::deque<ICoreSubsystemTreeNode*> getBackNavigationHistoryList() const;
void resetToInitialState(ICoreStudioSurface* parent);
void kill();
void setAlive();
bool isAlive() const;
~ICoreTab();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreTabDragController.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/ICoreTabDragController.h
ICoreTabDragController#
ICoreTabDragController.h:31 · class · 6 declaration(s)
The tab-header drag, as ONE gesture with ONE owner (W10.123).
class ICoreTabDragController {
public:
ICoreTabDragController() = delete;
// A left press on `tab`'s header, at `pressInHeader` in the header's own
// coordinates. Ends any gesture still in flight first.
static void arm(ICoreTab* tab, const ICorePoint& pressInHeader);
// Delivered-event hints: step the gesture now rather than on the next tick.
static void pointerMoved();
static void pointerReleased();
// A tab that is closing or being recycled takes its gesture with it; a no-op
// for any other tab.
static void forget(const ICoreTab* tab);
[[nodiscard]] static bool isDragging();
};
};
ICoreTabHeader.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/ICoreTabHeader.h
The strip this header is drawn in, or null while it is in none (recycled, or between two strips mid-migration). Written by ICoreTabHeadersBar alone: it is the bar's record of which headers it holds, kept here so a header can always be taken out of the strip it is really in.
ICoreTabHeader#
ICoreTabHeader.h:20 · class · final · bases public ICoreWidget · pImpl · 25 declaration(s)
class ICoreTabHeader final : public ICoreWidget {
public:
explicit ICoreTabHeader(ICoreTab* associatedTab, ICoreWidget* parent = nullptr);
double backgroundOpacity() const;
void setBackgroundOpacity(double o);
double hoverProgress() const;
void setHoverProgress(double p);
void setLabelText(const ICoreString& newText) const;
void setFocusedStyle();
void removeFocusedStyle();
void loadTreeNodeInfo(ICoreSubsystemTreeNode* nodeToLoad) const;
// The strip this header is drawn in, or null while it is in none (recycled,
// or between two strips mid-migration). Written by ICoreTabHeadersBar alone:
// it is the bar's record of which headers it holds, kept here so a header
// can always be taken out of the strip it is really in.
ICoreTabHeadersBar* owningBar() const;
void setOwningBar(ICoreTabHeadersBar* bar);
// Dims the header while it is being dragged, so the gap it will leave reads
// as the tab that is moving. Set and cleared by ICoreTabDragController.
void setDragSource(bool isSource);
// Re-reads the hover state from where the pointer actually is now. A drag
// ends with no crossing event at all -- the press grabbed the pointer, and
// the header may end the gesture in another window -- so the controller
// asks for this once the drop has settled.
void syncHoverWithPointer();
void resetToInitialState(ICoreTab* associatedTab, ICoreNativeWidget* parent = nullptr);
void kill();
void setAlive();
bool isAlive() const;
~ICoreTabHeader() override;
protected:
void pointerEntered() override;
void pointerLeft() override;
void paintContent(ICorePainter& p) override;
// The close button's LEAVE, watched through watchPointerCrossingsOf. The
// parameter is ICoreAnyWidget (= QWidget) rather than ICoreWidget for
// exactly this site: closeButton is an ICoreButton, which derives
// QPushButton, so an ICoreWidget* parameter would not even accept it — the
// watch would have been silently unusable here. P5.1 widened it for this.
void watchedPointerLeft(ICoreNativeWidget* watched) override;
// A left press arms the tab drag; moves and the release are HINTS to
// ICoreTabDragController, which owns the gesture and does not depend on
// either arriving (`W10.123`).
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;
};
ICoreCanvas.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/ICoreCanvas.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.
ICoreCanvas#
ICoreCanvas.h:29 · class · bases public ICoreGraphicsObject · pImpl · 50 declaration(s)
class ICoreCanvas : public ICoreGraphicsObject {
public:
explicit ICoreCanvas(ICoreTab* parentTab);
ICoreRect contentBounds() const override;
void paintContent(ICorePainter& painter) override;
void reconstructDescendents();
void freeAllCanvasChildren() const;
void setLoadedTreeNode(ICoreSubsystemTreeNode* nodeToLoad);
// Driven by ICoreCanvasParent's hooks, so these take the ICore event rather
// than the toolkit's -- the view no longer has a QMouseEvent to hand on
// once it is on ICoreGraphicsView's hook surface (P2.11b). Same shape
// ICoreLinkBranchSegmentMover's identically-named trio already used.
//
// Still void: the accept()/ignore() calls these used to make were already
// dead, because ICoreCanvasParent::mousePressEvent overwrote the flag on
// the very next line and then ran the base handler regardless.
void handleMousePress(const ICoreMouseEvent& event);
void handleMouseMove(const ICoreMouseEvent& event);
void handleMouseRelease(const ICoreMouseEvent& event);
ICoreRect getUsedCanvasArea() const;
// The canvas is unbounded and never moves what is on it. What the view may
// scroll over is the scene rect: the used area plus
// the panning margin or one viewport, whichever is larger, united with what
// is on screen -- so setting it never moves the view. Call
// updateScrollExtent() when a gesture ends or the diagram changed size.
ICoreRect scrollExtentFor(double zoom) const;
void updateScrollExtent();
void widenScrollExtentForZoom(double newZoom);
// Zoom to `zoom` (clamped to the user's range) with `centre` in the middle.
void showSceneAt(double zoom, const ICorePoint& centre);
// Fits the diagram into the view (never above 100 %) and centres it; an
// empty one is shown at 100 % with the origin anchor at the bottom-left.
// Before the view is laid out it is deferred to viewResized().
void resetCanvasPanAndZoom_Core();
// A tab keeps its own zoom and pan: the canvas parent remembers the
// outgoing canvas's view, and focusing its tab restores it.
void rememberView();
bool restoreRememberedView();
// ICoreCanvasParent::resized() -> runs a deferred reset, else refreshes
// the scroll extent for the new viewport.
void viewResized();
void assignChildrenZOrder();
void resetCanvasPanAndZoom();
void setLoadedCanvasParent(ICoreCanvasParent* newCanvasParent);
void selectObjectsInRectangle(const ICoreRect& rectangle, bool clearAllSelectionBefore = true) const;
void ensureAllChildrenAreLoadedToParentScene();
ICoreTab* getParentTab() const;
ICoreSubsystemTreeNode* getLoadedTreeNode() const;
ICoreCanvasParent* getLoadedToCanvasParent() const;
std::string getClassID() const;
ICoreCanvasSelectionRectangle* getSelectionRectangle() const;
ICoreCanvasObjectMover* getObjectMover() const;
ICoreCanvasSelectionModel* getObjectSelector() const;
ICoreCanvasObjectMover* getCanvasObjectMover() const;
ICoreCanvasAlignmentGuide* getAlignmentGuide() const;
ICoreCanvasConnectHints* getConnectHints() const;
ICoreCanvasAutoInserter* getAutoInserter() const;
ICoreMenu* getContextMenu() const;
ICoreCanvasFloatingObjectsParent* getFloatingObjectsParent() const;
ICorePoint getPosInCanvas(ICoreNativeItem* grandChild);
void resetToInitialState(ICoreTab* parentTab);
void kill();
void setAlive();
bool isAlive() const;
~ICoreCanvas() override;
protected:
bool mousePressed(const ICoreMouseEvent& event) override;
bool mouseMoved(const ICoreMouseEvent& event) override;
bool mouseReleased(const ICoreMouseEvent& event) override;
bool mouseDoubleClicked(const ICoreMouseEvent& event) override;
bool contextMenuRequested(const ICoreMouseEvent& event) override;
bool dragEntered(const ICoreDragEvent& event) override;
bool dragMovedOver(const ICoreDragEvent& event) override;
bool payloadDropped(const ICoreDragEvent& event) override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasFloatingObjectsParent.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/ICoreCanvasFloatingObjectsParent.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.
ICoreCanvasFloatingObjectsParent#
ICoreCanvasFloatingObjectsParent.h:10 · class · bases public ICoreGraphicsObject · pImpl · 6 declaration(s)
class ICoreCanvasFloatingObjectsParent : public ICoreGraphicsObject {
public:
explicit ICoreCanvasFloatingObjectsParent(ICoreGraphicsObject* parent);
ICoreRect contentBounds() const override;
void paintContent(ICorePainter& painter) override;
void setZValue_Public(const int& newZValue);
void reset();
~ICoreCanvasFloatingObjectsParent() override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasObjectMover.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/ICoreCanvasObjectMover.h
ICoreCanvasObjectMover#
ICoreCanvasObjectMover.h:11 · class · pImpl · 4 declaration(s)
class ICoreCanvasObjectMover {
public:
explicit ICoreCanvasObjectMover(ICoreCanvas* parentCanvas, ICoreCanvasSelectionModel* objectSelector);
void translateSelectedObjects(const void* movingObject, ICorePoint offset) const;
void resetToInitialState(ICoreCanvas* parentCanvas, ICoreCanvasSelectionModel* objectSelector);
~ICoreCanvasObjectMover();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasSelectionModel.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/ICoreCanvasSelectionModel.h
"Is this an ADDITIVE click?" -- Ctrl on Windows/Linux, Meta on macOS.
Started file-local to ICoreCanvasSelectionModel.cpp, where it replaced twelve hand-written copies of the same test. It is declared here now because ICoreCanvasSelectionRectangle's five scan helpers ask the same question of the same event and had their own five copies -- so the platform rule lives in exactly one place for both halves of selection. Free function rather than a static member: it is about the EVENT, not about the model.
ICoreCanvasSelectionModel#
ICoreCanvasSelectionModel.h:30 · class · pImpl · 47 declaration(s)
class ICoreCanvasSelectionModel {
public:
explicit ICoreCanvasSelectionModel();
void clearAllSelections();
void selectAllTreeNodeChildren(ICoreSubsystemTreeNode* ICoreSubsystemTreeNode);
void handleVariablesSpaceSelection_Pressed(ICoreVariablesSpace* variablesSpace, const ICoreMouseEvent& event);
void handleBlockSelection_Pressed(ICoreBlock* block, const ICoreMouseEvent& event);
void handleLinkBranchSelection_Pressed(ICoreLinkBranch* linkBranch, const ICoreMouseEvent& event);
void handleCanvasAreaSelection_Pressed(ICoreCanvasArea* CanvasArea, const ICoreMouseEvent& event);
void handleTextBoxSelection_Pressed(ICoreCanvasTextBox* textbox, const ICoreMouseEvent& event);
void handleImageSelection_Pressed(ICoreImage* image, const ICoreMouseEvent& event);
void handleVariablesSpaceSelection_Released(ICoreVariablesSpace* variablesSpace, const ICoreMouseEvent& event);
void handleBlockSelection_Released(ICoreBlock* block, const ICoreMouseEvent& event);
void handleLinkBranchSelection_Released(ICoreLinkBranch* linkBranch, const ICoreMouseEvent& event);
void handleCanvasAreaSelection_Released(ICoreCanvasArea* CanvasArea, const ICoreMouseEvent& event);
void handleTextBoxSelection_Released(ICoreCanvasTextBox* textbox, const ICoreMouseEvent& event);
void handleImageSelection_Released(ICoreImage* image, const ICoreMouseEvent& event);
// Each returns false without selecting anything when `object`'s parent tree
// node isn't the current selection's parent (a selection may only ever hold
// siblings — see acceptsParent); true otherwise (including when the object
// was already selected).
bool selectionAPI_VariablesSpace(ICoreVariablesSpace* variablesSpace);
bool selectionAPI_Block(ICoreBlock* block);
bool selectionAPI_EntireLink(const ICoreLink* link);
bool selectionAPI_LinkBranch(ICoreLinkBranch* linkBranch);
bool selectionAPI_CanvasArea(ICoreCanvasArea* area);
bool selectionAPI_Note(ICoreCanvasTextBox* note);
bool selectionAPI_Image(ICoreImage* image);
void deSelectionAPI_VariablesSpace(ICoreVariablesSpace* variablesSpace);
void deSelectionAPI_Block(ICoreBlock* block);
void deSelectionAPI_LinkBranch(ICoreLinkBranch* linkBranch);
void deSelectionAPI_CanvasArea(ICoreCanvasArea* area);
void deSelectionAPI_Note(ICoreCanvasTextBox* note);
void deSelectionAPI_Image(ICoreImage* block);
ICoreVariablesSpace* getSelectedVariablesSpace() const;
std::vector<ICoreBlock*> getSelectedBlocks();
std::vector<ICoreLinkBranch*> getSelectedLinkBranches();
std::vector<ICoreCanvasArea*> getSelectedCanvasAreas();
std::vector<ICoreCanvasTextBox*> getSelectedTextBoxes();
std::vector<ICoreImage*> getSelectedImages();
bool containsBlock(const ICoreBlock* block);
bool containsLinkBranch(const ICoreLinkBranch* branch);
bool containsCanvasArea(const ICoreCanvasArea* area);
bool containsTextBox(const ICoreCanvasTextBox* note);
bool containsImage(const ICoreImage* image);
ICoreRect getSelectionBoundingRect() const;
bool isEmpty() const;
bool isEmptyExceptForLinks() const;
void resetToInitialState();
void kill();
void setAlive();
bool isAlive() const;
~ICoreCanvasSelectionModel();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasSelectionRectangle.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/ICoreCanvasSelectionRectangle.h
ICoreCanvasSelectionRectangle#
ICoreCanvasSelectionRectangle.h:16 · class · bases public ICoreGraphicsRect · pImpl · 6 declaration(s)
class ICoreCanvasSelectionRectangle : public ICoreGraphicsRect {
public:
explicit ICoreCanvasSelectionRectangle(ICoreCanvas* grandParentCanvas = nullptr, ICoreCanvasSelectionModel* parentSelector = nullptr);
void start(const ICorePoint& pos);
void updateRect(const ICorePoint& pos, const ICoreMouseEvent& event);
void stop();
void resetToInitialState(ICoreCanvas* grandParentCanvas = nullptr, ICoreCanvasSelectionModel* parentSelector = nullptr);
~ICoreCanvasSelectionRectangle() override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasAlignmentGuide.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/AlignmentGuides/ICoreCanvasAlignmentGuide.h
ICoreCanvasAlignmentGuide#
ICoreCanvasAlignmentGuide.h:26 · class · pImpl · 8 declaration(s)
A canvas's snapping: one per canvas, asked once per pointer move by whatever is being dragged.
class ICoreCanvasAlignmentGuide {
public:
explicit ICoreCanvasAlignmentGuide(ICoreCanvas* parentCanvas = nullptr);
// A block drag. `candidate` is the dragged block's bounds, in canvas
// coordinates, where the pointer alone puts it; `moving` is every block
// travelling with it, none of which is caught on. Draws what caught it and
// returns the offset to add to the pointer's position: zero on an axis
// nothing caught, and never longer than the catch distance on either.
ICorePoint snapBlockMove(const ICoreRect& candidate, const std::vector<ICoreBlock*>& moving);
// A resize anchor's centre, where the pointer puts it, against the corners
// of every block but those in `moving`. Same answer, centres only.
ICorePoint snapResizeAnchor(const ICorePoint& candidate, const std::vector<ICoreBlock*>& moving);
// Takes every guide off the canvas: the end of a gesture, and the start of
// the next one.
void hideGuides();
// What is drawn now -- the last snap's answer, or nothing after
// hideGuides(). For tests and tools; the canvas never reads it back.
const ICoreCanvasSnapResult& shownSnap() const;
void setParentItem(ICoreCanvas* newGraphicsParent) const;
void resetToInitialState(ICoreCanvas* parentCanvas = nullptr);
~ICoreCanvasAlignmentGuide();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasGuideLine.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/AlignmentGuides/ICoreCanvasGuideLine.h
ICoreCanvasGuideLine#
ICoreCanvasGuideLine.h:20 · class · final · bases public ICoreGraphicsObject · pImpl · 5 declaration(s)
One dashed stroke of a snapping guide, drawn on the canvas above every diagram object.
class ICoreCanvasGuideLine final : public ICoreGraphicsObject {
public:
// Centre: a centre lined up with another. Spacing: a stroke of a gap marker.
enum class Style { Centre, Spacing };
ICoreCanvasGuideLine(ICoreCanvas* parentCanvas, Style style);
ICoreRect contentBounds() const override;
void paintContent(ICorePainter& painter) override;
// Shows the stroke from `start` to `end`, in canvas coordinates. Hidden
// with hide(); a hidden line is not painted and holds no stale geometry.
void showBetween(const ICorePoint& start, const ICorePoint& end);
~ICoreCanvasGuideLine() override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasSnapEngine.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/AlignmentGuides/ICoreCanvasSnapEngine.h
The geometry of canvas snapping and nothing else: no canvas, no block, no guide item. A drag asks it one question -- "the pointer puts the moving object HERE; how far should it move, and what should be drawn?" -- and the answer depends on that question alone.
⚠ STATELESS ON PURPOSE. The scan this replaced kept flags and neighbour pointers on the canvas between two moves, and read the dragged block's position from the PREVIOUS move instead of the pointer's: a flag set by one move and read by a later one is how a block between two neighbours snapped to a gap between blocks that had stopped being its neighbours. Nothing here outlives the call.
The rules, per axis and independently on x and y:
- Every target within
reachoffers what it can catch: its CENTRE; and,
ICoreCanvasSnapLine#
ICoreCanvasSnapEngine.h:37 · struct · 0 declaration(s)
One centre guide, at the snapped position: from the centre caught on to the moving object's centre.
struct ICoreCanvasSnapLine {
public:
ICorePoint from;
ICorePoint to;
};
};
ICoreCanvasSnapGap#
ICoreCanvasSnapEngine.h:44 · struct · 0 declaration(s)
One gap to draw, at the snapped position.
struct ICoreCanvasSnapGap {
public:
ICoreRect before;
ICoreRect after;
bool vertical = false;
};
};
ICoreCanvasSnapQuery#
ICoreCanvasSnapEngine.h:50 · struct · 0 declaration(s)
struct ICoreCanvasSnapQuery {
public:
// Where the pointer alone would put the moving object.
ICoreRect moving;
// What it may catch on. The moving object itself must not be among them.
std::vector<ICoreRect> targets;
// The furthest a snap may move the object, per axis, in canvas units.
double catchDistance = 20;
// Targets whose centre is further than this on either axis offer nothing.
double reach = 3000;
// False: centres only -- for a point, where middles and gaps mean nothing.
bool spacing = true;
// How many facing neighbours on each side a gap may be taken from, nearest
// first. At least one.
int neighbours = 3;
};
};
ICoreCanvasSnapResult#
ICoreCanvasSnapEngine.h:66 · struct · 0 declaration(s)
struct ICoreCanvasSnapResult {
public:
// Add to the position the pointer gave. Zero on an axis nothing caught.
ICorePoint offset;
bool caughtX = false;
bool caughtY = false;
std::vector<ICoreCanvasSnapLine> lines;
std::vector<ICoreCanvasSnapGap> gaps;
};
};
ICoreCanvasSpacingGuide.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/AlignmentGuides/ICoreCanvasSpacingGuide.h
ICoreCanvasSpacingGuide#
ICoreCanvasSpacingGuide.h:14 · class · pImpl · 6 declaration(s)
The marker for one gap between two rectangles: a dimension line with an arrowhead at each end, set off from the rectangles, and an extension line from each rectangle's own edge to it.
class ICoreCanvasSpacingGuide {
public:
explicit ICoreCanvasSpacingGuide(ICoreCanvas* parentCanvas);
// The gap between `before` and `after`: along x with `before` on the left,
// or along y (`vertical`) with `before` above.
void show(const ICoreRect& before, const ICoreRect& after, bool vertical) const;
void hide() const;
void setParentItem(ICoreCanvas* newGraphicsParent) const;
void setZValue(double z) const;
~ICoreCanvasSpacingGuide();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasAutoInserter.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/AutoInserter/ICoreCanvasAutoInserter.h
ICoreCanvasAutoInserterList#
ICoreCanvasAutoInserter.h:24 · class · final · bases public ICoreGraphicsObject · pImpl · 4 declaration(s)
Lightweight, non-painting host for the scrollable button column.
class ICoreCanvasAutoInserterList final : public ICoreGraphicsObject {
public:
explicit ICoreCanvasAutoInserterList(ICoreGraphicsObject* parent = nullptr);
// Declared, defined in the .cpp: the residue below is a unique_ptr to an
// Impl this header cannot see.
~ICoreCanvasAutoInserterList() override;
ICoreRect contentBounds() const override;
// No paint override at all, and the empty paint() this replaced is NOT
// missing: ICoreGraphicsObject::paint() draws its rounded fill and border
// from m_fillColor/m_borderColor, both of which default to transparent and
// which this class never sets. So the base draws two invisible shapes where
// the old override drew nothing -- identical pixels, and the container gets
// its look from its children regardless.
void setSize(double width, double height);
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasAutoInserter#
ICoreCanvasAutoInserter.h:57 · class · final · bases public ICoreGraphicsObject · pImpl · 21 declaration(s)
The double-click popup that drops a block where the pointer is.
class ICoreCanvasAutoInserter final : public ICoreGraphicsObject {
public:
explicit ICoreCanvasAutoInserter(ICoreGraphicsObject *parent = nullptr, ICoreCanvas* parentCanvas = nullptr);
ICoreRect contentBounds() const override;
void paintContent(ICorePainter& painter) override;
void reconstructDescendents();
// Filters the whole library by the given query and repopulates the panel with the
// matches, best first. An empty query restores the starter blocks.
void runSearch(const ICoreString& query);
// Forwards a wheel delta to the scrollable list (same units the canvas
// passes to the variables-space / config panels: angleDelta().y()).
void triggerScroll(double scrollDelta);
// True when the inserter is showing and the given scene point falls inside
// it, so the canvas can route wheel scrolling here instead of zooming.
bool isUnderCursor(const ICorePoint& scenePos) const;
void showAtPos(ICorePoint posToShowAt);
void hide();
void setPosX(double newPosX);
void setPosY(double newPosY);
void setPos(double newPosX, double newPosY);
void setWidth(double width) override;
void setHeight(double height);
double getPosX() const;
double getPosY() const;
ICorePoint getPos() const;
double getWidth() const;
double getHeight() const;
~ICoreCanvasAutoInserter() override;
protected:
// The search bar's field holds the keyboard for as long as the panel is open, so
// the keys that drive the result list (Up/Down/Enter/Escape) are caught on their
// way to it — the same arrangement ICoreGlobalSearchDialog has with its anchor.
// watchedKeyPressed, not an eventFilter override: that is a QObject service,
// and this class stopped being one at P2.9d-5e (the facade's Impl is the
// filter; watchKeyPressesOf in the constructor is the registration).
bool watchedKeyPressed(const ICoreKeyEvent& event) override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasAutoInserterBlockButton.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/AutoInserter/ICoreCanvasAutoInserterBlockButton.h
ICoreCanvasAutoInserterBlockButton#
ICoreCanvasAutoInserterBlockButton.h:17 · class · bases public ICoreGraphicsButton · pImpl · 9 declaration(s)
One row of the auto-inserter panel: the block's library icon on the left, its leaf name as the title, and the "Grand Family / Family" trail it lives under dimmed on the right — so two blocks with t...
class ICoreCanvasAutoInserterBlockButton : public ICoreGraphicsButton {
public:
explicit ICoreCanvasAutoInserterBlockButton(ICoreGraphicsObject* parent = nullptr,
ICoreCanvas* grandParentCanvas = nullptr,
const ICoreString& blockFullType = "");
// Dresses the row for a library type ("Grand_Family/Family/Block_Name"): title,
// trail and icon all come from the type itself.
void setBlockToInsertType(const std::string& type);
// The row width has to travel through here rather than through the base
// setWidth(), which is not virtual and knows nothing about the right-aligned trail.
void setRowWidth(double width);
// Creates the block on the parent canvas at the panel's position, then closes the
// panel. Shared by a click on the row and by the panel's Enter key.
void insertBlock();
// The row Enter would insert, dressed the way a selected row is dressed in the
// Search Everywhere panel: filled with the accent, text flipped to read on it.
void setSelected(bool selected);
// Re-parents what this row owns on top of the base button's own label. Hides the
// (non-virtual) base method deliberately: every call site holds a row pointer.
void reconstructDescendents();
[[nodiscard]] const std::string& getBlockTypeToInsert() const;
~ICoreCanvasAutoInserterBlockButton() override;
protected:
bool mousePressed(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;
};
ICoreCanvasScanner.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/CanvasListener/ICoreCanvasScanner.h
ICoreCanvasScanner#
ICoreCanvasScanner.h:17 · class · 13 declaration(s)
class ICoreCanvasScanner {
public:
static std::optional<ICoreBlock*> getBlockUnderCursor(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static std::optional<ICorePort*> getPortUnderCursor(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static std::optional<ICoreLinkBranchTailPane*> getLinkTailPaneUnderCursor(const ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static std::optional<ICoreLinkBranchHeadPane*> getLinkHeadPaneUnderCursor(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static std::optional<ICoreLinkBranchSegment*> getLinkSegmentUnderCursor(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static std::optional<ICoreCanvasArea*> getCanvasAreaRigidComponentsUnderCursor(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static std::optional<ICoreImage*> getImageUnderCursor(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static std::optional<ICoreCanvasTextBox*> getTextBoxUnderCursor(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static bool isVariablesSpaceUnderCursor(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static ICoreBlock* getBlockConfigUnderCursor(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static ICoreBlock* getBlockConfigUnderCursor_ConfigPanel(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static ICoreBlock* getBlockConfigUnderCursor_DescriptionPanel(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint);
static bool isUnderCursorEmpty(ICoreSubsystemTreeNode* loadedNodeOnCanvas, ICorePoint targetPoint) ;
};
};
ICoreCanvasObjectsRoot.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/CanvasObjectsRoot/ICoreCanvasObjectsRoot.h
The Q_PROPERTY(width)/Q_PROPERTY(height) pair that stood here is GONE (P2.9d-5d): the shrink/expand animations drive setWidth()/setHeight() through ICoreValueAnimation::onValueChanged now, so nothing resolves either name through the metaobject. The Q_OBJECT that outlived them 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.
ICoreCanvasObjectsRoot#
ICoreCanvasObjectsRoot.h:20 · class · bases public ICoreGraphicsObject · pImpl · 49 declaration(s)
class ICoreCanvasObjectsRoot : public ICoreGraphicsObject {
public:
// Which shadow a root carries, decided once at construction because the two
// answers follow different user preferences.
//
// CanvasItem -- canvas CONTENT (blocks, text boxes, images, areas).
// Follows Canvas Items Shadows, which is off by default:
// one effect per diagram item is the most expensive thing
// a large diagram can carry.
// FloatingPanel -- a panel that sits OVER the canvas: the block
// configuration overlay and its two dialogs. Follows the
// floating-panel preference and casts the same shadow the
// canvas context menu casts.
//
// A root gets ONE of the two. They both drive the item's single graphics
// effect, so a root that followed both would have each preference deleting
// the other's shadow.
enum class ShadowPolicy { CanvasItem, FloatingPanel };
explicit ICoreCanvasObjectsRoot(ICoreGraphicsObject *parent = nullptr, bool resizable = true,
ShadowPolicy shadowPolicy = ShadowPolicy::CanvasItem);
ICoreRect contentBounds() const override;
void paintContent(ICorePainter& painter) override;
void recenterTransformOrigin();
// Recenter the transform origin after a size change, compensating the position
// so a rotated object's visual center stays put (otherwise moving the rotation
// center makes the object jump). Shared by the resizer anchors and the recipe
// resize command.
void recenterTransformOriginKeepingCenter();
virtual void reconstructDescendents();
void setPosX(double newPosX);
void setPosY(double newPosY);
virtual void setPos(double newPosX, double newPosY);
virtual void setWidth(double width) override;
virtual void setHeight(double height);
void setFillColor(ICoreColor newColor);
void setBorderColor(ICoreColor newColor);
ICorePoint centerInParent() const;
ICoreRect boundsInParent() const;
double getWidth() const;
double getHeight() const;
double width() const;
double height() const;
void setMinResizerHeight(const double& newMinHeight);
void disableLeftTopResizing() const;
void disableRightTopResizing() const;
void disableLeftBottomResizing() const;
std::vector<ICoreCanvasObjectsRootResizerAnchor*> getResizerAnchors() const;
ICoreCanvasObjectsRootResizer *getResizer() const;
void cacheSize();
void removeSelectionStyle();
virtual void setSelectionStyle();
virtual void updateAllMouseListenersValues();
void setAllowMouseListenerUpdates(bool newAllowMouse);
virtual void updateAllChildrenPositions();
void animateContentShrinking(bool deleteAfterFinish = false);
void animateContentExpanding();
void setCachedHeight(double newHeight);
void setCachedWidth(double newWidth);
double getCachedHeight() const;
double getCachedWidth() const;
// [[nodiscard]] ICoreCanvasObjectsRootResizer* getResizer() const; Careful this could return nullptr. Not used so far!
ICoreRect getBoundsInCanvas() const;
void offsetPosition(ICorePoint offset);
bool isPinnedToCanvas() const;
void setIsPinnedToCanvas(const bool& newIsPinned);
bool areMouseListenerUpdatesAllowed() const;
virtual bool isMouseOverRigidElements();
bool getAllowMouseListenerUpdates() const;
// ---------------------------------------------------------------------
// Hover affordances -- the controls a root REVEALS while the pointer is on
// it and puts away afterwards: the resize anchors (this class's own), and
// whatever a subclass adds (ICoreBlockView's rotater and config button,
// ICoreCanvasAreaView's tool bar).
//
// ⚠⚠ REGISTERED RATHER THAN OVERRIDDEN, AND THAT IS A DELIBERATE CHOICE
// OVER A PAIR OF NEW VIRTUALS. A virtual added to a polymorphic base
// changes the vtable for it and every descendant while moving NO mangled
// name, so a build that straddles the change links perfectly and crashes at
// runtime -- the hazard every layout-changing edit carries,
// and the same reasoning `icoreApplyStyleSpec` records where it reached for
// a dynamic_cast instead. A std::function member costs nothing a reader has
// to know about and cannot do that.
//
// `revealed` is true when the pointer arrives and false when the grace
// period below expires. A subclass registers ONCE, in its constructor.
void addHoverAffordance(std::function<void(bool revealed)> apply);
// Put them away this instant, skipping the grace period below. For the one
// shape the grace period cannot serve: the canvas is about to stop showing
// this root at all (ICoreBlockViewFrame's double click loads the block's
// subsystem into the tab), so there is no "pointer moves away" to wait for
// -- the pointer stays exactly where it is and the thing under it changes.
void concealHoverAffordancesNow();
// ⚠ THE REVEAL IS IMMEDIATE AND THE CONCEAL IS NOT, WHICH IS THE WHOLE
// POINT OF THE PAIR. Owner instruction (A10.20): *"the show event is fine
// without this margin, just the hide needs an update"*. Hiding on the
// crossing itself makes the affordances unreachable -- a pointer travelling
// to the rotater above a block leaves the block before it arrives at the
// rotater, and the rotater goes away underneath it. The conceal therefore
// waits until the pointer is genuinely AWAY: this many points outside the
// root's own scene rectangle, measured from the rectangle's edge and not
// from its centre.
//
// ⚠ 30, AND THE OWNER'S FIRST NUMBER WAS 20. Raised on his instruction
// mid-implementation (*"at task 6, increase the distance from 20px to
// 30px"*) -- it is a feel number, it is his to set, and it is here rather
// than at the three sites that used to hide things so that there is one
// place to set it next time.
static constexpr double kHoverConcealMarginPx = 30.0;
void resetToInitialState_CanvasObjectsRoot(ICoreNativeItem* parent = nullptr, bool resizable = true);
~ICoreCanvasObjectsRoot() override;
protected:
void pointerEntered(const ICoreMouseEvent& event) override;
void pointerLeft() override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasObjectsRootResizer.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/CanvasObjectsRoot/ICoreCanvasObjectsRootResizer.h
ICoreCanvasObjectsRootResizer#
ICoreCanvasObjectsRootResizer.h:11 · class · pImpl · 15 declaration(s)
class ICoreCanvasObjectsRootResizer {
public:
explicit ICoreCanvasObjectsRootResizer(ICoreCanvasObjectsRoot* canvasObjectsRoot);
void showAnchors() const;
void hideAnchors() const;
void updateAllAnchorsPos() const;
void moveAnchor(ICoreCanvasObjectsRootResizerAnchor* anchor, ICorePoint newFocusedAnchorPos, ICorePoint oppositeAnchorNewPos) const;
ICorePoint getOppositeCornerCenter(ICoreCanvasObjectsRootResizerAnchor* focusedAnchor) const;
void setParentItem(ICoreCanvasObjectsRoot* newGraphicsParent) const;
void setMinimumWidth(const double& newMinWidth);
void setMinimumHeight(const double& newMinHeight);
ICoreCanvasObjectsRootResizerAnchor* getLeftTopAnchor() const;
ICoreCanvasObjectsRootResizerAnchor* getLeftBottomAnchor() const;
ICoreCanvasObjectsRootResizerAnchor* getRightTopAnchor() const;
ICoreCanvasObjectsRootResizerAnchor* getRightBottomAnchor() const;
void resetToInitialState(ICoreCanvasObjectsRoot* canvasObjectsRoot);
~ICoreCanvasObjectsRootResizer();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasObjectsRootResizerAnchor.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/CanvasObjectsRoot/ICoreCanvasObjectsRootResizerAnchor.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.
ICoreCanvasObjectsRootResizerAnchor#
ICoreCanvasObjectsRootResizerAnchor.h:18 · class · bases public ICoreGraphicsObject · pImpl · 19 declaration(s)
class ICoreCanvasObjectsRootResizerAnchor : public ICoreGraphicsObject {
public:
explicit ICoreCanvasObjectsRootResizerAnchor(ICoreCanvasObjectsRootResizer* parent, ICoreCanvasObjectsRoot *grandParentTextBoxUI = nullptr, int xDir = 1, int yDir = 1);
ICoreRect contentBounds() const override;
void paintContent(ICorePainter& painter) override;
ICorePoint getAnchorCenterRespectToBlockCenter() const;
void updatePosition();
ICorePoint alignmentGuideManager(const ICorePoint& refPoint) const;
void setEnabled(const bool newVal);
bool isEnabled() const;
// Fade this anchor's opacity, through an owned restarted animation
// (P2.9d-5d). The resizer used to drive all four anchors' `opacity`
// property by name through one Parallel group; the fade lives on the
// anchor now, and the resizer just calls each enabled one.
void animateOpacity(double startOpacity, double endOpacity);
ICorePoint getAnchorCenterRespectToAreaCenter() const;
ICorePoint getCenterInGrandParent() const;
int getXDir() const;
int getYDir() const;
~ICoreCanvasObjectsRootResizerAnchor() override;
protected:
// Hover events
void pointerEntered(const ICoreMouseEvent& event) override;
void pointerLeft() override;
// Mouse events
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;
};
ICoreCanvasConnectHints.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/ConnectHints/ICoreCanvasConnectHints.h
ICoreCanvasConnectHints#
ICoreCanvasConnectHints.h:39 · class · final · bases public ICoreGraphicsObject · pImpl · nested Verdict · 11 declaration(s)
While the user holds a link end, everything on the canvas the end could land on says whether it would: a target the wire would snap to glows, every other one wears a "no entry" mark.
class ICoreCanvasConnectHints final : public ICoreGraphicsObject {
public:
// One marked target. `branch` is the branch whose segments, or whose
// dangling end, is marked; `port` is set for a port and nothing else.
struct Verdict {
enum class Target { Port, Segments, HeadPane, TailPane };
Target target = Target::Port;
const ICorePort* port = nullptr;
const ICoreLinkBranch* branch = nullptr;
bool takes = false;
};
explicit ICoreCanvasConnectHints(ICoreCanvas* parentCanvas = nullptr);
// A HEAD is being dragged, and `sourceTypeId` is what drives the branch
// (empty when nothing does yet). `anchoredAt` is the port the wire stays
// fixed to and `dragged` the branch in the user's hand; neither is marked.
// Takes the hints off any other canvas first: one gesture at a time.
static void headDragStarted(ICoreSubsystemTreeNode* node, const std::string& sourceTypeId,
const ICorePort* anchoredAt, const ICoreLinkBranch* dragged);
// A TAIL is being dragged, and `headPort` is the end that must accept
// the candidate source (null when the branch has no head yet).
static void tailDragStarted(ICoreSubsystemTreeNode* node, const ICorePort* headPort,
const ICorePort* anchoredAt, const ICoreLinkBranch* dragged);
// Takes the marks off whichever canvas shows them. Every drag's release
// calls it, and so does every move that ends the drag early by connecting
// it -- a tail pane that commits in its move handler, or a merge, may
// never see its release.
static void dragEnded();
// The port the wire is snapped to on this move, or null for none. Each
// handler reports it where its port scan settles, every move; that port's
// mark is drawn CAUGHT -- locked on -- rather than merely available. Only
// a repaint when it changes, and nothing while no marks are shown.
static void setCaught(const ICorePort* port);
ICoreRect contentBounds() const override;
// Empty: nothing on this item is ever hit.
ICorePainterPath contentShape() const override;
void paintContent(ICorePainter& painter) override;
void hideHints();
// What is marked now; empty after dragEnded(). For tests and tools; the
// canvas never reads it back.
std::vector<Verdict> shownVerdicts() const;
// The port drawn caught now, or null. For tests and tools, as above.
const ICorePort* caughtPort() const;
void resetToInitialState(ICoreCanvas* parentCanvas = nullptr);
~ICoreCanvasConnectHints() override;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreCanvasPrinter.h#
src/ICoreBlocks/ICoreStudio/StudioObjects/StudioSurface/Tab/Canvas/Printing/ICoreCanvasPrinter.h
ICoreCanvasPrinter#
ICoreCanvasPrinter.h:34 · class · 5 declaration(s)
Putting a canvas on paper.
class ICoreCanvasPrinter {
public:
// Which theme the page is drawn in, independent of the one on screen. Light
// is the default because paper is white and the Dark theme on paper is a
// sheet of toner -- but a page bound for a screen or a dark slide deck
// wants the diagram as the editor shows it, so it is the user's call.
//
// Session-lived, like the signal-type and block-name modes this toolbar
// already carries: it is a property of the print about to be made, not of
// the project.
enum class PageTheme { Light, Dark };
static void setPageTheme(const PageTheme& newPageTheme);
static PageTheme getPageTheme();
// Opens the platform print panel for `canvas` and prints what comes back.
// Cancelling is silent -- it is not a failure.
static void printCanvas(ICoreCanvas* canvas, ICoreNativeWidget* dialogParent);
// Asks for a path, then writes that same page there as a PDF.
static void exportCanvasAsPDF(ICoreCanvas* canvas, ICoreNativeWidget* dialogParent);
// The PDF write on its own, for callers that already have a path.
static bool writePDF(ICoreCanvas* canvas, const ICoreString& filePath);
};
};