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