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