package com.example.widgets; import com.example.data.ChartDataService; import com.example.data.DashboardFilter; import com.vaadin.flow.shared.Registration; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.function.Consumer; /** * The dashboard's current {@link DashboardFilter} plus the widgets listening to * it — the small event bus between the filter bar (which sets) and the widgets * (which subscribe and re-request their data from * {@link ChartDataService}). Neither side knows the other. *

* One context per dashboard instance, deliberately not a Spring bean: it is * view state, so nothing leaks between users, tabs or visits. For the same * reason the filter is not persisted — a reload starts from * {@link DashboardFilter#defaults()}, unlike the grid layout, which * {@code GridStackLayout} keeps in {@code localStorage}. */ public class DashboardContext { private final List> listeners = new ArrayList<>(); private DashboardFilter filter = DashboardFilter.defaults(); public DashboardFilter getFilter() { return filter; } /** * Applies a filter and hands it to every listener. A filter equal to the * current one changes nothing and notifies nobody, so re-picking the same * value in the filter bar does not make the widgets re-fetch. */ public void setFilter(DashboardFilter filter) { Objects.requireNonNull(filter, "filter"); if (this.filter.equals(filter)) { return; } this.filter = filter; // Over a copy: a listener may unsubscribe while being notified (a // widget closing in reaction to the update). List.copyOf(listeners).forEach(listener -> listener.accept(filter)); } /** * Subscribes to later filter changes. The listener is not called with the * current filter — a widget is built from it already — so a subscriber * feeds itself once and then only reacts. */ public Registration addFilterChangeListener(Consumer listener) { listeners.add(listener); return () -> listeners.remove(listener); } /** How many widgets are currently listening; for tests and diagnostics. */ public int getListenerCount() { return listeners.size(); } }