/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.scenegraph.swing; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.geom.Rectangle2D; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JTextField; import javax.swing.border.Border; import org.simantics.scenegraph.utils.InitValueSupport; public class SymbolMonitorNode extends ComponentNode implements ActionListener, FocusListener, PropertyChangeListener, InitValueSupport { private static final long serialVersionUID = 6438147255141035799L; final static private Font defaultFont = Font.decode("Arial 3"); protected boolean editable = false; protected String value = ""; protected transient ActionListener actionListener = null; private boolean doResize = false; protected Font font = null; protected Color color = null; static class TextField extends JTextField { private static final long serialVersionUID = -668522226693100386L; // workaround for 4530952 @Override public void setText(String s) { if (getText().equals(s)) { return; } super.setText(s); } @Override public void setBorder(Border border) { super.setBorder(null); } public void setBorder(double borderWidth) { super.setBorder(null); } } @Override public String toString() { return super.toString() + "[editable=" + editable + ", value=" + value + "]"; } @Override public void init() { component = new TextField(); component.setEditable(editable); component.setEnabled(editable); component.addActionListener(this); component.addFocusListener(this); setVisible(false); super.init(); } @SyncField("editable") public void setEditable(boolean value) { this.editable = value; if(component != null) { component.setEditable(value); component.setEnabled(value); } } // private static final FontRenderContext FRC = // new FontRenderContext( // new AffineTransform(), // true, true); @SyncField("value") public void setText(String value) { this.value = value; if(value == null) { setVisible(false); return; } else { setVisible(true); } // RemoteViewer does not have component initialized if (component != null) { component.setText(value); doResize = true; } } @SyncField("font") public void setFont(Font font) { this.font = font; if (component != null) { setComponentFont(font); doResize = true; } } @SyncField("color") public void setColor(Color color) { this.color = color; if (component != null) { component.setForeground(color); doResize = true; } } @Override public void render(Graphics2D g2d) { if(doResize) { doResize = false; recalculateSize(g2d); } // TODO: fix this!! component.setScrollOffset(0); super.render(g2d); } private void recalculateSize(Graphics2D g2d) { if(component == null || value == null) return; Font font = component.getFont(); if (font != null) { FontMetrics metrics = component.getFontMetrics(font); Rectangle2D size = metrics.getStringBounds(value, g2d); int xPadding = 0; int yPadding = 0; setBounds(new Rectangle2D.Double(0, 0, xPadding + (int) Math.ceil(size.getWidth()), yPadding + (int) Math.ceil(size.getHeight()))); component.setScrollOffset(0); } } public String getText() { return value; } @Override public void propertyChange(PropertyChangeEvent evt) { if("value".equals(evt.getPropertyName()) && component != null) { component.setText((String)evt.getNewValue()); doResize = true; } else if("editable".equals(evt.getPropertyName()) && component != null) { component.setEditable((Boolean)evt.getNewValue()); component.setEnabled((Boolean)evt.getNewValue()); } } public void setActionListener(ActionListener actionListener) { this.actionListener = actionListener; } @Override public void actionPerformed(ActionEvent e) { // performAction(e); if(container.getParent() != null) container.getParent().requestFocusInWindow(); // Loose focus } @Override public void focusGained(FocusEvent arg0) { } @Override public void focusLost(FocusEvent arg0) { ActionEvent e = new ActionEvent(component, ActionEvent.ACTION_PERFORMED, ((TextField)component).getText()); performAction(e); } /** * Wrapper method to send event to serverside * * @param e */ @ServerSide public void performAction(ActionEvent e) { if(actionListener != null) actionListener.actionPerformed(e); } public void setValue(String key, Object value) { if("text".equals(key)) { // System.out.println("monitornode text -> " + value); if(value instanceof String) { setText((String)value); } else { String error = "monitornode expects a string as 'text' (got " + (value != null ? value.getClass().getName() : "null") + ")."; System.out.println(error); setText(error); } } if("font".equals(key)) { // System.out.println("monitornode font -> " + value); setFont(Font.decode((String)value)); } } @Override public void initValues() { setText(null); setFont(defaultFont); } }