001package jmri.jmrit.display.controlPanelEditor.shape;
002
003import java.awt.Graphics;
004import java.awt.Point;
005import java.awt.Rectangle;
006import java.awt.event.ActionEvent;
007
008import javax.swing.JMenu;
009import javax.swing.JMenuItem;
010
011import jmri.jmrit.display.Editor;
012import jmri.jmrit.display.Positionable;
013import jmri.util.swing.JmriJOptionPane;
014import jmri.util.swing.JmriMouseEvent;
015
016/**
017 * @author Pete Cressman Copyright (c) 2012
018 */
019public class ShapeDrawer {
020
021    private final Editor _editor;
022    private DrawFrame _drawFrame;
023    private PositionableShape _currentSelection;
024
025    public ShapeDrawer(Editor ed) {
026        _editor = ed;
027    }
028
029    public JMenu makeMenu() {
030        JMenu drawMenu = new JMenu(Bundle.getMessage("drawShapes"));
031
032        JMenuItem shapeItem = new JMenuItem(Bundle.getMessage("drawSth", Bundle.getMessage("Rectangle")));
033        drawMenu.add(shapeItem);
034        shapeItem.addActionListener((ActionEvent event) -> newRectangle());
035        shapeItem = new JMenuItem(Bundle.getMessage("drawSth", Bundle.getMessage("roundRect")));
036        drawMenu.add(shapeItem);
037        shapeItem.addActionListener((ActionEvent event) -> newRoundRectangle());
038
039        shapeItem = new JMenuItem(Bundle.getMessage("drawSth", Bundle.getMessage("Polygon")));
040        drawMenu.add(shapeItem);
041        shapeItem.addActionListener((ActionEvent event) -> newPolygon());
042
043        shapeItem = new JMenuItem(Bundle.getMessage("drawSth", Bundle.getMessage("Circle")));
044        drawMenu.add(shapeItem);
045        shapeItem.addActionListener((ActionEvent event) -> newCircle());
046        shapeItem = new JMenuItem(Bundle.getMessage("drawSth", Bundle.getMessage("Ellipse")));
047        drawMenu.add(shapeItem);
048        shapeItem.addActionListener((ActionEvent event) -> newEllipse());
049
050        return drawMenu;
051    }
052
053    private void newRectangle() {
054        if (makeNewShape()) {
055            _drawFrame = new DrawRectangle("newShape", "Rectangle", null, _editor, true);
056        }
057    }
058
059    private void newRoundRectangle() {
060        if (makeNewShape()) {
061            _drawFrame = new DrawRoundRect("newShape", "roundRect", null, _editor, true);
062        }
063    }
064
065    private void newPolygon() {
066        if (makeNewShape()) {
067            _drawFrame = new DrawPolygon("newShape", "Polygon", null, _editor, true);
068        }
069    }
070
071    private void newCircle() {
072        if (makeNewShape()) {
073            _drawFrame = new DrawCircle("newShape", "Circle", null, _editor, true);
074        }
075    }
076
077    private void newEllipse() {
078        if (makeNewShape()) {
079            _drawFrame = new DrawEllipse("newShape", "Ellipse", null, _editor, true);
080        }
081    }
082
083    protected boolean makeNewShape() {
084        if (_drawFrame != null) {
085            int ans = JmriJOptionPane.showConfirmDialog(_drawFrame,
086                   Bundle.getMessage("cancelFrame", _drawFrame.getTitle()),
087                   Bundle.getMessage("QuestionTitle"),
088                   JmriJOptionPane.YES_NO_OPTION, JmriJOptionPane.QUESTION_MESSAGE);
089            if (ans == JmriJOptionPane.YES_OPTION) {
090                _drawFrame.closingEvent(true);
091                return true;
092            } else {
093                _drawFrame.toFront();
094                _drawFrame.setVisible(true);
095                return false;
096            }
097        } else {
098            return true;
099        }
100    }
101
102    protected boolean setDrawFrame(DrawFrame f) {
103        if (f == null) {
104            _drawFrame = null;
105            if (_currentSelection != null) {
106                _currentSelection.removeHandles();
107                _currentSelection = null;
108            }
109            return true;
110        }
111        if (makeNewShape()) {
112            _drawFrame = f;
113            _currentSelection = _drawFrame._shape;
114            _currentSelection.drawHandles();
115            _editor.deselectSelectionGroup();
116            return true;
117        }
118       return false;
119    }
120
121    public void paint(Graphics g) {
122        if (_drawFrame instanceof DrawPolygon) {
123            ((DrawPolygon) _drawFrame).drawShape(g);
124        }
125    }
126
127    ///////////////////////////// Mouse /////////////////////////////
128    /**
129     * @param event the event to process
130     * @param pos   the item to check
131     * @return true if creating or editing; false otherwise
132     */
133    public boolean doMousePressed(JmriMouseEvent event, Positionable pos) {
134        log.debug("Mouse Pressed _drawFrame= {}, _currentSelection= {}",
135               (_drawFrame==null ? "null" : _drawFrame.getTitle()),
136               (_currentSelection == null ? "null" :_currentSelection.getClass().getName()));
137        if (_drawFrame != null) {
138            if (_drawFrame instanceof DrawPolygon && _drawFrame._shape != null) {
139                ((DrawPolygon) _drawFrame).anchorPoint(event.getX(), event.getY());
140            }
141            return true;
142        }
143        if (pos instanceof PositionableShape && _editor.isEditable()) {
144            if (_currentSelection != null) {
145                _currentSelection.removeHandles();
146            }
147            _currentSelection = (PositionableShape) pos;
148            _currentSelection.drawHandles();
149            return true;
150        }
151        if (_currentSelection != null) {
152            _currentSelection.removeHandles();
153            _currentSelection = null;
154        }
155        return false;
156    }
157
158    /*
159     * For all PositionableShapes except PositionablePolygon, this terminates the first
160     * phase of creating the PositionableShape. The initial DrawFrame is discarded and
161     * the shape is created, entered into the Editor'c content and the editing version
162     * of the DrawFrame is made.
163     * For a PositionablePolygon, the releases add a vertex to the shape. The actual
164     * creation of the PositionablePolygon, and the above actions are done at doMouseClicked
165     *
166     */
167    public boolean doMouseReleased(Positionable selection, JmriMouseEvent event, Editor ed) {
168        log.debug("Mouse Released _drawFrame= {}", (_drawFrame==null ? "null" : _drawFrame.getTitle()));
169        if (_drawFrame != null && _drawFrame._shape == null && _drawFrame._create) {
170            if (_drawFrame instanceof DrawPolygon) {
171                ((DrawPolygon)_drawFrame).makeVertex(event, ed);
172            } else {
173                Rectangle r = ed.getSelectRect();
174                PositionableShape shape;
175                if (r != null) {
176                    shape = _drawFrame.makeFigure(r, ed);
177                } else {
178                    return false;
179                }
180                shape.setWidth(r.width);
181                shape.setHeight(r.height);
182                shape.setLocation(r.x, r.y);
183                shape.updateSize();
184                _drawFrame.closingEvent(false);       // close opening create prompt frame
185                _drawFrame = shape.makeEditFrame(true); // make finishing create frame;
186                try {
187                    ed.putItem(shape);
188                } catch (Positionable.DuplicateIdException e) {
189                    // This should never happen
190                    log.error("Editor.putItem() with null id has thrown DuplicateIdException", e);
191                }
192                return true;
193            }
194        }
195        return false;
196    }
197
198    public boolean doMouseClicked(JmriMouseEvent event, Editor ed) {
199        log.debug("Mouse Clicked _drawFrame= {}", (_drawFrame==null ? "null" : _drawFrame.getTitle()));
200        if (_drawFrame != null && _drawFrame._create) {
201            PositionableShape shape;
202            if (_drawFrame instanceof DrawPolygon && event.getClickCount() > 1) {
203                shape = _drawFrame.makeFigure(null, ed);
204                if (shape != null) {
205                    Point pt = ((DrawPolygon)_drawFrame).getStartPoint();
206                    shape.setLocation(pt.x, pt.y);
207                    shape.updateSize();
208                    _drawFrame.closingEvent(false);       // close opening create prompt frame
209                    _drawFrame = shape.makeEditFrame(true); // make finishing create frame;
210                    try {
211                        ed.putItem(shape);
212                    } catch (Positionable.DuplicateIdException e) {
213                        // This should never happen
214                        log.error("Editor.putItem() with null id has thrown DuplicateIdException", e);
215                    }
216                    return true;
217                }
218            }
219        }
220        return false;
221    }
222
223    public boolean doMouseDragged(JmriMouseEvent event) {
224        log.debug("Mouse Dragged _drawFrame= {}, _currentSelection= {}",
225                (_drawFrame==null ? "null" : _drawFrame.getTitle()),
226                (_currentSelection == null ? "null" :_currentSelection.getClass().getName()));
227        if (_currentSelection == null && _drawFrame instanceof DrawPolygon) {
228            ((DrawPolygon) _drawFrame).moveTo(event.getX(), event.getY());
229            return true;  // no select rect
230        } else if (_currentSelection != null) {
231            return _currentSelection.doHandleMove(event);
232        }
233        return false;
234    }
235
236    /*
237     * Make rubber band line
238     */
239    public boolean doMouseMoved(JmriMouseEvent event) {
240        if (_drawFrame instanceof DrawPolygon) {
241            ((DrawPolygon) _drawFrame).moveTo(event.getX(), event.getY());
242            return true;     // no dragging when editing
243        }
244        return false;
245    }
246
247    public void add(boolean up) {
248        if (_drawFrame instanceof DrawPolygon) {
249            ((DrawPolygon) _drawFrame).addVertex(up);
250        }
251    }
252
253    public void delete() {
254        if (_drawFrame instanceof DrawPolygon) {
255            ((DrawPolygon) _drawFrame).deleteVertex();
256        }
257    }
258
259    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ShapeDrawer.class);
260
261}