Work on the graphical interface for presenting requirements details

This commit is contained in:
Sylvain Schneider
2026-03-13 16:34:34 +01:00
parent 25fc14d6bd
commit 03d2e94f8b
17 changed files with 859 additions and 82 deletions

View File

@@ -0,0 +1,233 @@
#include "requirementDetailPanel.h"
using namespace std;
using namespace gui;
//--------------------------------------------------------------
/* Constructor */
RequirementDetailPanel::RequirementDetailPanel(wxWindow *parentWindow, dBus::Bus &bus)
: wxScrolledWindow(parentWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER | wxVSCROLL)
, m_bus(bus)
{
// Initialization
SetScrollRate(0, 10); // Set the scroll rate for the panel (vertical only)
// Creating controls
createControls();
// Post initialization
}
//--------------------------------------------------------------
/* Creating controls */
void RequirementDetailPanel::createControls()
{
const auto mainPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(500, -1), wxSIMPLE_BORDER);
// Controls positioning
const auto ctrlSizer = new wxBoxSizer(wxVERTICAL);
ctrlSizer->Add(createControls_metadata(mainPanel), wxSizerFlags(0).Expand());
ctrlSizer->Add(createControls_details(mainPanel), wxSizerFlags(0).Expand());
ctrlSizer->Add(createControls_classification(mainPanel), wxSizerFlags(0).Expand());
mainPanel->SetSizer(ctrlSizer);
const auto mainSizer = new wxBoxSizer(wxHORIZONTAL);
mainSizer->Add(mainPanel, wxSizerFlags(0).Expand());
mainSizer->AddStretchSpacer(1);
SetSizer(mainSizer);
// Set the virtual size to match the size of the child panel,
// enabling scrolling if necessary
FitInside();
// Harmonize the sizes of the title controls to ensure they have the same width
updateTitleSizes();
Layout();
}
//--------------------------------------------------------------
/* Creating controls for requirement metadata (ID, UUID, name, description, etc.) */
wxSizer *RequirementDetailPanel::createControls_metadata(wxWindow *owner)
{
struct Item
{
wxWindow *titleCtrl;
wxWindow *inputCtrl;
};
std::vector<Item> items;
{
const Item item{ .titleCtrl = createTitle(owner, _T("UUID:")),
.inputCtrl = new wxTextCtrl(owner, wxID_ANY) };
items.push_back(item);
}
{
const Item item{ .titleCtrl = createTitle(owner, _T("ID:")),
.inputCtrl = new wxTextCtrl(owner, wxID_ANY) };
items.push_back(item);
}
{
const Item item{ .titleCtrl = createTitle(owner, _("Author:")),
.inputCtrl = new wxTextCtrl(owner, wxID_ANY) };
items.push_back(item);
}
{
const Item item{ .titleCtrl = createTitle(owner, _("Created at:")),
.inputCtrl = new wxTextCtrl(owner, wxID_ANY) };
items.push_back(item);
}
{
const Item item{ .titleCtrl = createTitle(owner, _("Updated at:")),
.inputCtrl = new wxTextCtrl(owner, wxID_ANY) };
items.push_back(item);
}
// Controls positioning
const auto ctrlSizer = new wxFlexGridSizer(2, 5, 5);
for (const auto &item : items)
{
ctrlSizer->Add(item.titleCtrl, wxSizerFlags(0).Expand().CenterVertical());
ctrlSizer->Add(item.inputCtrl, wxSizerFlags(1).Expand());
}
ctrlSizer->AddGrowableCol(1, 1);
// Controls positioning
const auto localSizer = new wxStaticBoxSizer(wxVERTICAL, owner, "Metadata");
localSizer->Add(ctrlSizer, wxSizerFlags(0).Expand().Border(wxALL, 5));
return localSizer;
}
//--------------------------------------------------------------
/* Creating controls for requirement details (e.g., custom attributes, child requirements, etc.) */
wxSizer *RequirementDetailPanel::createControls_details(wxWindow *owner)
{
struct Item
{
wxWindow *titleCtrl;
wxWindow *inputCtrl;
};
std::vector<Item> items;
{
const Item item{ .titleCtrl = createTitle(owner, _("Title:")),
.inputCtrl = new wxTextCtrl(owner, wxID_ANY) };
items.push_back(item);
}
{
const Item item{ .titleCtrl = createTitle(owner, _("Description:")),
.inputCtrl = new wxTextCtrl(owner,
wxID_ANY,
wxEmptyString,
wxDefaultPosition,
wxDefaultSize,
wxTE_PROCESS_TAB | wxTE_MULTILINE | wxVSCROLL | wxTE_AUTO_URL) };
items.push_back(item);
item.inputCtrl->SetMinSize(wxSize(-1, 200));
}
{
const Item item{ .titleCtrl = createTitle(owner, _("Acceptance criteria:")),
.inputCtrl = new wxTextCtrl(owner,
wxID_ANY,
wxEmptyString,
wxDefaultPosition,
wxDefaultSize,
wxTE_PROCESS_TAB | wxTE_MULTILINE | wxVSCROLL) };
items.push_back(item);
item.inputCtrl->SetMinSize(wxSize(-1, 100));
}
{
const Item item{ .titleCtrl = new wxPanel(owner),
.inputCtrl = new wxCheckBox(owner, wxID_ANY, _("S.M.A.R.T.")) };
items.push_back(item);
}
// Controls positioning
const auto ctrlSizer = new wxFlexGridSizer(2, 5, 5);
for (const auto &item : items)
{
ctrlSizer->Add(item.titleCtrl, wxSizerFlags(0).Expand().CenterVertical());
ctrlSizer->Add(item.inputCtrl, wxSizerFlags(1).Expand());
}
ctrlSizer->AddGrowableCol(1, 1);
const auto localSizer = new wxStaticBoxSizer(wxVERTICAL, owner, "Details");
localSizer->Add(ctrlSizer, wxSizerFlags(0).Expand().Border(wxALL, 5));
return localSizer;
}
//--------------------------------------------------------------
/* Creating controls for requirement classification (e.g., priority, severity, etc.) */
wxSizer *RequirementDetailPanel::createControls_classification(wxWindow *owner)
{
struct Item
{
wxWindow *titleCtrl;
wxWindow *inputCtrl;
};
std::vector<Item> items;
{
const Item item{ .titleCtrl = createTitle(owner, "Type:"),
.inputCtrl = new wxTextCtrl(owner, wxID_ANY) };
items.push_back(item);
}
{
const Item item{ .titleCtrl = createTitle(owner, "Category:"),
.inputCtrl = new wxTextCtrl(owner, wxID_ANY) };
items.push_back(item);
}
{
const Item item{ .titleCtrl = createTitle(owner, "Priority:"),
.inputCtrl = new wxTextCtrl(owner, wxID_ANY) };
items.push_back(item);
}
{
const Item item{ .titleCtrl = createTitle(owner, "Status:"),
.inputCtrl = new wxTextCtrl(owner, wxID_ANY) };
items.push_back(item);
}
// Controls positioning
const auto ctrlSizer = new wxFlexGridSizer(2, 5, 5);
for (const auto &item : items)
{
ctrlSizer->Add(item.titleCtrl, wxSizerFlags(0).Expand().CenterVertical());
ctrlSizer->Add(item.inputCtrl, wxSizerFlags(1).Expand());
}
ctrlSizer->AddGrowableCol(1, 1);
const auto localSizer = new wxStaticBoxSizer(wxVERTICAL, owner, "Classification");
localSizer->Add(ctrlSizer, wxSizerFlags(0).Expand().Border(wxALL, 5));
return localSizer;
}
//--------------------------------------------------------------
/* Helper function to create a section title control */
wxStaticText *RequirementDetailPanel::createTitle(wxWindow *owner, const wxString &title)
{
const auto ctrl = new wxStaticText(owner,
wxID_ANY,
title,
wxDefaultPosition,
wxDefaultSize,
wxST_NO_AUTORESIZE | wxALIGN_RIGHT);
m_titleControls.push_back(ctrl);
return ctrl;
}
//--------------------------------------------------------------
/* Harmonize the sizes of the title controls to ensure they have the same width */
void RequirementDetailPanel::updateTitleSizes() const
{
int maxWidth = 0;
for (const auto &ctrl : m_titleControls)
{
maxWidth = std::max(maxWidth, ctrl->GetSize().GetWidth());
}
for (const auto &ctrl : m_titleControls)
{
ctrl->SetMinSize(wxSize(maxWidth, -1));
}
}
//--------------------------------------------------------------

