Java tutorial
/* * IncomeExpensesTopComponent.java * * Copyright (C) 2009 Francois Duchemin * * This file is part of GrisbiGraphs. * * GrisbiGraphs is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * GrisbiGraphs is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GrisbiGraphs; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package gg.view.overview; import gg.db.datamodel.Datamodel; import gg.db.entities.Currency; import gg.db.datamodel.Period; import gg.db.datamodel.PeriodType; import gg.db.datamodel.Periods; import gg.db.datamodel.SearchCriteria; import gg.utilities.Utilities; import gg.wallet.Wallet; import java.awt.BorderLayout; import java.awt.Color; import java.awt.GradientPaint; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.List; import java.util.Properties; import java.util.logging.Logger; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.CategoryAxis; import org.jfree.chart.axis.CategoryLabelPositions; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.renderer.category.BarRenderer; import org.jfree.data.category.DefaultCategoryDataset; import org.joda.time.LocalDate; import org.netbeans.api.settings.ConvertAsProperties; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; /** * Top component which displays a chart showing the total income vs expenses * for the current month and for each currency. */ @ConvertAsProperties(dtd = "-//gg.view.overview//IncomeExpenses//EN", autostore = false) public final class IncomeExpensesTopComponent extends TopComponent { /** Singleton instance of the topcomponent */ private static IncomeExpensesTopComponent instance; /** Path to the icon used by the component and its open action */ private static final String ICON_PATH = "gg/resources/icons/IncomeExpenses.png"; /** ID of the component */ private static final String PREFERRED_ID = "IncomeExpensesTopComponent"; /** Logger */ private Logger log = Logger.getLogger(this.getClass().getName()); /** Creates a new instance of IncomeExpensesTopComponent */ public IncomeExpensesTopComponent() { initComponents(); setName(NbBundle.getMessage(IncomeExpensesTopComponent.class, "CTL_IncomeExpensesTopComponent")); setToolTipText(NbBundle.getMessage(IncomeExpensesTopComponent.class, "HINT_IncomeExpensesTopComponent")); setIcon(ImageUtilities.loadImage(ICON_PATH, true)); putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE); putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE); putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jPanelIncomeExpenses = new javax.swing.JPanel(); jPanelIncomeExpenses.setLayout(new java.awt.BorderLayout()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout .createSequentialGroup().addContainerGap().addComponent(jPanelIncomeExpenses, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) .addContainerGap())); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup().addContainerGap().addComponent(jPanelIncomeExpenses, javax.swing.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE) .addContainerGap())); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel jPanelIncomeExpenses; // End of variables declaration//GEN-END:variables /** * Gets default instance. Do not use directly: reserved for *.settings files only, * i.e. deserialization routines; otherwise you could get a non-deserialized instance. * To obtain the singleton instance, use {@link #findInstance}. * @return Default instance */ public static synchronized IncomeExpensesTopComponent getDefault() { if (instance == null) { instance = new IncomeExpensesTopComponent(); } return instance; } /** * Obtain the IncomeExpensesTopComponent instance. Never call {@link #getDefault} directly! * @return IncomeExpensesTopComponent instance */ public static synchronized IncomeExpensesTopComponent findInstance() { TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); if (win == null) { Logger.getLogger(IncomeExpensesTopComponent.class.getName()).warning("Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system."); return getDefault(); } if (win instanceof IncomeExpensesTopComponent) { return (IncomeExpensesTopComponent) win; } Logger.getLogger(IncomeExpensesTopComponent.class.getName()) .warning("There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior."); return getDefault(); } /** * Gets the persistence type * @return Persistence type */ @Override public int getPersistenceType() { return TopComponent.PERSISTENCE_ALWAYS; } /** * Saves properties * @param p Properties to save */ public void writeProperties(Properties p) { p.setProperty("version", "1.0"); } /** * Reads properties * @param p properties to save * @return TopComponent with loaded properties */ public Object readProperties(Properties p) { IncomeExpensesTopComponent singleton = IncomeExpensesTopComponent.getDefault(); singleton.readPropertiesImpl(p); return singleton; } /** * Reads properties * @param p Properties to read */ private void readPropertiesImpl(Properties p) { String version = p.getProperty("version"); } /** * Gets the topcomponent's ID * @return Topcomponent's ID */ @Override protected String preferredID() { return PREFERRED_ID; } /** Displays the total income vs expenses for the current month */ public void displayData() { log.info("Income vs Expenses graph computed and displayed"); // Display hourglass cursor Utilities.changeCursorWaitStatus(true); // Create a dataset (the dataset will contain the plotted values) DefaultCategoryDataset dataset = new DefaultCategoryDataset(); // Create an empty chart JFreeChart chart = ChartFactory.createBarChart("", // chart title "", // x axis label NbBundle.getMessage(IncomeExpensesTopComponent.class, "IncomeExpensesTopComponent.Amount"), // y axis label dataset, // data displayed in the chart PlotOrientation.VERTICAL, false, // include legend true, // tooltips false // urls ); // Update the chart color chart.setBackgroundPaint(jPanelIncomeExpenses.getBackground()); CategoryPlot plot = (CategoryPlot) chart.getPlot(); plot.setBackgroundPaint(Color.WHITE); // Set the orientation of the categories on the domain axis (X axis) CategoryAxis domainAxis = plot.getDomainAxis(); domainAxis.setCategoryLabelPositions(CategoryLabelPositions.STANDARD); // Set the range axis (Y axis) to display integers only NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); // Set the bar renderer BarRenderer renderer = (BarRenderer) plot.getRenderer(); renderer.setDrawBarOutline(false); renderer.setMaximumBarWidth(0.1); GradientPaint gradientPaint = new GradientPaint(0.0f, 0.0f, new Color(49, 106, 196), 0.0f, 0.0f, Color.LIGHT_GRAY); renderer.setSeriesPaint(0, gradientPaint); // Create a period for the current month LocalDate today = new LocalDate(); Period currentMonth = new Period(Periods.getAdjustedStartDate(today, PeriodType.MONTH), Periods.getAdjustedEndDate(today, PeriodType.MONTH), PeriodType.MONTH); // Fill the dataset List<Currency> currencies = Wallet.getInstance().getActiveCurrencies(); for (Currency currency : currencies) { // Filter on the currency and on the current month SearchCriteria searchCriteria = new SearchCriteria(currency, null, currentMonth, null, null, null, false); // Get income BigDecimal currencyIncome = Datamodel.getIncome(searchCriteria); currencyIncome = currencyIncome.setScale(2, RoundingMode.HALF_EVEN); // Get expenses BigDecimal currencyExpenses = Datamodel.getExpenses(searchCriteria).abs(); currencyExpenses = currencyExpenses.setScale(2, RoundingMode.HALF_EVEN); // Plot income and expenses for the current month and for the current currency on the chart dataset.addValue(currencyIncome, currency.getName(), NbBundle.getMessage(IncomeExpensesTopComponent.class, "IncomeExpensesTopComponent.Income", new Object[] { currency })); dataset.addValue(currencyExpenses, currency.getName(), NbBundle.getMessage(IncomeExpensesTopComponent.class, "IncomeExpensesTopComponent.Expenses", new Object[] { currency })); } // Create the chart panel that contains the chart ChartPanel chartPanel = new ChartPanel(chart); // Display the chart jPanelIncomeExpenses.removeAll(); jPanelIncomeExpenses.add(chartPanel, BorderLayout.CENTER); // Display the normal cursor Utilities.changeCursorWaitStatus(false); } }