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