View Javadoc
1   /*
2    * Copyright 2020-2025 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.demo.gui;
6   
7   import java.awt.BorderLayout;
8   import java.awt.Color;
9   import java.awt.GridBagConstraints;
10  import java.awt.GridBagLayout;
11  import java.text.DecimalFormat;
12  import java.text.DecimalFormatSymbols;
13  import java.util.ArrayList;
14  import java.util.List;
15  import java.util.Locale;
16  
17  import javax.swing.JPanel;
18  import javax.swing.Timer;
19  
20  import org.jfree.chart.ChartFactory;
21  import org.jfree.chart.ChartPanel;
22  import org.jfree.chart.JFreeChart;
23  import org.jfree.chart.labels.PieSectionLabelGenerator;
24  import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
25  import org.jfree.chart.plot.PiePlot;
26  import org.jfree.chart.title.TextTitle;
27  import org.jfree.chart.title.Title;
28  import org.jfree.data.general.DefaultPieDataset;
29  
30  import oshi.PlatformEnum;
31  import oshi.SystemInfo;
32  import oshi.software.os.FileSystem;
33  import oshi.software.os.OSFileStore;
34  import oshi.util.FormatUtil;
35  
36  /**
37   * Displays used and free space on all filesystems.
38   */
39  public class FileStorePanel extends OshiJPanel { // NOSONAR squid:S110
40  
41      private static final long serialVersionUID = 1L;
42  
43      private static final String USED = "Used";
44      private static final String AVAILABLE = "Available";
45  
46      private static final DecimalFormatSymbols ROOT_SYMBOLS = DecimalFormatSymbols.getInstance(Locale.ROOT);
47  
48      public FileStorePanel(SystemInfo si) {
49          super();
50          init(si.getOperatingSystem().getFileSystem());
51      }
52  
53      private void init(FileSystem fs) {
54          List<OSFileStore> fileStores = fs.getFileStores();
55          @SuppressWarnings("unchecked")
56          DefaultPieDataset<String>[] fsData = new DefaultPieDataset[fileStores.size()];
57          JFreeChart[] fsCharts = new JFreeChart[fsData.length];
58  
59          JPanel fsPanel = new JPanel();
60          fsPanel.setLayout(new GridBagLayout());
61          GridBagConstraints fsConstraints = new GridBagConstraints();
62          fsConstraints.weightx = 1d;
63          fsConstraints.weighty = 1d;
64          fsConstraints.fill = GridBagConstraints.BOTH;
65  
66          int modBase = (int) (fileStores.size() * (Config.GUI_HEIGHT + Config.GUI_WIDTH)
67                  / (Config.GUI_WIDTH * Math.sqrt(fileStores.size())));
68          for (int i = 0; i < fileStores.size(); i++) {
69              fsData[i] = new DefaultPieDataset<>();
70              fsCharts[i] = ChartFactory.createPieChart(null, fsData[i], true, true, false);
71              configurePlot(fsCharts[i]);
72              fsConstraints.gridx = i % modBase;
73              fsConstraints.gridy = i / modBase;
74              fsPanel.add(new ChartPanel(fsCharts[i]), fsConstraints);
75          }
76          updateDatasets(fs, fsData, fsCharts);
77  
78          add(fsPanel, BorderLayout.CENTER);
79  
80          Timer timer = new Timer(Config.REFRESH_SLOWER, e -> {
81              if (!updateDatasets(fs, fsData, fsCharts)) {
82                  ((Timer) e.getSource()).stop();
83                  fsPanel.removeAll();
84                  init(fs);
85                  fsPanel.revalidate();
86                  fsPanel.repaint();
87              }
88          });
89          timer.start();
90      }
91  
92      private static boolean updateDatasets(FileSystem fs, DefaultPieDataset<String>[] fsData, JFreeChart[] fsCharts) {
93          List<OSFileStore> fileStores = fs.getFileStores();
94          if (fileStores.size() != fsData.length) {
95              return false;
96          }
97          int i = 0;
98          for (OSFileStore store : fileStores) {
99              fsCharts[i].setTitle(store.getName());
100             List<Title> subtitles = new ArrayList<>();
101             if (SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) {
102                 subtitles.add(new TextTitle(store.getLabel()));
103             }
104             long usable = store.getUsableSpace();
105             long total = store.getTotalSpace();
106             subtitles.add(new TextTitle(
107                     "Available: " + FormatUtil.formatBytes(usable) + "/" + FormatUtil.formatBytes(total)));
108             fsCharts[i].setSubtitles(subtitles);
109             fsData[i].setValue(USED, (double) total - usable);
110             fsData[i].setValue(AVAILABLE, usable);
111             i++;
112         }
113         return true;
114     }
115 
116     private static void configurePlot(JFreeChart chart) {
117         @SuppressWarnings("unchecked")
118         PiePlot<String> plot = (PiePlot<String>) chart.getPlot();
119         plot.setSectionPaint(USED, Color.red);
120         plot.setSectionPaint(AVAILABLE, Color.green);
121         plot.setExplodePercent(USED, 0.10);
122         plot.setSimpleLabels(true);
123 
124         PieSectionLabelGenerator labelGenerator = new StandardPieSectionLabelGenerator("{0}: {1} ({2})",
125                 new DecimalFormat("0", ROOT_SYMBOLS), new DecimalFormat("0%", ROOT_SYMBOLS));
126         plot.setLabelGenerator(labelGenerator);
127     }
128 
129 }