Sample Window Shortcut Panel Implementation

In this implementation, we provide an attributes shortcut panel for a FK window. This panel only contains two spinners to change the scale and a peel/reveal sub panel.

Extending AbstractViewerWindowAttributesShortcutPanel

The following panel class was created using the Netbeans Matisse editor, then customized to extend com.interactive.intviewerapi.editors.AbstractViewerWindowAttributesShortcutPanel.

XSECTIONWINDOWATTRIBUTESSHORTCUTPANEL.JAVA

/*
 * XSectionWindowAttributesShortcutPanel.java
 *
 * Created on Mar 17, 2011, 4:27:49 PM
 */
package com.interactive.intviewer.seismic.editor.shortcut;
import com.interactive.intviewer.seismic.util.XSectionWindowUtil;
import com.interactive.intviewer.view2d.LayeredViewerWindow;
import com.interactive.intviewer.view2d.ViewerPlotXV;
import com.interactive.intviewer.view2d.XSectionLayeredWindow;
import com.interactive.intviewerapi.editors.AbstractViewerWindowAttributesShortcutPanel;
import com.interactive.intviewerapi.events.EventBroadcaster;
import com.interactive.intviewerapi.events.IEventSubscriber;
import com.interactive.intviewerapi.events.PropertyProviderEvent;
import com.interactive.intviewerapi.events.WindowScaleEvent;
import com.interactive.intviewerapi.layers.ISeismicLayer;
import java.awt.Toolkit;
import javax.swing.JSpinner;
import javax.swing.SwingConstants;
public class XSectionWindowAttributesShortcutPanel extends AbstractViewerWindowAttributesShortcutPanel {
    private int pixelsPerInch;
    private ViewerPlotXV plot;
    private boolean isUnitImperial;
    private String verticalUnitLabel;
    private IEventSubscriber<WindowScaleEvent> subscriber;
    // receives XSectionLayeredWindow so that it can be reused for FK display
    public XSectionWindowAttributesShortcutPanel(XSectionLayeredWindow window) {
        super(window);
        initComponents();
        initConstants();
        initGUI();
        this.setReady(true);
        subscriber = new IEventSubscriber<WindowScaleEvent>() {
            @Override
            public void onEvent(WindowScaleEvent t) {
                XSectionWindowAttributesShortcutPanel.this.setReady(false);
                XSectionWindowAttributesShortcutPanel.this.initGUI();
                XSectionWindowAttributesShortcutPanel.this.setReady(true);
            }
        };
        EventBroadcaster.getInstance().subscribe(WindowScaleEvent.class, subscriber, 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.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {
        xSectionWindowMoviePanel1 = new com.interactive.intviewer.seismic.editor.shortcut.XSectionWindowMoviePanel();
        jLayeredPane1 = new javax.swing.JLayeredPane();
        horizontalScaleLabel = new javax.swing.JLabel();
        horizontalScaleSpinner = new javax.swing.JSpinner();
        verticalScaleLabel = new javax.swing.JLabel();
        verticalScaleSpinner = new javax.swing.JSpinner();
        jLayeredPane1.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(XSectionWindowAttributesShortcutPanel.class, "XSectionWindowAttributesShortcutPanel.jLayeredPane1.border.title"))); // NOI18N
        horizontalScaleLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        horizontalScaleLabel.setText(org.openide.util.NbBundle.getMessage(XSectionWindowAttributesShortcutPanel.class, "XSectionWindowAttributesShortcutPanel.horizontalScaleLabel.text_1")); // NOI18N
        horizontalScaleLabel.setBounds(0, 20, 70, 20);
        jLayeredPane1.add(horizontalScaleLabel, javax.swing.JLayeredPane.DEFAULT_LAYER);
        horizontalScaleSpinner.setModel(new javax.swing.SpinnerNumberModel(Double.valueOf(50.0d), Double.valueOf(0.0010d), null, Double.valueOf(1.0d)));
        horizontalScaleSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                horizontalScaleSpinnerStateChanged(evt);
            }
        });
        horizontalScaleSpinner.setBounds(70, 20, 60, 20);
        jLayeredPane1.add(horizontalScaleSpinner, javax.swing.JLayeredPane.DEFAULT_LAYER);
        verticalScaleLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        verticalScaleLabel.setText(org.openide.util.NbBundle.getMessage(XSectionWindowAttributesShortcutPanel.class, "XSectionWindowAttributesShortcutPanel.verticalScaleLabel.text")); // NOI18N
        verticalScaleLabel.setBounds(140, 20, 50, 20);
        jLayeredPane1.add(verticalScaleLabel, javax.swing.JLayeredPane.DEFAULT_LAYER);
        verticalScaleSpinner.setModel(new javax.swing.SpinnerNumberModel(Double.valueOf(50.0d), Double.valueOf(0.0010d), null, Double.valueOf(0.1d)));
        verticalScaleSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                verticalScaleSpinnerStateChanged(evt);
            }
        });
        verticalScaleSpinner.setBounds(190, 20, 60, 20);
        jLayeredPane1.add(verticalScaleSpinner, javax.swing.JLayeredPane.DEFAULT_LAYER);
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jLayeredPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 261, Short.MAX_VALUE)
            .addComponent(xSectionWindowMoviePanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 261, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jLayeredPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(xSectionWindowMoviePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// </editor-fold>                        
    private void horizontalScaleSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {                                                    
        if (!isReady()) {
            return;
        }
        if (this.getViewerWindow() == null) {
            return;
        }
        if (evt.getSource() != horizontalScaleSpinner) {
            return;
        }
        ISeismicLayer layer = (ISeismicLayer) plot.getAxisLayer();
        if (layer == null) {
            return;
        }
        double userValue = new Double(horizontalScaleSpinner.getValue().toString());
        double horizontalScale = XSectionWindowUtil.convertUserToPlotHorizontalScale(userValue, pixelsPerInch, isUnitImperial);
        double verticalScale = plot.getVerticalScaleFactor();
        EventBroadcaster.getInstance().unsubscribe(WindowScaleEvent.class, subscriber);
        XSectionWindowUtil.scalePlot(plot, horizontalScale, verticalScale);
        EventBroadcaster.getInstance().subscribe(WindowScaleEvent.class, subscriber);
    }                                                   
    private void verticalScaleSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {                                                  
        if (!isReady()) {
            return;
        }
        if (this.getViewerWindow() == null) {
            return;
        }
        if (evt.getSource() != verticalScaleSpinner) {
            return;
        }
        ISeismicLayer layer = (ISeismicLayer) plot.getAxisLayer();
        if (layer == null) {
            return;
        }
        float sampleRate = layer.getReader().getDataStatistics().getSampleRate();
        double userValue = new Double(verticalScaleSpinner.getValue().toString());
        double horizontalScale = plot.getHorizontalScaleFactor();
        double verticalScale = XSectionWindowUtil.convertUserToPlotVerticalScale(userValue, pixelsPerInch, isUnitImperial,
                sampleRate, verticalUnitLabel);
        EventBroadcaster.getInstance().unsubscribe(WindowScaleEvent.class, subscriber);
        XSectionWindowUtil.scalePlot(plot, horizontalScale, verticalScale);
        EventBroadcaster.getInstance().subscribe(WindowScaleEvent.class, subscriber);
    }                                                 
    // Variables declaration - do not modify                     
    private javax.swing.JLabel horizontalScaleLabel;
    private javax.swing.JSpinner horizontalScaleSpinner;
    private javax.swing.JLayeredPane jLayeredPane1;
    private javax.swing.JLabel verticalScaleLabel;
    private javax.swing.JSpinner verticalScaleSpinner;
    private com.interactive.intviewer.seismic.editor.shortcut.XSectionWindowMoviePanel xSectionWindowMoviePanel1;
    // End of variables declaration                   
    private void initGUI() {
        ISeismicLayer layer = (ISeismicLayer) plot.getAxisLayer();
        if (layer == null) {
            return;
        }
        float sampleRate = layer.getReader().getDataStatistics().getSampleRate();
        double horizontalValue = XSectionWindowUtil.convertPlotToUserHorizontalScale(plot.getHorizontalScaleFactor(), pixelsPerInch, isUnitImperial);
        double verticalValue = XSectionWindowUtil.convertPlotToUserVerticalScale(plot.getVerticalScaleFactor(), pixelsPerInch, isUnitImperial, sampleRate, verticalUnitLabel);
        this.horizontalScaleSpinner.setModel(new javax.swing.SpinnerNumberModel(Double.valueOf(50.0d), Double.valueOf(0.0010d), null, horizontalValue / 20d));
        this.verticalScaleSpinner.setModel(new javax.swing.SpinnerNumberModel(Double.valueOf(50.0d), Double.valueOf(0.0010d), null, verticalValue / 20d));
        this.horizontalScaleSpinner.setValue(horizontalValue);
        this.verticalScaleSpinner.setValue(verticalValue);
        JSpinner.NumberEditor horizontalEditor = (JSpinner.NumberEditor) horizontalScaleSpinner.getEditor();
        horizontalEditor.getTextField().setHorizontalAlignment(SwingConstants.CENTER);
        JSpinner.NumberEditor verticalEditor = (JSpinner.NumberEditor) verticalScaleSpinner.getEditor();
        verticalEditor.getTextField().setHorizontalAlignment(SwingConstants.CENTER);
    }
    @Override
    protected void processEvent(PropertyProviderEvent e) {
        // ignore, we only care about scale events
    }
    private void initConstants() {
        this.pixelsPerInch = Toolkit.getDefaultToolkit().getScreenResolution();
        this.plot = (ViewerPlotXV) ((LayeredViewerWindow) this.getViewerWindow()).getViewerPlot();
        String horizontalScaleUnit = plot.getHorizontalScaleUnit(); // should not change, even when preferences are changed
        String verticalScaleUnit = plot.getVerticalScaleUnit(); // should not change, even when preferences are changed
        this.horizontalScaleLabel.setToolTipText("in " + horizontalScaleUnit);
        this.verticalScaleLabel.setToolTipText("in " + verticalScaleUnit);
        this.verticalUnitLabel = plot.getCurrentVerticalUnitLabel();
        this.isUnitImperial = plot.isUnitImperial(); // should not change, even when preferences are changed
    }
    @Override
    public void dispose() {
        EventBroadcaster.getInstance().unsubscribe(WindowScaleEvent.class, subscriber);
        super.dispose();
        this.plot = null;
    }
}

Extending AbstractViewerWindowAttributesShortcutEditor

The following editor class does a lazy-instantiation of the panel created earlier.

XSECTIONWINDOWATTRIBUTESSHORTCUTEDITOR.JAVA

package com.interactive.intviewer.seismic.editor.shortcut;
import com.interactive.intviewer.view2d.XSectionLayeredWindow;
import com.interactive.intviewer.view2d.actions.XSectionAnnotationAction;
import com.interactive.intviewerapi.editors.AbstractViewerWindowAttributesShortcutEditor;
import javax.swing.JComponent;
public class XSectionWindowAttributesShortcutEditor extends AbstractViewerWindowAttributesShortcutEditor {
    private XSectionWindowAttributesShortcutPanel panel;
    public XSectionWindowAttributesShortcutEditor(XSectionLayeredWindow window) {
        super(window);
    }
    @Override
    public JComponent getComponent() {
        if (panel == null) {
            panel = new XSectionWindowAttributesShortcutPanel((XSectionLayeredWindow) this.getViewerWindow());
        }
        return panel;
    }
    @Override
    public void showDialog() {
        XSectionAnnotationAction.setObjectEditorNodeVisible((XSectionLayeredWindow) this.getViewerWindow());
    }
    @Override
    public void dispose() {
        super.dispose();
        panel = null;
    }
}

Implementing IAttributesShortcutAdapter

The following adapter class verifies that the object is a FK window, and vends the editor created earlier.

FKWINDOWSHORTCUTADAPTER.JAVA

package com.interactive.intviewer.fk.editor.shortcut;
import com.interactive.intviewer.fk.FKWindow;
import com.interactive.intviewer.seismic.editor.shortcut.XSectionWindowAttributesShortcutEditor;
import com.interactive.intviewerapi.editors.IAttributesShortcutAdapter;
import com.interactive.intviewerapi.editors.IAttributesShortcutProvider;
import com.interactive.intviewerapi.windows.IFKWindow;
public class FKWindowShortcutAdapter implements IAttributesShortcutAdapter {
    @Override
    public Class<?> getSupportedClass() {
        return FKWindow.class;
    }
    @Override
    public boolean canProcess(Object o) {
        return (o instanceof FKWindow);
    }
    @Override
    public IAttributesShortcutProvider getProvider(Object o) {
        if (o instanceof FKWindow) {
            return new FKWindowShortcutProvider((FKWindow) o);
        } else {
            return null;
        }
    }
    static class FKWindowShortcutProvider implements IAttributesShortcutProvider {
        IFKWindow window;
        public FKWindowShortcutProvider(IFKWindow window) {
            this.window = window;
        }
        @Override
        public IAttributesShortcutEditor[] getEditors() {
            return new IAttributesShortcutEditor[]{new XSectionWindowAttributesShortcutEditor((FKWindow) window)};
        }
    }
}

Important: In the getSupportedClass method, indicate the implementation class, not the interface. To get the implementation class of a window, use window.getClass().

Registering the adapter

The following layer registration adds the adapter created earlier to the INTViewer desktop.

LAYER.XML

<filesystem>
    <folder name="ShortcutEditors">
        <folder name="WindowShortcut">
            <file name="com-interactive-intviewer-fk-editor-shortcut-FKWindowShortcutAdapter.instance"/>
        </folder>
    </folder>
</filesystem>