001package jmri.jmrit.display;
002
003import java.awt.Color;
004import java.awt.Font;
005import java.awt.GraphicsEnvironment;
006import java.awt.event.ActionEvent;
007import java.util.ArrayList;
008import javax.swing.AbstractAction;
009import javax.swing.BorderFactory;
010import javax.swing.ButtonGroup;
011import javax.swing.JCheckBoxMenuItem;
012import javax.swing.JComponent;
013import javax.swing.JLabel;
014import javax.swing.JMenu;
015import javax.swing.JMenuItem;
016import javax.swing.JPopupMenu;
017import javax.swing.JRadioButtonMenuItem;
018import javax.swing.JTextField;
019import javax.swing.border.Border;
020import javax.swing.border.CompoundBorder;
021import javax.swing.border.LineBorder;
022import jmri.util.MenuScroller;
023import jmri.util.swing.JmriColorChooser;
024import org.slf4j.Logger;
025import org.slf4j.LoggerFactory;
026
027/**
028 * This class handles text attributes for Positionables. Font, size, style and
029 * color. Margin size and color, Border size and color, Fixed sizes.
030 * Justification.
031 * <p>
032 * moved from PositionableLabel
033 *
034 * @author Pete Cressman copyright (C) 2010
035 */
036public class PositionablePopupUtil {
037
038    protected JComponent _textComponent;    // closest ancestor for JLabel and JTextField
039    protected int _textType;                // JComponent does not have text, used for casting
040    protected Positionable _parent;
041    protected PositionablePopupUtil _self;
042    protected PositionablePropertiesUtil _propertiesUtil;
043
044    private final Color defaultBorderColor;
045    private boolean _suppressRecentColor = false;
046
047    protected final int LABEL = 1;
048    protected final int TEXTFIELD = 2;
049    protected final int JCOMPONENT = 3;
050
051    public PositionablePopupUtil(Positionable parent, JComponent textComp) {
052        _parent = parent;
053        if (textComp instanceof JLabel) {
054            _textType = LABEL;
055        } else if (textComp instanceof JTextField) {
056            _textType = TEXTFIELD;
057        } else {
058            _textType = JCOMPONENT;
059        }
060        _textComponent = textComp;
061        _self = this;
062
063        defaultBorderColor = _parent.getBackground();
064        _propertiesUtil = new PositionablePropertiesUtil(_parent);
065    }
066
067    public PositionablePopupUtil clone(Positionable parent, JComponent textComp) {
068        PositionablePopupUtil util = new PositionablePopupUtil(parent, textComp);
069        util.setJustification(getJustification());
070        util.setHorizontalAlignment(getJustification());
071        util.setFixedWidth(getFixedWidth());
072        util.setFixedHeight(getFixedHeight());
073        util.setMargin(getMargin());
074        util.setBorderSize(getBorderSize());
075        util.setBorderColor(getBorderColor());
076        util.setFont(getFont().deriveFont(getFontStyle()));
077        util.setFontSize(getFontSize());
078        util.setFontStyle(getFontStyle());
079        util.setOrientation(getOrientation());
080        util.setBackgroundColor(getBackground());
081        util.setForeground(getForeground());
082        util.setHasBackground(hasBackground());     // must do this AFTER setBackgroundColor
083        return util;
084    }
085
086    @Override
087    public String toString() {
088        return _parent.getNameString() + ": fixedWidth= " + fixedWidth + ", fixedHeight= " + fixedHeight
089                + ", margin= " + margin + ", borderSize= " + borderSize;
090    }
091
092    /**
093     * *************************************************************************************
094     */
095    static final public int FONT_COLOR = 0x00;
096    static final public int BACKGROUND_COLOR = 0x01;
097    static final public int BORDER_COLOR = 0x02;
098    static final public int MIN_SIZE = 5;
099
100    private int fixedWidth = 0;
101    private int fixedHeight = 0;
102    private int margin = 0;
103    private int borderSize = 0;
104    private Color borderColor = null;
105    private Border borderMargin = BorderFactory.createEmptyBorder(0, 0, 0, 0);
106    private Border outlineBorder = BorderFactory.createEmptyBorder(0, 0, 0, 0);
107    private boolean _hasBackground;      // Should background be painted or clear
108
109    JMenuItem italic = null;
110    JMenuItem bold = null;
111
112    public void propertyUtil(JPopupMenu popup) {
113        JMenuItem edit = new JMenuItem(Bundle.getMessage("MenuItemProperties") + "...");
114        edit.addActionListener((ActionEvent e) -> _propertiesUtil.display());
115        popup.add(edit);
116    }
117
118    public void setFixedTextMenu(JPopupMenu popup) {
119        JMenu edit = new JMenu(Bundle.getMessage("EditFixed"));
120        JMenuItem jmi;
121        if (getFixedWidth() == 0) {
122            jmi = edit.add("Width = Auto");
123        } else {
124            jmi = edit.add("Width = " + _parent.maxWidth());
125        }
126        jmi.setEnabled(false);
127
128        if (getFixedHeight() == 0) {
129            jmi = edit.add("Height = Auto");
130        } else {
131            jmi = edit.add("Height = " + _parent.maxHeight());
132        }
133        jmi.setEnabled(false);
134
135        edit.add(CoordinateEdit.getFixedSizeEditAction(_parent));
136
137        popup.add(edit);
138    }
139
140    public void setTextMarginMenu(JPopupMenu popup) {
141        JMenu edit = new JMenu(Bundle.getMessage("EditMargin"));
142        if ((fixedHeight == 0) || (fixedWidth == 0)) {
143            JMenuItem jmi = edit.add("Margin = " + getMargin());
144            jmi.setEnabled(false);
145            edit.add(CoordinateEdit.getMarginEditAction(_parent));
146        }
147        popup.add(edit);
148    }
149
150    public void setBackgroundMenu(JPopupMenu popup) {
151        JMenuItem edit = new JMenuItem(Bundle.getMessage("FontBackgroundColor"));
152        edit.addActionListener((ActionEvent event) -> {
153            Color desiredColor = JmriColorChooser.showDialog(_textComponent,
154                                 Bundle.getMessage("FontBackgroundColor"),
155                                 getBackground());
156            if (desiredColor!=null ) {
157               setBackgroundColor(desiredColor);
158           }
159        });
160
161        popup.add(edit);
162
163    }
164
165    public void setTextBorderMenu(JPopupMenu popup) {
166        JMenu edit = new JMenu(Bundle.getMessage("EditBorder"));
167        JMenuItem jmi = edit.add("Border Size = " + borderSize);
168        jmi.setEnabled(false);
169        edit.add(CoordinateEdit.getBorderEditAction(_parent));
170        JMenuItem colorMenu = new JMenuItem(Bundle.getMessage("BorderColorMenu"));
171        colorMenu.addActionListener((ActionEvent event) -> {
172            Color desiredColor = JmriColorChooser.showDialog(_textComponent,
173                                 Bundle.getMessage("BorderColorMenu"),
174                                 defaultBorderColor);
175            if (desiredColor!=null ) {
176               setBorderColor(desiredColor);
177           }
178        });
179        edit.add(colorMenu);
180        popup.add(edit);
181    }
182
183    public void setTextFontMenu(JPopupMenu popup) {
184        JMenu edit = new JMenu(Bundle.getMessage("EditFont"));
185        edit.add(makeFontMenu());
186        edit.add(makeFontSizeMenu());
187        edit.add(makeFontStyleMenu());
188        JMenuItem colorMenu = new JMenuItem(Bundle.getMessage("FontColor"));
189        colorMenu.addActionListener((ActionEvent event) -> {
190            Color desiredColor = JmriColorChooser.showDialog(_textComponent,
191                                 Bundle.getMessage("FontColor"),
192                                 _textComponent.getForeground());
193            if (desiredColor!=null ) {
194               _textComponent.setForeground(desiredColor);
195           }
196        });
197        edit.add(colorMenu);
198        popup.add(edit);
199    }
200
201    public int getMargin() {
202        return margin;
203    }
204
205    public void setMargin(int m) {
206        margin = m;
207        if (_parent.isOpaque()) {
208            borderMargin = new LineBorder(getBackground(), m);
209        } else {
210            borderMargin = BorderFactory.createEmptyBorder(m, m, m, m);
211        }
212        if (_showBorder) {
213            _parent.setBorder(new CompoundBorder(outlineBorder, borderMargin));
214        }
215        _parent.updateSize();
216    }
217
218    public int getFixedWidth() {
219        return fixedWidth;
220    }
221
222    public void setFixedWidth(int w) {
223        fixedWidth = w;
224        if (log.isDebugEnabled()) {
225            log.debug("setFixedWidth()={}", getFixedWidth());
226        }
227        _parent.updateSize();
228    }
229
230    public int getFixedHeight() {
231        return fixedHeight;
232    }
233
234    public void setFixedHeight(int h) {
235        fixedHeight = h;
236        log.debug("setFixedHeight()={}", getFixedHeight());
237        _parent.updateSize();
238    }
239
240    public void setFixedSize(int w, int h) {
241        fixedWidth = w;
242        fixedHeight = h;
243        log.debug("setFixedSize()=({},{})", getFixedWidth(), getFixedHeight());
244        _parent.updateSize();
245    }
246
247    public void setBorderSize(int border) {
248        borderSize = border;
249
250        if (borderColor != null) {
251            outlineBorder = new LineBorder(borderColor, borderSize);
252            _parent.setBorder(new CompoundBorder(outlineBorder, borderMargin));
253            //setHorizontalAlignment(CENTRE);
254        }
255        _parent.updateSize();
256    }
257
258    private boolean _showBorder = true;
259
260    public void setBorder(boolean set) {
261        _showBorder = set;
262        if (set) {
263            if (borderColor != null ) {
264                outlineBorder = new LineBorder(borderColor, borderSize);
265                _parent.setBorder(new CompoundBorder(outlineBorder, borderMargin));
266            }
267        } else {
268            _parent.setBorder(null);
269        }
270    }
271
272    public int getBorderSize() {
273        return borderSize;
274    }
275
276    public void setBorderColor(Color border) {
277        borderColor = border;
278        if (borderColor != null && _showBorder) {
279            outlineBorder = new LineBorder(borderColor, borderSize);
280            _parent.setBorder(new CompoundBorder(outlineBorder, borderMargin));
281        }
282        if (!_suppressRecentColor) {
283            JmriColorChooser.addRecentColor(border);
284        }
285    }
286
287    public Color getBorderColor() {
288        if (borderColor == null) {
289            borderColor = _parent.getBackground();
290        }
291        return borderColor;
292    }
293
294    public void setForeground(Color c) {
295        _textComponent.setForeground(c);
296        _parent.updateSize();
297        if (!_suppressRecentColor) {
298            JmriColorChooser.addRecentColor(c);
299        }
300    }
301
302    public Color getForeground() {
303        return _textComponent.getForeground();
304    }
305
306    public void setBackgroundColor(Color color) {
307        if (color == null || color.getAlpha() == 0) {
308            setHasBackground(false);
309            _textComponent.setBackground(color); // retain the passed color
310                                                 // which may not be null
311        } else {
312            setHasBackground(true);
313            _textComponent.setBackground(color);
314            _parent.setBackground(color);
315            if (!_suppressRecentColor) {
316                JmriColorChooser.addRecentColor(color);
317            }
318        }
319        if (hasBackground()) {
320            setMargin(margin);  //This rebuilds margin and sets it colour.
321        }
322        _parent.updateSize();
323    }
324    
325    public void setSuppressRecentColor(boolean b) {
326        _suppressRecentColor = b;
327    }
328
329    public void setHasBackground(boolean set) {
330        _hasBackground = set;
331        if (_textComponent instanceof PositionableJPanel) {
332            _textComponent.setOpaque(_hasBackground);
333        }
334        if (!_hasBackground) {
335            _parent.setOpaque(false);
336            _textComponent.setOpaque(false);
337        }
338    }
339
340    public boolean hasBackground() {
341        return _hasBackground;
342    }
343
344    public Color getBackground() {
345        Color c = _textComponent.getBackground();
346        if (c==null) {
347            c = Color.WHITE;
348        }
349        if (!_hasBackground) {
350            // make sure the alpha value is set to 0
351            c = jmri.util.ColorUtil.setAlpha(c,0);
352        }
353        return c;
354    }
355
356    protected JMenu makeFontMenu() {
357        JMenu fontMenu = new JMenu("Font"); // create font menu
358        //fontMenu.setMnemonic('n'); // set mnemonic to n
359
360        // get the current font family name
361        String defaultFontFamilyName = _textComponent.getFont().getFamily();
362
363        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
364        String[] fontFamilyNames = ge.getAvailableFontFamilyNames();
365
366        // create radiobutton menu items for font names
367        ButtonGroup fontButtonGroup = new ButtonGroup(); // manages font names
368
369        // create Font radio button menu items
370        for (String fontFamilyName : fontFamilyNames) {
371            // create its menu item
372            JCheckBoxMenuItem fontMenuItem = new JCheckBoxMenuItem(fontFamilyName);
373            Font menuFont = fontMenuItem.getFont();
374            menuFont = new Font(fontFamilyName, menuFont.getStyle(), menuFont.getSize());
375            fontMenuItem.setFont(menuFont);
376
377            // set its action listener
378            fontMenuItem.addActionListener((ActionEvent e) -> {
379                Font oldFont = _textComponent.getFont();
380                Font newFont = new Font(fontFamilyName, oldFont.getStyle(), oldFont.getSize());
381                if (!oldFont.equals(newFont)) {
382                    setFont(newFont);
383                }
384            });
385
386            // add to button group
387            fontButtonGroup.add(fontMenuItem);
388            // set (de)selected
389            fontMenuItem.setSelected(defaultFontFamilyName.equals(fontFamilyName));
390            // add to font menu
391            fontMenu.add(fontMenuItem);
392        }
393
394        MenuScroller.setScrollerFor(fontMenu, 36);
395
396        return fontMenu;
397    }
398
399    protected JMenu makeFontSizeMenu() {
400        JMenu sizeMenu = new JMenu("Font Size");
401        ButtonGroup buttonGrp = new ButtonGroup();
402        addFontSizeMenuEntry(sizeMenu, buttonGrp, 6);
403        addFontSizeMenuEntry(sizeMenu, buttonGrp, 8);
404        addFontSizeMenuEntry(sizeMenu, buttonGrp, 10);
405        addFontSizeMenuEntry(sizeMenu, buttonGrp, 11);
406        addFontSizeMenuEntry(sizeMenu, buttonGrp, 12);
407        addFontSizeMenuEntry(sizeMenu, buttonGrp, 14);
408        addFontSizeMenuEntry(sizeMenu, buttonGrp, 16);
409        addFontSizeMenuEntry(sizeMenu, buttonGrp, 18);
410        addFontSizeMenuEntry(sizeMenu, buttonGrp, 20);
411        addFontSizeMenuEntry(sizeMenu, buttonGrp, 24);
412        addFontSizeMenuEntry(sizeMenu, buttonGrp, 28);
413        addFontSizeMenuEntry(sizeMenu, buttonGrp, 32);
414        addFontSizeMenuEntry(sizeMenu, buttonGrp, 36);
415        return sizeMenu;
416    }
417
418    void addFontSizeMenuEntry(JMenu menu, ButtonGroup fontButtonGroup, final int size) {
419        JRadioButtonMenuItem r = new JRadioButtonMenuItem("" + size);
420        r.addActionListener((ActionEvent e) -> setFontSize(size));
421        fontButtonGroup.add(r);
422        r.setSelected(_textComponent.getFont().getSize() == size);
423        menu.add(r);
424    }
425
426    public void setFont(Font font) {
427        Font oldFont = _textComponent.getFont();
428        Font newFont = new Font(font.getFamily(), oldFont.getStyle(), oldFont.getSize());
429        if (!oldFont.equals(newFont)) {
430            _textComponent.setFont(newFont);
431            _parent.updateSize();
432            _parent.getEditor().setAttributes(_self, _parent);
433        }
434    }
435
436    public Font getFont() {
437        return _textComponent.getFont();
438    }
439
440    public void setFontSize(float newSize) {
441        _textComponent.setFont(_textComponent.getFont().deriveFont(newSize));
442        _parent.updateSize();
443        ///_parent.getEditor().setAttributes(_self, _parent);
444    }
445
446    public int getFontSize() {
447        return _textComponent.getFont().getSize();
448    }
449
450    void setItalic() {
451        log.debug("When style item selected italic state is {}", italic.isSelected());
452        if (italic.isSelected()) {
453            setFontStyle(Font.ITALIC, 0);
454        } else {
455            setFontStyle(0, Font.ITALIC);
456        }
457    }
458
459    void setBold() {
460        log.debug("When style item selected bold state is {}", bold.isSelected());
461        if (bold.isSelected()) {
462            setFontStyle(Font.BOLD, 0);
463        } else {
464            setFontStyle(0, Font.BOLD);
465        }
466    }
467
468    protected JMenu makeFontStyleMenu() {
469        JMenu styleMenu = new JMenu(Bundle.getMessage("FontStyle"));
470        styleMenu.add(italic = newStyleMenuItem(new AbstractAction(Bundle.getMessage("Italic")) {
471            @Override
472            public void actionPerformed(ActionEvent e) {
473                if (log.isDebugEnabled()) { // Avoid action lookup unless needed
474                    log.debug("When style item selected {} italic state is {}", getValue(NAME), italic.isSelected());
475                }
476                if (italic.isSelected()) {
477                    setFontStyle(Font.ITALIC, 0);
478                } else {
479                    setFontStyle(0, Font.ITALIC);
480                }
481            }
482        }, Font.ITALIC));
483
484        styleMenu.add(bold = newStyleMenuItem(new AbstractAction(Bundle.getMessage("Bold")) {
485            @Override
486            public void actionPerformed(ActionEvent e) {
487                if (log.isDebugEnabled()) { // Avoid action lookup unless needed
488                    log.debug("When style item selected {} bold state is {}",
489                            getValue(NAME), bold.isSelected());
490                }
491                if (bold.isSelected()) {
492                    setFontStyle(Font.BOLD, 0);
493                } else {
494                    setFontStyle(0, Font.BOLD);
495                }
496            }
497        }, Font.BOLD));
498        return styleMenu;
499    }
500
501    public void setFontStyle(int style) {
502        _textComponent.setFont(_textComponent.getFont().deriveFont(style));
503        _parent.updateSize();
504    }
505
506    public void setFontStyle(int addStyle, int dropStyle) {
507        int styleValue = (getFontStyle() & ~dropStyle) | addStyle;
508        log.debug("setFontStyle: addStyle={}, dropStyle={}, net styleValue is {}", addStyle, dropStyle, styleValue);
509        if (bold != null) {
510            bold.setSelected((styleValue & Font.BOLD) != 0);
511        }
512        if (italic != null) {
513            italic.setSelected((styleValue & Font.ITALIC) != 0);
514        }
515        _textComponent.setFont(_textComponent.getFont().deriveFont(styleValue));
516
517        //setSize(getPreferredSize().width, getPreferredSize().height);
518        _parent.updateSize();
519    }
520
521    public int getFontStyle() {
522        return _textComponent.getFont().getStyle();
523    }
524
525    protected JMenuItem newStyleMenuItem(AbstractAction a, int mask) {
526        // next two lines needed because JCheckBoxMenuItem(AbstractAction) not in 1.1.8
527        JCheckBoxMenuItem c = new JCheckBoxMenuItem((String) a.getValue(AbstractAction.NAME));
528        c.addActionListener(a);
529        if (log.isDebugEnabled()) { // Avoid action lookup unless needed
530            log.debug("When creating style item {} mask was {} state was {}",
531                     a.getValue(AbstractAction.NAME), mask, getFontStyle());
532        }
533        if ((mask & getFontStyle()) == mask) {
534            c.setSelected(true);
535        }
536        return c;
537    }
538
539    public void copyItem(JPopupMenu popup) {
540        JMenuItem edit = new JMenuItem("Copy");
541        edit.addActionListener((ActionEvent e) -> _parent.getEditor().copyItem(_parent));
542        popup.add(edit);
543    }
544
545    /*
546     * ************* Justification ***********************
547     */
548    public void setTextJustificationMenu(JPopupMenu popup) {
549        JMenu justMenu = new JMenu(Bundle.getMessage("Justification"));
550        addJustificationMenuEntry(justMenu, LEFT);
551        addJustificationMenuEntry(justMenu, RIGHT);
552        addJustificationMenuEntry(justMenu, CENTRE);
553        popup.add(justMenu);
554    }
555
556    static public final int LEFT = 0x00;
557    static public final int RIGHT = 0x02;
558    static public final int CENTRE = 0x04;
559
560    private int justification = CENTRE; //Default is always Centre
561
562    public void setJustification(int just) {
563        log.debug("setJustification: justification={}", just);
564        justification = just;
565        setHorizontalAlignment(justification);
566        _parent.updateSize();
567    }
568
569    public void setJustification(String just) {
570        log.debug("setJustification: justification ={}", just);
571        switch (just) {
572            case "right":
573                justification = RIGHT;
574                break;
575            case "center":
576            case "centre":
577                // allow US or UK spellings
578                justification = CENTRE;
579                break;
580            default:
581                justification = LEFT;
582                break;
583        }
584        setHorizontalAlignment(justification);
585        _parent.updateSize();
586    }
587
588    public int getJustification() {
589        log.debug("getJustification: justification ={}", justification);
590        return justification;
591    }
592
593    void addJustificationMenuEntry(JMenu menu, final int just) {
594        ButtonGroup justButtonGroup = new ButtonGroup();
595        JRadioButtonMenuItem r;
596        switch (just) {
597            case RIGHT:
598                r = new JRadioButtonMenuItem(Bundle.getMessage("right"));
599                break;
600            case CENTRE:
601                r = new JRadioButtonMenuItem(Bundle.getMessage("center"));
602                break;
603            case LEFT:
604            default:
605                r = new JRadioButtonMenuItem(Bundle.getMessage("left"));
606        }
607        r.addActionListener((ActionEvent e) -> setJustification(just) //final int justification = just;
608        );
609        justButtonGroup.add(r);
610        if (justification == just) {
611            r.setSelected(true);
612        } else {
613            r.setSelected(false);
614        }
615        menu.add(r);
616    }
617
618    public void setHorizontalAlignment(int alignment) {
619        if (_textType == LABEL) {
620            switch (alignment) {
621                case LEFT:
622                    ((JLabel) _textComponent).setHorizontalAlignment(JLabel.LEFT);
623                    break;
624                case RIGHT:
625                    ((JLabel) _textComponent).setHorizontalAlignment(JLabel.RIGHT);
626                    break;
627                case CENTRE:
628                default:
629                    ((JLabel) _textComponent).setHorizontalAlignment(JLabel.CENTER);
630            }
631        } else if (_textType == TEXTFIELD) {
632            switch (alignment) {
633                case LEFT:
634                    ((JTextField) _textComponent).setHorizontalAlignment(JTextField.LEFT);
635                    break;
636                case RIGHT:
637                    ((JTextField) _textComponent).setHorizontalAlignment(JTextField.RIGHT);
638                    break;
639                case CENTRE:
640                default:
641                    ((JTextField) _textComponent).setHorizontalAlignment(JTextField.CENTER);
642            }
643        }
644    }
645
646    public String getText() {
647        if (_textType == LABEL) {
648            return ((JLabel) _textComponent).getText();
649        } else if (_textType == TEXTFIELD) {
650            return ((JTextField) _textComponent).getText();
651        }
652        return null;
653    }
654
655    public final static int HORIZONTAL = 0x00;
656    public final static int VERTICAL_UP = 0x01;
657    public final static int VERTICAL_DOWN = 0x02;
658
659    private int orientation = HORIZONTAL;
660
661    public int getOrientation() {
662        return orientation;
663    }
664
665    public void setOrientation(int ori) {
666        orientation = ori;
667        _parent.updateSize();
668    }
669
670    public void setOrientation(String ori) {
671        switch (ori) {
672            case "vertical_up":
673                setOrientation(VERTICAL_UP);
674                break;
675            case "vertical_down":
676                setOrientation(VERTICAL_DOWN);
677                break;
678            default:
679                setOrientation(HORIZONTAL);
680                break;
681        }
682    }
683
684    public void setTextOrientationMenu(JPopupMenu popup) {
685        JMenu oriMenu = new JMenu(Bundle.getMessage("Orientation"));
686        addOrientationMenuEntry(oriMenu, HORIZONTAL);
687        addOrientationMenuEntry(oriMenu, VERTICAL_UP);
688        addOrientationMenuEntry(oriMenu, VERTICAL_DOWN);
689        popup.add(oriMenu);
690    }
691
692    void addOrientationMenuEntry(JMenu menu, final int ori) {
693        ButtonGroup justButtonGroup = new ButtonGroup();
694        JRadioButtonMenuItem r;
695        switch (ori) {
696            default:
697            case HORIZONTAL:
698                r = new JRadioButtonMenuItem("Horizontal");
699                break;
700            case VERTICAL_UP:
701                r = new JRadioButtonMenuItem("Vertical Up");
702                break;
703            case VERTICAL_DOWN:
704                r = new JRadioButtonMenuItem("Vertical Down");
705                break;
706        }
707        r.addActionListener((ActionEvent e) -> setOrientation(ori));
708        justButtonGroup.add(r);
709        if (orientation == ori) {
710            r.setSelected(true);
711        } else {
712            r.setSelected(false);
713        }
714        menu.add(r);
715    }
716
717    ArrayList<JMenuItem> editAdditionalMenu = new ArrayList<>(0);
718    ArrayList<JMenuItem> viewAdditionalMenu = new ArrayList<>(0);
719
720    /**
721     * Add a menu item to be displayed when the popup menu is called for when in
722     * edit mode.
723     *
724     * @param menu the item to add
725     */
726    public void addEditPopUpMenu(JMenuItem menu) {
727        if (!editAdditionalMenu.contains(menu)) {
728            editAdditionalMenu.add(menu);
729        }
730    }
731
732    /**
733     * Add a menu item to be displayed when the popup menu is called for when in
734     * view mode.
735     *
736     * @param menu menu item or submenu to add
737     */
738    public void addViewPopUpMenu(JMenuItem menu) {
739        if (!viewAdditionalMenu.contains(menu)) {
740            viewAdditionalMenu.add(menu);
741        }
742    }
743
744    /**
745     * Add the menu items to the edit popup menu
746     *
747     * @param popup the menu to add items to
748     */
749    public void setAdditionalEditPopUpMenu(JPopupMenu popup) {
750        if (editAdditionalMenu.isEmpty()) {
751            return;
752        }
753        popup.addSeparator();
754        editAdditionalMenu.forEach(popup::add);
755    }
756
757    /**
758     * Add the menu items to the view popup menu.
759     *
760     * @param popup the menu to add items to
761     */
762    public void setAdditionalViewPopUpMenu(JPopupMenu popup) {
763        if (viewAdditionalMenu.isEmpty()) {
764            return;
765        }
766        viewAdditionalMenu.forEach(popup::add);
767    }
768
769    private final static Logger log = LoggerFactory.getLogger(PositionablePopupUtil.class);
770}