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.MIN_CHECKBOXES and OperationsFrame.MAX_CHECKBOXES
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    protected void adjustTextAreaColumnWidth(JScrollPane scrollPane, JTextArea textArea, Dimension size) {
148        this.getContentPane().adjustTextAreaColumnWidth(scrollPane, textArea, size);
149    }
150
151    /**
152     * Load the table width, position, and sorting status from the user
153     * preferences file.
154     *
155     * @param table The table to be adjusted.
156     *
157     */
158    public void loadTableDetails(JTable table) {
159        this.getContentPane().loadTableDetails(table);
160    }
161
162    protected void clearTableSort(JTable table) {
163        this.getContentPane().clearTableSort(table);
164    }
165
166    /**
167     * Code at frame level to clear modified flag
168     */
169    protected synchronized void createShutDownTask() {
170        InstanceManager.getDefault(OperationsManager.class)
171        .setShutDownTask(new SwingShutDownTask("Operations Train Window Check", // NOI18N
172                Bundle.getMessage("PromptQuitWindowNotWritten"), Bundle.getMessage("PromptSaveQuit"), this) {
173            @Override
174            public boolean checkPromptNeeded() {
175                setModifiedFlag(false); // allow only one popup requesting save operation files
176                if (Setup.isAutoSaveEnabled()) {
177                    storeValues();
178                    return true;
179                }
180                return !OperationsXml.areFilesDirty();
181            }
182
183            @Override
184            public void didPrompt() {
185                storeValues();
186            }
187        });
188    }
189    
190    @Override
191    protected void storeValues() {
192        this.getContentPane().storeValues();
193    }
194
195    @Override
196    public void dispose() {
197        this.getContentPane().dispose();
198        super.dispose();
199    }
200
201    /*
202     * Kludge fix for horizontal scrollbar encroaching buttons at bottom of a scrollable window.
203     */
204    protected void addHorizontalScrollBarKludgeFix(JScrollPane pane, JPanel panel) {
205        this.getContentPane().addHorizontalScrollBarKludgeFix(pane, panel);
206    }
207
208    /**
209     * {@inheritDoc}
210     * <p>
211     * This implementation only accepts the content pane if it is an
212     * {@link OperationsPanel}.
213     *
214     * @throws java.lang.IllegalArgumentException if the content pane is not an
215     *                                            OperationsPanel
216     */
217    @Override
218    public void setContentPane(Container contentPane) {
219        if (contentPane instanceof OperationsPanel) {
220            super.setContentPane(contentPane);
221        } else {
222            throw new IllegalArgumentException("OperationsFrames can only use an OperationsPanel as the contentPane");
223        }
224    }
225
226    /**
227     * {@inheritDoc}
228     * <p>
229     * This implementation only returns the content pane if it is an
230     * {@link OperationsPanel}.
231     *
232     * @throws java.lang.IllegalArgumentException if the content pane is not an
233     *                                            OperationsPanel
234     */
235    @Override
236    public OperationsPanel getContentPane() {
237        Container c = super.getContentPane();
238        if (c instanceof OperationsPanel) {
239            return (OperationsPanel) c;
240        }
241        throw new IllegalArgumentException("OperationsFrames can only use an OperationsPanel as the contentPane");
242    }
243}