001package jmri.jmrit.display.layoutEditor.LayoutEditorDialogs;
002
003import java.awt.*;
004import java.awt.event.*;
005
006import javax.annotation.Nonnull;
007import javax.swing.*;
008
009import jmri.InvokeOnGuiThread;
010import jmri.jmrit.display.layoutEditor.LayoutEditor;
011import jmri.util.JmriJFrame;
012
013/**
014 * Layout Editor Dialogs implements some dialogs for the Layout Editor
015 *
016 * @author George Warner Copyright (c) 2019
017 */
018public class ScaleTrackDiagramDialog {
019
020    // operational instance variables shared between tools
021    private LayoutEditor layoutEditor = null;
022
023    // constructor method
024    public ScaleTrackDiagramDialog(@Nonnull LayoutEditor thePanel) {
025        layoutEditor = thePanel;
026    }
027
028    /*===============================*\
029    |*  Dialog box to enter scale /  *|
030    |*  translate track diagram info *|
031    \*===============================*/
032    //operational variables for scale/translate track diagram pane
033    private JmriJFrame scaleTrackDiagramFrame = null;
034    private boolean scaleTrackDiagramOpen = false;
035    private final JTextField xFactorField = new JTextField(6);
036    private final JTextField yFactorField = new JTextField(6);
037    private final JTextField xTranslateField = new JTextField(6);
038    private final JTextField yTranslateField = new JTextField(6);
039    private JButton scaleTrackDiagramDone;
040    private JButton scaleTrackDiagramCancel;
041
042    //display dialog for scaling the track diagram
043    @InvokeOnGuiThread
044    public void scaleTrackDiagram() {
045        if (scaleTrackDiagramOpen) {
046            scaleTrackDiagramFrame.setVisible(true);
047            return;
048        }
049
050        // Initialize if needed
051        if (scaleTrackDiagramFrame == null) {
052            scaleTrackDiagramFrame = new JmriJFrame(Bundle.getMessage("ScaleTrackDiagram"));
053            scaleTrackDiagramFrame.addHelpMenu("package.jmri.jmrit.display.ScaleTrackDiagram", true);
054            scaleTrackDiagramFrame.setLocation(70, 30);
055            Container theContentPane = scaleTrackDiagramFrame.getContentPane();
056            theContentPane.setLayout(new BoxLayout(theContentPane, BoxLayout.PAGE_AXIS));
057
058            // setup x translate
059            JPanel panel31 = new JPanel();
060            panel31.setLayout(new FlowLayout());
061            JLabel xTranslateLabel = new JLabel(Bundle.getMessage("XTranslateLabel"));
062            panel31.add(xTranslateLabel);
063            xTranslateLabel.setLabelFor(xTranslateField);
064            panel31.add(xTranslateField);
065            xTranslateField.setToolTipText(Bundle.getMessage("XTranslateHint"));
066            theContentPane.add(panel31);
067
068            //setup y translate
069            JPanel panel32 = new JPanel();
070            panel32.setLayout(new FlowLayout());
071            JLabel yTranslateLabel = new JLabel(Bundle.getMessage("YTranslateLabel"));
072            panel32.add(yTranslateLabel);
073            yTranslateLabel.setLabelFor(yTranslateField);
074            panel32.add(yTranslateField);
075            yTranslateField.setToolTipText(Bundle.getMessage("YTranslateHint"));
076            theContentPane.add(panel32);
077
078            //setup information message 1
079            JPanel panel33 = new JPanel();
080            panel33.setLayout(new FlowLayout());
081            JLabel message1Label = new JLabel(Bundle.getMessage("Message1Label"));
082            panel33.add(message1Label);
083            theContentPane.add(panel33);
084
085            //setup x factor
086            JPanel panel21 = new JPanel();
087            panel21.setLayout(new FlowLayout());
088            JLabel xFactorLabel = new JLabel(Bundle.getMessage("XFactorLabel"));
089            panel21.add(xFactorLabel);
090            xFactorLabel.setLabelFor(xFactorField);
091            panel21.add(xFactorField);
092            xFactorField.setToolTipText(Bundle.getMessage("FactorHint"));
093            theContentPane.add(panel21);
094
095            //setup y factor
096            JPanel panel22 = new JPanel();
097            panel22.setLayout(new FlowLayout());
098            JLabel yFactorLabel = new JLabel(Bundle.getMessage("YFactorLabel"));
099            panel22.add(yFactorLabel);
100            yFactorLabel.setLabelFor(yFactorField);
101            panel22.add(yFactorField);
102            yFactorField.setToolTipText(Bundle.getMessage("FactorHint"));
103            theContentPane.add(panel22);
104
105            //setup information message 2
106            JPanel panel23 = new JPanel();
107            panel23.setLayout(new FlowLayout());
108            JLabel message2Label = new JLabel(Bundle.getMessage("Message2Label"));
109            panel23.add(message2Label);
110            theContentPane.add(panel23);
111
112            //set up Done and Cancel buttons
113            JPanel panel5 = new JPanel();
114            panel5.setLayout(new FlowLayout());
115            panel5.add(scaleTrackDiagramDone = new JButton(Bundle.getMessage("ScaleTranslate")));
116            scaleTrackDiagramDone.addActionListener(this::scaleTrackDiagramDonePressed);
117            scaleTrackDiagramDone.setToolTipText(Bundle.getMessage("ScaleTranslateHint"));
118
119            panel5.add(scaleTrackDiagramCancel = new JButton(Bundle.getMessage("ButtonCancel")));
120            scaleTrackDiagramCancel.addActionListener(this::scaleTrackDiagramCancelPressed);
121            scaleTrackDiagramCancel.setToolTipText(Bundle.getMessage("CancelHint", Bundle.getMessage("ButtonCancel")));
122            theContentPane.add(panel5);
123
124            //make this button the default button (return or enter activates)
125            JRootPane rootPane = SwingUtilities.getRootPane(scaleTrackDiagramDone);
126            rootPane.setDefaultButton(scaleTrackDiagramDone);
127        }
128
129        // Set up for Entry of Scale and Translation
130        xFactorField.setText("1.0");
131        yFactorField.setText("1.0");
132        xTranslateField.setText("0");
133        yTranslateField.setText("0");
134        scaleTrackDiagramFrame.addWindowListener(new WindowAdapter() {
135            @Override
136            public void windowClosing(WindowEvent event) {
137                scaleTrackDiagramCancelPressed(null);
138            }
139        });
140        scaleTrackDiagramFrame.pack();
141        scaleTrackDiagramFrame.setVisible(true);
142        scaleTrackDiagramOpen = true;
143    }
144
145    private void scaleTrackDiagramDonePressed(@Nonnull ActionEvent event) {
146        boolean changeFlag = false;
147        boolean translateError = false;
148        float xTranslation, yTranslation, xFactor, yFactor;
149
150        // get x translation
151        String newText = xTranslateField.getText().trim();
152        try {
153            xTranslation = Float.parseFloat(newText);
154        } catch (NumberFormatException e) {
155            showEntryErrorDialog(scaleTrackDiagramFrame, e);
156            return;
157        }
158
159        // get y translation
160        newText = yTranslateField.getText().trim();
161        try {
162            yTranslation = Float.parseFloat(newText);
163        } catch (NumberFormatException e) {
164            showEntryErrorDialog(scaleTrackDiagramFrame, e);
165            return;
166        }
167
168        // get x factor
169        newText = xFactorField.getText().trim();
170        try {
171            xFactor = Float.parseFloat(newText);
172        } catch (NumberFormatException e) {
173            showEntryErrorDialog(scaleTrackDiagramFrame, e);
174            return;
175        }
176
177        // get y factor
178        newText = yFactorField.getText().trim();
179        try {
180            yFactor = Float.parseFloat(newText);
181        } catch (NumberFormatException e) {
182            showEntryErrorDialog(scaleTrackDiagramFrame, e);
183            return;
184        }
185
186        // here when all numbers read in successfully - check for translation
187        if ((xTranslation != 0.0F) || (yTranslation != 0.0F)) {
188            //apply translation
189            if (layoutEditor.translateTrack(xTranslation, yTranslation)) {
190                changeFlag = true;
191            } else {
192                log.error("Error translating track diagram");
193                translateError = true;
194            }
195        }
196
197        if (!translateError && ((xFactor != 1.0) || (yFactor != 1.0))) {
198            //apply scale change
199            if (layoutEditor.scaleTrack(xFactor, yFactor)) {
200                changeFlag = true;
201            } else {
202                log.error("Error scaling track diagram");
203            }
204        }
205        layoutEditor.clearSelectionGroups();
206
207        scaleTrackDiagramCancelPressed(null);
208
209        if (changeFlag) {
210            layoutEditor.redrawPanel();
211            layoutEditor.setDirty();
212        }
213    }
214
215    private void scaleTrackDiagramCancelPressed(ActionEvent event) {
216        scaleTrackDiagramOpen = false;
217        scaleTrackDiagramFrame.setVisible(false);
218        scaleTrackDiagramFrame.dispose();
219        scaleTrackDiagramFrame = null;
220    }
221
222    /**
223     * showEntryErrorDialog(Component parentComponent, NumberFormatException e)
224     *
225     * @param parentComponent determines the <code>Frame</code> in which the
226     *                        dialog is displayed; if <code>null</code>, or if
227     *                        the <code>parentComponent</code> has no
228     *                        <code>Frame</code>, a default <code>Frame</code>
229     *                        is used
230     * @param e               Exception thrown to indicate that the application
231     *                        has attempted to convert a string to one of the
232     *                        numeric types, but that the string does not have
233     *                        the appropriate format.
234     */
235    private void showEntryErrorDialog(Component parentComponent, NumberFormatException e) {
236        JOptionPane.showMessageDialog(parentComponent,
237                String.format("%s: %s %s", Bundle.getMessage("EntryError"),
238                        e, Bundle.getMessage("TryAgain")),
239                Bundle.getMessage("ErrorTitle"),
240                JOptionPane.ERROR_MESSAGE);
241    }
242
243    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(
244            ScaleTrackDiagramDialog.class);
245}