mirror of
https://github.com/NohamR/Reclass.git
synced 2026-05-10 19:59:21 +00:00
feat: enum editing UI, protect enums from struct ops, New Class opens two tabs
- New Class creates two Unnamed tabs, selects the first - New Enum creates 5 placeholder members (Member0-4) - Right-click enum member: Add Member Above/Below, Remove Member - Right-click enum header: Add Member, Rename, Delete only - Enum nodes fully protected from struct operations (no Add Child, Insert, Convert)
This commit is contained in:
@@ -1777,7 +1777,41 @@ void RcxController::showContextMenu(RcxEditor* editor, int line, int nodeIdx,
|
|||||||
&& !node.bitfieldMembers.isEmpty()
|
&& !node.bitfieldMembers.isEmpty()
|
||||||
&& subLine >= 0 && subLine < node.bitfieldMembers.size();
|
&& subLine >= 0 && subLine < node.bitfieldMembers.size();
|
||||||
|
|
||||||
|
bool isEnumNode = node.resolvedClassKeyword() == QStringLiteral("enum");
|
||||||
|
|
||||||
if (isEnumMember || isBitfieldMember) {
|
if (isEnumMember || isBitfieldMember) {
|
||||||
|
if (isEnumMember) {
|
||||||
|
menu.addAction(icon("diff-added.svg"), "Add Member Above", [this, nodeId, subLine]() {
|
||||||
|
int ni = m_doc->tree.indexOfId(nodeId);
|
||||||
|
if (ni < 0) return;
|
||||||
|
auto members = m_doc->tree.nodes[ni].enumMembers;
|
||||||
|
int64_t val = (subLine > 0) ? members[subLine - 1].second + 1 : 0;
|
||||||
|
auto oldMembers = members;
|
||||||
|
members.insert(subLine, {QStringLiteral("NewMember"), val});
|
||||||
|
m_doc->undoStack.push(new RcxCommand(this,
|
||||||
|
cmd::ChangeEnumMembers{nodeId, oldMembers, members}));
|
||||||
|
});
|
||||||
|
menu.addAction(icon("diff-added.svg"), "Add Member Below", [this, nodeId, subLine]() {
|
||||||
|
int ni = m_doc->tree.indexOfId(nodeId);
|
||||||
|
if (ni < 0) return;
|
||||||
|
auto members = m_doc->tree.nodes[ni].enumMembers;
|
||||||
|
int64_t val = members[subLine].second + 1;
|
||||||
|
auto oldMembers = members;
|
||||||
|
members.insert(subLine + 1, {QStringLiteral("NewMember"), val});
|
||||||
|
m_doc->undoStack.push(new RcxCommand(this,
|
||||||
|
cmd::ChangeEnumMembers{nodeId, oldMembers, members}));
|
||||||
|
});
|
||||||
|
menu.addAction(icon("trash.svg"), "Remove Member", [this, nodeId, subLine]() {
|
||||||
|
int ni = m_doc->tree.indexOfId(nodeId);
|
||||||
|
if (ni < 0) return;
|
||||||
|
auto members = m_doc->tree.nodes[ni].enumMembers;
|
||||||
|
auto oldMembers = members;
|
||||||
|
members.remove(subLine);
|
||||||
|
m_doc->undoStack.push(new RcxCommand(this,
|
||||||
|
cmd::ChangeEnumMembers{nodeId, oldMembers, members}));
|
||||||
|
});
|
||||||
|
menu.addSeparator();
|
||||||
|
}
|
||||||
if (isBitfieldMember) {
|
if (isBitfieldMember) {
|
||||||
const auto& bm = node.bitfieldMembers[subLine];
|
const auto& bm = node.bitfieldMembers[subLine];
|
||||||
if (bm.bitWidth == 1) {
|
if (bm.bitWidth == 1) {
|
||||||
@@ -1792,6 +1826,28 @@ void RcxController::showContextMenu(RcxEditor* editor, int line, int nodeIdx,
|
|||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
}
|
}
|
||||||
// Fall through to always-available actions
|
// Fall through to always-available actions
|
||||||
|
} else if (isEnumNode) {
|
||||||
|
// Enum header line — enum-specific actions only (no struct ops)
|
||||||
|
menu.addAction(icon("diff-added.svg"), "Add Member", [this, nodeId]() {
|
||||||
|
int ni = m_doc->tree.indexOfId(nodeId);
|
||||||
|
if (ni < 0) return;
|
||||||
|
auto members = m_doc->tree.nodes[ni].enumMembers;
|
||||||
|
int64_t nextVal = members.isEmpty() ? 0 : members.last().second + 1;
|
||||||
|
auto oldMembers = members;
|
||||||
|
members.append({QStringLiteral("NewMember"), nextVal});
|
||||||
|
m_doc->undoStack.push(new RcxCommand(this,
|
||||||
|
cmd::ChangeEnumMembers{nodeId, oldMembers, members}));
|
||||||
|
});
|
||||||
|
menu.addAction(icon("edit.svg"), "&Rename...", [this, editor, line]() {
|
||||||
|
editor->beginInlineEdit(EditTarget::Name, line);
|
||||||
|
});
|
||||||
|
menu.addSeparator();
|
||||||
|
menu.addAction(icon("trash.svg"), "&Delete", [this, nodeId]() {
|
||||||
|
int ni = m_doc->tree.indexOfId(nodeId);
|
||||||
|
if (ni >= 0) removeNode(ni);
|
||||||
|
});
|
||||||
|
menu.addSeparator();
|
||||||
|
// Fall through to always-available actions
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// ── Quick-convert suggestions (top-level for fast access) ──
|
// ── Quick-convert suggestions (top-level for fast access) ──
|
||||||
|
|||||||
23
src/main.cpp
23
src/main.cpp
@@ -1920,6 +1920,26 @@ void MainWindow::setupDockTabBars() {
|
|||||||
|
|
||||||
// Build a minimal empty struct for new documents
|
// Build a minimal empty struct for new documents
|
||||||
static void buildEmptyStruct(NodeTree& tree, const QString& classKeyword = QString()) {
|
static void buildEmptyStruct(NodeTree& tree, const QString& classKeyword = QString()) {
|
||||||
|
// ── Enum: bare node with empty enumMembers, no hex children ──
|
||||||
|
if (classKeyword == QStringLiteral("enum")) {
|
||||||
|
Node root;
|
||||||
|
root.kind = NodeKind::Struct;
|
||||||
|
root.name = "Unnamed";
|
||||||
|
root.structTypeName = "Unnamed";
|
||||||
|
root.classKeyword = classKeyword;
|
||||||
|
root.parentId = 0;
|
||||||
|
root.offset = 0;
|
||||||
|
root.enumMembers = {
|
||||||
|
{QStringLiteral("Member0"), 0},
|
||||||
|
{QStringLiteral("Member1"), 1},
|
||||||
|
{QStringLiteral("Member2"), 2},
|
||||||
|
{QStringLiteral("Member3"), 3},
|
||||||
|
{QStringLiteral("Member4"), 4},
|
||||||
|
};
|
||||||
|
tree.addNode(root);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Node root;
|
Node root;
|
||||||
root.kind = NodeKind::Struct;
|
root.kind = NodeKind::Struct;
|
||||||
root.name = "instance";
|
root.name = "instance";
|
||||||
@@ -1988,7 +2008,10 @@ MainWindow::~MainWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::newClass() {
|
void MainWindow::newClass() {
|
||||||
|
auto* first = project_new(QStringLiteral("class"));
|
||||||
project_new(QStringLiteral("class"));
|
project_new(QStringLiteral("class"));
|
||||||
|
// Select the first tab
|
||||||
|
if (first) first->raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::newStruct() {
|
void MainWindow::newStruct() {
|
||||||
|
|||||||
Reference in New Issue
Block a user