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    @Override
199    public void setValueEditDisabled(boolean isDisabled) {
200    }
201
202    @Override
203    public boolean isValueEditDisabled() {
204        return false;
205    }
206
207    /**
208     * Delayed setDisplayLevel for DnD.
209     *
210     * @param l the new level
211     */
212    public void setLevel(int l) {
213        _displayLevel = l;
214    }
215
216    @Override
217    public void setDisplayLevel(int l) {
218        int oldDisplayLevel = _displayLevel;
219        _displayLevel = l;
220        if (oldDisplayLevel != l) {
221            log.debug("Changing label display level from {} to {}", oldDisplayLevel, _displayLevel);
222            _editor.displayLevelChange(this);
223        }
224    }
225
226    @Override
227    public int getDisplayLevel() {
228        return _displayLevel;
229    }
230
231    @Override
232    public void setShowToolTip(boolean set) {
233        _showTooltip = set;
234    }
235
236    @Override
237    public boolean showToolTip() {
238        return _showTooltip;
239    }
240
241    @Override
242    public void setToolTip(ToolTip tip) {
243        _tooltip = tip;
244    }
245
246    @Override
247    public ToolTip getToolTip() {
248        return _tooltip;
249    }
250
251    @Override
252    public void setScale(double s) {
253        _scale = s;
254    }
255
256    @Override
257    public double getScale() {
258        return _scale;
259    }
260
261    // no subclasses support rotations (yet)
262    @Override
263    public void rotate(int deg) {
264    }
265
266    @Override
267    public int getDegrees() {
268        return 0;
269    }
270
271    @Override
272    @Nonnull
273    public String getTypeString() {
274        return Bundle.getMessage("PositionableType_PositionableJComponent");
275    }
276
277    @Override
278    public String getNameString() {
279        return getName();
280    }
281
282    @Override
283    public Editor getEditor() {
284        return _editor;
285    }
286
287    @Override
288    public void setEditor(Editor ed) {
289        _editor = ed;
290    }
291
292    // overide where used - e.g. momentary
293    @Override
294    public void doMousePressed(JmriMouseEvent event) {
295    }
296
297    @Override
298    public void doMouseReleased(JmriMouseEvent event) {
299    }
300
301    @Override
302    public void doMouseClicked(JmriMouseEvent event) {
303    }
304
305    @Override
306    public void doMouseDragged(JmriMouseEvent event) {
307    }
308
309    @Override
310    public void doMouseMoved(JmriMouseEvent event) {
311    }
312
313    @Override
314    public void doMouseEntered(JmriMouseEvent event) {
315    }
316
317    @Override
318    public void doMouseExited(JmriMouseEvent event) {
319    }
320
321    @Override
322    public boolean storeItem() {
323        return true;
324    }
325
326    @Override
327    public boolean doViemMenu() {
328        return true;
329    }
330
331    @Override
332    public boolean setRotateOrthogonalMenu(JPopupMenu popup) {
333        return false;
334    }
335
336    @Override
337    public boolean setRotateMenu(JPopupMenu popup) {
338        return false;
339    }
340
341    @Override
342    public boolean setScaleMenu(JPopupMenu popup) {
343        return false;
344    }
345
346    @Override
347    public boolean setDisableControlMenu(JPopupMenu popup) {
348        return false;
349    }
350
351    @Override
352    public boolean setTextEditMenu(JPopupMenu popup) {
353        return false;
354    }
355
356    @Override
357    public boolean setEditItemMenu(JPopupMenu popup) {
358        return false;
359    }
360
361    @Override
362    public boolean showPopUp(JPopupMenu popup) {
363        return false;
364    }
365
366    @Override
367    public boolean setEditIconMenu(JPopupMenu popup) {
368        return false;
369    }
370
371    @Override
372    public PositionablePopupUtil getPopupUtility() {
373        return null;
374    }
375
376    @Override
377    public void setPopupUtility(PositionablePopupUtil tu) {
378    }
379
380    @Override
381    public void updateSize() {
382    }
383
384    @Override
385    public int maxWidth() {
386        return getWidth();
387    }
388
389    @Override
390    public int maxHeight() {
391        return getHeight();
392    }
393
394    /*
395     ************** end Positionable methods *********************
396     */
397    /**
398     * Removes this object from display and persistance
399     */
400    @Override
401    public void remove() {
402        _editor.removeFromContents(this);
403        cleanup();
404        // remove from persistance by flagging inactive
405        active = false;
406    }
407
408    /**
409     * To be overridden if any special work needs to be done.
410     */
411    void cleanup() {
412    }
413
414    boolean active = true;
415
416    /**
417     * Check if the component is still displayed, and should be stored.
418     *
419     * @return true if active; false otherwise
420     */
421    public boolean isActive() {
422        return active;
423    }
424
425    @Override
426    public jmri.NamedBean getNamedBean() {
427        return null;
428    }
429
430    /** {@inheritDoc} */
431    @Override
432    public LogixNG getLogixNG() {
433        return _logixNG;
434    }
435
436    /** {@inheritDoc} */
437    @Override
438    public void setLogixNG(LogixNG logixNG) {
439        this._logixNG = logixNG;
440    }
441
442    /** {@inheritDoc} */
443    @Override
444    public void setLogixNG_SystemName(String systemName) {
445        this._logixNG_SystemName = systemName;
446    }
447
448    /** {@inheritDoc} */
449    @Override
450    public void setupLogixNG() {
451        _logixNG = InstanceManager.getDefault(LogixNG_Manager.class)
452                .getBySystemName(_logixNG_SystemName);
453        if (_logixNG == null) {
454            throw new RuntimeException(String.format(
455                    "LogixNG %s is not found for positional %s in panel %s",
456                    _logixNG_SystemName, getNameString(), getEditor().getName()));
457        }
458        _logixNG.setInlineLogixNG(this);
459    }
460
461    private final static Logger log = LoggerFactory.getLogger(PositionableJComponent.class);
462}