001package jmri.jmrit.operations;
002
003import java.awt.Container;
004import java.awt.Dimension;
005import java.awt.event.ActionEvent;
006
007import javax.swing.*;
008import javax.swing.event.ChangeEvent;
009
010import jmri.InstanceManager;
011import jmri.implementation.swing.SwingShutDownTask;
012import jmri.jmrit.operations.setup.Control;
013import jmri.jmrit.operations.setup.Setup;
014import jmri.util.JmriJFrame;
015
016/**
017 * Frame for operations
018 *
019 * @author Dan Boudreau Copyright (C) 2008, 2012
020 */
021public class OperationsFrame extends JmriJFrame {
022
023    public static final String NEW_LINE = "\n"; // NOI18N
024    public static final String NONE = ""; // NOI18N
025
026    public OperationsFrame(String s) {
027        this(s, new OperationsPanel());
028    }
029
030    public OperationsFrame() {
031        this(new OperationsPanel());
032    }
033
034    public OperationsFrame(OperationsPanel p) {
035        super();
036        this.setContentPane(p);
037        this.setEscapeKeyClosesWindow(true);
038    }
039
040    public OperationsFrame(String s, OperationsPanel p) {
041        super(s);
042        this.setContentPane(p);
043        this.setEscapeKeyClosesWindow(true);
044    }
045
046    @Override
047    public void initComponents() {
048        // default method does nothing, but fail to call super.initComponents,
049        // so that Exception does not need to be caught
050    }
051
052    public void initMinimumSize() {
053        initMinimumSize(new Dimension(Control.panelWidth500, Control.panelHeight250));
054    }
055
056    public void initMinimumSize(Dimension dimension) {
057        setMinimumSize(dimension);
058        pack();
059        setVisible(true);
060    }
061
062    protected void addItem(JComponent c, int x, int y) {
063        this.getContentPane().addItem(c, x, y);
064    }
065
066    protected void addItem(JPanel p, JComponent c, int x, int y) {
067        this.getContentPane().addItem(p, c, x, y);
068    }
069
070    protected void addItemLeft(JPanel p, JComponent c, int x, int y) {
071        this.getContentPane().addItemLeft(p, c, x, y);
072    }
073
074    protected void addItemTop(JPanel p, JComponent c, int x, int y) {
075        this.getContentPane().addItemTop(p, c, x, y);
076    }
077
078    protected void addItemWidth(JPanel p, JComponent c, int width, int x, int y) {
079        this.getContentPane().addItemWidth(p, c, width, x, y);
080    }
081
082    /**
083     * Gets the number of checkboxes(+1) that can fix in one row see
084     * OperationsFrame.minCheckboxes and OperationsFrame.maxCheckboxes
085     *
086     * @return the number of checkboxes, minimum is 5 (6 checkboxes)
087     */
088    protected int getNumberOfCheckboxesPerLine() {
089        return this.getContentPane().getNumberOfCheckboxesPerLine(this.getPreferredSize());
090    }
091
092    protected void addButtonAction(JButton b) {
093        b.addActionListener(this::buttonActionPerformed);
094    }
095
096    protected void buttonActionPerformed(ActionEvent ae) {
097        this.getContentPane().buttonActionPerformed(ae);
098    }
099
100    protected void addRadioButtonAction(JRadioButton b) {
101        b.addActionListener(this::radioButtonActionPerformed);
102    }
103
104    protected void radioButtonActionPerformed(ActionEvent ae) {
105        this.getContentPane().radioButtonActionPerformed(ae);
106    }
107
108    protected void addCheckBoxAction(JCheckBox b) {
109        b.addActionListener(this::checkBoxActionPerformed);
110    }
111
112    protected void checkBoxActionPerformed(ActionEvent ae) {
113        this.getContentPane().checkBoxActionPerformed(ae);
114    }
115
116    protected void addSpinnerChangeListerner(JSpinner s) {
117        s.addChangeListener(this::spinnerChangeEvent);
118    }
119
120    protected void spinnerChangeEvent(ChangeEvent ae) {
121        this.getContentPane().spinnerChangeEvent(ae);
122    }
123
124    protected void addComboBoxAction(JComboBox<?> b) {
125        b.addActionListener(this::comboBoxActionPerformed);
126    }
127
128    protected void comboBoxActionPerformed(ActionEvent ae) {
129        this.getContentPane().comboBoxActionPerformed(ae);
130    }
131
132    protected void selectNextItemComboBox(JComboBox<?> b) {
133        this.getContentPane().selectNextItemComboBox(b);
134    }
135
136    /**
137     * Will modify the character column width of a TextArea box to 90% of a
138     * panels width. ScrollPane is set to 95% of panel width.
139     *
140     * @param scrollPane the pane containing the textArea
141     * @param textArea   the textArea to adjust
142     */
143    protected void adjustTextAreaColumnWidth(JScrollPane scrollPane, JTextArea textArea) {
144        this.getContentPane().adjustTextAreaColumnWidth(scrollPane, textArea, this.getPreferredSize());
145    }
146
147    /**
148     * Load the table width, position, and sorting status from the user
149     * preferences file.
150     *
151     * @param table The table to be adjusted.
152     *
153     */
154    public void loadTableDetails(JTable table) {
155        this.getContentPane().loadTableDetails(table);
156    }
157
158    protected void clearTableSort(JTable table) {
159        this.getContentPane().clearTableSort(table);
160    }
161
162    /**
163     * Code at frame level to clear modified flag
164     */
165    protected synchronized void createShutDownTask() {
166        InstanceManager.getDefault(OperationsManager.class)
167        .setShutDownTask(new SwingShutDownTask("Operations Train Window Check", // NOI18N
168                Bundle.getMessage("PromptQuitWindowNotWritten"), Bundle.getMessage("PromptSaveQuit"), this) {
169            @Override
170            public boolean checkPromptNeeded() {
171                setModifiedFlag(false); // allow only one popup requesting save operation files
172                if (Setup.isAutoSaveEnabled()) {
173                    storeValues();
174                    return true;
175                }
176                return !OperationsXml.areFilesDirty();
177            }
178
179            @Override
180            public void didPrompt() {
181                storeValues();
182            }
183        });
184    }
185    
186    @Override
187    protected void storeValues() {
188        this.getContentPane().storeValues();
189    }
190
191    @Override
192    public void dispose() {
193        this.getContentPane().dispose();
194        super.dispose();
195    }
196
197    /*
198     * Kludge fix for horizontal scrollbar encroaching buttons at bottom of a scrollable window.
199     */
200    protected void addHorizontalScrollBarKludgeFix(JScrollPane pane, JPanel panel) {
201        this.getContentPane().addHorizontalScrollBarKludgeFix(pane, panel);
202    }
203
204    /**
205     * {@inheritDoc}
206     * <p>
207     * This implementation only accepts the content pane if it is an
208     * {@link OperationsPanel}.
209     *
210     * @throws java.lang.IllegalArgumentException if the content pane is not an
211     *                                            OperationsPanel
212     */
213    @Override
214    public void setContentPane(Container contentPane) {
215        if (contentPane instanceof OperationsPanel) {
216            super.setContentPane(contentPane);
217        } else {
218            throw new IllegalArgumentException("OperationsFrames can only use an OperationsPanel as the contentPane");
219        }
220    }
221
222    /**
223     * {@inheritDoc}
224     * <p>
225     * This implementation only returns the content pane if it is an
226     * {@link OperationsPanel}.
227     *
228     * @throws java.lang.IllegalArgumentException if the content pane is not an
229     *                                            OperationsPanel
230     */
231    @Override
232    public OperationsPanel getContentPane() {
233        Container c = super.getContentPane();
234        if (c instanceof OperationsPanel) {
235            return (OperationsPanel) c;
236        }
237        throw new IllegalArgumentException("OperationsFrames can only use an OperationsPanel as the contentPane");
238    }
239}