001package jmri.jmrit.display;
002
003import java.util.Objects;
004import java.util.HashSet;
005import java.util.Set;
006
007import javax.annotation.Nonnull;
008import javax.swing.JCheckBoxMenuItem;
009import javax.swing.JComponent;
010import javax.swing.JMenuItem;
011import javax.swing.JPopupMenu;
012
013import jmri.InstanceManager;
014import jmri.jmrit.logixng.LogixNG;
015import jmri.jmrit.logixng.LogixNG_Manager;
016import jmri.util.swing.JmriMouseEvent;
017
018import org.slf4j.Logger;
019import org.slf4j.LoggerFactory;
020
021/**
022 *
023 * <a href="doc-files/Heirarchy.png"><img src="doc-files/Heirarchy.png" alt="UML class diagram for package" height="33%" width="33%"></a>
024 * @author Howard G. Penny copyright (C) 2005
025 */
026public class PositionableJComponent extends JComponent implements Positionable {
027
028    protected Editor _editor = null;
029
030    private String _id;            // user's Id or null if no Id
031    private final Set<String> _classes = new HashSet<>(); // user's classes
032
033    private ToolTip _tooltip;
034    private boolean _showTooltip = true;
035    private boolean _editable = true;
036    private boolean _positionable = true;
037    private boolean _viewCoordinates = false;
038    private boolean _controlling = true;
039    private boolean _hidden = false;
040    private boolean _emptyHidden = false;
041    private int _displayLevel;
042    private double _scale;         // user's scaling factor
043
044    JMenuItem lock = null;
045    JCheckBoxMenuItem showTooltipItem = null;
046
047    private LogixNG _logixNG;
048    private String _logixNG_SystemName;
049
050    public PositionableJComponent(Editor editor) {
051        _editor = editor;
052        _scale = 1.0;
053    }
054
055    @Override
056    public Positionable deepClone() {
057        PositionableJComponent pos = new PositionableJComponent(_editor);
058        return finishClone(pos);
059    }
060
061    protected Positionable finishClone(PositionableJComponent pos) {
062        pos.setLocation(getX(), getY());
063        pos.setDisplayLevel(getDisplayLevel());
064        pos.setControlling(isControlling());
065        pos.setHidden(isHidden());
066        pos.setPositionable(isPositionable());
067        pos.setShowToolTip(showToolTip());
068        pos.setToolTip(getToolTip());
069        pos.setEditable(isEditable());
070        pos.updateSize();
071        return pos;
072    }
073
074    /** {@inheritDoc} */
075    @Override
076    public void setId(String id) throws Positionable.DuplicateIdException {
077        if (Objects.equals(this._id, id)) return;
078        _editor.positionalIdChange(this, id);
079        this._id = id;
080    }
081
082    /** {@inheritDoc} */
083    @Override
084    public String getId() {
085        return _id;
086    }
087
088    /** {@inheritDoc} */
089    @Override
090    public void addClass(String className) {
091        _editor.positionalAddClass(this, className);
092        _classes.add(className);
093    }
094
095    /** {@inheritDoc} */
096    @Override
097    public void removeClass(String className) {
098        _editor.positionalRemoveClass(this, className);
099        _classes.remove(className);
100    }
101
102    /** {@inheritDoc} */
103    @Override
104    public void removeAllClasses() {
105        for (String className : _classes) {
106            _editor.positionalRemoveClass(this, className);
107        }
108        _classes.clear();
109    }
110
111    /** {@inheritDoc} */
112    @Override
113    public Set<String> getClasses() {
114        return java.util.Collections.unmodifiableSet(_classes);
115    }
116
117    @Override
118    public JComponent getTextComponent() {
119        return this;
120    }
121
122    public void displayState() {
123    }
124
125    //
126    // *************** Positionable methods *********************
127    //
128    @Override
129    public void setPositionable(boolean enabled) {
130        _positionable = enabled;
131    }
132
133    @Override
134    public boolean isPositionable() {
135        return _positionable;
136    }
137
138    @Override
139    public void setEditable(boolean enabled) {
140        _editable = enabled;
141        showHidden();
142    }
143
144    @Override
145    public boolean isEditable() {
146        return _editable;
147    }
148
149    @Override
150    public void setViewCoordinates(boolean enabled) {
151        _viewCoordinates = enabled;
152    }
153
154    @Override
155    public boolean getViewCoordinates() {
156        return _viewCoordinates;
157    }
158
159    @Override
160    public void setControlling(boolean enabled) {
161        _controlling = enabled;
162    }
163
164    @Override
165    public boolean isControlling() {
166        return _controlling;
167    }
168
169    @Override
170    public void setHidden(boolean hide) {
171        _hidden = hide;
172    }
173
174    @Override
175    public boolean isHidden() {
176        return _hidden;
177    }
178
179    @Override
180    public void showHidden() {
181        if (!_hidden || _editor.isEditable()) {
182            setVisible(true);
183        } else {
184            setVisible(false);
185        }
186    }
187
188    @Override
189    public void setEmptyHidden(boolean hide) {
190        _emptyHidden = hide;
191    }
192
193    @Override
194    public boolean isEmptyHidden() {
195        return _emptyHidden;
196    }
197
198    /**
199     * Delayed setDisplayLevel for DnD.
200     *
201     * @param l the new level
202     */
203    public void setLevel(int l) {
204        _displayLevel = l;
205    }
206
207    @Override
208    public void setDisplayLevel(int l) {
209        int oldDisplayLevel = _displayLevel;
210        _displayLevel = l;
211        if (oldDisplayLevel != l) {
212            log.debug("Changing label display level from {} to {}", oldDisplayLevel, _displayLevel);
213            _editor.displayLevelChange(this);
214        }
215    }
216
217    @Override
218    public int getDisplayLevel() {
219        return _displayLevel;
220    }
221
222    @Override
223    public void setShowToolTip(boolean set) {
224        _showTooltip = set;
225    }
226
227    @Override
228    public boolean showToolTip() {
229        return _showTooltip;
230    }
231
232    @Override
233    public void setToolTip(ToolTip tip) {
234        _tooltip = tip;
235    }
236
237    @Override
238    public ToolTip getToolTip() {
239        return _tooltip;
240    }
241
242    @Override
243    public void setScale(double s) {
244        _scale = s;
245    }
246
247    @Override
248    public double getScale() {
249        return _scale;
250    }
251
252    // no subclasses support rotations (yet)
253    @Override
254    public void rotate(int deg) {
255    }
256
257    @Override
258    public int getDegrees() {
259        return 0;
260    }
261
262    @Override
263    @Nonnull
264    public String getTypeString() {
265        return Bundle.getMessage("PositionableType_PositionableJComponent");
266    }
267
268    @Override
269    public String getNameString() {
270        return getName();
271    }
272
273    @Override
274    public Editor getEditor() {
275        return _editor;
276    }
277
278    @Override
279    public void setEditor(Editor ed) {
280        _editor = ed;
281    }
282
283    // overide where used - e.g. momentary
284    @Override
285    public void doMousePressed(JmriMouseEvent event) {
286    }
287
288    @Override
289    public void doMouseReleased(JmriMouseEvent event) {
290    }
291
292    @Override
293    public void doMouseClicked(JmriMouseEvent event) {
294    }
295
296    @Override
297    public void doMouseDragged(JmriMouseEvent event) {
298    }
299
300    @Override
301    public void doMouseMoved(JmriMouseEvent event) {
302    }
303
304    @Override
305    public void doMouseEntered(JmriMouseEvent event) {
306    }
307
308    @Override
309    public void doMouseExited(JmriMouseEvent event) {
310    }
311
312    @Override
313    public boolean storeItem() {
314        return true;
315    }
316
317    @Override
318    public boolean doViemMenu() {
319        return true;
320    }
321
322    @Override
323    public boolean setRotateOrthogonalMenu(JPopupMenu popup) {
324        return false;
325    }
326
327    @Override
328    public boolean setRotateMenu(JPopupMenu popup) {
329        return false;
330    }
331
332    @Override
333    public boolean setScaleMenu(JPopupMenu popup) {
334        return false;
335    }
336
337    @Override
338    public boolean setDisableControlMenu(JPopupMenu popup) {
339        return false;
340    }
341
342    @Override
343    public boolean setTextEditMenu(JPopupMenu popup) {
344        return false;
345    }
346
347    @Override
348    public boolean setEditItemMenu(JPopupMenu popup) {
349        return false;
350    }
351
352    @Override
353    public boolean showPopUp(JPopupMenu popup) {
354        return false;
355    }
356
357    @Override
358    public boolean setEditIconMenu(JPopupMenu popup) {
359        return false;
360    }
361
362    @Override
363    public PositionablePopupUtil getPopupUtility() {
364        return null;
365    }
366
367    @Override
368    public void setPopupUtility(PositionablePopupUtil tu) {
369    }
370
371    @Override
372    public void updateSize() {
373    }
374
375    @Override
376    public int maxWidth() {
377        return getWidth();
378    }
379
380    @Override
381    public int maxHeight() {
382        return getHeight();
383    }
384
385    /*
386     ************** end Positionable methods *********************
387     */
388    /**
389     * Removes this object from display and persistance
390     */
391    @Override
392    public void remove() {
393        _editor.removeFromContents(this);
394        cleanup();
395        // remove from persistance by flagging inactive
396        active = false;
397    }
398
399    /**
400     * To be overridden if any special work needs to be done.
401     */
402    void cleanup() {
403    }
404
405    boolean active = true;
406
407    /**
408     * Check if the component is still displayed, and should be stored.
409     *
410     * @return true if active; false otherwise
411     */
412    public boolean isActive() {
413        return active;
414    }
415
416    @Override
417    public jmri.NamedBean getNamedBean() {
418        return null;
419    }
420
421    /** {@inheritDoc} */
422    @Override
423    public LogixNG getLogixNG() {
424        return _logixNG;
425    }
426
427    /** {@inheritDoc} */
428    @Override
429    public void setLogixNG(LogixNG logixNG) {
430        this._logixNG = logixNG;
431    }
432
433    /** {@inheritDoc} */
434    @Override
435    public void setLogixNG_SystemName(String systemName) {
436        this._logixNG_SystemName = systemName;
437    }
438
439    /** {@inheritDoc} */
440    @Override
441    public void setupLogixNG() {
442        _logixNG = InstanceManager.getDefault(LogixNG_Manager.class)
443                .getBySystemName(_logixNG_SystemName);
444        if (_logixNG == null) {
445            throw new RuntimeException(String.format(
446                    "LogixNG %s is not found for positional %s in panel %s",
447                    _logixNG_SystemName, getNameString(), getEditor().getName()));
448        }
449        _logixNG.setInlineLogixNG(this);
450    }
451
452    private final static Logger log = LoggerFactory.getLogger(PositionableJComponent.class);
453}