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