/*********************************************************************************** * * Copyright (c) 2014 Kamil Baczkowicz * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * * Kamil Baczkowicz - initial API and implementation and/or initial documentation * */ package pl.baczkowicz.mqttspy.ui; import java.net.URL; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.ResourceBundle; import java.util.Set; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.chart.PieChart; import javafx.scene.chart.PieChart.Data; import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; import javafx.scene.layout.AnchorPane; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pl.baczkowicz.spy.messages.FormattedMessage; import pl.baczkowicz.spy.ui.properties.SubscriptionTopicSummaryProperties; /** * Controller for pie chart pane. */ public class PieChartPaneController<T extends FormattedMessage> implements Initializable, ListChangeListener<SubscriptionTopicSummaryProperties<T>> { private final static Logger logger = LoggerFactory.getLogger(PieChartPaneController.class); private static boolean lastAutoRefresh = true; @FXML private AnchorPane chartPane; @FXML private Label showRangeLabel; @FXML private Button refreshButton; @FXML private CheckBox autoRefreshCheckBox; private PieChart pieChart; private ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(); private Map<String, PieChart.Data> pieChartDataMapping = new HashMap<>(); private ObservableList<SubscriptionTopicSummaryProperties<T>> observableList; public void initialize(URL location, ResourceBundle resources) { autoRefreshCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { lastAutoRefresh = autoRefreshCheckBox.isSelected(); // Only refresh when auto-refresh enabled if (lastAutoRefresh) { refresh(); } } }); } public void init() { pieChart = new PieChart(pieChartData); chartPane.getChildren().add(pieChart); AnchorPane.setBottomAnchor(pieChart, 0.0); AnchorPane.setLeftAnchor(pieChart, 0.0); AnchorPane.setTopAnchor(pieChart, 45.0); AnchorPane.setRightAnchor(pieChart, 0.0); autoRefreshCheckBox.setSelected(lastAutoRefresh); observableList.addListener(this); } public void cleanup() { observableList.removeListener(this); } @Override public void onChanged(final ListChangeListener.Change<? extends SubscriptionTopicSummaryProperties<T>> c) { logger.info("New data available"); if (autoRefreshCheckBox.isSelected()) { synchronized (pieChartData) { logger.info("New data available"); refreshFromList(observableList); } } } @FXML private void refresh() { refreshFromList(observableList); } private void refreshFromList(final Collection<SubscriptionTopicSummaryProperties<T>> list) { final Set<String> currentTopics = new HashSet<String>(); currentTopics.addAll(pieChartDataMapping.keySet()); synchronized (pieChartData) { for (final SubscriptionTopicSummaryProperties<T> newValue : list) { final String topic = newValue.topicProperty().getValue(); final Data lastValue = pieChartDataMapping.get(topic); if (lastValue == null) { final PieChart.Data data = new PieChart.Data(topic, newValue.countProperty().getValue()); pieChartDataMapping.put(topic, data); pieChartData.add(data); } else { lastValue.setPieValue(newValue.countProperty().getValue()); } // Mark as processed currentTopics.remove(topic); } // Remove objects not on the list for (final String topic : currentTopics) { pieChartData.remove(pieChartDataMapping.get(topic)); } } } // =============================== // === Setters and getters ======= // =============================== public void setObservableList(final ObservableList<SubscriptionTopicSummaryProperties<T>> observableList) { this.observableList = observableList; } }