View File

@@ -0,0 +1,35 @@
#pragma once
#include <dBus/dBus.h>
#include <wx/wx.h>
namespace gui
{
//--------------------------------------------------------------
class RequirementDetailPanel : public wxScrolledWindow
{
public:
RequirementDetailPanel() = delete; // Default constructor
virtual ~RequirementDetailPanel() = default; // Default destructor
RequirementDetailPanel(const RequirementDetailPanel &obj) = delete; // Copy constructor
RequirementDetailPanel(RequirementDetailPanel &&obj) noexcept = delete; // Move constructor
RequirementDetailPanel &operator=(const RequirementDetailPanel &obj) = delete; // Copy assignment operator
RequirementDetailPanel &operator=(RequirementDetailPanel &&obj) noexcept = delete; // Move assignment operator
explicit RequirementDetailPanel(wxWindow *parentWindow, dBus::Bus &bus); // Constructor
protected:
dBus::Bus &m_bus; // Reference to the application bus
std::vector<wxControl *> m_titleControls; // Titles controls for each section (metadata, details, classification)
private:
void createControls(); // Creating controls
wxSizer *createControls_metadata(wxWindow *owner); // Creating controls for requirement metadata
wxSizer *createControls_details(wxWindow *owner); // Creating controls for requirement details
wxSizer *createControls_classification(wxWindow *owner); // Creating controls for requirement classification
wxStaticText *createTitle(wxWindow *owner, const wxString &title); // Helper function to create a section title control
void updateTitleSizes() const; // Harmonize the sizes of the title controls to ensure they have the same width
};
//--------------------------------------------------------------
} // namespace gui