mirror of
https://github.com/NohamR/Reclass.git
synced 2026-05-10 19:59:21 +00:00
Dynamic name column width + click-in-padding keeps edit active
- Compute effective name column width from longest field name (8-22 chars) - Store layout in ComposeResult, cache in editor for span calculations - Parameterize span functions to use runtime nameW instead of fixed constant - Click within column padding during edit moves cursor to end instead of committing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ struct ComposeState {
|
|||||||
QSet<uint64_t> visiting; // cycle detection for struct recursion
|
QSet<uint64_t> visiting; // cycle detection for struct recursion
|
||||||
QSet<qulonglong> ptrVisiting; // cycle guard for pointer expansions
|
QSet<qulonglong> ptrVisiting; // cycle guard for pointer expansions
|
||||||
int currentLine = 0;
|
int currentLine = 0;
|
||||||
|
int nameW = kColName; // effective name column width
|
||||||
|
|
||||||
// Precomputed for O(1) lookups
|
// Precomputed for O(1) lookups
|
||||||
QHash<uint64_t, QVector<int>> childMap;
|
QHash<uint64_t, QVector<int>> childMap;
|
||||||
@@ -119,7 +120,8 @@ void composeLeaf(ComposeState& state, const NodeTree& tree,
|
|||||||
lm.markerMask = computeMarkers(node, prov, absAddr, isCont, depth);
|
lm.markerMask = computeMarkers(node, prov, absAddr, isCont, depth);
|
||||||
lm.foldLevel = computeFoldLevel(depth, false);
|
lm.foldLevel = computeFoldLevel(depth, false);
|
||||||
|
|
||||||
QString lineText = fmt::fmtNodeLine(node, prov, absAddr, depth, sub);
|
QString lineText = fmt::fmtNodeLine(node, prov, absAddr, depth, sub,
|
||||||
|
/*comment=*/{}, state.nameW);
|
||||||
state.emitLine(lineText, lm);
|
state.emitLine(lineText, lm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,6 +277,17 @@ ComposeResult compose(const NodeTree& tree, const Provider& prov) {
|
|||||||
for (int i = 0; i < tree.nodes.size(); i++)
|
for (int i = 0; i < tree.nodes.size(); i++)
|
||||||
state.absOffsets[i] = tree.computeOffset(i);
|
state.absOffsets[i] = tree.computeOffset(i);
|
||||||
|
|
||||||
|
// Compute effective name column width from longest name
|
||||||
|
int maxNameLen = kMinNameW;
|
||||||
|
for (const Node& node : tree.nodes) {
|
||||||
|
// Skip hex/padding (they show ASCII preview, not name column)
|
||||||
|
if (isHexPreview(node.kind)) continue;
|
||||||
|
// Skip containers (struct/array headers have different layout)
|
||||||
|
if (node.kind == NodeKind::Struct || node.kind == NodeKind::Array) continue;
|
||||||
|
maxNameLen = qMax(maxNameLen, node.name.size());
|
||||||
|
}
|
||||||
|
state.nameW = qBound(kMinNameW, maxNameLen + 1, kMaxNameW);
|
||||||
|
|
||||||
QVector<int> roots = state.childMap.value(0);
|
QVector<int> roots = state.childMap.value(0);
|
||||||
std::sort(roots.begin(), roots.end(), [&](int a, int b) {
|
std::sort(roots.begin(), roots.end(), [&](int a, int b) {
|
||||||
return tree.nodes[a].offset < tree.nodes[b].offset;
|
return tree.nodes[a].offset < tree.nodes[b].offset;
|
||||||
@@ -284,7 +297,7 @@ ComposeResult compose(const NodeTree& tree, const Provider& prov) {
|
|||||||
composeNode(state, tree, prov, idx, 0);
|
composeNode(state, tree, prov, idx, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { state.text, state.meta };
|
return { state.text, state.meta, LayoutInfo{state.nameW} };
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<uint64_t> NodeTree::normalizePreferAncestors(const QSet<uint64_t>& ids) const {
|
QSet<uint64_t> NodeTree::normalizePreferAncestors(const QSet<uint64_t>& ids) const {
|
||||||
|
|||||||
27
src/core.h
27
src/core.h
@@ -434,11 +434,18 @@ struct LineMeta {
|
|||||||
uint32_t markerMask = 0;
|
uint32_t markerMask = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ── Layout Info ──
|
||||||
|
|
||||||
|
struct LayoutInfo {
|
||||||
|
int nameW = 22; // Effective name column width (default = kColName)
|
||||||
|
};
|
||||||
|
|
||||||
// ── ComposeResult ──
|
// ── ComposeResult ──
|
||||||
|
|
||||||
struct ComposeResult {
|
struct ComposeResult {
|
||||||
QString text;
|
QString text;
|
||||||
QVector<LineMeta> meta;
|
QVector<LineMeta> meta;
|
||||||
|
LayoutInfo layout;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ── Command ──
|
// ── Command ──
|
||||||
@@ -479,6 +486,8 @@ inline constexpr int kColValue = 32;
|
|||||||
inline constexpr int kColComment = 28; // "// Enter=Save Esc=Cancel" fits
|
inline constexpr int kColComment = 28; // "// Enter=Save Esc=Cancel" fits
|
||||||
inline constexpr int kColBaseAddr = 12; // "0x" + up to 10 hex digits (40-bit address)
|
inline constexpr int kColBaseAddr = 12; // "0x" + up to 10 hex digits (40-bit address)
|
||||||
inline constexpr int kSepWidth = 2;
|
inline constexpr int kSepWidth = 2;
|
||||||
|
inline constexpr int kMinNameW = 8; // Minimum name column width (matches ASCII preview)
|
||||||
|
inline constexpr int kMaxNameW = 22; // Maximum name column width (= kColName)
|
||||||
|
|
||||||
inline ColumnSpan typeSpanFor(const LineMeta& lm) {
|
inline ColumnSpan typeSpanFor(const LineMeta& lm) {
|
||||||
if (lm.lineKind != LineKind::Field || lm.isContinuation) return {};
|
if (lm.lineKind != LineKind::Field || lm.isContinuation) return {};
|
||||||
@@ -486,7 +495,7 @@ inline ColumnSpan typeSpanFor(const LineMeta& lm) {
|
|||||||
return {ind, ind + kColType, true};
|
return {ind, ind + kColType, true};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ColumnSpan nameSpanFor(const LineMeta& lm) {
|
inline ColumnSpan nameSpanFor(const LineMeta& lm, int nameW = kColName) {
|
||||||
if (lm.isContinuation || lm.lineKind != LineKind::Field) return {};
|
if (lm.isContinuation || lm.lineKind != LineKind::Field) return {};
|
||||||
|
|
||||||
int ind = kFoldCol + lm.depth * 3;
|
int ind = kFoldCol + lm.depth * 3;
|
||||||
@@ -496,10 +505,10 @@ inline ColumnSpan nameSpanFor(const LineMeta& lm) {
|
|||||||
if (isHexPreview(lm.nodeKind))
|
if (isHexPreview(lm.nodeKind))
|
||||||
return {start, start + 8, true};
|
return {start, start + 8, true};
|
||||||
|
|
||||||
return {start, start + kColName, true};
|
return {start, start + nameW, true};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ColumnSpan valueSpanFor(const LineMeta& lm, int /*lineLength*/) {
|
inline ColumnSpan valueSpanFor(const LineMeta& lm, int /*lineLength*/, int nameW = kColName) {
|
||||||
if (lm.lineKind == LineKind::Header || lm.lineKind == LineKind::Footer) return {};
|
if (lm.lineKind == LineKind::Header || lm.lineKind == LineKind::Footer) return {};
|
||||||
int ind = kFoldCol + lm.depth * 3;
|
int ind = kFoldCol + lm.depth * 3;
|
||||||
|
|
||||||
@@ -510,7 +519,7 @@ inline ColumnSpan valueSpanFor(const LineMeta& lm, int /*lineLength*/) {
|
|||||||
if (lm.isContinuation) {
|
if (lm.isContinuation) {
|
||||||
int prefixW = isHexPad
|
int prefixW = isHexPad
|
||||||
? (kColType + kSepWidth + 8 + kSepWidth)
|
? (kColType + kSepWidth + 8 + kSepWidth)
|
||||||
: (kColType + kColName + 4);
|
: (kColType + nameW + 4);
|
||||||
int start = ind + prefixW;
|
int start = ind + prefixW;
|
||||||
return {start, start + valWidth, true};
|
return {start, start + valWidth, true};
|
||||||
}
|
}
|
||||||
@@ -518,11 +527,11 @@ inline ColumnSpan valueSpanFor(const LineMeta& lm, int /*lineLength*/) {
|
|||||||
|
|
||||||
int start = isHexPad
|
int start = isHexPad
|
||||||
? (ind + kColType + kSepWidth + 8 + kSepWidth)
|
? (ind + kColType + kSepWidth + 8 + kSepWidth)
|
||||||
: (ind + kColType + kSepWidth + kColName + kSepWidth);
|
: (ind + kColType + kSepWidth + nameW + kSepWidth);
|
||||||
return {start, start + valWidth, true};
|
return {start, start + valWidth, true};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ColumnSpan commentSpanFor(const LineMeta& lm, int lineLength) {
|
inline ColumnSpan commentSpanFor(const LineMeta& lm, int lineLength, int nameW = kColName) {
|
||||||
if (lm.lineKind == LineKind::Header || lm.lineKind == LineKind::Footer) return {};
|
if (lm.lineKind == LineKind::Header || lm.lineKind == LineKind::Footer) return {};
|
||||||
int ind = kFoldCol + lm.depth * 3;
|
int ind = kFoldCol + lm.depth * 3;
|
||||||
|
|
||||||
@@ -533,12 +542,12 @@ inline ColumnSpan commentSpanFor(const LineMeta& lm, int lineLength) {
|
|||||||
if (lm.isContinuation) {
|
if (lm.isContinuation) {
|
||||||
int prefixW = isHexPad
|
int prefixW = isHexPad
|
||||||
? (kColType + kSepWidth + 8 + kSepWidth)
|
? (kColType + kSepWidth + 8 + kSepWidth)
|
||||||
: (kColType + kColName + 4);
|
: (kColType + nameW + 4);
|
||||||
start = ind + prefixW + valWidth;
|
start = ind + prefixW + valWidth;
|
||||||
} else {
|
} else {
|
||||||
start = isHexPad
|
start = isHexPad
|
||||||
? (ind + kColType + kSepWidth + 8 + kSepWidth + valWidth)
|
? (ind + kColType + kSepWidth + 8 + kSepWidth + valWidth)
|
||||||
: (ind + kColType + kSepWidth + kColName + kSepWidth + valWidth);
|
: (ind + kColType + kSepWidth + nameW + kSepWidth + valWidth);
|
||||||
}
|
}
|
||||||
return {start, lineLength, start < lineLength};
|
return {start, lineLength, start < lineLength};
|
||||||
}
|
}
|
||||||
@@ -599,7 +608,7 @@ namespace fmt {
|
|||||||
QString fmtPointer64(uint64_t v);
|
QString fmtPointer64(uint64_t v);
|
||||||
QString fmtNodeLine(const Node& node, const Provider& prov,
|
QString fmtNodeLine(const Node& node, const Provider& prov,
|
||||||
uint64_t addr, int depth, int subLine = 0,
|
uint64_t addr, int depth, int subLine = 0,
|
||||||
const QString& comment = {});
|
const QString& comment = {}, int colName = kColName);
|
||||||
QString fmtOffsetMargin(int64_t relativeOffset, bool isContinuation);
|
QString fmtOffsetMargin(int64_t relativeOffset, bool isContinuation);
|
||||||
QString fmtStructHeader(const Node& node, int depth);
|
QString fmtStructHeader(const Node& node, int depth);
|
||||||
QString fmtStructHeaderWithBase(const Node& node, int depth, uint64_t baseAddress);
|
QString fmtStructHeaderWithBase(const Node& node, int depth, uint64_t baseAddress);
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ void RcxEditor::setupLexer() {
|
|||||||
|
|
||||||
// Dark theme colors
|
// Dark theme colors
|
||||||
m_lexer->setColor(QColor("#569cd6"), QsciLexerCPP::Keyword);
|
m_lexer->setColor(QColor("#569cd6"), QsciLexerCPP::Keyword);
|
||||||
m_lexer->setColor(QColor("#4ec9b0"), QsciLexerCPP::KeywordSet2);
|
m_lexer->setColor(QColor("#569cd6"), QsciLexerCPP::KeywordSet2);
|
||||||
m_lexer->setColor(QColor("#b5cea8"), QsciLexerCPP::Number);
|
m_lexer->setColor(QColor("#b5cea8"), QsciLexerCPP::Number);
|
||||||
m_lexer->setColor(QColor("#ce9178"), QsciLexerCPP::DoubleQuotedString);
|
m_lexer->setColor(QColor("#ce9178"), QsciLexerCPP::DoubleQuotedString);
|
||||||
m_lexer->setColor(QColor("#ce9178"), QsciLexerCPP::SingleQuotedString);
|
m_lexer->setColor(QColor("#ce9178"), QsciLexerCPP::SingleQuotedString);
|
||||||
@@ -280,6 +280,7 @@ void RcxEditor::applyDocument(const ComposeResult& result) {
|
|||||||
endInlineEdit();
|
endInlineEdit();
|
||||||
|
|
||||||
m_meta = result.meta;
|
m_meta = result.meta;
|
||||||
|
m_layout = result.layout;
|
||||||
|
|
||||||
m_sci->setReadOnly(false);
|
m_sci->setReadOnly(false);
|
||||||
m_sci->setText(result.text);
|
m_sci->setText(result.text);
|
||||||
@@ -449,8 +450,8 @@ int RcxEditor::currentNodeIndex() const {
|
|||||||
// ── Column span computation ──
|
// ── Column span computation ──
|
||||||
|
|
||||||
ColumnSpan RcxEditor::typeSpan(const LineMeta& lm) { return typeSpanFor(lm); }
|
ColumnSpan RcxEditor::typeSpan(const LineMeta& lm) { return typeSpanFor(lm); }
|
||||||
ColumnSpan RcxEditor::nameSpan(const LineMeta& lm) { return nameSpanFor(lm); }
|
ColumnSpan RcxEditor::nameSpan(const LineMeta& lm, int nameW) { return nameSpanFor(lm, nameW); }
|
||||||
ColumnSpan RcxEditor::valueSpan(const LineMeta& lm, int lineLength) { return valueSpanFor(lm, lineLength); }
|
ColumnSpan RcxEditor::valueSpan(const LineMeta& lm, int lineLength, int nameW) { return valueSpanFor(lm, lineLength, nameW); }
|
||||||
|
|
||||||
// ── Multi-selection ──
|
// ── Multi-selection ──
|
||||||
|
|
||||||
@@ -591,8 +592,8 @@ bool RcxEditor::resolvedSpanFor(int line, EditTarget t,
|
|||||||
ColumnSpan s;
|
ColumnSpan s;
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case EditTarget::Type: s = typeSpan(*lm); break;
|
case EditTarget::Type: s = typeSpan(*lm); break;
|
||||||
case EditTarget::Name: s = nameSpan(*lm); break;
|
case EditTarget::Name: s = nameSpan(*lm, m_layout.nameW); break;
|
||||||
case EditTarget::Value: s = valueSpan(*lm, textLen); break;
|
case EditTarget::Value: s = valueSpan(*lm, textLen, m_layout.nameW); break;
|
||||||
case EditTarget::BaseAddress: s = baseAddressSpanFor(*lm, lineText); break;
|
case EditTarget::BaseAddress: s = baseAddressSpanFor(*lm, lineText); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +640,8 @@ RcxEditor::HitInfo RcxEditor::hitTest(const QPoint& vp) const {
|
|||||||
static bool hitTestTarget(QsciScintilla* sci,
|
static bool hitTestTarget(QsciScintilla* sci,
|
||||||
const QVector<LineMeta>& meta,
|
const QVector<LineMeta>& meta,
|
||||||
const QPoint& viewportPos,
|
const QPoint& viewportPos,
|
||||||
int& outLine, EditTarget& outTarget)
|
int& outLine, EditTarget& outTarget,
|
||||||
|
int nameW = kColName)
|
||||||
{
|
{
|
||||||
long pos = sci->SendScintilla(QsciScintillaBase::SCI_POSITIONFROMPOINTCLOSE,
|
long pos = sci->SendScintilla(QsciScintillaBase::SCI_POSITIONFROMPOINTCLOSE,
|
||||||
(unsigned long)viewportPos.x(), (long)viewportPos.y());
|
(unsigned long)viewportPos.x(), (long)viewportPos.y());
|
||||||
@@ -655,8 +657,8 @@ static bool hitTestTarget(QsciScintilla* sci,
|
|||||||
|
|
||||||
const LineMeta& lm = meta[line];
|
const LineMeta& lm = meta[line];
|
||||||
ColumnSpan ts = RcxEditor::typeSpan(lm);
|
ColumnSpan ts = RcxEditor::typeSpan(lm);
|
||||||
ColumnSpan ns = RcxEditor::nameSpan(lm);
|
ColumnSpan ns = RcxEditor::nameSpan(lm, nameW);
|
||||||
ColumnSpan vs = RcxEditor::valueSpan(lm, textLen);
|
ColumnSpan vs = RcxEditor::valueSpan(lm, textLen, nameW);
|
||||||
ColumnSpan bs = baseAddressSpanFor(lm, lineText); // Base address for root headers
|
ColumnSpan bs = baseAddressSpanFor(lm, lineText); // Base address for root headers
|
||||||
|
|
||||||
if (!ns.valid)
|
if (!ns.valid)
|
||||||
@@ -687,13 +689,34 @@ bool RcxEditor::eventFilter(QObject* obj, QEvent* event) {
|
|||||||
&& m_editState.active) {
|
&& m_editState.active) {
|
||||||
auto* me = static_cast<QMouseEvent*>(event);
|
auto* me = static_cast<QMouseEvent*>(event);
|
||||||
auto h = hitTest(me->pos());
|
auto h = hitTest(me->pos());
|
||||||
bool insideEdit = false;
|
|
||||||
if (h.line == m_editState.line) {
|
if (h.line == m_editState.line) {
|
||||||
int editEnd = editEndCol();
|
int editEnd = editEndCol();
|
||||||
insideEdit = (h.col >= m_editState.spanStart && h.col <= editEnd);
|
bool insideTrimmed = (h.col >= m_editState.spanStart && h.col <= editEnd);
|
||||||
|
|
||||||
|
if (insideTrimmed)
|
||||||
|
return false; // inside trimmed text: let Scintilla position cursor
|
||||||
|
|
||||||
|
// Check raw span (full column width) - click in padding moves cursor to end
|
||||||
|
const LineMeta* lm = metaForLine(m_editState.line);
|
||||||
|
if (lm) {
|
||||||
|
QString lineText = getLineText(m_sci, h.line);
|
||||||
|
ColumnSpan raw;
|
||||||
|
switch (m_editState.target) {
|
||||||
|
case EditTarget::Type: raw = typeSpan(*lm); break;
|
||||||
|
case EditTarget::Name: raw = nameSpan(*lm, m_layout.nameW); break;
|
||||||
|
case EditTarget::Value: raw = valueSpan(*lm, lineText.size(), m_layout.nameW); break;
|
||||||
|
case EditTarget::BaseAddress: raw = baseAddressSpanFor(*lm, lineText); break;
|
||||||
|
}
|
||||||
|
if (raw.valid && h.col >= raw.start && h.col < raw.end) {
|
||||||
|
// Within raw span but outside trimmed text → move cursor to end
|
||||||
|
long endPos = posFromCol(m_sci, m_editState.line, editEnd);
|
||||||
|
m_sci->SendScintilla(QsciScintillaBase::SCI_GOTOPOS, endPos);
|
||||||
|
return true; // consume event
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (insideEdit)
|
|
||||||
return false; // inside edit span: let Scintilla position cursor
|
|
||||||
commitInlineEdit();
|
commitInlineEdit();
|
||||||
m_currentSelIds.clear(); // stale — normal handler will re-establish
|
m_currentSelIds.clear(); // stale — normal handler will re-establish
|
||||||
// Fall through to normal click handler below
|
// Fall through to normal click handler below
|
||||||
@@ -725,7 +748,7 @@ bool RcxEditor::eventFilter(QObject* obj, QEvent* event) {
|
|||||||
// Single-click on editable token of already-selected node → edit
|
// Single-click on editable token of already-selected node → edit
|
||||||
if (alreadySelected && plain) {
|
if (alreadySelected && plain) {
|
||||||
int tLine; EditTarget t;
|
int tLine; EditTarget t;
|
||||||
if (hitTestTarget(m_sci, m_meta, me->pos(), tLine, t)) {
|
if (hitTestTarget(m_sci, m_meta, me->pos(), tLine, t, m_layout.nameW)) {
|
||||||
m_pendingClickNodeId = 0;
|
m_pendingClickNodeId = 0;
|
||||||
return beginInlineEdit(t, tLine);
|
return beginInlineEdit(t, tLine);
|
||||||
}
|
}
|
||||||
@@ -801,7 +824,7 @@ bool RcxEditor::eventFilter(QObject* obj, QEvent* event) {
|
|||||||
&& event->type() == QEvent::MouseButtonDblClick) {
|
&& event->type() == QEvent::MouseButtonDblClick) {
|
||||||
auto* me = static_cast<QMouseEvent*>(event);
|
auto* me = static_cast<QMouseEvent*>(event);
|
||||||
int line; EditTarget t;
|
int line; EditTarget t;
|
||||||
if (hitTestTarget(m_sci, m_meta, me->pos(), line, t)) {
|
if (hitTestTarget(m_sci, m_meta, me->pos(), line, t, m_layout.nameW)) {
|
||||||
m_pendingClickNodeId = 0; // cancel deferred selection change
|
m_pendingClickNodeId = 0; // cancel deferred selection change
|
||||||
return beginInlineEdit(t, line);
|
return beginInlineEdit(t, line);
|
||||||
}
|
}
|
||||||
@@ -959,7 +982,7 @@ bool RcxEditor::beginInlineEdit(EditTarget target, int line) {
|
|||||||
|
|
||||||
// Store fixed comment column position for value editing
|
// Store fixed comment column position for value editing
|
||||||
if (target == EditTarget::Value) {
|
if (target == EditTarget::Value) {
|
||||||
ColumnSpan cs = commentSpanFor(*lm, lineText.size());
|
ColumnSpan cs = commentSpanFor(*lm, lineText.size(), m_layout.nameW);
|
||||||
m_editState.commentCol = cs.valid ? cs.start : -1;
|
m_editState.commentCol = cs.valid ? cs.start : -1;
|
||||||
m_editState.lastValidationOk = true; // original value is always valid
|
m_editState.lastValidationOk = true; // original value is always valid
|
||||||
} else {
|
} else {
|
||||||
@@ -1214,7 +1237,7 @@ void RcxEditor::applyHoverCursor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int line; EditTarget t;
|
int line; EditTarget t;
|
||||||
bool tokenHit = hitTestTarget(m_sci, m_meta, m_lastHoverPos, line, t);
|
bool tokenHit = hitTestTarget(m_sci, m_meta, m_lastHoverPos, line, t, m_layout.nameW);
|
||||||
|
|
||||||
// Apply hover span indicator (blue text like a link)
|
// Apply hover span indicator (blue text like a link)
|
||||||
if (tokenHit) {
|
if (tokenHit) {
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ public:
|
|||||||
|
|
||||||
// ── Column span computation ──
|
// ── Column span computation ──
|
||||||
static ColumnSpan typeSpan(const LineMeta& lm);
|
static ColumnSpan typeSpan(const LineMeta& lm);
|
||||||
static ColumnSpan nameSpan(const LineMeta& lm);
|
static ColumnSpan nameSpan(const LineMeta& lm, int nameW = kColName);
|
||||||
static ColumnSpan valueSpan(const LineMeta& lm, int lineLength);
|
static ColumnSpan valueSpan(const LineMeta& lm, int lineLength, int nameW = kColName);
|
||||||
|
|
||||||
// ── Multi-selection ──
|
// ── Multi-selection ──
|
||||||
QSet<int> selectedNodeIndices() const;
|
QSet<int> selectedNodeIndices() const;
|
||||||
@@ -55,6 +55,7 @@ private:
|
|||||||
QsciScintilla* m_sci = nullptr;
|
QsciScintilla* m_sci = nullptr;
|
||||||
QsciLexerCPP* m_lexer = nullptr;
|
QsciLexerCPP* m_lexer = nullptr;
|
||||||
QVector<LineMeta> m_meta;
|
QVector<LineMeta> m_meta;
|
||||||
|
LayoutInfo m_layout; // cached from ComposeResult
|
||||||
|
|
||||||
int m_marginStyleBase = -1;
|
int m_marginStyleBase = -1;
|
||||||
int m_hintLine = -1;
|
int m_hintLine = -1;
|
||||||
|
|||||||
@@ -213,12 +213,12 @@ QString readValue(const Node& node, const Provider& prov,
|
|||||||
|
|
||||||
QString fmtNodeLine(const Node& node, const Provider& prov,
|
QString fmtNodeLine(const Node& node, const Provider& prov,
|
||||||
uint64_t addr, int depth, int subLine,
|
uint64_t addr, int depth, int subLine,
|
||||||
const QString& comment) {
|
const QString& comment, int colName) {
|
||||||
QString ind = indent(depth);
|
QString ind = indent(depth);
|
||||||
QString type = typeName(node.kind);
|
QString type = typeName(node.kind);
|
||||||
QString name = fit(node.name, COL_NAME);
|
QString name = fit(node.name, colName);
|
||||||
// Blank prefix for continuation lines (same width as type+sep+name+sep)
|
// Blank prefix for continuation lines (same width as type+sep+name+sep)
|
||||||
const int prefixW = COL_TYPE + COL_NAME + 4; // 2 seps × 2 chars
|
const int prefixW = COL_TYPE + colName + 4; // 2 seps × 2 chars
|
||||||
|
|
||||||
// Comment suffix (padded or empty)
|
// Comment suffix (padded or empty)
|
||||||
QString cmtSuffix = comment.isEmpty() ? QString(COL_COMMENT, ' ')
|
QString cmtSuffix = comment.isEmpty() ? QString(COL_COMMENT, ' ')
|
||||||
|
|||||||
Reference in New Issue
Block a user