From f58705bbc67bf1d35d6834cc5c3ee27515f14052 Mon Sep 17 00:00:00 2001 From: Josh Siegle Date: Fri, 29 Dec 2023 14:31:01 -0800 Subject: [PATCH] Display additional stream info in popup window --- Source/Processors/Editors/DelayMonitor.cpp | 11 +- Source/Processors/Editors/DelayMonitor.h | 4 + Source/Processors/Editors/GenericEditor.cpp | 32 ++-- Source/Processors/Editors/GenericEditor.h | 3 + Source/Processors/Editors/StreamSelector.cpp | 180 +++++++++++++++---- Source/Processors/Editors/StreamSelector.h | 12 +- Source/Processors/Editors/TTLMonitor.cpp | 6 + Source/Processors/Editors/TTLMonitor.h | 3 + 8 files changed, 203 insertions(+), 48 deletions(-) diff --git a/Source/Processors/Editors/DelayMonitor.cpp b/Source/Processors/Editors/DelayMonitor.cpp index 45e40bca3..5ecfda157 100644 --- a/Source/Processors/Editors/DelayMonitor.cpp +++ b/Source/Processors/Editors/DelayMonitor.cpp @@ -35,11 +35,12 @@ DelayMonitor::DelayMonitor() : DelayMonitor::~DelayMonitor() { - std::cout << "DELAY MONITOR DELETING" << std::endl; + //std::cout << "DELAY MONITOR DELETING" << std::endl; } void DelayMonitor::setDelay(float delayMs) { + //std::cout << "Delay monitor::setDelay " << delayMs << std::endl; delay = delayMs; } @@ -72,7 +73,15 @@ void DelayMonitor::timerCallback() void DelayMonitor::paint(Graphics& g) { + g.setColour(colour); g.setFont(font); g.drawText(String(delay, 2) + " ms", 0, 0, 60, 20, Justification::centredLeft); + } + + +void DelayMonitor::handleCommandMessage(int commandId) +{ + repaint(); +} \ No newline at end of file diff --git a/Source/Processors/Editors/DelayMonitor.h b/Source/Processors/Editors/DelayMonitor.h index de9abdc16..08d5049e7 100644 --- a/Source/Processors/Editors/DelayMonitor.h +++ b/Source/Processors/Editors/DelayMonitor.h @@ -69,12 +69,16 @@ class PLUGIN_API DelayMonitor : /** Stops the timer*/ void stopAcquisition(); + /** Sends repaint command asynchronously */ + void handleCommandMessage(int commandId); + private: bool isEnabled; Colour colour; float delay; Font font; + bool canRepaint = true; }; diff --git a/Source/Processors/Editors/GenericEditor.cpp b/Source/Processors/Editors/GenericEditor.cpp index d793687e6..6683d50bd 100755 --- a/Source/Processors/Editors/GenericEditor.cpp +++ b/Source/Processors/Editors/GenericEditor.cpp @@ -499,6 +499,18 @@ bool GenericEditor::checkDrawerButton(Button* button) } +void GenericEditor::updateDelayAndTTLMonitors() +{ + for (auto stream : getProcessor()->getDataStreams()) + { + delayMonitors[stream->getStreamId()] = streamSelector->getDelayMonitor(stream); + ttlMonitors[stream->getStreamId()] = streamSelector->getTTLMonitor(stream); + + streamSelector->getTTLMonitor(stream)->updateSettings(stream->getEventChannels()); + + } +} + void GenericEditor::update(bool isEnabled_) { isEnabled = isEnabled_; @@ -540,14 +552,7 @@ void GenericEditor::update(bool isEnabled_) selectedStream = streamSelector->finishedUpdate(); - for (auto stream : p->getDataStreams()) - { - delayMonitors[stream->getStreamId()] = streamSelector->getDelayMonitor(stream); - ttlMonitors[stream->getStreamId()] = streamSelector->getTTLMonitor(stream); - - streamSelector->getTTLMonitor(stream)->updateSettings(stream->getEventChannels()); - - } + updateDelayAndTTLMonitors(); if (numChannels == 0) { @@ -573,13 +578,20 @@ void GenericEditor::update(bool isEnabled_) void GenericEditor::setTTLState(uint16 streamId, int bit, bool state) { if (ttlMonitors.find(streamId) != ttlMonitors.end()) - ttlMonitors[streamId]->setState(bit, state); + { + if (ttlMonitors[streamId] != nullptr) + ttlMonitors[streamId]->setState(bit, state); + } } void GenericEditor::setMeanLatencyMs(uint16 streamId, float latencyMs) { if (delayMonitors.find(streamId) != delayMonitors.end()) - delayMonitors[streamId]->setDelay(latencyMs); + { + if (delayMonitors[streamId] != nullptr) + delayMonitors[streamId]->setDelay(latencyMs); + } + } bool GenericEditor::getCollapsedState() diff --git a/Source/Processors/Editors/GenericEditor.h b/Source/Processors/Editors/GenericEditor.h index 98a92898c..37ffaa5d9 100755 --- a/Source/Processors/Editors/GenericEditor.h +++ b/Source/Processors/Editors/GenericEditor.h @@ -264,6 +264,9 @@ class PLUGIN_API GenericEditor : public AudioProcessorEditor /** Get the ID of the stream that's currently selected.*/ uint16 getCurrentStream() { return selectedStream; } + /** Called when new TTL and Delay monitors are created */ + void updateDelayAndTTLMonitors(); + /** Notifies editor that the selected stream has changed.*/ virtual void selectedStreamHasChanged(); diff --git a/Source/Processors/Editors/StreamSelector.cpp b/Source/Processors/Editors/StreamSelector.cpp index 77e79fecc..e6cb74953 100644 --- a/Source/Processors/Editors/StreamSelector.cpp +++ b/Source/Processors/Editors/StreamSelector.cpp @@ -58,16 +58,30 @@ StreamInfoView::StreamInfoView(const DataStream* stream_, GenericEditor* editor_ streamName = stream->getName(); sourceNodeId = stream->getNodeId(); + delayMonitor = nullptr; + ttlMonitor = nullptr; + } void StreamInfoView::setDelayMonitor(DelayMonitor* monitor) { - delayMonitor = monitor; + + if (monitor != delayMonitor) + { + LOGD(streamName, " UPDATING DELAY MONITOR to ", monitor); + delayMonitor = monitor; + } + } void StreamInfoView::setTTLMonitor(TTLMonitor* monitor) { - ttlMonitor = monitor; + if (monitor != ttlMonitor) + { + LOGD(streamName, " UPDATING TTL MONITOR to ", monitor); + ttlMonitor = monitor; + } + } @@ -183,6 +197,7 @@ void StreamInfoView::buttonClicked(Button* button) } } + void StreamInfoView::resized() { @@ -579,6 +594,7 @@ Component* StreamTableModel::refreshComponentForCell(int rowNumber, if (delayMonitor == nullptr) { delayMonitor = new DelayMonitor(); + LOGD("CREATING NEW DELAY MONITOR ", delayMonitor); } streams[rowNumber]->setDelayMonitor(delayMonitor); @@ -593,6 +609,7 @@ Component* StreamTableModel::refreshComponentForCell(int rowNumber, if (ttlMonitor == nullptr) { ttlMonitor = new TTLMonitor(8, 8); + LOGD("CREATING NEW TTL MONITOR ", ttlMonitor); } streams[rowNumber]->setTTLMonitor(ttlMonitor); @@ -676,27 +693,8 @@ StreamSelectorTable::StreamSelectorTable(GenericEditor* ed_) : { tableModel = std::make_unique(this); - - streamTable = std::make_unique("Stream Table", tableModel.get()); + streamTable.reset(createTableView()); tableModel->table = streamTable.get(); - streamTable->setHeader(std::make_unique()); - - streamTable->getHeader().addColumn(" ", StreamTableModel::Columns::SELECTED, 12, 12, 12, TableHeaderComponent::notResizableOrSortable); - //streamTable->getHeader().addColumn("ID", StreamTableModel::Columns::PROCESSOR_ID, 30, 30, 30, TableHeaderComponent::notResizableOrSortable); - streamTable->getHeader().addColumn("Name", StreamTableModel::Columns::NAME, 94, 94, 94, TableHeaderComponent::notResizableOrSortable); - //streamTable->getHeader().addColumn("# CH", StreamTableModel::Columns::NUM_CHANNELS, 20, 20, 20, TableHeaderComponent::notResizableOrSortable); - //streamTable->getHeader().addColumn("Hz", StreamTableModel::Columns::SAMPLE_RATE, 40, 40, 40, TableHeaderComponent::notResizableOrSortable); - streamTable->getHeader().addColumn("DELAY", StreamTableModel::Columns::DELAY, 50, 50, 50, TableHeaderComponent::notResizableOrSortable); - streamTable->getHeader().addColumn("TTL", StreamTableModel::Columns::TTL_LINE_STATES, 60, 60, 60, TableHeaderComponent::notResizableOrSortable); - //streamTable->getHeader().addColumn("ENABLE", StreamTableModel::Columns::ENABLED, 15, 15, 15, TableHeaderComponent::notResizableOrSortable); - - streamTable->getHeader().setColour(TableHeaderComponent::ColourIds::backgroundColourId, Colour(240, 240, 240)); - streamTable->getHeader().setColour(TableHeaderComponent::ColourIds::highlightColourId, Colour(240, 240, 240)); - streamTable->getHeader().setColour(TableHeaderComponent::ColourIds::textColourId, Colour(20, 20, 20)); - - streamTable->setHeaderHeight(0); - streamTable->setRowHeight(20); - streamTable->setMultipleSelectionEnabled(false); addAndMakeVisible(streamTable.get()); streamTable->setBounds(2, 18, 231, 80); @@ -716,6 +714,40 @@ StreamSelectorTable::StreamSelectorTable(GenericEditor* ed_) : } +TableListBox* StreamSelectorTable::createTableView(bool expanded) +{ + TableListBox* table = new TableListBox("Stream Table", tableModel.get()); + + table->setHeader(std::make_unique()); + + table->getHeader().addColumn(" ", StreamTableModel::Columns::SELECTED, 12, 12, 12, TableHeaderComponent::notResizableOrSortable); + table->getHeader().addColumn("Name", StreamTableModel::Columns::NAME, 94, 94, 94, TableHeaderComponent::notResizableOrSortable); + table->getHeader().addColumn("DELAY", StreamTableModel::Columns::DELAY, 50, 50, 50, TableHeaderComponent::notResizableOrSortable); + table->getHeader().addColumn("TTL", StreamTableModel::Columns::TTL_LINE_STATES, 60, 60, 60, TableHeaderComponent::notResizableOrSortable); + + if (expanded) + { + table->getHeader().addColumn("ID", StreamTableModel::Columns::PROCESSOR_ID, 30, 30, 30, TableHeaderComponent::notResizableOrSortable); + table->getHeader().addColumn("# CH", StreamTableModel::Columns::NUM_CHANNELS, 20, 20, 20, TableHeaderComponent::notResizableOrSortable); + table->getHeader().addColumn("Hz", StreamTableModel::Columns::SAMPLE_RATE, 40, 40, 40, TableHeaderComponent::notResizableOrSortable); + table->getHeader().addColumn("ENABLE", StreamTableModel::Columns::ENABLED, 15, 15, 15, TableHeaderComponent::notResizableOrSortable); + } + + table->getHeader().setColour(TableHeaderComponent::ColourIds::backgroundColourId, Colour(240, 240, 240)); + table->getHeader().setColour(TableHeaderComponent::ColourIds::highlightColourId, Colour(240, 240, 240)); + table->getHeader().setColour(TableHeaderComponent::ColourIds::textColourId, Colour(20, 20, 20)); + + if (expanded) + table->setHeaderHeight(20); + else + table->setHeaderHeight(0); + + table->setRowHeight(20); + table->setMultipleSelectionEnabled(false); + + return table; +} + StreamSelectorTable::~StreamSelectorTable() { @@ -726,16 +758,67 @@ void StreamSelectorTable::buttonClicked(Button* button) { if (button == expanderButton.get()) { + LOGD("EXPANDER BUTTON CLICKED "); + + auto* table = createTableView(true); + table->setBounds(0, 0, 356, streams.size() * 20 + 20); + table->selectRow(viewedStreamIndex); + tableModel->table = table; + table->setLookAndFeel(customTableLookAndFeel.get()); + CallOutBox& myBox - = CallOutBox::launchAsynchronously(std::unique_ptr(streamTable.get()), + = CallOutBox::launchAsynchronously(std::unique_ptr(table), button->getScreenBounds(), nullptr); - myBox.setArrowSize(0); + + //Rectangle screenBounds1 = getScreenBounds(); + // screenBounds1.setLeft(screenBounds1.getTopLeft().x - 18); + + //if (streams.size() == 1) + // { + // screenBounds1.setTop(screenBounds1.getTopLeft().y - 18); + // } + //// else { + // screenBounds1.setTop(screenBounds1.getTopLeft().y + 2); + // } + + + + //Rectangle screenBounds2 = getScreenBounds(); + //screenBounds2.setLeft(screenBounds1.getTopLeft().x - 20); + //screenBounds2.setTop(screenBounds1.getTopLeft().y - 20); + + // myBox.updatePosition(button->getScreenBounds(), screenBounds1); myBox.setDismissalMouseClicksAreAlwaysConsumed(true); + myBox.addComponentListener(this); + + editor->updateDelayAndTTLMonitors(); + } } + +void StreamSelectorTable::componentBeingDeleted(Component& component) +{ + LOGD("POPUP TABLE CLOSED"); + + tableModel->table = streamTable.get(); + streamTable->selectRow(viewedStreamIndex); + + Array newStreams; + + for (auto stream : streams) + { + newStreams.add(stream); + } + + tableModel->update(newStreams, viewedStreamIndex); + + editor->updateDelayAndTTLMonitors(); + +} + int StreamSelectorTable::getDesiredWidth() { return 240; @@ -826,18 +909,26 @@ void StreamSelectorTable::timerCallback() for (auto stream : streams) { - stream->getTTLMonitor()->repaint(); + TTLMonitor* ttlMonitor = stream->getTTLMonitor(); + + if (ttlMonitor != nullptr) + stream->getTTLMonitor()->repaint(); // postCommandMessage(0); } counter++; - if (counter == 5) + if (counter == 10) { counter = 0; for (auto stream : streams) { - stream->getDelayMonitor()->repaint(); + DelayMonitor* delayMonitor = stream->getDelayMonitor(); + + if (delayMonitor != nullptr) + delayMonitor->repaint(); // postCommandMessage(0); + + //LOGD(delayMonitor); } } } @@ -878,7 +969,7 @@ void StreamSelectorTable::paint(Graphics& g) g.setColour(Colours::darkgrey); - g.fillRect(0, 20, getWidth()-5, getHeight() - 20); + g.fillRect(0, 20, getWidth()-5, getHeight() - 21); g.fillRoundedRectangle(0, 0, getWidth() - 5, getHeight() - 40, 5.0f); g.setColour(Colours::lightgrey); g.setFont(12); @@ -889,12 +980,11 @@ void StreamSelectorTable::paint(Graphics& g) const DataStream* StreamSelectorTable::getCurrentStream() { - /*if (streams.size() > 0) - return streams[0]->getStream(); + if (streams.size() > 0) + return streams[viewedStreamIndex]->getStream(); else - return nullptr;*/ + return nullptr; - return nullptr; } @@ -924,12 +1014,30 @@ uint16 StreamSelectorTable::finishedUpdate() tableModel->update(newStreams, viewedStreamIndex); - if (viewedStreamIndex > -1) - return streams[viewedStreamIndex]->getStream()->getStreamId(); - else + + + if (streams.size() == 0) + { + expanderButton->setEnabled(false); return 0; + } + else { + expanderButton->setEnabled(true); + + if (viewedStreamIndex < streams.size()) + { + streamTable->selectRow(viewedStreamIndex); + return streams[viewedStreamIndex]->getStream()->getStreamId(); + } + else + { + viewedStreamIndex = streams.size() - 1; + streamTable->selectRow(viewedStreamIndex); + return streams[viewedStreamIndex]->getStream()->getStreamId(); + } + + } - return 0; } void StreamSelectorTable::remove(StreamInfoView* stream) diff --git a/Source/Processors/Editors/StreamSelector.h b/Source/Processors/Editors/StreamSelector.h index 14954c837..7466422cf 100644 --- a/Source/Processors/Editors/StreamSelector.h +++ b/Source/Processors/Editors/StreamSelector.h @@ -318,6 +318,9 @@ class CustomTableLookAndFeel : public LookAndFeel_V4 { public: CustomTableLookAndFeel(); + + void drawCallOutBoxBackground(CallOutBox& box, Graphics& g, + const Path& path, Image& cachedImage) override { } }; /** @@ -329,7 +332,8 @@ Lives inside the GenericEditor */ class PLUGIN_API StreamSelectorTable : public Component, public Button::Listener, - public Timer + public Timer, + public ComponentListener { public: @@ -396,6 +400,9 @@ class PLUGIN_API StreamSelectorTable : public Component, /** Used to enable and disable a given stream*/ void setStreamEnabledState(uint16 streamId, bool isEnabled); + /** Called when popup window is deleted */ + void componentBeingDeleted(Component& component) override; + /** Pointer to editor */ GenericEditor* editor; @@ -407,6 +414,9 @@ class PLUGIN_API StreamSelectorTable : public Component, /** Renders delay & TTL monitors */ void timerCallback(); + /** Creates a new table view */ + TableListBox* createTableView(bool expanded = false); + std::unique_ptr tableModel; std::unique_ptr streamTable; std::unique_ptr expanderButton; diff --git a/Source/Processors/Editors/TTLMonitor.cpp b/Source/Processors/Editors/TTLMonitor.cpp index 3c20a205d..6a11f9e2b 100644 --- a/Source/Processors/Editors/TTLMonitor.cpp +++ b/Source/Processors/Editors/TTLMonitor.cpp @@ -129,3 +129,9 @@ void TTLMonitor::stopAcquisition() { stopTimer(); } + + +void TTLMonitor::handleCommandMessage(int commandId) +{ + repaint(); +} \ No newline at end of file diff --git a/Source/Processors/Editors/TTLMonitor.h b/Source/Processors/Editors/TTLMonitor.h index 3ab2bfe9e..ed029d655 100644 --- a/Source/Processors/Editors/TTLMonitor.h +++ b/Source/Processors/Editors/TTLMonitor.h @@ -101,6 +101,9 @@ class PLUGIN_API TTLMonitor : public Component, /** Repaints the TTL bits*/ void timerCallback(); + /** Sends repaint command asynchronously */ + void handleCommandMessage(int commandId); + private: Array colours;