From a75dd7388020c01b7d9b617810e6b514cbeb5158 Mon Sep 17 00:00:00 2001 From: fredzo Date: Tue, 27 Jan 2026 15:30:11 +0100 Subject: [PATCH 01/12] Added ENABLE/DISABLE toggle on oscillopscope channels. --- src/ngscopeclient/StreamBrowserDialog.cpp | 47 ++++++++++++++++++++--- src/ngscopeclient/StreamBrowserDialog.h | 2 +- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/ngscopeclient/StreamBrowserDialog.cpp b/src/ngscopeclient/StreamBrowserDialog.cpp index 6a283862..f984b6ec 100644 --- a/src/ngscopeclient/StreamBrowserDialog.cpp +++ b/src/ngscopeclient/StreamBrowserDialog.cpp @@ -416,8 +416,10 @@ bool StreamBrowserDialog::renderOnOffToggle(const char* label, bool alignRight, @param inst the instrument to render the progress channel for @param chan the channel to render the progress for @param isLast true if it is the last channel of the instrument + + @return Returns true if the progress bar has been rendered */ -void StreamBrowserDialog::renderDownloadProgress(std::shared_ptr inst, InstrumentChannel *chan, bool isLast) +bool StreamBrowserDialog::renderDownloadProgress(std::shared_ptr inst, InstrumentChannel *chan, bool isLast) { static const char* const download[] = {"DOWNLOADING", "DOWNLOAD" ,"DL","D", NULL}; @@ -516,7 +518,7 @@ void StreamBrowserDialog::renderDownloadProgress(std::shared_ptr ins } if (!shouldRender) - return; + return false; /// @brief Width used to display progress bars (e.g. download progress bar) #define PROGRESS_BAR_WIDTH 80 @@ -548,10 +550,11 @@ void StreamBrowserDialog::renderDownloadProgress(std::shared_ptr ins ImGui::ProgressBar(chan->GetDownloadProgress(), ImVec2(PROGRESS_BAR_WIDTH, ImGui::GetFontSize())); } - return; + return true; } } // well, shoot -- I guess there wasn't enough room to do *anything* useful! + return true; } /** @@ -1525,17 +1528,49 @@ void StreamBrowserDialog::renderChannelNode(shared_ptr instrument, s startBadgeLine(); if (scopechan) { + bool chanEnabled = scopechan->IsEnabled(); + //"trigger" badge on trigger inputs to show they're not displayable channels if(scopechan->GetType(0) == Stream::STREAM_TYPE_TRIGGER) renderBadge(ImGui::ColorConvertU32ToFloat4(prefs.GetColor("Appearance.Stream Browser.instrument_disabled_badge_color")), "TRIG ONLY", "TRIG","--", nullptr); // Scope channel - else if (!scopechan->IsEnabled()) - renderBadge(ImGui::ColorConvertU32ToFloat4(prefs.GetColor("Appearance.Stream Browser.instrument_disabled_badge_color")), "DISABLED", "DISA","--", nullptr); + else if (!chanEnabled) + { + if(renderToggle( + "###scopeChanEnable", + true, + ImGui::ColorConvertU32ToFloat4(prefs.GetColor("Appearance.Stream Browser.instrument_disabled_badge_color")), + chanEnabled, + "DISABLED", + "ENABLE", + 3)) + { + if(chanEnabled) + scope->EnableChannel(channelIndex); + } + //renderBadge(ImGui::ColorConvertU32ToFloat4(prefs.GetColor("Appearance.Stream Browser.instrument_disabled_badge_color")), "DISABLED", "DISA","--", nullptr); + } //Download in progress else - renderDownloadProgress(instrument, channel, isLast); + { + if(!renderDownloadProgress(instrument, channel, isLast)) + { // No download in progress, we can show the ENABLE/DISABLE toggle + if(renderToggle( + "###scopeChanEnable", + true, + ImGui::ColorConvertU32ToFloat4(prefs.GetColor("Appearance.Stream Browser.instrument_on_badge_color")), + chanEnabled, + "DISABLE", + "ENABLED", + 3)) + { + if(!chanEnabled) + scope->DisableChannel(channelIndex); + } + } + } } else if(psu) { diff --git a/src/ngscopeclient/StreamBrowserDialog.h b/src/ngscopeclient/StreamBrowserDialog.h index b4b280a3..5e9fdd2f 100644 --- a/src/ngscopeclient/StreamBrowserDialog.h +++ b/src/ngscopeclient/StreamBrowserDialog.h @@ -155,7 +155,7 @@ class StreamBrowserDialog : public Dialog uint8_t cropTextTo = 0, float paddingRight = 0); bool renderOnOffToggle(const char* label, bool alignRight, bool& curValue, const char* valueOff = "OFF", const char* valueOn = "ON", uint8_t cropTextTo = 0, float paddingRight = 0); - void renderDownloadProgress(std::shared_ptr inst, InstrumentChannel *chan, bool isLast); + bool renderDownloadProgress(std::shared_ptr inst, InstrumentChannel *chan, bool isLast); bool renderPsuRows(bool isVoltage, bool cc, PowerSupplyChannel* chan, std::string& currentValue, float& committedValue, std::string& measuredValue, bool &clicked, bool &hovered); void renderAwgProperties(std::shared_ptr awg, FunctionGeneratorChannel* awgchan); void renderDmmProperties(std::shared_ptr dmm, MultimeterChannel* dmmchan, bool isMain, bool &clicked, bool &hovered); From 25e30474db62d1bb6fc9f6379d0f1584722b1bfb Mon Sep 17 00:00:00 2001 From: fredzo Date: Wed, 28 Jan 2026 18:16:57 +0100 Subject: [PATCH 02/12] Firt step to DigitalBank drang and drop support. --- src/ngscopeclient/StreamBrowserDialog.cpp | 15 ++++++++- src/ngscopeclient/WaveformArea.cpp | 41 +++++++++++++++++++++-- src/ngscopeclient/WaveformArea.h | 2 ++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/ngscopeclient/StreamBrowserDialog.cpp b/src/ngscopeclient/StreamBrowserDialog.cpp index f984b6ec..78fa1131 100644 --- a/src/ngscopeclient/StreamBrowserDialog.cpp +++ b/src/ngscopeclient/StreamBrowserDialog.cpp @@ -1138,12 +1138,25 @@ void StreamBrowserDialog::renderInstrumentNode(shared_ptr instrument renderChannelNode(instrument,i,(i == lastEnabledChannelIndex)); } int bankNumber = 1; + bool bankIsOpen; for(auto bank : digitalBanks) { // Iterate on digital banks if(bank.size() > 1) { // Only show Digital Bank node if there is more than on channel in the bank string nodeName = "Digital Bank " + to_string(bankNumber); - if(ImGui::TreeNodeEx(nodeName.c_str())) + bankIsOpen = ImGui::TreeNodeEx(nodeName.c_str()); + // Add dragdrop source for this bank + if(ImGui::BeginDragDropSource()) + { + StreamGroupDescriptor* s = new StreamGroupDescriptor(nodeName, bank); + ImGui::SetDragDropPayload("StreamGroup", &s, sizeof(s)); + ImGui::TextUnformatted(s->GetName().c_str()); + ImGui::EndDragDropSource(); + } + else + DoItemHelp(); + + if(bankIsOpen) { ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); for(auto channel : bank) diff --git a/src/ngscopeclient/WaveformArea.cpp b/src/ngscopeclient/WaveformArea.cpp index 95e1a1c8..ed670e9b 100644 --- a/src/ngscopeclient/WaveformArea.cpp +++ b/src/ngscopeclient/WaveformArea.cpp @@ -3463,7 +3463,8 @@ void WaveformArea::CenterLeftDropArea(ImVec2 start, ImVec2 size) return; bool isWaveform = payload->IsDataType("Waveform"); bool isStream = payload->IsDataType("Stream"); - if(!isWaveform && !isStream) + bool isStreamGroup = payload->IsDataType("StreamGroup"); + if(!isWaveform && !isStream &&!isStreamGroup) return; //Peek the payload. If not compatible, don't even display the target @@ -3528,12 +3529,35 @@ void WaveformArea::CenterLeftDropArea(ImVec2 start, ImVec2 size) //Reject streams not compatible with this plot //TODO: display nice error message if not - if(!IsCompatible(stream)) + if(!IsCompatible(stream)||IsShowing(stream)) ok = false; else if(payload->IsDelivery()) AddStream(stream); } + //Accept stream group + auto sgpay = ImGui::AcceptDragDropPayload("StreamGroup", + ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect); + if(sgpay) + { + hover = true; + StreamGroupDescriptor* streamGroup = *reinterpret_cast(sgpay->Data); + //Reject streams not compatible with this plot + //TODO: display nice error message if not + ok = false; + for(auto channel : streamGroup->m_channels) + { + StreamDescriptor s(channel, 0); + if(IsCompatible(s) && !IsShowing(s)) + { // At least one stream is compatible + ok = true; + if(payload->IsDelivery()) + { + AddStream(s); + } + } + } + } ImGui::EndDragDropTarget(); } @@ -4388,6 +4412,19 @@ bool WaveformArea::IsCompatible(StreamDescriptor desc) return true; } +/** + @brief Checks if provided stream descriptor is already present in this waveform area + */ +bool WaveformArea::IsShowing(StreamDescriptor desc) +{ + for(auto channel : m_displayedChannels) + { + if(channel->GetStream() == desc) + return true; + } + return false; +} + /** @brief Checks if this area is currently displaying a provided stream */ diff --git a/src/ngscopeclient/WaveformArea.h b/src/ngscopeclient/WaveformArea.h index 963114d7..4f28ca4f 100644 --- a/src/ngscopeclient/WaveformArea.h +++ b/src/ngscopeclient/WaveformArea.h @@ -488,6 +488,8 @@ class WaveformArea : public SerializableObject bool IsCompatible(StreamDescriptor desc); + bool IsShowing(StreamDescriptor desc); + void RemoveStream(size_t i); void ClearPersistence(); From 190a23c705119e6e0ba9f427e074bd4769908050 Mon Sep 17 00:00:00 2001 From: fredzo Date: Wed, 28 Jan 2026 18:36:59 +0100 Subject: [PATCH 03/12] Moved to latest scopehal. --- lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib b/lib index 759ccb03..c53e9f46 160000 --- a/lib +++ b/lib @@ -1 +1 @@ -Subproject commit 759ccb037818efae7ffe46e2df95128de4aa1311 +Subproject commit c53e9f4675a288c5715d8a071b6b5ee9f03c0c5e From 35b18a88900dd62f7dd2af542fc00fffc98b5d10 Mon Sep 17 00:00:00 2001 From: fredzo Date: Wed, 28 Jan 2026 19:37:02 +0100 Subject: [PATCH 04/12] Added drop to center right wave area for Digital Banks. --- src/ngscopeclient/WaveformArea.cpp | 32 +++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/ngscopeclient/WaveformArea.cpp b/src/ngscopeclient/WaveformArea.cpp index ed670e9b..197714ce 100644 --- a/src/ngscopeclient/WaveformArea.cpp +++ b/src/ngscopeclient/WaveformArea.cpp @@ -3618,7 +3618,8 @@ void WaveformArea::CenterRightDropArea(ImVec2 start, ImVec2 size) return; bool isWaveform = payload->IsDataType("Waveform"); bool isStream = payload->IsDataType("Stream"); - if(!isWaveform && !isStream) + bool isStreamGroup = payload->IsDataType("StreamGroup"); + if(!isWaveform && !isStream && !isStreamGroup) return; //Add drop target @@ -3658,6 +3659,35 @@ void WaveformArea::CenterRightDropArea(ImVec2 start, ImVec2 size) } } + //Accept drag/drop payloads for digital banks + auto sgpay = ImGui::AcceptDragDropPayload("StreamGroup", ImGuiDragDropFlags_AcceptPeekOnly); + if(sgpay) + { + hover = true; + StreamGroupDescriptor* streamGroup = *reinterpret_cast(sgpay->Data); + + if( (streamGroup->GetXAxisUnits() == m_group->GetXAxisUnit()) && payload->IsDelivery() ) + { + std::shared_ptr area; + bool first = true; + bool singleArea = ImGui::IsKeyDown(ImGuiKey_LeftShift)||ImGui::IsKeyDown(ImGuiKey_RightShift); + for(auto channel : streamGroup->m_channels) + { + StreamDescriptor s(channel, 0); + if(first || !singleArea) + { + area = make_shared(s, m_group, m_parent); + m_group->AddArea(area); + first = false; + } + else + { + area->AddStream(s); + } + } + } + } + ImGui::EndDragDropTarget(); } From 1eda7e4ea0f921578cdb407ad20f744113102b95 Mon Sep 17 00:00:00 2001 From: fredzo Date: Thu, 29 Jan 2026 17:29:49 +0100 Subject: [PATCH 05/12] Added DigitalBank drop to split group. --- lib | 2 +- src/ngscopeclient/MainWindow.cpp | 37 +++++++++++++--- src/ngscopeclient/MainWindow.h | 54 ++++++++++++++++++++--- src/ngscopeclient/StreamBrowserDialog.cpp | 7 +-- src/ngscopeclient/StreamBrowserDialog.h | 3 ++ src/ngscopeclient/WaveformArea.cpp | 17 ++++++- 6 files changed, 103 insertions(+), 17 deletions(-) diff --git a/lib b/lib index c53e9f46..d715e23d 160000 --- a/lib +++ b/lib @@ -1 +1 @@ -Subproject commit c53e9f4675a288c5715d8a071b6b5ee9f03c0c5e +Subproject commit d715e23d1bf0239292a67b04667a07d64c1f6bd3 diff --git a/src/ngscopeclient/MainWindow.cpp b/src/ngscopeclient/MainWindow.cpp index e3d2b8cf..1a5b2654 100644 --- a/src/ngscopeclient/MainWindow.cpp +++ b/src/ngscopeclient/MainWindow.cpp @@ -1283,12 +1283,37 @@ void MainWindow::DockingArea() } ImGui::DockBuilderDockWindow(group->GetID().c_str(), node->ID); - //Add a new waveform area for our stream to the new group - LogTrace("Making new area for %s in %s\n", - request.m_stream.GetName().c_str(), - group->GetID().c_str()); - auto area = make_shared(request.m_stream, group, this); - group->AddArea(area); + //Add a new waveform area for our stream/streamGroup to the new group + if(request.m_stream) + { + LogTrace("Making new area for %s in %s\n", + request.m_stream.GetName().c_str(), + group->GetID().c_str()); + auto area = make_shared(request.m_stream, group, this); + group->AddArea(area); + } + else if(request.m_streamGroup) + { + std::shared_ptr area; + bool first = true; + for(auto channel : request.m_streamGroup->m_channels) + { + StreamDescriptor s(channel, 0); + LogTrace("Making new area for %s in %s\n", + s.GetName().c_str(), + group->GetID().c_str()); + if(first || !request.m_singleArea) + { + area = make_shared(s, group, this); + group->AddArea(area); + first = false; + } + else + { + area->AddStream(s); + } + } + } } //Finish up diff --git a/src/ngscopeclient/MainWindow.h b/src/ngscopeclient/MainWindow.h index 02a68690..e1d8ad53 100644 --- a/src/ngscopeclient/MainWindow.h +++ b/src/ngscopeclient/MainWindow.h @@ -65,34 +65,74 @@ class SplitGroupRequest : m_group(group) , m_direction(direction) , m_stream(stream) + , m_streamGroup(nullptr) { auto schan = dynamic_cast(stream.m_channel); if(schan) schan->AddRef(); } + SplitGroupRequest(std::shared_ptr group, ImGuiDir direction, std::shared_ptr streamGroup, bool singleArea) + : m_group(group) + , m_direction(direction) + , m_streamGroup(streamGroup) + , m_singleArea(singleArea) + { + if(streamGroup) + { + for(auto chan : streamGroup->m_channels) + { + chan->AddRef(); + } + } + } + SplitGroupRequest(const SplitGroupRequest& rhs) : m_group(rhs.m_group) , m_direction(rhs.m_direction) , m_stream(rhs.m_stream) + , m_streamGroup(rhs.m_streamGroup) + , m_singleArea(rhs.m_singleArea) { - auto schan = dynamic_cast(rhs.m_stream.m_channel); - if(schan) - schan->AddRef(); + if(rhs.m_stream) + { + auto schan = dynamic_cast(rhs.m_stream.m_channel); + if(schan) + schan->AddRef(); + } + else if(rhs.m_streamGroup) + { + for(auto chan : rhs.m_streamGroup->m_channels) + { + chan->AddRef(); + } + } } SplitGroupRequest& operator=(const SplitGroupRequest& /*rhs*/) =delete; ~SplitGroupRequest() { - auto schan = dynamic_cast(m_stream.m_channel); - if(schan) - schan->Release(); + if(m_stream) + { + auto schan = dynamic_cast(m_stream.m_channel); + if(schan) + schan->Release(); + } + else if(m_streamGroup) + { + for(auto chan : m_streamGroup->m_channels) + { + chan->Release(); + } + } } std::shared_ptr m_group; ImGuiDir m_direction; StreamDescriptor m_stream; + std::shared_ptr m_streamGroup; + bool m_singleArea; }; /** @@ -128,6 +168,8 @@ class MainWindow : public VulkanWindow void QueueSplitGroup(std::shared_ptr group, ImGuiDir direction, StreamDescriptor stream) { m_splitRequests.push_back(SplitGroupRequest(group, direction, stream)); } + void QueueSplitGroup(std::shared_ptr group, ImGuiDir direction, std::shared_ptr streamGroup, bool singleArea) + { m_splitRequests.push_back(SplitGroupRequest(group, direction, streamGroup, singleArea)); } void ShowChannelProperties(OscilloscopeChannel* channel); void ShowInstrumentProperties(std::shared_ptr instrument); diff --git a/src/ngscopeclient/StreamBrowserDialog.cpp b/src/ngscopeclient/StreamBrowserDialog.cpp index 78fa1131..a2dac5ec 100644 --- a/src/ngscopeclient/StreamBrowserDialog.cpp +++ b/src/ngscopeclient/StreamBrowserDialog.cpp @@ -1148,9 +1148,10 @@ void StreamBrowserDialog::renderInstrumentNode(shared_ptr instrument // Add dragdrop source for this bank if(ImGui::BeginDragDropSource()) { - StreamGroupDescriptor* s = new StreamGroupDescriptor(nodeName, bank); - ImGui::SetDragDropPayload("StreamGroup", &s, sizeof(s)); - ImGui::TextUnformatted(s->GetName().c_str()); + m_streamGroupDesciptor = make_shared(nodeName, bank); + auto ptr = m_streamGroupDesciptor.get(); + ImGui::SetDragDropPayload("StreamGroup", &ptr, sizeof(m_streamGroupDesciptor)); + ImGui::TextUnformatted(m_streamGroupDesciptor->GetName().c_str()); ImGui::EndDragDropSource(); } else diff --git a/src/ngscopeclient/StreamBrowserDialog.h b/src/ngscopeclient/StreamBrowserDialog.h index 5e9fdd2f..50092af5 100644 --- a/src/ngscopeclient/StreamBrowserDialog.h +++ b/src/ngscopeclient/StreamBrowserDialog.h @@ -189,6 +189,9 @@ class StreamBrowserDialog : public Dialog ///@brief Map of instruments to timebase settings std::map, std::shared_ptr > m_timebaseConfig; + ///@brief Reference to currently dragged StreamGroupDesciptor + std::shared_ptr m_streamGroupDesciptor; + ///@brief Helper to render a small button that's non-interactive void SmallDisabledButton(const char* label) { diff --git a/src/ngscopeclient/WaveformArea.cpp b/src/ngscopeclient/WaveformArea.cpp index 197714ce..fd333762 100644 --- a/src/ngscopeclient/WaveformArea.cpp +++ b/src/ngscopeclient/WaveformArea.cpp @@ -3330,7 +3330,8 @@ void WaveformArea::EdgeDropArea(const string& name, ImVec2 start, ImVec2 size, I bool isWaveform = payload->IsDataType("Waveform"); bool isStream = payload->IsDataType("Stream"); - if(!isWaveform && !isStream) + bool isStreamGroup = payload->IsDataType("StreamGroup"); + if(!isWaveform && !isStream && !isStreamGroup) return; //Add drop target @@ -3369,6 +3370,20 @@ void WaveformArea::EdgeDropArea(const string& name, ImVec2 start, ImVec2 size, I } } + auto sgpay = ImGui::AcceptDragDropPayload("StreamGroup", ImGuiDragDropFlags_AcceptPeekOnly); + if(sgpay) + { + StreamGroupDescriptor* streamGroup = *reinterpret_cast(sgpay->Data); + bool singleArea = ImGui::IsKeyDown(ImGuiKey_LeftShift)||ImGui::IsKeyDown(ImGuiKey_RightShift); + hover = true; + + //Add request to split our current group + if(payload->IsDelivery()) + { + LogTrace("splitting\n"); + m_parent->QueueSplitGroup(m_group, splitDir, streamGroup->shared_from_this(), singleArea); + } + } ImGui::EndDragDropTarget(); } From 24c2ad889b186ebfe38218d2df5e1ee49b18e055 Mon Sep 17 00:00:00 2001 From: fredzo Date: Thu, 29 Jan 2026 19:08:16 +0100 Subject: [PATCH 06/12] Fixe PSU on/off toggle. Added ENABLE/DSIABLE toggle to Digital Banks. --- src/ngscopeclient/StreamBrowserDialog.cpp | 55 +++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/src/ngscopeclient/StreamBrowserDialog.cpp b/src/ngscopeclient/StreamBrowserDialog.cpp index a2dac5ec..169e7e9f 100644 --- a/src/ngscopeclient/StreamBrowserDialog.cpp +++ b/src/ngscopeclient/StreamBrowserDialog.cpp @@ -1061,10 +1061,11 @@ void StreamBrowserDialog::renderInstrumentNode(shared_ptr instrument } } bool result; + bool changed; if(allOn || someOn) { result = true; - renderToggle( + changed = renderToggle( "###psuon", true, allOn ? @@ -1074,9 +1075,9 @@ void StreamBrowserDialog::renderInstrumentNode(shared_ptr instrument else { result = false; - renderOnOffToggle("###psuon", true, result); + changed = renderOnOffToggle("###psuon", true, result); } - if(result != allOn) + if(changed) { if(psu->SupportsMasterOutputSwitching()) psu->SetMasterPowerEnable(result); @@ -1145,6 +1146,7 @@ void StreamBrowserDialog::renderInstrumentNode(shared_ptr instrument { // Only show Digital Bank node if there is more than on channel in the bank string nodeName = "Digital Bank " + to_string(bankNumber); bankIsOpen = ImGui::TreeNodeEx(nodeName.c_str()); + // Add dragdrop source for this bank if(ImGui::BeginDragDropSource()) { @@ -1157,6 +1159,53 @@ void StreamBrowserDialog::renderInstrumentNode(shared_ptr instrument else DoItemHelp(); + // Add Banck on/off toggle + startBadgeLine(); + bool allOn = true; + bool someOn = false; + for(auto channel : bank) + { // Iterate on bank's channel + size_t i = channel->GetIndex(); + if(scope->IsChannelEnabled(i)) + { + someOn = true; + } + else + { + allOn = false; + } + } + bool result; + bool changed; + string toggleId = "###"+nodeName+"on"; + if(allOn || someOn) + { + result = true; + changed = renderToggle( + toggleId.c_str(), + true, + allOn ? + ImGui::ColorConvertU32ToFloat4(prefs.GetColor("Appearance.Stream Browser.instrument_on_badge_color")) : + ImGui::ColorConvertU32ToFloat4(prefs.GetColor("Appearance.Stream Browser.instrument_partial_badge_color")), result,"DISABLE","ENABLED",3); + } + else + { + result = false; + changed = renderToggle( + toggleId.c_str(), + true, + ImGui::ColorConvertU32ToFloat4(prefs.GetColor("Appearance.Stream Browser.instrument_off_badge_color")), + result,"DISABLED","ENABLE",3); + } + if(changed) + { + for(auto channel : bank) + { // Iterate on bank's channel + size_t i = channel->GetIndex(); + result ? scope->EnableChannel(i) : scope->DisableChannel(i); + } + } + if(bankIsOpen) { ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); From 0446cf146f1695df62312b2ead0e86abda51a6df Mon Sep 17 00:00:00 2001 From: fredzo Date: Thu, 29 Jan 2026 20:10:08 +0100 Subject: [PATCH 07/12] Merge start --- lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib b/lib index d715e23d..569f0c33 160000 --- a/lib +++ b/lib @@ -1 +1 @@ -Subproject commit d715e23d1bf0239292a67b04667a07d64c1f6bd3 +Subproject commit 569f0c331d2fcf2ac42f42dfa9c349429169f2dd From ddd79cfe2aa3fa865bebd4860b76c38968ce347c Mon Sep 17 00:00:00 2001 From: fredzo Date: Thu, 29 Jan 2026 20:11:14 +0100 Subject: [PATCH 08/12] Merge end --- lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib b/lib index 569f0c33..01f582e5 160000 --- a/lib +++ b/lib @@ -1 +1 @@ -Subproject commit 569f0c331d2fcf2ac42f42dfa9c349429169f2dd +Subproject commit 01f582e5a8e91ff1ff8d354042f9506370d8f0b3 From 7274f00d4b3affcfc6f3837cb4388cb1944dd28e Mon Sep 17 00:00:00 2001 From: fredzo Date: Thu, 29 Jan 2026 22:08:45 +0100 Subject: [PATCH 09/12] Removed Enable/Disable toggle on scope channels / digital banks. --- src/ngscopeclient/StreamBrowserDialog.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ngscopeclient/StreamBrowserDialog.cpp b/src/ngscopeclient/StreamBrowserDialog.cpp index 169e7e9f..85660581 100644 --- a/src/ngscopeclient/StreamBrowserDialog.cpp +++ b/src/ngscopeclient/StreamBrowserDialog.cpp @@ -1158,7 +1158,7 @@ void StreamBrowserDialog::renderInstrumentNode(shared_ptr instrument } else DoItemHelp(); - + /* Currently, enable/disable state is coupled to node reference counting, so we can't let the user manually enable/disable channels // Add Banck on/off toggle startBadgeLine(); bool allOn = true; @@ -1205,7 +1205,7 @@ void StreamBrowserDialog::renderInstrumentNode(shared_ptr instrument result ? scope->EnableChannel(i) : scope->DisableChannel(i); } } - + */ if(bankIsOpen) { ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); @@ -1597,6 +1597,7 @@ void StreamBrowserDialog::renderChannelNode(shared_ptr instrument, s if(scopechan->GetType(0) == Stream::STREAM_TYPE_TRIGGER) renderBadge(ImGui::ColorConvertU32ToFloat4(prefs.GetColor("Appearance.Stream Browser.instrument_disabled_badge_color")), "TRIG ONLY", "TRIG","--", nullptr); + /* Currently, enable/disable state is coupled to node reference counting, so we can't let the user manually enable/disable channels // Scope channel else if (!chanEnabled) { @@ -1613,13 +1614,15 @@ void StreamBrowserDialog::renderChannelNode(shared_ptr instrument, s scope->EnableChannel(channelIndex); } //renderBadge(ImGui::ColorConvertU32ToFloat4(prefs.GetColor("Appearance.Stream Browser.instrument_disabled_badge_color")), "DISABLED", "DISA","--", nullptr); - } + } + */ //Download in progress else { if(!renderDownloadProgress(instrument, channel, isLast)) { // No download in progress, we can show the ENABLE/DISABLE toggle + /* Currently, enable/disable state is coupled to node reference counting, so we can't let the user manually enable/disable channels if(renderToggle( "###scopeChanEnable", true, @@ -1632,6 +1635,7 @@ void StreamBrowserDialog::renderChannelNode(shared_ptr instrument, s if(!chanEnabled) scope->DisableChannel(channelIndex); } + */ } } } From c7208f80f25a8ee1c8ecfc998ea9f69c306f6512 Mon Sep 17 00:00:00 2001 From: fredzo Date: Mon, 9 Feb 2026 17:16:27 +0100 Subject: [PATCH 10/12] Prepare merge. --- lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib b/lib index 01f582e5..aaa5296f 160000 --- a/lib +++ b/lib @@ -1 +1 @@ -Subproject commit 01f582e5a8e91ff1ff8d354042f9506370d8f0b3 +Subproject commit aaa5296f177cc12f2a7ae622bc3f3c3064baae0b From bf96aec5f2c892319f538bb92a178a589eb89dd2 Mon Sep 17 00:00:00 2001 From: fredzo Date: Mon, 9 Feb 2026 17:50:18 +0100 Subject: [PATCH 11/12] Prepare merge. --- src/ngscopeclient/MainWindow.cpp | 45 +++++--------------- src/ngscopeclient/MainWindow.h | 73 ++++++++++---------------------- 2 files changed, 33 insertions(+), 85 deletions(-) diff --git a/src/ngscopeclient/MainWindow.cpp b/src/ngscopeclient/MainWindow.cpp index 1a5b2654..b5395011 100644 --- a/src/ngscopeclient/MainWindow.cpp +++ b/src/ngscopeclient/MainWindow.cpp @@ -1283,37 +1283,14 @@ void MainWindow::DockingArea() } ImGui::DockBuilderDockWindow(group->GetID().c_str(), node->ID); - //Add a new waveform area for our stream/streamGroup to the new group - if(request.m_stream) - { - LogTrace("Making new area for %s in %s\n", - request.m_stream.GetName().c_str(), - group->GetID().c_str()); - auto area = make_shared(request.m_stream, group, this); - group->AddArea(area); - } - else if(request.m_streamGroup) - { - std::shared_ptr area; - bool first = true; - for(auto channel : request.m_streamGroup->m_channels) - { - StreamDescriptor s(channel, 0); - LogTrace("Making new area for %s in %s\n", - s.GetName().c_str(), - group->GetID().c_str()); - if(first || !request.m_singleArea) - { - area = make_shared(s, group, this); - group->AddArea(area); - first = false; - } - else - { - area->AddStream(s); - } - } - } + //Add a new waveform area for our stream to the new group + LogTrace("Making new area for %s in %s\n", + request.m_stream.GetName().c_str(), + group->GetID().c_str()); + auto area = make_shared(request.m_stream, group, this); + if(request.m_ramp != "") + area->GetDisplayedChannel(0)->m_colorRamp = request.m_ramp; + group->AddArea(area); } //Finish up @@ -1702,7 +1679,7 @@ void MainWindow::RenameRecentInstrument(std::shared_ptr inst, co inst->GetTransportName() + ":" + inst->GetTransportConnectionString(); auto it = m_recentInstruments.find(oldConnectionString); - if (it != m_recentInstruments.end()) + if (it != m_recentInstruments.end()) { auto now = time(NULL); auto newConnectionString = @@ -1731,7 +1708,7 @@ void MainWindow::RepathRecentInstrument(std::shared_ptr inst, co inst->GetTransportName() + ":" + oldPath; auto it = m_recentInstruments.find(oldConnectionString); - if (it != m_recentInstruments.end()) + if (it != m_recentInstruments.end()) { auto now = time(NULL); auto newConnectionString = @@ -1894,7 +1871,7 @@ void MainWindow::RenderLoadWarningPopup() { if(!m_errorPopupTitle.empty()) return; // Already showing Error popup, skip Warning for now - + static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | diff --git a/src/ngscopeclient/MainWindow.h b/src/ngscopeclient/MainWindow.h index e1d8ad53..348441a4 100644 --- a/src/ngscopeclient/MainWindow.h +++ b/src/ngscopeclient/MainWindow.h @@ -61,78 +61,47 @@ class CreateFilterBrowser; class SplitGroupRequest { public: - SplitGroupRequest(std::shared_ptr group, ImGuiDir direction, StreamDescriptor stream) + SplitGroupRequest( + std::shared_ptr group, + ImGuiDir direction, + StreamDescriptor stream, + std::string ramp) : m_group(group) , m_direction(direction) , m_stream(stream) - , m_streamGroup(nullptr) + , m_ramp(ramp) { auto schan = dynamic_cast(stream.m_channel); if(schan) schan->AddRef(); } - SplitGroupRequest(std::shared_ptr group, ImGuiDir direction, std::shared_ptr streamGroup, bool singleArea) - : m_group(group) - , m_direction(direction) - , m_streamGroup(streamGroup) - , m_singleArea(singleArea) - { - if(streamGroup) - { - for(auto chan : streamGroup->m_channels) - { - chan->AddRef(); - } - } - } - SplitGroupRequest(const SplitGroupRequest& rhs) : m_group(rhs.m_group) , m_direction(rhs.m_direction) , m_stream(rhs.m_stream) - , m_streamGroup(rhs.m_streamGroup) - , m_singleArea(rhs.m_singleArea) + , m_ramp(rhs.m_ramp) { - if(rhs.m_stream) - { - auto schan = dynamic_cast(rhs.m_stream.m_channel); - if(schan) - schan->AddRef(); - } - else if(rhs.m_streamGroup) - { - for(auto chan : rhs.m_streamGroup->m_channels) - { - chan->AddRef(); - } - } + auto schan = dynamic_cast(rhs.m_stream.m_channel); + if(schan) + schan->AddRef(); } SplitGroupRequest& operator=(const SplitGroupRequest& /*rhs*/) =delete; ~SplitGroupRequest() { - if(m_stream) - { - auto schan = dynamic_cast(m_stream.m_channel); - if(schan) - schan->Release(); - } - else if(m_streamGroup) - { - for(auto chan : m_streamGroup->m_channels) - { - chan->Release(); - } - } + auto schan = dynamic_cast(m_stream.m_channel); + if(schan) + schan->Release(); } std::shared_ptr m_group; ImGuiDir m_direction; StreamDescriptor m_stream; - std::shared_ptr m_streamGroup; - bool m_singleArea; + + ///@brief Color ramp request (may be blank if unspecified) + std::string m_ramp; }; /** @@ -166,10 +135,12 @@ class MainWindow : public VulkanWindow void OnScopeAdded(std::shared_ptr scope, bool createViews); - void QueueSplitGroup(std::shared_ptr group, ImGuiDir direction, StreamDescriptor stream) - { m_splitRequests.push_back(SplitGroupRequest(group, direction, stream)); } - void QueueSplitGroup(std::shared_ptr group, ImGuiDir direction, std::shared_ptr streamGroup, bool singleArea) - { m_splitRequests.push_back(SplitGroupRequest(group, direction, streamGroup, singleArea)); } + void QueueSplitGroup( + std::shared_ptr group, + ImGuiDir direction, + StreamDescriptor stream, + std::string colorRamp) + { m_splitRequests.push_back(SplitGroupRequest(group, direction, stream, colorRamp)); } void ShowChannelProperties(OscilloscopeChannel* channel); void ShowInstrumentProperties(std::shared_ptr instrument); From d43f827d89f01a8f222e05ba284963b6d0ce9c0d Mon Sep 17 00:00:00 2001 From: fredzo Date: Mon, 9 Feb 2026 18:24:31 +0100 Subject: [PATCH 12/12] Finisehd merge. --- src/ngscopeclient/MainWindow.cpp | 41 ++++++++++++++++++----- src/ngscopeclient/MainWindow.h | 56 ++++++++++++++++++++++++++++---- 2 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/ngscopeclient/MainWindow.cpp b/src/ngscopeclient/MainWindow.cpp index b5395011..d5348a38 100644 --- a/src/ngscopeclient/MainWindow.cpp +++ b/src/ngscopeclient/MainWindow.cpp @@ -1283,14 +1283,39 @@ void MainWindow::DockingArea() } ImGui::DockBuilderDockWindow(group->GetID().c_str(), node->ID); - //Add a new waveform area for our stream to the new group - LogTrace("Making new area for %s in %s\n", - request.m_stream.GetName().c_str(), - group->GetID().c_str()); - auto area = make_shared(request.m_stream, group, this); - if(request.m_ramp != "") - area->GetDisplayedChannel(0)->m_colorRamp = request.m_ramp; - group->AddArea(area); + //Add a new waveform area for our stream/streamGroup to the new group + if(request.m_stream) + { + LogTrace("Making new area for %s in %s\n", + request.m_stream.GetName().c_str(), + group->GetID().c_str()); + auto area = make_shared(request.m_stream, group, this); + if(request.m_ramp != "") + area->GetDisplayedChannel(0)->m_colorRamp = request.m_ramp; + group->AddArea(area); + } + else if(request.m_streamGroup) + { + std::shared_ptr area; + bool first = true; + for(auto channel : request.m_streamGroup->m_channels) + { + StreamDescriptor s(channel, 0); + LogTrace("Making new area for %s in %s\n", + s.GetName().c_str(), + group->GetID().c_str()); + if(first || !request.m_singleArea) + { + area = make_shared(s, group, this); + group->AddArea(area); + first = false; + } + else + { + area->AddStream(s); + } + } + } } //Finish up diff --git a/src/ngscopeclient/MainWindow.h b/src/ngscopeclient/MainWindow.h index 348441a4..5773afc0 100644 --- a/src/ngscopeclient/MainWindow.h +++ b/src/ngscopeclient/MainWindow.h @@ -70,30 +70,68 @@ class SplitGroupRequest , m_direction(direction) , m_stream(stream) , m_ramp(ramp) + , m_streamGroup(nullptr) { auto schan = dynamic_cast(stream.m_channel); if(schan) schan->AddRef(); } + SplitGroupRequest(std::shared_ptr group, ImGuiDir direction, std::shared_ptr streamGroup, bool singleArea) + : m_group(group) + , m_direction(direction) + , m_streamGroup(streamGroup) + , m_singleArea(singleArea) + { + if(streamGroup) + { + for(auto chan : streamGroup->m_channels) + { + chan->AddRef(); + } + } + } + SplitGroupRequest(const SplitGroupRequest& rhs) : m_group(rhs.m_group) , m_direction(rhs.m_direction) , m_stream(rhs.m_stream) , m_ramp(rhs.m_ramp) + , m_streamGroup(rhs.m_streamGroup) + , m_singleArea(rhs.m_singleArea) { - auto schan = dynamic_cast(rhs.m_stream.m_channel); - if(schan) - schan->AddRef(); + if(rhs.m_stream) + { + auto schan = dynamic_cast(rhs.m_stream.m_channel); + if(schan) + schan->AddRef(); + } + else if(rhs.m_streamGroup) + { + for(auto chan : rhs.m_streamGroup->m_channels) + { + chan->AddRef(); + } + } } SplitGroupRequest& operator=(const SplitGroupRequest& /*rhs*/) =delete; ~SplitGroupRequest() { - auto schan = dynamic_cast(m_stream.m_channel); - if(schan) - schan->Release(); + if(m_stream) + { + auto schan = dynamic_cast(m_stream.m_channel); + if(schan) + schan->Release(); + } + else if(m_streamGroup) + { + for(auto chan : m_streamGroup->m_channels) + { + chan->Release(); + } + } } std::shared_ptr m_group; @@ -102,6 +140,9 @@ class SplitGroupRequest ///@brief Color ramp request (may be blank if unspecified) std::string m_ramp; + + std::shared_ptr m_streamGroup; + bool m_singleArea; }; /** @@ -142,6 +183,9 @@ class MainWindow : public VulkanWindow std::string colorRamp) { m_splitRequests.push_back(SplitGroupRequest(group, direction, stream, colorRamp)); } + void QueueSplitGroup(std::shared_ptr group, ImGuiDir direction, std::shared_ptr streamGroup, bool singleArea) + { m_splitRequests.push_back(SplitGroupRequest(group, direction, streamGroup, singleArea)); } + void ShowChannelProperties(OscilloscopeChannel* channel); void ShowInstrumentProperties(std::shared_ptr instrument); void ShowTriggerProperties();