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.
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; }}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; }}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().
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>