001: /*
002: * StringPropertyEditor.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.gui.components;
013:
014: import java.awt.EventQueue;
015: import java.awt.event.FocusEvent;
016: import java.awt.event.FocusListener;
017: import java.lang.reflect.Method;
018: import javax.swing.JTextField;
019: import javax.swing.event.DocumentEvent;
020: import javax.swing.event.DocumentListener;
021: import workbench.interfaces.SimplePropertyEditor;
022: import workbench.log.LogMgr;
023:
024: /**
025: *
026: * @author support@sql-workbench.net
027: */
028: public class StringPropertyEditor extends JTextField implements
029: DocumentListener, SimplePropertyEditor, FocusListener {
030: private Object source;
031: private Method setter;
032: private Method getter;
033:
034: // "dirty" flag, if this is true, the target object
035: // has not been updated to reflect the state of this editor
036: private boolean changed;
037:
038: private boolean immediateUpdate = false;
039: private String propName;
040:
041: public StringPropertyEditor() {
042: super ();
043: this .addFocusListener(this );
044: this .addMouseListener(new TextComponentMouseListener());
045: }
046:
047: public void setSourceObject(Object aSource, String aProperty) {
048: this .setSourceObject(aSource, aProperty, null);
049: }
050:
051: public void setSourceObject(Object aSource, String aProperty,
052: String initialText) {
053: this .source = aSource;
054: this .changed = false;
055: this .propName = aProperty;
056:
057: this .getDocument().removeDocumentListener(this );
058:
059: if (aSource == null) {
060: this .setText("");
061: this .getter = null;
062: this .setter = null;
063: return;
064: }
065:
066: String propertyName = Character
067: .toUpperCase(aProperty.charAt(0))
068: + aProperty.substring(1);
069:
070: if (initialText != null) {
071: this .setText(initialText);
072: }
073:
074: try {
075: String name = "get" + propertyName;
076: Class cls = aSource.getClass();
077: this .getter = cls.getMethod(name, (Class[]) null);
078:
079: name = "set" + propertyName;
080: Class[] parms = { String.class };
081: this .setter = cls.getMethod(name, parms);
082:
083: if (initialText == null) {
084: String value = (String) this .getter.invoke(this .source,
085: (Object[]) null);
086: this .setText(value);
087: }
088: } catch (Exception e) {
089: LogMgr.logError("StringPropertyEditor.setSourceObject()",
090: "Error during init", e);
091: }
092: this .getDocument().addDocumentListener(this );
093: }
094:
095: public void applyChanges() {
096: if (!this .changed)
097: return;
098: if (this .source == null)
099: return;
100: if (this .setter == null)
101: return;
102: Object args[] = new Object[1];
103: args[0] = this .getText();
104: try {
105: this .setter.invoke(this .source, args);
106: this .changed = false;
107: } catch (Exception e) {
108: e.printStackTrace();
109: }
110: }
111:
112: public boolean isChanged() {
113: return this .changed;
114: }
115:
116: public void changedUpdate(DocumentEvent e) {
117: documentChanged();
118: }
119:
120: public void insertUpdate(DocumentEvent e) {
121: documentChanged();
122: }
123:
124: public void removeUpdate(DocumentEvent e) {
125: documentChanged();
126: }
127:
128: private void documentChanged() {
129: this .changed = true;
130: if (this .immediateUpdate) {
131: this .applyChanges();
132: }
133: EventQueue.invokeLater(new Runnable() {
134: public void run() {
135: firePropertyChange(propName, null, getText());
136: }
137: });
138: }
139:
140: public void setImmediateUpdate(boolean aFlag) {
141: this .immediateUpdate = aFlag;
142: if (aFlag)
143: this .applyChanges();
144: }
145:
146: public boolean getImmediateUpdate() {
147: return this .immediateUpdate;
148: }
149:
150: /** Invoked when a component gains the keyboard focus.
151: *
152: */
153: public void focusGained(FocusEvent e) {
154: //System.out.println(e.getOppositeComponent().getClass().getName());
155: // When the popup menu for copy & paste is used, the oppositeComponent()
156: // is the RootPane. In this case we don't want to chage the selection
157: if (!(e.getOppositeComponent() instanceof javax.swing.JRootPane)) {
158: this .selectAll();
159: }
160: }
161:
162: /** Invoked when a component loses the keyboard focus.
163: *
164: */
165: public void focusLost(FocusEvent e) {
166: if (!this.immediateUpdate)
167: this.applyChanges();
168: }
169: }
|