API — ICoreEssentials/UI/Backends/WinUI/Graphics
The public contract of 7 header(s) under ICoreEssentials/UI/Backends/WinUI/Graphics — 9 class/struct definition(s), 41 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.
ICoreWinUIItemAccess.h#
ICoreEssentials/UI/Backends/WinUI/Graphics/ICoreWinUIItemAccess.h
Backend-internal access to the three things an item does NOT publish: the scene it is in, which node of that scene it is, and how a ROOT item is put into one.
⚠ NOTHING ABOVE THE BACKEND ZONE MAY INCLUDE THIS. The peers are Painting/ICoreWinUIPaintAccess.h, Painting/ICoreWinUIPathAccess.h and Values/ICoreWinUIFontAccess.h, and the argument is the same each time: a seat hands its own machinery what the public surface deliberately does not.
⚠ WITHOUT THESE, AN ITEM TREE CANNOT BE DRAWN AT ALL, which is why they are part of the seat rather than a later convenience. ICoreGraphicsItem's whole public surface is about ONE item; drawing happens over a whole scene, and the object that owns the scene is reachable from any attached node and nowhere else. The view (W4.1) and the scene wrapper are the callers this exists for.
Declares no class of its own — see the file.
ICoreWinUIItemScene.h#
ICoreEssentials/UI/Backends/WinUI/Graphics/ICoreWinUIItemScene.h
The scene an ICoreGraphicsItem is painted from on this backend: one
ICoreScenefrom the portable core, plus the one thing that core deliberately does not hold -- what each item LOOKS like and how it draws itself.⚠ NOTHING ABOVE THE BACKEND ZONE MAY INCLUDE THIS. It is the peer of Painting/ICoreWinUIPaintAccess.h and Values/ICoreWinUIFontAccess.h: a seat handing its own machinery what the public surface has no verb for.
⚠ THE NODE IS AUTHORITATIVE AND THE CORE IS A PROJECTION OF IT, which is the AppKit seat's decision adopted rather than re-derived (see Backends/AppKit/Graphics/ICoreAppKitSceneNode.h, which states both candidates and why). An item that is in no scene is still fully usable --
setWidth()before the item is ever parented is what every construction site in this tree
ICoreWinUIItemVisual#
ICoreWinUIItemScene.h:47 · struct · 0 declaration(s)
What one item looks like, read from the live wrapper at draw time rather than cached.
struct ICoreWinUIItemVisual {
public:
bool hasFill = false;
int fillR = 0, fillG = 0, fillB = 0, fillA = 255;
bool hasBorder = false;
int borderR = 0, borderG = 0, borderB = 0, borderA = 255;
double borderWidth = 2.0;
double cornerRadius = 5.0;
};
};
ICoreWinUIItemScene#
ICoreWinUIItemScene.h:67 · class · pImpl · 18 declaration(s)
class ICoreWinUIItemScene {
public:
ICoreWinUIItemScene();
~ICoreWinUIItemScene();
ICoreWinUIItemScene(const ICoreWinUIItemScene&) = delete;
ICoreWinUIItemScene& operator=(const ICoreWinUIItemScene&) = delete;
ICoreScene& scene();
const ICoreScene& scene() const;
// Attach the appearance and the content hook to an id already in the scene.
// Re-binding the same id replaces both.
void bind(const ICoreSceneItemId& id,
ICoreWinUIItemVisualFn visual,
ICoreWinUIItemContentFn content);
// Record which NODE an id is, so a hit test can be turned back into the
// wrapper whose hooks answer for it.
//
// ⚠ SEPARATE FROM bind(), AND CALLED EARLIER. A node is registered by
// ICoreWinUISceneNode::attachTo the instant its id exists -- before
// pushAll() and before bindSelf() -- because the node is what those two
// run ON. Folding it into bind() would mean every seat's bindSelf() had to
// remember to pass `this`, which is the per-seat discipline the `tag`
// field already failed at: one of the five seated item types sets `tag`,
// and it is not the one with the event hooks.
void bindNode(const ICoreSceneItemId& id, ICoreWinUISceneNode* node);
// The node behind an id, or null -- for an id that is not in this scene,
// for a RECYCLED slot whose generation no longer matches, and for an item
// that has been unbound. All three are normal answers.
ICoreWinUISceneNode* nodeAt(const ICoreSceneItemId& id) const;
// The XAML element an item wants placed OVER the painted scene, or null
// for the ordinary case. Passing null clears it.
//
// ⚠⚠ AN OVERLAY IS A REAL CONTROL AND CANNOT BE PAINTED INTO THE SCENE.
// This is what ICoreGraphicsProxyWidget carries: a live widget with the
// platform's own text editing, cursor, focus ring and automation. The other
// toolkit hands its widget to the scene, which paints it through the same
// transform as any item; there is no such transport here, so the control
// stays a real child of the VIEW's element and something has to keep its
// frame where the item would have been drawn. This is the half the scene
// knows: which id has one. The view does the placing.
//
// ⚠ THE ITEM STILL EXISTS IN THE SCENE, and that is deliberately not
// shortcut. It is a real node with a real position, size, parent and z, so
// hit-testing, the parent chain and setGeometry in the PARENT's coordinates
// all behave as they do on the other toolkit. Only the DRAWING is a child
// element. A seat that skipped the node and stored a rectangle would answer
// setParentItem and every ancestor transform wrong the moment the panel
// holding it moved -- the AppKit seat states the same and for the same
// reason.
void bindOverlay(const ICoreSceneItemId& id, ICoreWinUIWidgetElement* element);
ICoreWinUIWidgetElement* overlayAt(const ICoreSceneItemId& id) const;
// Every overlay this scene currently has bound, with the id carrying it.
//
// ⚠⚠ IT EXISTS SO A HIDE CAN BE DRIVEN FROM THE BINDINGS RATHER THAN FROM
// THE DRAW ORDER (`W10.105`, 2026-09-21). The view places overlays by
// walking `icoreSceneDrawOrder`, and that walk PRUNES invisible subtrees --
// so an overlay whose item goes invisible vanishes from the list and its
// element was simply never touched again, staying mounted and hit-testable.
// Deciding what to hide needs the set of overlays that EXIST, which is this
// map and not that walk.
//
// ⚠ THE ELEMENT COMES FROM HERE, LIVE, AND THAT IS THE POINT. The view also
// keeps a set of adopted element ADDRESSES whose own banner forbids
// dereferencing them; this hands back the pointer the binding holds now, so
// the caller never has to turn a remembered address back into an object.
void forEachOverlay(
const std::function<void(const ICoreSceneItemId&, ICoreWinUIWidgetElement*)>& visit) const;
// Whether ANY item in this scene carries one.
//
// ⚠ IT EXISTS SO THE VIEW CAN SKIP A WHOLE TRAVERSAL, which is the common
// case: placing overlays needs the draw order in VIEW coordinates, and
// building it is a second walk over the visible tree on top of the one the
// paint already does. There is exactly ONE proxy widget in this product, so
// almost every scene answers false here and pays nothing.
bool hasOverlays() const;
// Ask every node in this scene whether its wrapper's contentBounds() still
// agrees with the core's copy, and re-push the ones that have drifted.
//
// ⚠ THE VIEW CALLS THIS BEFORE IT READS THE STORED BOUNDS -- before a paint
// and before a hit test -- because those are the moments a stale copy is
// observable. See ICoreWinUISceneNode::reconcileBounds for WHY a copy goes
// stale at all, and why this is a pull rather than a pending list.
//
// ⚠ THE COST IS ONE VIRTUAL CALL PER BOUND ITEM PER CONSULT, which is what
// the other toolkit pays per item per paint anyway -- it asks
// boundingRect() on every one of them every frame. Nothing is pushed unless
// it actually differs, so a scene that is not changing size pays the
// comparison and no dirtying at all.
void reconcileBounds();
void unbind(const ICoreSceneItemId& id);
bool isBound(const ICoreSceneItemId& id) const;
unsigned int boundCount() const;
// Draw the whole scene back to front through the Direct2D core.
//
// Returns the number of items DRAWN. An entry with no binding is skipped
// and not counted -- an item exists in the core for the instant between
// being added and being bound, and drawing a half-registered item would be
// worse than drawing nothing.
//
// ⚠ THE PAINTER IS ASSUMED TO BE IN VIEW SPACE ON ENTRY and is left exactly
// as it was found: each command is bracketed by save()/restore(), so a
// view's pan and zoom survive the walk and no item can leak a clip or a
// transform onto the next.
int draw(ICoreWinUIPainter& painter) const;
// The same walk, skipping every item whose subtree cannot reach `exposed`
// (scene units). What a partial frame draws: the surface keeps every pixel
// outside the region, so an item that cannot touch it has nothing to add.
int draw(ICoreWinUIPainter& painter, const ICoreSceneRect& exposed) const;
// Draw one command. The unit the suite drives, and what a dirty-region walk
// calls after filtering the list itself.
bool drawCommand(const ICoreSceneDrawCommand& command,
ICoreWinUIPainter& painter) const;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
File-scope declarations#
using ICoreWinUIItemVisualFn = std::function<ICoreWinUIItemVisual()>;
// The paintContent() hook, already bound to its owner.
//
// ⚠ IT IS A THUNK AND NOT A POINTER TO THE WRAPPER, because paintContent() is
// PROTECTED. Only ICoreGraphicsItem::Impl -- a member of the class -- may call
// it, so the call has to be manufactured on that side and handed here.
using ICoreWinUIItemContentFn = std::function<void(ICorePainter&)>;
ICoreWinUISceneNode.h#
ICoreEssentials/UI/Backends/WinUI/Graphics/ICoreWinUISceneNode.h
ICoreWinUISceneEvent#
ICoreWinUISceneNode.h:96 · struct · 0 declaration(s)
struct ICoreWinUISceneEvent {
public:
ICoreWinUISceneEventKind kind = ICoreWinUISceneEventKind::Moved;
// Where it happened, in the SCENE's coordinates and in the ITEM's own.
// Both are carried because the hooks publish both, and mapping one into
// the other costs a walk up the item's transform chain that the caller has
// already paid for.
double sceneX = 0.0;
double sceneY = 0.0;
double itemX = 0.0;
double itemY = 0.0;
// The screen position, for the hook's globalPos.
//
// ⚠⚠ IT IS WINDOW-LOCAL SINCE `W10.91` (2026-09-20), WHICH IS THE SPACE
// ICoreMenu::popupAt() PLACES IN ON THIS BACKEND. The view fills it through
// ICoreGraphicsView::mapViewportToGlobal(), which adds the view's own origin
// inside the window; `screenOrigin` -- the window's origin on the DESKTOP --
// is still a separate additive term and still (0, 0) tree-wide.
//
// ⚠ THE SENTENCE THAT STOOD HERE EXPIRED ON THAT ROW: *"⚠ IT IS
// WIDGET-LOCAL TREE-WIDE TODAY, because nothing in a winui configure calls
// setScreenOrigin -- measured, and stated the same way on
// ICoreWinUIWidgetElement. Mapping through the same number as the events do
// is exactly as right as they are and AGREES with them, which is the
// property a caller needs; it also leaves ONE place to fix."* It is quoted
// rather than deleted because agreeing with the other events was precisely
// the reasoning that kept the canvas context menu opening in the wrong place
// for as long as it did: every producer agreed, and every one of them was
// short of what the CONSUMER placed in.
double globalX = 0.0;
double globalY = 0.0;
ICoreMouseButton button = ICoreMouseButton::None;
ICoreMouseButtons buttons = 0;
ICoreKeyModifiers modifiers = 0;
// Wheel travel, for WheelScrolled and zero for everything else.
double wheelDeltaY = 0.0;
// The dropped payload, for the three drag kinds and null for every other.
//
// ⚠⚠ AN OPAQUE POINTER, AND FOR THE SAME REASON THE POSITIONS ABOVE ARE
// PLAIN DOUBLES: the real type is `const ICoreMimePayload*`, and that type
// carries ICoreString and ICoreStringList, which reach Qt today. Naming it
// in this header would pull Qt into every translation unit that includes it
// -- both item seats, the scene host, the view and the proxy. The view
// points this at a payload that lives on ITS stack for the duration of the
// call, and the thunk in ICoreGraphicsObject.cpp -- which may name the type
// -- casts it back. It is never stored and never outlives the delivery.
const void* payload = nullptr;
};
};
ICoreWinUISceneEventResult#
ICoreWinUISceneNode.h:159 · struct · 0 declaration(s)
⚠ TWO BOOLS AND NOT ONE, because the wrapper's hook surface is two axes rather than three values of one return -- ICoreMouseEvent.h states the decision and names the call site it exists for.
struct ICoreWinUISceneEventResult {
public:
bool handled = false;
bool ignored = false;
};
};
ICoreWinUISceneNode#
ICoreWinUISceneNode.h:164 · struct · 19 declaration(s)
struct ICoreWinUISceneNode {
public:
// ⚠ DECLARED RATHER THAN `= default`, AND THE REASON IS IN THE .cpp: this
// node's ADDRESS is the identity `ICoreWeakObject` binds to on this
// backend, so construction and destruction have to be told to the zone's
// liveness registry. A defaulted constructor cannot say anything.
ICoreWinUISceneNode();
virtual ~ICoreWinUISceneNode();
ICoreWinUISceneNode(const ICoreWinUISceneNode&) = delete;
ICoreWinUISceneNode& operator=(const ICoreWinUISceneNode&) = delete;
// Null until the item is put into a scene, directly or by being parented
// to something already in one. NULL IS A NORMAL ANSWER, not an error.
ICoreWinUIItemScene* host = nullptr;
ICoreSceneItemId id;
// The scene TREE, which exists whether or not either end is in a scene.
ICoreWinUISceneNode* parent = nullptr;
std::vector<ICoreWinUISceneNode*> children;
// -- the operations, one implementation for every seat ------------------
// Put this node and its subtree into `newHost` under `parentNode` (null
// for a root). No-op when already attached or when the host is null.
void attachTo(ICoreWinUIItemScene* newHost, ICoreWinUISceneNode* parentNode);
// Leave the scene, this node only. Children are handled by detachSubtree.
void detachFromScene();
void detachSubtree();
// Unlink from the current parent's child list; the tree only, no scene.
void detachFromParent();
// Re-parent. Refuses self-parenting and cycles, migrates in place when
// both ends are already in the SAME scene, and otherwise detaches the
// subtree and re-attaches it under the new parent.
//
// ⚠ A NULL PARENT MAKES THIS NODE A ROOT OF ITS OWN TREE, NOT AN ITEM IN
// NO TREE -- which is what an unparented, unscened QGraphicsItem is on the
// toolkit, where it still carries a position, a z and a visibility, and
// the families here set all three before adding themselves to anything.
void setParentNode(ICoreWinUISceneNode* newParent);
// What every seat's ~Impl calls FIRST. Children become usable roots rather
// than going hollow; then this node leaves its parent and its scene.
void teardownNode();
// The wrapper above this node WHEN IT IS AN ICoreGraphicsObject, and null
// for every other item type.
//
// ⚠ A VIRTUAL, NOT A dynamic_cast AND NOT A REGISTRY. The AppKit seat
// answers the same question through a std::unordered_map keyed on the node,
// because its node is a plain struct with no vtable to hang the question
// on. This one already has one, so the answer costs a slot instead of a
// hash lookup and a process-lifetime table's teardown order. Declining by
// default is what makes ICoreGraphicsItem's answer -- null -- the same
// honest one a foreign QGraphicsItem gives on the Qt seat.
// ⚠ OUT OF LINE, and not `{ return nullptr; }` here: the header surface
// rule admits no body in a header, and R4.2 says so with a file and a line.
virtual ICoreGraphicsObject* asGraphicsObject();
// The cursor shape this item asks for, when it asks for one at all.
//
// ⚠ A VIRTUAL ON THE NODE RATHER THAN A READ OF THE SEAT'S FIELD, AND THE
// REASON IS ACCESS CONTROL RATHER THAN TASTE. The shape is held by
// ICoreGraphicsObject::Impl, which is declared in that class's PRIVATE
// section -- a free accessor may not name the type, so it cannot reach the
// member however it is spelled. Dispatching through the base it CAN name is
// the same manoeuvre attachRoot() needed, one member over.
//
// False for an item that has no cursor, and for ICoreGraphicsItem, which
// has no such capability at all.
virtual bool cursorShape(ICoreCursorShape& shapeOut) const;
// The hover tooltip a caller set with setToolTip(), UTF-8, when it set a
// non-empty one. The cursor's virtual for the cursor's two reasons: the
// text is held by ICoreGraphicsObject::Impl, which is PRIVATE, and an item
// has no XAML element of its own to hang a ToolTipService on -- so the item
// records and the view shows.
//
// ⚠ std::string AND NOT ICoreString, to keep this header's include list as
// tight as it is -- the AppKit seat's twin made the same choice for the
// same reason.
virtual bool toolTip(std::string& textOut) const;
// Re-publish this node's contentBounds into the core IF the wrapper's
// answer has drifted from what the core holds. A no-op for a seat whose
// bounds cannot drift.
//
// ⚠⚠ IT EXISTS BECAUSE THE WHOLE GRAPHICS TIER IS SUBCLASSES THAT OVERRIDE
// contentBounds(), KEEP THEIR OWN WIDTH AND NEVER CALL THE BASE'S SETTER.
// `QGraphicsItem::boundingRect()` is a virtual the toolkit calls whenever it
// likes, so on Qt such a subclass is correct with no further work. The scene
// core STORES contentBounds, so somebody has to push it -- and
// ICoreGraphicsTable::setWidth, ICoreGraphicsScrollPane::setHeight, both
// table rows, the scrollable area and the scroll bar all mutate their size
// through nothing but `prepareGeometryChange()`, which damages the OLD
// rectangle and pushes nothing. Measured on the gallery's catalogue: the
// scrollable area answers 216x110 and the core still said 60x60, which is
// wrong culling, wrong clipping and wrong hit-testing on every one of them.
//
// ⚠ A PULL, NOT A PENDING LIST, AND THE AppKit SEAT ALREADY TRIED THE OTHER
// ONE. Recording the node in prepareGeometryChange() looks right and fails
// because every caller follows Qt's contract and calls that BEFORE the
// mutation, so the record is drained while the old width is still in place.
// It is also one more thing to erase when an item dies. Asking each node
// "does your wrapper still agree with the core?" is order-independent, has
// no list to keep, and cannot be flushed at the wrong moment. See
// Backends/AppKit/Graphics/ICoreAppKitGraphicsObjectAccess.h, which reached
// this by the same road and measured the same defect on the same class.
//
// ⚠ AND IT MUST COMPARE BEFORE IT WRITES. `icoreSceneSetContentBounds`
// dirties unconditionally rather than on a change in value, so a reconcile
// that pushed every node every pass would mark the entire scene dirty on
// every frame and every mouse move -- turning a correctness fix into a
// full-scene repaint loop.
virtual void reconcileBounds();
// Give up the scene's keyboard focus, running whatever focus-loss hooks the
// wrapper publishes. A no-op for an item type that cannot hold focus.
//
// ⚠⚠ IT EXISTS BECAUSE A PRESS THAT LANDS ELSEWHERE HAS TO TAKE THE FOCUS
// WITH IT, AND ON THIS BACKEND NOTHING DID. QGraphicsScene resolves the
// mouse grabber, then sets its focus item to the topmost focusABLE item
// under the point -- clearing it when there is none. That single rule is
// what dismisses a scene combo box: ICoreGraphicsComboBox opens its dropdown
// from mousePressed and closes it ONLY from focusLosing, so a press on one
// of its own options (a plain button, not focusable) is what tells it to
// shut. With no such rule the dropdown opens and stays open for ever --
// which is strictly worse than the dropdown that could not be opened at all.
//
// ⚠ THE HOOKS ARE THE POINT, not the core's `focusItem` field.
// `icoreSceneClearFocus` is one assignment and calls nothing; every label in
// the text tier commits its text in focusLosing, so a view that only cleared
// the field would drop an edit on every click elsewhere. Dispatching through
// the node is what lets the view reach a protected hook it may not call.
virtual void releaseSceneFocus();
// Deliver one KEY to whatever wrapper sits above this node. Declining by
// default, which is the honest answer for every item type but one: only
// ICoreGraphicsText publishes key hooks at all -- ICoreGraphicsObject has
// none, so a canvas node cannot be typed into and never could be.
//
// ⚠⚠ AN OPAQUE POINTER, FOR THE SAME REASON THE DRAG PAYLOAD IS ONE.
// The real type is `const ICoreKeyEvent*`, and that struct carries an
// ICoreString -- which reaches Qt today, so naming it in this header would
// pull Qt into every translation unit that includes it: both item seats,
// the scene host and the view. The view points this at an event on ITS
// stack for the duration of the call; the thunk that may name the type
// casts it back and copies nothing.
virtual ICoreWinUISceneEventResult deliverKey(const void* keyEvent);
// Deliver one gesture to whatever wrapper sits above this node.
//
// ⚠⚠ WITHOUT THIS THE ENTIRE ITEM HOOK SURFACE IS DEAD, AND IT LOOKS
// FINISHED FROM EVERY ANGLE. The scene core already resolves WHICH item a
// press, drag, release or hover belongs to, and the view already asks it --
// but nothing turned that answer into a call on the item's own
// mousePressed() / pointerEntered() family, so all thirteen virtuals were
// definitions nothing ever reached. Every geometry check in this zone
// passed throughout, because none of them clicks an item and asks whether
// the ITEM heard. It is the exact twin of an unwired paint hook, on the
// input side, and the AppKit zone found it the same way.
//
// ⚠ A VIRTUAL ON THE NODE, for the reason cursorShape() gives one line up:
// the hooks are PROTECTED members of ICoreGraphicsObject, so only something
// inside that class may call them. Dispatching through the base this header
// CAN name is what lets a view reach them without being a friend of every
// item type -- and it keeps ICoreGraphicsItem, which has no hooks at all,
// answering honestly rather than being handed a body that does nothing.
//
// Declining by default: an item type with no hook surface did not handle
// the event and did not ignore it.
virtual ICoreWinUISceneEventResult deliverEvent(const ICoreWinUISceneEvent& event);
protected:
// Mirror everything this seat holds into the core. Called on every attach
// and by the seat's own setters. The base calls it; only the seat knows
// what it has.
virtual void pushAll() = 0;
// Register this node's appearance and its content hook with the host.
// Called immediately after the id exists.
virtual void bindSelf() = 0;
};
};
File-scope declarations#
// The ONE type every scene
// item's native handle points at on this backend, and the ONE implementation of
// attaching, detaching and re-parenting one.
//
// ⚠ THE ROW THAT ADDED THIS IS NAMED IN ICoreWinUISceneNode.cpp AND NOT HERE, per
// this zone's README: the docs generator lifts HEADER comments into public API
enum class ICoreWinUISceneEventKind {
Pressed,
Moved,
Released,
DoubleClicked,
PointerEntered,
PointerMoved,
PointerLeft,
ContextMenu,
WheelScrolled,
// W1.10. The three the item tier publishes; there is no DragLeft, because
// ICoreGraphicsObject has no hook for one.
DragEntered,
DragMovedOver,
PayloadDropped
};
ICoreWinUIScenePainter.h#
ICoreEssentials/UI/Backends/WinUI/Graphics/ICoreWinUIScenePainter.h
Draws an ICoreScene through the Direct2D painter: the first consumer of the portable scene core on this backend.
The scene core computes WHAT is drawn and in what order and never draws; the painter draws and knows nothing about scenes. This is the seam between them, and it is deliberately the whole of it -- there is no third place where a scene decision and a painting decision meet.
⚠ THE GEOMETRY IS MAPPED HERE, NOT SET ON THE PAINTER, and that is a real constraint rather than a preference. ICoreScene produces an arbitrary affine world transform; ICoreWinUIPainter exposes translate / rotate / scale and no general 2x3 setter. Decomposing an affine into those three is exact only while there is no shear, and a scene that has composed a rotation with a non-uniform scale HAS shear. So this file maps the four corners itself
ICoreWinUIItemStyle#
ICoreWinUIScenePainter.h:39 · struct · 0 declaration(s)
What one item looks like.
struct ICoreWinUIItemStyle {
public:
bool hasFill = false;
int fillR = 0, fillG = 0, fillB = 0, fillA = 255;
bool hasStroke = false;
int strokeR = 0, strokeG = 0, strokeB = 0, strokeA = 255;
double strokeWidth = 1.0;
};
};
File-scope declarations#
// Asked for each entry in draw order. Returning a style with neither fill nor
// stroke draws nothing for that item, which is how a caller says "this one is
// a group, not a shape".
using ICoreWinUIItemStyler = std::function<ICoreWinUIItemStyle(ICoreSceneItemId)>;
ICoreWinUISceneRender.h#
ICoreEssentials/UI/Backends/WinUI/Graphics/ICoreWinUISceneRender.h
Run a whole scene down a painter: the body ICoreGraphicsScene::renderTo has carried since this backend's scene seat was written, lifted out so a SECOND caller does not become a second copy of it.
⚠ WHY IT MOVED. The chart tier needs the same operation from the other end: ICoreChartBase's three export routes render THE SCENE THE CHART SITS IN, and they reach it from an ITEM rather than from a scene wrapper. The other toolkit answers both with one call (
QGraphicsScene::render); here the walk is ours, so the choice was a shared body or a duplicated one -- and a duplicated draw loop is the shape that ends with two callers disagreeing about clipping in a way nothing reports. The AppKit zone reached this conclusion first and by the same road; see its ICoreAppKitSceneRender.h.⚠ NOTHING ABOVE THE BACKEND ZONE MAY INCLUDE THIS. Peers:
Declares no class of its own — see the file.
ICoreWinUISceneTrace.h#
ICoreEssentials/UI/Backends/WinUI/Graphics/ICoreWinUISceneTrace.h
ICoreWinUISceneTimer#
ICoreWinUISceneTrace.h:49 · class · pImpl · 4 declaration(s)
Times one phase for the length of a scope, when the trace is on.
class ICoreWinUISceneTimer {
public:
explicit ICoreWinUISceneTimer(ICoreWinUIScenePhase phase);
~ICoreWinUISceneTimer();
ICoreWinUISceneTimer(const ICoreWinUISceneTimer&) = delete;
ICoreWinUISceneTimer& operator=(const ICoreWinUISceneTimer&) = delete;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
File-scope declarations#
// W10.131 -- where a canvas's time goes, phase by phase.
//
// ICORE_WINUI_FRAME_TRACE says how long a FLUSH took; it cannot say whether
// that was the scene walk, the bounds reconcile or the drawing, and it never
// sees a pointer move at all -- which is where a drag spends the rest of its
// time. `ICORE_WINUI_SCENE_TRACE=1` prints, once a second, the microseconds and
enum class ICoreWinUIScenePhase {
MoveOwner, // the view wrapper's own mouseMoved()
MoveReconcile, // pulling every node's bounds before routing
MoveRoute, // icoreSceneViewRouteMove: hit-test and hover
MoveDeliver, // the items' handlers -- the application's drag code
Refresh, // refreshSceneBounds(): reconcile plus the scene extent
DrawOrder, // icoreSceneDrawOrder for a frame
DrawCommands, // painting the commands it returned
ItemContent, // inside DrawCommands: the items' own paint hooks
Pixmap, // inside those: drawPixmap, upload included
Text, // inside those: drawText*, layout included
Shape, // inside those: rect, rounded rect, ellipse, line, poly*
Path, // inside those: fillPath, strokePath, drawPath
Clip, // inside those: setClip*, restore
Count
};
ICoreWinUITablePainter.h#
ICoreEssentials/UI/Backends/WinUI/Graphics/ICoreWinUITablePainter.h
Draws a graphics table on Direct2D from the portable layout core: the core's first consumer, and the reason its arithmetic is more than a claim.
The core computes WHERE everything is and never draws; this issues painter calls and decides nothing. It takes no row count, column count or geometry of its own -- every rectangle it fills comes from icoreTableGeometry() and icoreTableColumnEdges(), so a disagreement between the two is impossible rather than merely unlikely.
⚠ IT DRAWS THE CHROME, NOT THE CONTENT. Cell text belongs to the text stack and needs a font; what a table's own painter owes is the body, the header band, the row bands and the column separators -- the part that is geometry wearing colour.
ICoreWinUITableStyle#
ICoreWinUITablePainter.h:26 · struct · 0 declaration(s)
The colours a table wears.
struct ICoreWinUITableStyle {
public:
int bodyFillR = 255, bodyFillG = 255, bodyFillB = 255, bodyFillA = 255;
int borderR = 160, borderG = 160, borderB = 160, borderA = 255;
int headerFillR = 230, headerFillG = 230, headerFillB = 230, headerFillA = 255;
int rowFillR = 245, rowFillG = 245, rowFillB = 245, rowFillA = 255;
// The Qt table's own body override: radius 1.0 and pen width 2.0, where the
// graphics base draws 5.0 / 1.0. Kept as the default so a port starts
// identical rather than starting prettier.
double borderWidth = 2.0;
double cornerRadius = 1.0;
// Separators sit on the interior column edges. The outer two are the
// table's own border and are never drawn twice.
bool drawColumnSeparators = true;
double separatorWidth = 1.0;
};
};
ICoreWinUITableDrawStats#
ICoreWinUITablePainter.h:45 · struct · 0 declaration(s)
What was drawn, so a caller can tell an empty table from a failed one.
struct ICoreWinUITableDrawStats {
public:
int rowsDrawn = 0;
int separatorsDrawn = 0;
bool bodyDrawn = false;
bool headerDrawn = false;
};
};