Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package be.nbb.demetra.dfm; import static be.nbb.demetra.dfm.DfmController.DFM_STATE_PROPERTY; import be.nbb.demetra.dfm.DfmController.DfmState; import ec.nbdemetra.ui.DemetraUI; import ec.nbdemetra.ui.DemetraUiIcon; import ec.nbdemetra.ui.NbComponents; import ec.nbdemetra.ui.nodes.ExceptionNode; import ec.nbdemetra.ui.notification.MessageType; import ec.nbdemetra.ui.notification.NotifyUtil; import ec.nbdemetra.ui.properties.OpenIdePropertySheetBeanEditor; import ec.nbdemetra.ws.WorkspaceItem; import ec.tss.dfm.DfmDocument; import ec.tss.dfm.DfmProcessingFactory; import ec.tss.dfm.VersionedDfmDocument; import ec.tstoolkit.algorithm.CompositeResults; import ec.tstoolkit.algorithm.IProcessingHook; import ec.tstoolkit.algorithm.IProcessingNode; import ec.tstoolkit.dfm.DfmEstimationSpec; import ec.tstoolkit.dfm.DfmSpec; import ec.util.chart.ColorScheme; import ec.util.chart.swing.Charts; import ec.util.chart.swing.SwingColorSchemeSupport; import ec.util.various.swing.JCommand; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.util.List; import java.util.concurrent.ExecutionException; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.SwingWorker; import org.jfree.chart.ChartPanel; import org.jfree.data.time.DynamicTimeSeriesCollection; import org.jfree.data.time.Second; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; import org.netbeans.api.settings.ConvertAsProperties; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.util.Cancellable; import static org.openide.util.ImageUtilities.createDisabledIcon; import org.openide.util.NbBundle.Messages; import org.openide.windows.TopComponent; /** * Top component which displays something. */ @ConvertAsProperties(dtd = "-//be.nbb.demetra.dfm//DfmExecView//EN", autostore = false) @TopComponent.Description(preferredID = "DfmExecViewTopComponent", //iconBase="SET/PATH/TO/ICON/HERE", persistenceType = TopComponent.PERSISTENCE_NEVER) @TopComponent.Registration(mode = "editor", openAtStartup = false) @Messages({ "CTL_DfmExecViewAction=DfmExecView", "CTL_DfmExecViewTopComponent=DfmExecView Window", "HINT_DfmExecViewTopComponent=This is a DfmExecView window" }) public final class DfmExecViewTopComponent extends AbstractDfmDocumentTopComponent { private DynamicTimeSeriesCollection dataset; private ChartPanel sparkline; public DfmExecViewTopComponent() { this(null, new DfmController()); } DfmExecViewTopComponent(WorkspaceItem<VersionedDfmDocument> document, DfmController controller) { super(document, controller); initComponents(); setToolTipText(Bundle.HINT_DfmExecViewTopComponent()); jEditorPane1.setEditable(false); dataset = new DynamicTimeSeriesCollection(1, 200, new Second()); dataset.setTimeBase(new Second()); dataset.addSeries(new float[] {}, 0, "loglikelihood"); } /** * 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() { jScrollPane1 = NbComponents.newJScrollPane(); jEditorPane1 = new javax.swing.JEditorPane(); setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS)); jScrollPane1.setViewportView(jEditorPane1); add(jScrollPane1); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JEditorPane jEditorPane1; private javax.swing.JScrollPane jScrollPane1; // End of variables declaration//GEN-END:variables void writeProperties(java.util.Properties p) { } void readProperties(java.util.Properties p) { } @Override public JComponent getToolbarRepresentation() { JToolBar toolBar = NbComponents.newInnerToolbar(); toolBar.addSeparator(); toolBar.add(Box.createRigidArea(new Dimension(5, 0))); JToggleButton startStop = (JToggleButton) toolBar .add(new JToggleButton(StartStopCommand.INSTANCE.toAction(this))); startStop.setIcon(DemetraUiIcon.COMPILE_16); startStop.setDisabledIcon(createDisabledIcon(startStop.getIcon())); startStop.setToolTipText("Start/Stop"); JButton edit = toolBar.add(EditSpecCommand.INSTANCE.toAction(this)); edit.setIcon(DemetraUiIcon.PREFERENCES); edit.setDisabledIcon(createDisabledIcon(edit.getIcon())); edit.setToolTipText("Specification"); JButton clear = toolBar.add(ClearCommand.INSTANCE.toAction(this)); clear.setIcon(DemetraUiIcon.EDIT_CLEAR_16); clear.setDisabledIcon(createDisabledIcon(clear.getIcon())); clear.setToolTipText("Clear"); SwingColorSchemeSupport colorSchemeSupport = SwingColorSchemeSupport .from(DemetraUI.getInstance().getColorScheme()); sparkline = (ChartPanel) toolBar .add(Charts.avoidScaling(new ChartPanel(Charts.createSparkLineChart(null)))); sparkline.setPreferredSize(new Dimension(150, 16)); sparkline.setMaximumSize(new Dimension(150, 16)); sparkline.getChart().getXYPlot().setDataset(dataset); sparkline.getChart().getXYPlot().getRenderer() .setBasePaint(colorSchemeSupport.getLineColor(ColorScheme.KnownColor.GREEN)); sparkline.setBackground(colorSchemeSupport.getPlotColor()); sparkline.setBorder(BorderFactory.createLineBorder(colorSchemeSupport.getGridColor())); sparkline.setToolTipText("loglikelihood"); return toolBar; } //</editor-fold> private void appendText(String text) { jEditorPane1.setText(jEditorPane1.getText() + text); } private ProgressHandle progressHandle; private SwingWorkerImpl swingWorker; @Override protected void onDfmStateChange() { switch (controller.getDfmState()) { case CANCELLED: appendText("\nCANCELLED"); progressHandle.finish(); break; case DONE: appendText("\nDONE"); if (progressHandle != null) { progressHandle.finish(); } break; case FAILED: appendText("\nFAILED"); if (progressHandle != null) { progressHandle.finish(); } break; case READY: jEditorPane1.setText(""); break; case STARTED: swingWorker = new SwingWorkerImpl(); progressHandle = ProgressHandleFactory.createHandle(getName(), new Cancellable() { @Override public boolean cancel() { swingWorker.cancel(false); return true; } }, new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { DfmExecViewTopComponent.this.open(); DfmExecViewTopComponent.this.requestActive(); } }); progressHandle.start(); swingWorker.execute(); break; case CANCELLING: swingWorker.cancel(false); break; } super.onDfmStateChange(); } private void reportException(Exception ex) { new ExceptionNode(ex).getPreferredAction().actionPerformed(null); } private final class SwingWorkerImpl extends SwingWorker<CompositeResults, IProcessingHook.HookInformation<IProcessingNode, DfmProcessingFactory.EstimationInfo>> implements IProcessingHook<IProcessingNode, DfmProcessingFactory.EstimationInfo> { @Override protected CompositeResults doInBackground() throws Exception { DfmProcessingFactory processor = (DfmProcessingFactory) getDocument().getElement().getCurrent() .getProcessor(); try { processor.register(this); CompositeResults rslt = getDocument().getElement().getCurrent().getResults(); return rslt; } finally { processor.unregister(this); } } @Override protected void done() { if (isCancelled()) { NotifyUtil.show("Cancelled !", "Processing has been cancelled", MessageType.WARNING, null, null, null); controller.setDfmState(DfmState.CANCELLED); } else { try { CompositeResults results = get(); NotifyUtil.show("Done !", "Processing has completed successfuly", MessageType.SUCCESS, null, createChartImage(), null); controller.setDfmState(DfmState.DONE); } catch (InterruptedException | ExecutionException ex) { if (ex instanceof ExecutionException) { if (ex.getCause() != null && ex.getCause() instanceof Exception) { reportException((Exception) ex.getCause()); } else { reportException(ex); } } else { reportException(ex); } controller.setDfmState(DfmState.FAILED); } } } @Override public void process(HookInformation<IProcessingNode, DfmProcessingFactory.EstimationInfo> info, boolean cancancel) { if (isCancelled()) { info.cancel = true; } publish(info); } @Override protected void process(List<HookInformation<IProcessingNode, DfmProcessingFactory.EstimationInfo>> chunks) { for (HookInformation<IProcessingNode, DfmProcessingFactory.EstimationInfo> info : chunks) { progressHandle.progress(info.message); StringBuilder txt = new StringBuilder(); txt.append(info.source.getName()).append('\t').append(info.message).append('\t') .append(info.information.loglikelihood); txt.append("\r\n"); appendText(txt.toString()); dataset.advanceTime(); dataset.appendData(new float[] { (float) info.information.loglikelihood }); } } private JLabel createChartImage() { return new JLabel(new ImageIcon(sparkline.getChart().createBufferedImage(150, 16))); } } //<editor-fold defaultstate="collapsed" desc="Commands"> private static abstract class DfmExecCommand extends JCommand<DfmExecViewTopComponent> { @Override public JCommand.ActionAdapter toAction(DfmExecViewTopComponent c) { return super.toAction(c).withWeakPropertyChangeListener(c, DFM_STATE_PROPERTY); } } private static final class StartStopCommand extends DfmExecCommand { public static final StartStopCommand INSTANCE = new StartStopCommand(); @Override public void execute(DfmExecViewTopComponent c) throws Exception { if (c.controller.getDfmState() == DfmState.STARTED) { c.controller.setDfmState(DfmState.CANCELLING); } else { c.controller.setDfmState(DfmState.STARTED); } } @Override public boolean isEnabled(DfmExecViewTopComponent c) { return c.controller.getDfmState() != DfmState.CANCELLING; } @Override public boolean isSelected(DfmExecViewTopComponent c) { return c.controller.getDfmState() == DfmState.STARTED; } } private static final class EditSpecCommand extends DfmExecCommand { public static final EditSpecCommand INSTANCE = new EditSpecCommand(); @Override public void execute(DfmExecViewTopComponent c) throws Exception { DfmDocument doc = c.getDocument().getElement().getCurrent(); DfmSpec spec = doc.getSpecification(); DfmEstimationSpec newValue = spec.getEstimationSpec().clone(); if (OpenIdePropertySheetBeanEditor.editSheet(DfmSheets.onDfmEstimationSpec(newValue), "Edit spec", null)) { doc.forceSpecification(newValue); } } @Override public boolean isEnabled(DfmExecViewTopComponent c) { return c.controller.getDfmState() != DfmState.STARTED && c.controller.getDfmState() != DfmState.CANCELLING; } } private static final class ClearCommand extends DfmExecCommand { public static final ClearCommand INSTANCE = new ClearCommand(); @Override public void execute(DfmExecViewTopComponent c) throws Exception { DfmDocument current = c.getDocument().getElement().getCurrent(); DfmSpec spec = current.getSpecification(); if (spec.getModelSpec().isSpecified()) { NotifyDescriptor nd = new NotifyDescriptor.Confirmation(CLEAR_MESSAGE, NotifyDescriptor.OK_CANCEL_OPTION); if (DialogDisplayer.getDefault().notify(nd) == NotifyDescriptor.OK_OPTION) { current.forceFullComputation(); c.controller.setDfmState(DfmState.READY); } } } @Override public boolean isEnabled(DfmExecViewTopComponent c) { return c.controller.getDfmState().isFinished(); } } //</editor-fold> public static final String CLEAR_MESSAGE = "The model has already been computed. Are you sure you want to clear the results?"; }