Skip to content

Commit

Permalink
UI code for selecting/adding/removing block's context
Browse files Browse the repository at this point in the history
CLOSES: #212
Signed-off-by: Daniel Nicoletti <[email protected]>
  • Loading branch information
dantti committed Nov 29, 2024
1 parent 89dbddc commit ad61d5f
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 11 deletions.
2 changes: 1 addition & 1 deletion cmake/DependenciesSHAs.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(GIT_SHA_GNURADIO4 8e18ec00bcb9b74b3b09282c90b5f58104ca5d80 CACHE STRING "" FORCE) # main as of 2024-11-25
set(GIT_SHA_GNURADIO4 eaed8af2d858495dcb61e9736763838fcdb801c2 CACHE STRING "" FORCE) # main as of 2024-11-29

set(GIT_SHA_OPENCMW_CPP bb8996babab2000a4ae3612ea146a551a96e59c4 CACHE STRING "" FORCE) # main as of 2024-10-18

Expand Down
21 changes: 15 additions & 6 deletions src/ui/Flowgraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,15 +632,24 @@ ExecutionContext FlowGraph::createExecutionContext() {
}

void FlowGraph::handleMessage(const gr::Message& msg) {
graphModel.processMessage(msg);
const bool consumed = graphModel.processMessage(msg);

if (msg.serviceName != App::instance().schedulerUniqueName() && msg.endpoint == gr::block::property::kSetting) {
const auto it = std::ranges::find_if(m_blocks, [&](const auto& b) { return b->m_uniqueName == msg.serviceName; });
if (it == m_blocks.end()) {
auto error = fmt::format("Received settings for unknown block '{}'", msg.serviceName);
components::Notification::error(error);
if (msg.serviceName == App::instance().schedulerUniqueName()) {
return;
}

const auto it = std::ranges::find_if(m_blocks, [&](const auto& b) { return b->m_uniqueName == msg.serviceName; });
if (it == m_blocks.end()) {
if (consumed) {
return;
}

auto error = fmt::format("Received settings for unknown block '{}'", msg.serviceName);
components::Notification::error(error);
return;
}

if (msg.endpoint == gr::block::property::kSetting) {
if (!msg.data) {
auto error = fmt::format("Received settings error for block '{}': {}", msg.serviceName, msg.data.error());
components::Notification::error(error);
Expand Down
121 changes: 118 additions & 3 deletions src/ui/GraphModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ void updateFieldFrom(FieldType& field, const auto& data, const std::string& fiel
};
} // namespace

void UiGraphModel::processMessage(const gr::Message& message) {
bool UiGraphModel::processMessage(const gr::Message& message) {
namespace graph = gr::graph::property;
namespace block = gr::block::property;

if (!message.data) {
DigitizerUi::components::Notification::error(fmt::format("Received an error: {}\n", message.data.error().message));
return;
return false;
}

const auto& data = *message.data;
Expand Down Expand Up @@ -92,13 +92,27 @@ void UiGraphModel::processMessage(const gr::Message& message) {
} else if (message.endpoint == "LifecycleState") {
// Nothing to do for lifecycle state changes

} else if (message.endpoint == block::kActiveContext) {
handleBlockActiveContext(message.serviceName, data);

} else if (message.endpoint == block::kSettingsContexts) {
if (message.clientRequestID == "all") {
handleBlockAllContexts(message.serviceName, data);
}
} else if (message.endpoint == block::kSettingsCtx) {
if (message.clientRequestID == "add" || message.clientRequestID == "rm") {
handleBlockAddOrRemoveContext(message.serviceName, data);
}
} else {
fmt::print("Not processed: {} data: {}\n", message.endpoint, message.data.error());
if (!message.data) {
fmt::print("Not processed: {} data: {}\n", message.endpoint, message.data.error());
auto msg = fmt::format("Error: {}\n", message.data.error().message);
DigitizerUi::components::Notification::error(msg);
}
return false;
}

return true;
//
}

Check notice on line 118 in src/ui/GraphModel.cpp

View check run for this annotation

codefactor.io / CodeFactor

src/ui/GraphModel.cpp#L42-L118

Complex Method
Expand Down Expand Up @@ -170,6 +184,53 @@ void UiGraphModel::handleBlockSettingsChanged(const std::string& uniqueName, con

void UiGraphModel::handleBlockSettingsStaged(const std::string& uniqueName, const gr::property_map& data) { handleBlockSettingsChanged(uniqueName, data); }

void UiGraphModel::handleBlockActiveContext(const std::string& uniqueName, const gr::property_map& data) {
auto [blockIt, found] = findBlockByName(uniqueName);
if (!found) {
requestGraphUpdate();
return;
}

const auto ctx = std::get<std::string>(data.at("context"));
auto time = std::get<std::uint64_t>(data.at("time"));

blockIt->activeContext = UiGraphBlock::ContextTime{
.context = ctx,
.time = time,
};
}

void UiGraphModel::handleBlockAllContexts(const std::string& uniqueName, const gr::property_map& data) {
auto [blockIt, found] = findBlockByName(uniqueName);
if (!found) {
requestGraphUpdate();
return;
}

auto contexts = std::get<std::vector<std::string>>(data.at("contexts"));
auto times = std::get<std::vector<std::uint64_t>>(data.at("times"));

std::vector<UiGraphBlock::ContextTime> contextAndTimes;
for (int i = 0; i < contexts.size(); ++i) {
contextAndTimes.emplace_back(UiGraphBlock::ContextTime{
.context = contexts[i],
.time = times[i],
});
}
blockIt->contexts = contextAndTimes;
}

void UiGraphModel::handleBlockAddOrRemoveContext(const std::string& uniqueName, const gr::property_map& data) {
auto [blockIt, found] = findBlockByName(uniqueName);
if (!found) {
requestGraphUpdate();
return;
}

blockIt->getAllContexts();
blockIt->getActiveContext();
}

void UiGraphModel::handleEdgeEmplaced(const gr::property_map& data) {
UiGraphEdge edge(this);
if (setEdgeData(edge, data)) {
Expand Down Expand Up @@ -260,6 +321,9 @@ void UiGraphModel::setBlockData(auto& block, const gr::property_map& blockData)
processPorts(block.outputPorts, "outputPorts"s, gr::PortDirection::OUTPUT);
block.inputPortWidths.clear();
block.outputPortWidths.clear();

block.getAllContexts();
block.getActiveContext();
}

// TODO: When adding support for nested graphs, need to process
Expand Down Expand Up @@ -340,3 +404,54 @@ void UiGraphModel::removeEdgesForBlock(UiGraphBlock& block) {
edge.edgeDestinationPort->ownerBlock == blockPtr;
});
}

void UiGraphBlock::getAllContexts() {
App::instance().sendMessage(gr::Message{
.cmd = gr::Message::Get,
.serviceName = blockUniqueName,
.clientRequestID = "all",
.endpoint = gr::block::property::kSettingsContexts,
});
}

void UiGraphBlock::setActiveContext(const ContextTime& contextTime) {
const auto& [context, time] = contextTime;
App::instance().sendMessage(gr::Message{
.cmd = gr::Message::Set,
.serviceName = blockUniqueName,
.clientRequestID = "activate",
.endpoint = gr::block::property::kActiveContext,
.data = gr::property_map{{"context", context}, {"time", time}},
});
}

void UiGraphBlock::getActiveContext() {
App::instance().sendMessage(gr::Message{
.cmd = gr::Message::Get,
.serviceName = blockUniqueName,
.clientRequestID = "active",
.endpoint = gr::block::property::kActiveContext,
});
}

void UiGraphBlock::addContext(const ContextTime& contextTime) {
const auto& [context, time] = contextTime;
App::instance().sendMessage(gr::Message{
.cmd = gr::Message::Set,
.serviceName = blockUniqueName,
.clientRequestID = "add",
.endpoint = gr::block::property::kSettingsCtx,
.data = gr::property_map{{"context", context}, {"time", time}},
});
}

void UiGraphBlock::removeContext(const ContextTime& contextTime) {
const auto& [context, time] = contextTime;
App::instance().sendMessage(gr::Message{
.cmd = gr::Message::Disconnect,
.serviceName = blockUniqueName,
.clientRequestID = "rm",
.endpoint = gr::block::property::kSettingsCtx,
.data = gr::property_map{{"context", context}, {"time", time}},
});
}
23 changes: 22 additions & 1 deletion src/ui/GraphModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ struct UiGraphPort {
struct UiGraphBlock {
UiGraphModel* ownerGraph = nullptr;

struct ContextTime {
std::string context;
std::uint64_t time = 1;
};
ContextTime activeContext;
std::vector<ContextTime> contexts;

std::string blockUniqueName;
std::string blockName;
std::string blockTypeName;
Expand Down Expand Up @@ -57,6 +64,14 @@ struct UiGraphBlock {
// std::vector<UiGraphEdge> edges

UiGraphBlock(UiGraphModel* owner) : ownerGraph(owner) {}

void getAllContexts();

void setActiveContext(const ContextTime& contextTime);
void getActiveContext();

void addContext(const ContextTime& contextTime);
void removeContext(const ContextTime& contextTime);
};

struct UiGraphEdge {
Expand Down Expand Up @@ -108,7 +123,10 @@ class UiGraphModel {
const auto& edges() const { return _edges; }
auto& edges() { return _edges; }

void processMessage(const gr::Message& message);
/**
* @return true if consumed the message
*/
bool processMessage(const gr::Message& message);

void requestGraphUpdate();

Expand All @@ -126,6 +144,9 @@ class UiGraphModel {
void handleBlockDataUpdated(const std::string& uniqueName, const gr::property_map& blockData);
void handleBlockSettingsChanged(const std::string& uniqueName, const gr::property_map& data);
void handleBlockSettingsStaged(const std::string& uniqueName, const gr::property_map& data);
void handleBlockActiveContext(const std::string& uniqueName, const gr::property_map& data);
void handleBlockAllContexts(const std::string& uniqueName, const gr::property_map& data);
void handleBlockAddOrRemoveContext(const std::string& uniqueName, const gr::property_map& data);
void handleEdgeEmplaced(const gr::property_map& data);
void handleEdgeRemoved(const gr::property_map& data);
void handleGraphRedefined(const gr::property_map& data);
Expand Down
77 changes: 77 additions & 0 deletions src/ui/components/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

namespace DigitizerUi::components {

constexpr const char* addContextPopupId = "Add Context";
constexpr const char* removeContextPopupId = "Remove Context";

void setItemTooltip(const char* fmt, auto&&... args) {
if (ImGui::IsItemHovered()) {
if constexpr (sizeof...(args) == 0) {
Expand All @@ -22,6 +25,39 @@ void setItemTooltip(const char* fmt, auto&&... args) {
}
}

void drawAddContextPopup(UiGraphBlock* block) {
ImGui::SetNextWindowSize({600, 120}, ImGuiCond_Once);
if (auto popup = IMW::ModalPopup(addContextPopupId, nullptr, 0)) {
ImGui::AlignTextToFramePadding();
ImGui::Text("Name:");
ImGui::SameLine();
static std::string name;
if (ImGui::IsWindowAppearing()) {
name = {};
}
ImGui::InputText("##contextName", &name);

const bool okEnabled = !name.empty();

if (components::DialogButtons(okEnabled) == components::DialogButton::Ok) {
block->addContext(UiGraphBlock::ContextTime{
.context = name,
.time = 1,
});
}
}
}

bool drawRemoveContextPopup(const std::string& context) {
ImGui::SetNextWindowSize({600, 100}, ImGuiCond_Once);
if (auto popup = IMW::ModalPopup(removeContextPopupId, nullptr, 0)) {
ImGui::AlignTextToFramePadding();
ImGui::Text("Do you wanto to remove '%s' context?", context.c_str());
return components::DialogButtons() == components::DialogButton::Ok;
}
return false;
}

void BlockControlsPanel(Dashboard& dashboard, DashboardPage& dashboardPage, BlockControlsPanelContext& context, const ImVec2& pos, const ImVec2& frameSize, bool verticalLayout) {
if (!context.block) {
return;
Expand Down Expand Up @@ -262,6 +298,47 @@ void BlockControlsPanel(Dashboard& dashboard, DashboardPage& dashboardPage, Bloc
ImGui::TextUnformatted(context.block->blockName.c_str());
std::string_view typeName = context.block->blockTypeName;

const auto& activeContext = context.block->activeContext;

const std::string activeContextLabel = activeContext.context == "" ? "Default" : activeContext.context;
if (ImGui::BeginCombo("##contextNameCombo", activeContextLabel.c_str())) {
for (const auto& contextNameAndTime : context.block->contexts) {
const bool selected = activeContext.context == contextNameAndTime.context;
const std::string label = contextNameAndTime.context == "" ? "Default" : contextNameAndTime.context;
if (ImGui::Selectable(label.c_str(), selected)) {
context.block->setActiveContext(contextNameAndTime);
}
if (selected) {
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}

{
ImGui::SameLine();
IMW::Disabled disableDueDefaultAction(activeContext.context == "");
IMW::Font _(LookAndFeel::instance().fontIconsSolid);
if (ImGui::Button("\uf146")) {
ImGui::OpenPopup(removeContextPopupId);
}
}
setItemTooltip("%s", "Remove context");

{
ImGui::SameLine();
IMW::Font _(LookAndFeel::instance().fontIconsSolid);
if (ImGui::Button("\uf0fe")) {
ImGui::OpenPopup(addContextPopupId);
}
}
setItemTooltip("%s", "Add new context");

drawAddContextPopup(context.block);
if (drawRemoveContextPopup(activeContext.context)) {
context.block->removeContext(activeContext);
}

ImGui::TextUnformatted("<");
ImGui::SameLine();

Expand Down

0 comments on commit ad61d5f

Please sign in to comment.