001package jmri.jmrit.display.palette; 002 003import java.awt.Color; 004import java.awt.Dimension; 005import java.awt.Font; 006import java.awt.datatransfer.DataFlavor; 007import java.awt.datatransfer.UnsupportedFlavorException; 008import java.awt.event.ActionEvent; 009import java.awt.event.ActionListener; 010import java.awt.event.KeyEvent; 011import java.awt.event.KeyListener; 012import java.io.IOException; 013import java.util.HashMap; 014 015import javax.swing.BorderFactory; 016import javax.swing.Box; 017import javax.swing.BoxLayout; 018import javax.swing.ButtonGroup; 019import javax.swing.JButton; 020import javax.swing.JColorChooser; 021import javax.swing.JComboBox; 022import javax.swing.JComponent; 023import javax.swing.JLabel; 024import javax.swing.JPanel; 025import javax.swing.JRadioButton; 026import javax.swing.JSpinner; 027import javax.swing.JTabbedPane; 028import javax.swing.JTextField; 029import javax.swing.SpinnerModel; 030import javax.swing.SpinnerNumberModel; 031import javax.swing.border.Border; 032import javax.swing.border.CompoundBorder; 033import javax.swing.border.LineBorder; 034import javax.swing.event.ChangeEvent; 035import javax.swing.event.ChangeListener; 036 037import jmri.jmrit.catalog.NamedIcon; 038import jmri.jmrit.display.DisplayFrame; 039import jmri.jmrit.display.Editor; 040import jmri.jmrit.display.LinkingLabel; 041import jmri.jmrit.display.Positionable; 042import jmri.jmrit.display.PositionableLabel; 043import jmri.jmrit.display.PositionablePopupUtil; 044import jmri.jmrit.display.PreviewPanel; 045import jmri.jmrit.display.SensorIcon; 046import jmri.util.swing.ImagePanel; 047import jmri.util.swing.JmriColorChooser; 048 049import org.slf4j.Logger; 050import org.slf4j.LoggerFactory; 051 052/** 053 * ItemPanel for text labels. 054 * @see ItemPanel palette class diagram 055 * @author Pete Cressman Copyright (c) 2010, 2011, 2020 056 */ 057public class TextItemPanel extends ItemPanel { 058 059 private final ImagePanel _samplePanel; 060 061 private PositionablePopupUtil _util; 062 private final HashMap<String, PositionableLabel> _samples; 063 064 private String _selectedState; 065 private boolean _isPositionableLabel; 066 private JComponent _textEditComponent; 067 068 private JTabbedPane _tabPane; 069 070 private final ButtonGroup _buttonGroup = new ButtonGroup(); 071 private AJRadioButton _fontButton; 072 private AJRadioButton _borderButton; 073 private AJRadioButton _backgroundButton; 074 protected int _selectedButton; // allow access for testing 075 protected JColorChooser _chooser; // allow access for testing 076 077 protected AJSpinner _borderSpin; // allow testing access 078 protected AJSpinner _marginSpin; 079 private AJSpinner _widthSpin; 080 private AJSpinner _heightSpin; 081 082 public static final int BORDER = 1; 083 public static final int MARGIN = 2; 084 public static final int FWIDTH = 3; 085 public static final int FHEIGHT = 4; 086 087 static final int FOREGROUND_BUTTON = 1; 088 static final int BACKGROUND_BUTTON = 2; 089 static final int TRANSPARENT_BUTTON = 3; 090 static final int BORDERCOLOR_BUTTON = 4; 091 092 093 /** 094 * Constructor for Text Labels. 095 * 096 * @param parentFrame ItemPalette instance 097 * @param type identifier of the ItemPanel type, should be "Text" 098 */ 099 public TextItemPanel(DisplayFrame parentFrame, String type) { 100 super(parentFrame, type); 101 setToolTipText(Bundle.getMessage("ToolTipDragText")); 102 _samples = new HashMap<>(); 103 _samplePanel = new ImagePanel(); 104// _samplePanel.add(Box.createVerticalStrut(50)); 105 _samplePanel.setBorder(BorderFactory.createLineBorder(Color.black)); 106 _samplePanel.setName("SamplePanel"); // to find component for testing 107 _samplePanel.setImage(_frame.getPreviewBackground()); 108 } 109 JPanel dragger; 110 111 @Override 112 public void init() { 113 if (!_initialized) { 114 add(instructions()); 115 PositionableLabel label = new PositionableLabel(Bundle.getMessage("sample"), _frame.getEditor()); 116 label.setLevel(Editor.LABELS); 117 JPanel dragger; 118 try { 119 dragger = new LabelDragJComponent(new DataFlavor(Editor.POSITIONABLE_FLAVOR), label); 120 } catch (java.lang.ClassNotFoundException cnfe) { 121 log.error("Unable to find class supporting {}", Editor.POSITIONABLE_FLAVOR, cnfe); 122 dragger = new JPanel(); 123 } 124 _util = label.getPopupUtility(); 125 _samples.put("Text", label); 126 _selectedState = "Text"; 127 _isPositionableLabel = true; 128 _textEditComponent = makeTextPanel("Text", label, true); 129 _samplePanel.add(dragger); 130 _previewPanel = new PreviewPanel(_frame, _samplePanel, null, true); 131 sampleBgColorChange(); 132 log.debug("LabelDragJComponent size {} | panel size {}", label.getPreferredSize(), _samplePanel.getPreferredSize()); 133 finishInit(false); 134 dragger.setOpaque(false); 135 dragger.setToolTipText(Bundle.getMessage("ToolTipDragIcon")); 136 if (log.isDebugEnabled()) { 137 log.debug("end init: TextItemPanel size {}", getPreferredSize()); 138 } 139 super.init(); 140 initLinkPanel(); 141 } 142 } 143 144 public void init(ActionListener doneAction, Positionable pos) { 145 _update = true; 146 _doneAction = doneAction; 147 Positionable item = pos.deepClone(); // need copy of PositionableJPanel for PopupUtility 148 _util = item.getPopupUtility(); 149 item.remove(); // don't need copy any more. Removes ghost image of PositionableJPanels 150 _isPositionableLabel = (pos instanceof PositionableLabel); 151 152 _previewPanel = new PreviewPanel(_frame, _samplePanel, null, false); 153 sampleBgColorChange(); 154 155 boolean hasTextStates; 156 if (pos instanceof SensorIcon && !((SensorIcon)pos).isIcon()) { 157 SensorIcon si = (SensorIcon) pos; 158 hasTextStates = true; 159 if (!si.isIcon() && si.isText()) { 160 _tabPane = new JTabbedPane(); 161 _tabPane.addChangeListener(c -> { 162 TextPanel panel = (TextPanel)_tabPane.getSelectedComponent(); 163 _selectedState = panel.getState(); 164 log.debug("StateChange"); 165 setChooserColor(); 166 }); 167 PositionableLabel sample = new PositionableLabel(si.getActiveText(), _frame.getEditor()); 168 sample.setForeground(si.getTextActive()); 169 sample.setBackground(si.getBackgroundActive()); 170 JPanel panel = doPopupUtility("SensorStateActive", sample, true); // NOI18N 171 _tabPane.add(panel, Bundle.getMessage("SensorStateActive")); 172 173 sample = new PositionableLabel(si.getInactiveText(), _frame.getEditor()); 174 sample.setForeground(si.getTextInActive()); 175 sample.setBackground(si.getBackgroundInActive()); 176 panel = doPopupUtility("SensorStateInactive", sample, true); // NOI18N 177 _tabPane.add(panel, Bundle.getMessage("SensorStateInactive")); 178 179 sample = new PositionableLabel(si.getUnknownText(), _frame.getEditor()); 180 sample.setForeground(si.getTextUnknown()); 181 sample.setBackground(si.getBackgroundUnknown()); 182 panel = doPopupUtility("BeanStateUnknown", sample, true); // NOI18N 183 _tabPane.add(panel, Bundle.getMessage("BeanStateUnknown")); 184 185 sample = new PositionableLabel(si.getInconsistentText(), _frame.getEditor()); 186 sample.setForeground(si.getTextInconsistent()); 187 sample.setBackground(si.getBackgroundInconsistent()); 188 panel = doPopupUtility("BeanStateInconsistent", sample, true); // NOI18N 189 _tabPane.add(panel, Bundle.getMessage("BeanStateInconsistent")); 190 /* to be used later!!! 191 for (String state : si.getStateNameCollection()) { 192 PositionableLabel sample = new PositionableLabel(si.getActiveText(), _editor); 193 sample.setForeground(si.getTextActive()); 194 sample.setBackground(si.getBackgroundActive()); 195 JPanel panel = doPopupUtility(state, sample, true); // NOI18N 196 _tabPane.add(panel, Bundle.getMessage(state)); 197 } 198 */ 199 _textEditComponent = _tabPane; 200 } // else a non-text SensorIcon cannot be decorated. 201 } else { // not a SensorIcon 202 hasTextStates = false; 203 PositionableLabel sample = new PositionableLabel("", _frame.getEditor()); 204 sample.setForeground(_util.getForeground()); 205 sample.setBackground(_util.getBackground()); 206 PositionablePopupUtil util = sample.getPopupUtility(); 207 util.setHasBackground(_util.hasBackground()); 208 boolean addtextField; 209 if (pos instanceof PositionableLabel) { 210 sample.setText(((PositionableLabel)pos).getUnRotatedText()); 211 addtextField = !(pos instanceof jmri.jmrit.display.MemoryOrGVIcon); 212 } else { 213 // To display PositionableJPanel types as PositionableLabels, set fixed sizes. 214 util.setFixedWidth(pos.getWidth() - 2*_util.getBorderSize()); 215 util.setFixedHeight(pos.getHeight() - 2*_util.getBorderSize()); 216 if (pos instanceof jmri.jmrit.display.MemoryOrGVComboIcon) { 217 JComboBox<String> box = ((jmri.jmrit.display.MemoryOrGVComboIcon)pos).getTextComponent(); 218 sample.setText(box.getSelectedItem() != null ? box.getSelectedItem().toString() : ""); 219 addtextField = false; 220 } else if (pos instanceof jmri.jmrit.display.PositionableJPanel) { 221 JTextField field = (JTextField) pos.getTextComponent(); 222 sample.setText(field.getText()); 223 addtextField = false; 224 } else { 225 addtextField = true; 226 log.error("Unknown Postionable Type {}", pos.getClass().getName()); 227 } 228 } 229 _textEditComponent = doPopupUtility("Text", sample, addtextField); 230 if (log.isDebugEnabled()) { 231 log.debug("util width= {} height= {} POS width= {} height= {}", 232 util.getFixedWidth(), util.getFixedHeight(), pos.getWidth(), pos.getHeight()); 233 } 234 } 235 finishInit(hasTextStates); 236 _bottomPanel = new JPanel(); 237 JButton cancelButton = new JButton(Bundle.getMessage("ButtonCancel")); 238 cancelButton.addActionListener(a -> cancel()); 239 _bottomPanel.add(cancelButton); 240 _bottomPanel.add(makeUpdateButton(_doneAction)); 241 add(_bottomPanel); 242 } 243 244 protected void cancel() { 245 _frame.dispose(); 246 } 247 248 @Override 249 protected JPanel instructions() { 250 JPanel blurb = new JPanel(); 251 blurb.setLayout(new BoxLayout(blurb, BoxLayout.Y_AXIS)); 252 blurb.add(new JLabel(Bundle.getMessage("addTextAndAttrs"))); 253 blurb.add(new JLabel(Bundle.getMessage("ToolTipDragText"))); 254 blurb.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE)); 255 JPanel panel = new JPanel(); 256 panel.add(blurb); 257 return panel; 258 } 259 260 @Override 261 protected void previewColorChange() { 262 _previewPanel.setBackgroundSelection(_frame.getPreviewBg()); 263 } 264 265 protected JPanel makeDoneButtonPanel(ActionListener doneAction) { 266 JPanel panel = new JPanel(); 267 JButton updateButton = new JButton(Bundle.getMessage("updateButton")); // custom update label 268 updateButton.addActionListener(doneAction); 269 updateButton.setToolTipText(Bundle.getMessage("ToolTipPickFromTable")); 270 panel.add(updateButton); 271 272 JButton cancelButton = new JButton(Bundle.getMessage("ButtonCancel")); 273 cancelButton.addActionListener(a -> closeDialogs()); 274 panel.add(cancelButton); 275 return panel; 276 } 277 278 public void updateAttributes(PositionableLabel l) { 279 setAttributes(l); 280 PositionablePopupUtil util = getPositionablePopupUtil(); 281 l.setPopupUtility(util.clone(l, l.getTextComponent())); 282 l.setFont(util.getFont().deriveFont(util.getFontStyle())); 283 if (util.hasBackground()) { // unrotated 284 l.setOpaque(true); 285 } 286 } 287 288 @Override 289 protected JPanel makeSpecialBottomPanel(boolean update) {return null;} 290 @Override 291 protected JPanel makeItemButtonPanel() {return null;} 292 @Override 293 protected JPanel makeIconDisplayPanel(String k, HashMap<String, NamedIcon> m, boolean d) {return null;} 294 @Override 295 protected void initIconFamiliesPanel() {} 296 @Override 297 protected void hideIcons() {} 298 @Override 299 protected void makeFamiliesPanel() {} 300 301 302 protected class LabelDragJComponent extends DragJComponent { 303 304 public LabelDragJComponent(DataFlavor flavor, JComponent comp) { 305 super(flavor, comp); 306 } 307 308 @Override 309 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { 310 if (!isDataFlavorSupported(flavor)) { 311 return null; 312 } 313 314 if (flavor.isMimeTypeEqual(Editor.POSITIONABLE_FLAVOR)) { 315 String link = _linkName.getText().trim(); 316 PositionableLabel sample = (PositionableLabel)getThing(); 317 PositionableLabel label; 318 if (link.length() == 0) { 319 label = new PositionableLabel(sample.getText(), sample.getEditor()); 320 } else { 321 label = new LinkingLabel(sample.getText(), sample.getEditor(), link); 322 } 323 updateAttributes(label); 324 label.setLevel(sample.getDisplayLevel()); 325 return label; 326 } 327 return null; 328 } 329 } 330 331 /*************************************************************************/ 332 static class AJSpinner extends JSpinner { 333 int _which; 334 335 AJSpinner(SpinnerModel model, int which) { 336 super(model); 337 _which = which; 338 } 339 } 340 341 static class AJRadioButton extends JRadioButton { 342 int _which; 343 344 AJRadioButton(String text, int which) { 345 super(text); 346 _which = which; 347 } 348 } 349 350 static class TextPanel extends JPanel { 351 String _state; 352 TextPanel(String state) { 353 _state = state; 354 } 355 String getState() { 356 return _state; 357 } 358 } 359 360 361 private void finishInit(boolean addCaption) { 362 _selectedButton = FOREGROUND_BUTTON; 363 if (addCaption) { 364 _selectedState = "SensorStateActive"; 365 } else { 366 _selectedState = "Text"; 367 } 368 JPanel colorButtons = makeColorPanel(addCaption); 369 makeColorChooser(); 370 JPanel panel = makeFontPanel(); 371 if (addCaption) { 372 JPanel p = new JPanel(); 373 p.add(new JLabel(Bundle.getMessage("StateTextBlurb1"))); 374 panel.add(p); 375 } 376 this.add(panel); 377 if (addCaption) { 378 JPanel p = new JPanel(); 379 p.add(new JLabel(Bundle.getMessage("StateTextBlurb3"))); 380 this.add(p); 381 } 382 JPanel textEditPanel = new JPanel(); 383 textEditPanel.setLayout(new BoxLayout(textEditPanel, BoxLayout.Y_AXIS)); 384 textEditPanel.add(_textEditComponent); 385 this.add(textEditPanel); 386 this.add(_previewPanel); 387 this.add(Box.createVerticalGlue()); 388 this.add(colorButtons); 389 this.add(_chooser); 390 } 391 392 private JPanel doPopupUtility(String type, PositionableLabel sample, boolean editText) { 393 PositionablePopupUtil util = sample.getPopupUtility(); 394 util.setJustification(_util.getJustification()); 395 util.setHorizontalAlignment(_util.getJustification()); 396 if (_isPositionableLabel) { 397 int size = _util.getFixedWidth(); 398 util.setFixedWidth(size); 399 size = _util.getFixedHeight(); 400 util.setFixedHeight(size); 401 } 402 util.setMargin(_util.getMargin()); 403 util.setBorderSize(_util.getBorderSize()); 404 util.setBorderColor(_util.getBorderColor()); 405 util.setFont(util.getFont().deriveFont(_util.getFontStyle())); 406 util.setFontSize(_util.getFontSize()); 407 util.setFontStyle(_util.getFontStyle()); 408 util.setOrientation(_util.getOrientation()); 409 boolean back = (sample.getBackground() != null); 410 util.setHasBackground(back); 411 sample.setOpaque(back); 412 sample.updateSize(); 413 414 _samples.put(type, sample); 415 _selectedState = type; 416 JPanel panel = makeTextPanel(type, sample, editText); 417 _samplePanel.add(sample); 418 return panel; 419 } 420 421 protected void initLinkPanel() { 422 JPanel blurb = new JPanel(); 423 blurb.setLayout(new BoxLayout(blurb, BoxLayout.Y_AXIS)); 424 blurb.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE)); 425 blurb.add(new JLabel(Bundle.getMessage("ToLinkToURL", "Text"))); 426 blurb.add(new JLabel(Bundle.getMessage("enterPanel"))); 427 blurb.add(new JLabel(Bundle.getMessage("enterURL"))); 428 blurb.add(Box.createVerticalStrut(ItemPalette.STRUT_SIZE)); 429 blurb.add(new JLabel(Bundle.getMessage("LinkName"))); 430 blurb.add(_linkName); 431 _linkName.setToolTipText(Bundle.getMessage("ToolTipLink")); 432 blurb.setToolTipText(Bundle.getMessage("ToolTipLink")); 433 JPanel panel = new JPanel(); 434 panel.add(blurb); 435 JPanel linkPanel = new JPanel(); 436 linkPanel.add(panel); 437 add(linkPanel); 438 } 439 440 private void makeColorChooser() { 441 Color panelBackground = _frame.getEditor().getTargetPanel().getBackground(); // start using Panel background color 442 _chooser = JmriColorChooser.extendColorChooser(new JColorChooser(panelBackground)); 443 _chooser.getSelectionModel().addChangeListener(c -> chooserColorChange()); 444 _chooser.setPreviewPanel(new JPanel()); 445 JmriColorChooser.suppressAddRecentColor(true); 446 } 447 448 private void fontChange() { 449 log.debug("fontChange"); 450 if (_selectedButton != FOREGROUND_BUTTON) { 451 _selectedButton = FOREGROUND_BUTTON; 452 _fontButton.setSelected(true); // will change chooser color, if needed 453 } 454 updateSamples(); 455 } 456 457 private class SpinnerChangeListener implements ChangeListener { 458 @Override 459 public void stateChanged(ChangeEvent e) { 460 Object obj = e.getSource(); 461 int num = ((Number) ((AJSpinner) obj).getValue()).intValue(); 462 int which = ((AJSpinner) obj)._which; 463 switch (which) { 464 case BORDER: 465 _util.setBorderSize(num); 466 _borderButton.setSelected(true); 467 _selectedButton = BORDERCOLOR_BUTTON; 468 break; 469 case MARGIN: 470 _util.setMargin(num); 471 _selectedButton = BACKGROUND_BUTTON; 472 _backgroundButton.setSelected(true); 473 break; 474 case FWIDTH: 475 _util.setFixedWidth(num); 476 _selectedButton = BACKGROUND_BUTTON; 477 _backgroundButton.setSelected(true); 478 break; 479 case FHEIGHT: 480 _util.setFixedHeight(num); 481 _selectedButton = BACKGROUND_BUTTON; 482 _backgroundButton.setSelected(true); 483 break; 484 default: 485 log.warn("Unexpected _which {} in stateChanged", ((AJSpinner) obj)._which); 486 break; 487 } 488 updateSamples(); 489 log.debug("SpinnerChange which= {}, num= {}", which, num); 490 } 491 } 492 493 private JPanel makeFontPanel() { 494 JPanel panel = new JPanel(); 495 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 496 panel.setBorder(BorderFactory.createTitledBorder( 497 BorderFactory.createLineBorder(Color.black, 1), 498 Bundle.getMessage("FontDisplaySettings"))); 499 500 ActionListener fontAction = ((ActionEvent event) -> { 501 fontChange(); // callback 502 }); 503 FontPanel fontPanel = new FontPanel(_util, fontAction); 504 panel.add(fontPanel); 505 fontPanel.setFontSelections(); 506 507 ChangeListener listener = new SpinnerChangeListener(); 508 JPanel sizePanel = new JPanel(); 509 SpinnerNumberModel model = new SpinnerNumberModel(_util.getBorderSize(), 0, 100, 1); 510 _borderSpin = new AJSpinner(model, BORDER); 511 sizePanel.add(makeSpinPanel("borderSize", _borderSpin, listener)); 512 model = new SpinnerNumberModel(_util.getMargin(), 0, 100, 1); 513 _marginSpin = new AJSpinner(model, MARGIN); 514 sizePanel.add(makeSpinPanel("marginSize", _marginSpin, listener)); 515 if (_isPositionableLabel) { 516 model = new SpinnerNumberModel(_util.getFixedWidth(), 0, 1000, 1); 517 _widthSpin = new AJSpinner(model, FWIDTH); 518 sizePanel.add(makeSpinPanel("fixedWidth", _widthSpin, listener)); 519 model = new SpinnerNumberModel(_util.getFixedHeight(), 0, 1000, 1); 520 _heightSpin = new AJSpinner(model, FHEIGHT); 521 sizePanel.add(makeSpinPanel("fixedHeight", _heightSpin, listener)); 522 } 523 panel.add(sizePanel); 524 return panel; 525 } 526 527 public static JPanel makeSpinPanel(String caption, JSpinner spin, ChangeListener listener) { 528 JPanel panel = new JPanel(); 529 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 530 panel.add(new JLabel(Bundle.getMessage(caption))); 531 spin.addChangeListener(listener); 532 panel.add(spin); 533 return panel; 534 } 535 536 private JPanel makeTextPanel(String beanState, JLabel sample, boolean addTextField) { 537 JPanel panel = new TextPanel(beanState); 538 // use NamedBeanBundle property for captions 539 // sample is the preview JLable 540 panel.setBorder(BorderFactory.createTitledBorder( 541 BorderFactory.createLineBorder(Color.black, 1), 542 Bundle.getMessage(beanState))); 543 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 544 JPanel p = new JPanel(); 545 if (addTextField) { 546 JTextField textField = new JTextField(sample.getText(), 25); 547 textField.addKeyListener(new KeyListener() { 548 JLabel sample; 549 550 KeyListener init(JLabel s) { 551 sample = s; 552 return this; 553 } 554 555 @Override 556 public void keyTyped(KeyEvent evt) { 557 } 558 559 @Override 560 public void keyPressed(KeyEvent evt) { 561 } 562 563 @Override 564 public void keyReleased(KeyEvent evt) { 565 JTextField tmp = (JTextField) evt.getSource(); 566 sample.setText(tmp.getText()); 567 updateSamples(); 568 } 569 }.init(sample)); 570 p.add(textField); 571 panel.add(p); 572 } 573 return panel; 574 } 575 576 private JPanel makeColorPanel(boolean addCaption) { 577 JPanel panel = new JPanel(); 578 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 579 panel.setBorder(BorderFactory.createTitledBorder( 580 BorderFactory.createLineBorder(Color.black, 1), 581 Bundle.getMessage("ColorDisplaySettings"))); 582 583 JPanel buttonPanel = new JPanel(); 584 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); 585 _fontButton = makeColorRadioButton("FontColor", FOREGROUND_BUTTON); 586 buttonPanel.add(_fontButton); 587 588 _backgroundButton = makeColorRadioButton("FontBackgroundColor", BACKGROUND_BUTTON); 589 buttonPanel.add(_backgroundButton); 590 591 AJRadioButton button = makeColorRadioButton("transparentBack", TRANSPARENT_BUTTON); 592 buttonPanel.add(button); 593 594 _borderButton = makeColorRadioButton("borderColor", BORDERCOLOR_BUTTON); 595 buttonPanel.add(_borderButton); 596 597 panel.add(buttonPanel); 598 if (addCaption) { 599 JPanel p = new JPanel(); 600 p.add(new JLabel(Bundle.getMessage("StateTextBlurb2"))); 601 panel.add(p); 602 } 603 _fontButton.setSelected(true); 604 _selectedButton = FOREGROUND_BUTTON; 605 return panel; 606 } 607 608 private AJRadioButton makeColorRadioButton(String caption, int which) { 609 AJRadioButton button = new AJRadioButton(Bundle.getMessage(caption), which); 610 button.addActionListener(a -> { 611 if (button.isSelected()) { 612 _selectedButton = button._which; 613 log.debug("Button #{} selected.", which); 614 setChooserColor(); 615 } 616 }); 617 _buttonGroup.add(button); 618 return button; 619 } 620 621 private void chooserColorChange() { 622 PositionableLabel pos =_samples.get(_selectedState); 623 PositionablePopupUtil util = pos.getPopupUtility(); 624 switch (_selectedButton) { 625 case FOREGROUND_BUTTON: 626 util.setForeground(_chooser.getColor()); 627 break; 628 case BACKGROUND_BUTTON: 629 pos.setOpaque(true); 630 util.setBackgroundColor(_chooser.getColor()); 631 break; 632 case TRANSPARENT_BUTTON: 633// util.setBackgroundColor(null); 634 pos.setOpaque(false); 635 break; 636 case BORDERCOLOR_BUTTON: 637 _util.setBorderColor(_chooser.getColor()); // will remove later!!! 638 util.setBorderColor(_chooser.getColor()); 639 break; 640 default: 641 log.warn("Unexpected color change for state {}, button# {}", _selectedState, _selectedButton); 642 break; 643 } 644 log.debug("chooserColorChange opaque= {} _selectedState= {} _selectedButton= {} color= {}", 645 pos.isOpaque(), _selectedState, _selectedButton, _chooser.getColor().toString()); 646 updateSamples(); 647 } 648 649 private void setChooserColor() { 650 PositionableLabel pos =_samples.get(_selectedState); 651 PositionablePopupUtil util = pos.getPopupUtility(); 652 Color c = null; 653 switch (_selectedButton) { 654 case FOREGROUND_BUTTON: 655 c = util.getForeground(); 656 break; 657 case BACKGROUND_BUTTON: 658 c = util.getBackground(); 659 break; 660 case BORDERCOLOR_BUTTON: 661 c = util.getBorderColor(); 662 break; 663 case TRANSPARENT_BUTTON: 664 util.setBackgroundColor(null); 665 updateSamples(); 666 break; 667 default: 668 return; 669 } 670 _chooser.setColor(c); 671 } 672 673 protected void updateSamples() { 674 boolean isPalette = (_frame instanceof ItemPalette); 675 Dimension totalDim = _frame.getSize(); 676 Dimension oldDim = getSize(); 677 678 int mar = _util.getMargin(); 679 int bor = _util.getBorderSize(); 680 Border outlineBorder; 681 Font font = _util.getFont(); 682 int just = _util.getJustification(); 683 684 for (PositionableLabel sam : _samples.values()) { 685 PositionablePopupUtil util = sam.getPopupUtility(); 686 sam.setFont(font); 687 if (_isPositionableLabel) { 688 util.setFixedWidth(_util.getFixedWidth()); 689 util.setFixedHeight(_util.getFixedHeight()); 690 } else { 691 util.setFixedWidth(util.getFixedWidth() + 2 * (mar - util.getMargin()) /*+ bor - util.getBorderSize()*/); 692 util.setFixedHeight(util.getFixedHeight() + 2 * (mar - util.getMargin()) /*+ bor - util.getBorderSize()*/); 693 } 694 util.setMargin(mar); 695 util.setBorderSize(bor); 696 Border borderMargin; 697 if (sam.isOpaque()) { 698 borderMargin = new LineBorder(sam.getBackground(), mar); 699 } else { 700 borderMargin = BorderFactory.createEmptyBorder(mar, mar, mar, mar); 701 } 702 if (bor == 0) { 703 outlineBorder = BorderFactory.createEmptyBorder(0, 0, 0, 0); 704 } else { 705 outlineBorder = new LineBorder(_util.getBorderColor(), bor); // will remove later!!! 706// outlineBorder = new LineBorder(util.getBorderColor(), bor); // will use this 707 } 708 sam.setBorder(new CompoundBorder(outlineBorder, borderMargin)); 709 710 switch (just) { 711 case PositionablePopupUtil.LEFT: 712 sam.setHorizontalAlignment(JLabel.LEFT); 713 break; 714 case PositionablePopupUtil.RIGHT: 715 sam.setHorizontalAlignment(JLabel.RIGHT); 716 break; 717 default: 718 sam.setHorizontalAlignment(JLabel.CENTER); 719 } 720 sam.updateSize(); 721 sam.setPreferredSize(sam.getSize()); 722 sam.invalidate(); 723 if (log.isTraceEnabled()) { 724 log.debug("util width= {} height= {} SAM width= {} height= {}", util.getFixedWidth(), util.getFixedHeight(), sam.getWidth(), sam.getHeight()); 725 log.debug("margin = {}, border = {}, opaque= {}", util.getMargin(), util.getBorderSize(), sam.isOpaque()); 726 } 727 } 728 _previewPanel.invalidate(); 729 _textEditComponent.invalidate(); 730 if (dragger != null) { 731 dragger.invalidate(); 732 } 733 _samplePanel.invalidate(); 734 reSizeDisplay(isPalette, oldDim, totalDim); 735 } 736 737 // called when editor changed 738 protected void sampleBgColorChange() { 739 _previewPanel.setBackgroundSelection(_frame.getPreviewBg()); 740 } 741 742 public PositionablePopupUtil getPositionablePopupUtil() { 743 PositionableLabel pos =_samples.get(_selectedState); 744 PositionablePopupUtil util = pos.getPopupUtility(); 745 _util.setForeground(util.getForeground()); 746 _util.setBackgroundColor(util.getBackground()); 747 _util.setBorderColor(util.getBorderColor()); 748 return _util; 749 } 750 751 public void setAttributes(Positionable pos) { 752 if (pos instanceof SensorIcon && !((SensorIcon)pos).isIcon()) { 753 SensorIcon icon = (SensorIcon) pos; 754 PositionableLabel sample = _samples.get("SensorStateActive"); 755 if (sample.isOpaque()) { 756 icon.setBackgroundActive(sample.getBackground()); 757 } else { 758 icon.setBackgroundActive(null); 759 } 760 icon.setTextActive(sample.getForeground()); 761 icon.setActiveText(sample.getText()); 762 763 sample = _samples.get("SensorStateInactive"); 764 icon.setInactiveText(sample.getText()); 765 if (sample.isOpaque()) { 766 icon.setBackgroundInActive(sample.getBackground()); 767 } else { 768 icon.setBackgroundInActive(null); 769 } 770 icon.setTextInActive(sample.getForeground()); 771 772 sample = _samples.get("BeanStateUnknown"); 773 icon.setUnknownText(sample.getText()); 774 if (sample.isOpaque()) { 775 icon.setBackgroundUnknown(sample.getBackground()); 776 } else { 777 icon.setBackgroundUnknown(null); 778 } 779 icon.setTextUnknown(sample.getForeground()); 780 781 sample = _samples.get("BeanStateInconsistent"); 782 icon.setInconsistentText(sample.getText()); 783 if (sample.isOpaque()) { 784 icon.setBackgroundInconsistent(sample.getBackground()); 785 } else { 786 icon.setBackgroundInconsistent(null); 787 } 788 icon.setTextInconsistent(sample.getForeground()); 789 } else { 790 PositionableLabel sample = _samples.get("Text"); 791 if ( pos instanceof PositionableLabel && 792 !(pos instanceof jmri.jmrit.display.MemoryOrGVIcon)) { 793 ((PositionableLabel) pos).setText(sample.getText()); 794 } 795 PositionablePopupUtil posUtil = pos.getPopupUtility(); 796 PositionablePopupUtil samUtil = sample.getPopupUtility(); 797 if (sample.isOpaque()) { 798 posUtil.setBackgroundColor(samUtil.getBackground()); 799 } else { 800 posUtil.setBackgroundColor(null); 801 } 802 posUtil.setHasBackground(samUtil.hasBackground()); 803 posUtil.setForeground(samUtil.getForeground()); 804 posUtil.setBorderColor(samUtil.getBorderColor()); 805 posUtil.setFont(samUtil.getFont()); 806 posUtil.setFixedWidth(samUtil.getFixedWidth()); 807 posUtil.setFixedHeight(samUtil.getFixedHeight()); 808 posUtil.setMargin(samUtil.getMargin()); 809 posUtil.setBorderSize(samUtil.getBorderSize()); 810 } 811 pos.invalidate(); 812 } 813 814 public void close() { 815 JmriColorChooser.suppressAddRecentColor(false); 816 } 817 818 private final static Logger log = LoggerFactory.getLogger(TextItemPanel.class); 819 820}