ui: compact events block in the dock
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
b08494dd36
commit
baf1c73b21
5 files changed
+287
-5
No files matched your search
+28
-4
@@ -52,6 +52,7 @@ void sync_events_availability(App& app) {
|
||||
// the button that shows it must not go with the switch. `events_cached` is refreshed once a second
|
||||
// from the tick -- the store's list is a directory read, not a per-frame question.
|
||||
const bool available = app.event_recording || app.replaying || app.events_cached;
|
||||
dock_events_set_sensitive(app, available);
|
||||
gtk_widget_set_visible(app.events_toggle, available);
|
||||
if (!available) {
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(app.events_toggle), FALSE);
|
||||
@@ -132,11 +133,14 @@ bool record_event(App& app) {
|
||||
set_notice(app, "event cached: " + std::to_string(table.columns.size()) + " signals, " +
|
||||
std::to_string(table.rows()) + " samples",
|
||||
3);
|
||||
// Only while the pane is on screen: rebuilding every row per latch for a column nobody opened is
|
||||
// work the tick owes nothing, and the toggle's own handler refreshes when it is asked for.
|
||||
// The dock follows every latch; the pane's rows (with pictures) only while the pane is on screen:
|
||||
// rebuilding them per latch for a column nobody opened is work the tick owes nothing, and the toggle's
|
||||
// own handler refreshes when it is asked for.
|
||||
if (app.events_revealer != nullptr &&
|
||||
gtk_revealer_get_child_revealed(GTK_REVEALER(app.events_revealer))) {
|
||||
refresh_events_pane(app);
|
||||
} else {
|
||||
dock_rebuild_events(app);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -580,6 +584,7 @@ bool build_event_group(App& app, const std::vector<EventRecord>& records, EventG
|
||||
// Fit on open, once: the group's own span, framed.
|
||||
// As above: the tick pins the axis to the group's own span and marks the trigger.
|
||||
sync_events_availability(app);
|
||||
mark_events_on_screen(app); // the dock marks the group's members
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -781,6 +786,17 @@ void attach_preview_zoom(GtkWidget* frame, const std::string& path) {
|
||||
/// screen. One function because two callers write it -- the row builder and the in-place
|
||||
/// re-mark -- and a mark that reads differently depending on which of them last ran would be
|
||||
/// worse than no mark.
|
||||
bool event_on_screen(const App& app, const EventRecord& r) {
|
||||
return std::string(app.waveform_name) == r.file;
|
||||
}
|
||||
|
||||
/// Whether the event is one of the members of the comparison or accumulation on screen.
|
||||
bool event_in_group(const App& app, const EventRecord& r) {
|
||||
if (app.group_kind == EventGroupKind::None) return false;
|
||||
return std::any_of(app.group.begin(), app.group.end(),
|
||||
[&](const EventRecord& g) { return g.file == r.file; });
|
||||
}
|
||||
|
||||
std::string event_row_title(App& app, const EventRecord& r) {
|
||||
const std::time_t t = static_cast<std::time_t>(r.wall_time);
|
||||
std::tm tm{};
|
||||
@@ -789,11 +805,12 @@ std::string event_row_title(App& app, const EventRecord& r) {
|
||||
std::strftime(clock, sizeof(clock), "%H:%M:%S", &tm);
|
||||
char title[160];
|
||||
std::snprintf(title, sizeof(title), "%s %.3f s%s", clock, r.duration_s,
|
||||
std::string(app.waveform_name) == r.file ? " (on screen)" : "");
|
||||
event_on_screen(app, r) ? " (on screen)" : "");
|
||||
return title;
|
||||
}
|
||||
|
||||
void mark_events_on_screen(App& app) {
|
||||
dock_mark_events(app);
|
||||
if (app.events_list == nullptr) return;
|
||||
for (GtkWidget* row = gtk_widget_get_first_child(app.events_list); row != nullptr;
|
||||
row = gtk_widget_get_next_sibling(row)) {
|
||||
@@ -811,7 +828,7 @@ void mark_events_on_screen(App& app) {
|
||||
/// the whole pane describes whichever event happens to be newest rather than the one being read. The
|
||||
/// numbers are one line each: a list that has to load the samples to describe an event is a list that
|
||||
/// cannot show thirty of them.
|
||||
void refresh_events_pane(App& app) {
|
||||
static void rebuild_events_pane_list(App& app) {
|
||||
if (app.events_list == nullptr) return;
|
||||
while (GtkWidget* child = gtk_widget_get_first_child(app.events_list)) {
|
||||
gtk_list_box_remove(GTK_LIST_BOX(app.events_list), child);
|
||||
@@ -955,6 +972,13 @@ void refresh_events_pane(App& app) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Both views of the cache, rebuilt from the same list: the pane's rows (with their pictures) and the
|
||||
/// dock's compact ones. The dock follows even when the pane's list does not exist.
|
||||
void refresh_events_pane(App& app) {
|
||||
rebuild_events_pane_list(app);
|
||||
dock_rebuild_events(app);
|
||||
}
|
||||
|
||||
/// Clicking a row replays it: the same loader `--open` uses, on the event's file. The acquisition is
|
||||
/// stopped by `replay_event()` -- a live producer would overwrite the samples within a frame -- so the
|
||||
/// pane's own *Live* button is the way back.
|
||||
|
||||
Reference in new issue
Block a user