001: /* ====================================================================
002: * Copyright (c) 1998 - 2003 David F. Glasser. All rights
003: * reserved.
004: *
005: * This file is part of the QueryForm Database Tool.
006: *
007: * The QueryForm Database Tool is free software; you can redistribute it
008: * and/or modify it under the terms of the GNU General Public License as
009: * published by the Free Software Foundation; either version 2 of the
010: * License, or (at your option) any later version.
011: *
012: * The QueryForm Database Tool is distributed in the hope that it will
013: * be useful, but WITHOUT ANY WARRANTY; without even the implied
014: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
015: * See the GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with the QueryForm Database Tool; if not, write to:
019: *
020: * The Free Software Foundation, Inc.,
021: * 59 Temple Place, Suite 330
022: * Boston, MA 02111-1307 USA
023: *
024: * or visit http://www.gnu.org.
025: *
026: * ====================================================================
027: *
028: * This product includes software developed by the
029: * Apache Software Foundation (http://www.apache.org/).
030: *
031: * ====================================================================
032: *
033: * $Source: /cvsroot/qform/qform/src/org/glasser/qform/TextBox.java,v $
034: * $Revision: 1.7 $
035: * $Author: dglasser $
036: * $Date: 2005/06/06 03:06:34 $
037: *
038: * --------------------------------------------------------------------
039: */
040: package org.glasser.qform;
041:
042: import java.util.*;
043: import javax.swing.*;
044: import java.sql.*;
045: import javax.swing.text.*;
046: import javax.swing.border.*;
047: import javax.swing.event.*;
048: import java.awt.*;
049: import org.glasser.swing.*;
050: import org.glasser.sql.DBUtil;
051:
052: public class TextBox extends JTextArea {
053:
054: private static boolean debug = System.getProperty("TextBox.debug") != null;
055:
056: private Set editableTypes = null;
057:
058: String columnName;
059: Integer dataType;
060: String typeName;
061: int length;
062: boolean nullable;
063: boolean isNull = false;
064: int ordinal;
065: boolean constructorDone = false;
066: boolean managingFocus = false;
067:
068: boolean isPKComponent = false;
069:
070: boolean dirty = false;
071:
072: JLabel label = null;
073:
074: protected String dbEncoding = null;
075:
076: protected final static String APP_ENCODING = System
077: .getProperty("file.encoding");
078:
079: final Border redBorder = new LineBorder(Color.red);
080:
081: class RequiredFieldBorder extends CompoundBorder {
082: RequiredFieldBorder(Border innerBorder) {
083: super (redBorder, innerBorder);
084: }
085: };
086:
087: static java.awt.Color DISABLED = new java.awt.Color(0xE1E1E1);
088: static java.awt.Color WHITE = java.awt.Color.white;
089:
090: private String decode(String s) {
091: try {
092: if (dbEncoding == null)
093: return s;
094: String decoded = new String(s.getBytes(dbEncoding),
095: APP_ENCODING);
096: if (debug)
097: System.out.println("encoded: " + s + "\ndecoded: "
098: + decoded);
099: return decoded;
100: } catch (java.io.UnsupportedEncodingException ex) {
101: ex.printStackTrace();
102: return s;
103: }
104: }
105:
106: private String encode(String s) {
107: try {
108: if (dbEncoding == null)
109: return s;
110: String encoded = new String(s.getBytes(APP_ENCODING),
111: dbEncoding);
112: if (debug)
113: System.out.println("decoded: " + s + "\nencoded: "
114: + encoded);
115: return encoded;
116:
117: } catch (java.io.UnsupportedEncodingException ex) {
118: ex.printStackTrace();
119: return s;
120: }
121: }
122:
123: TextBox(String ColumnName, int DataType, String TypeName,
124: int Length, boolean Nullable, int Ordinal, JLabel lab) {
125: super ();
126: setText("");
127: columnName = ColumnName;
128: dataType = new Integer(DataType);
129:
130: typeName = TypeName;
131: length = Length;
132: nullable = Nullable;
133: ordinal = Ordinal;
134: label = lab;
135: String toolTip = columnName + ", type=" + dataType + " ("
136: + typeName + "), Length=" + length + ", nullable="
137: + nullable;
138: label.setToolTipText(toolTip);
139:
140: setBorder(normalBorder());
141:
142: setEditable(false);
143: setLineWrap(true);
144: setWrapStyleWord(true);
145: this .getDocument().addDocumentListener(new DocumentListener() {
146: public void insertUpdate(DocumentEvent e) {
147: dirty = true;
148: }
149:
150: public void removeUpdate(DocumentEvent e) {
151: dirty = true;
152: }
153:
154: public void changedUpdate(DocumentEvent e) {
155: dirty = true;
156: }
157: });
158:
159: // in Java versions 1.4 and later, this will cause the tab key to
160: // shift focus away from a JTextArea.
161: GUIHelper.setTabTraversal(this );
162:
163: dbEncoding = System.getProperty("qform.db.encode." + typeName);
164:
165: constructorDone = true;
166:
167: }
168:
169: public boolean isDirty() {
170: return dirty;
171: }
172:
173: public void setDirty(boolean b) {
174: dirty = b;
175: }
176:
177: public void setRequiredFieldBorder(boolean b) {
178: if (b && nullable == false) {
179: setBorder(new RequiredFieldBorder(normalBorder()));
180: } else {
181: setBorder(normalBorder());
182: }
183: }
184:
185: public void setLabel(JLabel l) {
186: label = l;
187: }
188:
189: public JLabel getLabel() {
190: return label;
191: }
192:
193: public String getColumnName() {
194: if (columnName == null)
195: return "";
196: else
197: return columnName;
198: }
199:
200: public Integer getDataType() {
201: return dataType;
202: }
203:
204: public int getLength() {
205: return length;
206: }
207:
208: public boolean isNullable() {
209: return nullable;
210: }
211:
212: public int getOrdinal() {
213: return ordinal;
214: }
215:
216: public boolean isTypeDisplayable() {
217: return (editableTypes != null && editableTypes
218: .contains(dataType))
219: || DBUtil.isDisplayableType(dataType.intValue());
220: }
221:
222: public boolean isTypeNumeric() {
223: return DBUtil.isNumericType(dataType.intValue());
224: }
225:
226: public void setEditable(boolean b) {
227: if (constructorDone == false) {
228: super .setEditable(b);
229: return;
230: }
231: if (isTypeDisplayable()) {
232: super .setEditable(b);
233: setColor(b);
234: } else {
235: super .setEditable(false);
236: setColor(false);
237:
238: }
239:
240: }
241:
242: public void setPkComponent(boolean isPKComponent) {
243: this .isPKComponent = isPKComponent;
244: if (isPKComponent) {
245: if (label != null) {
246: label.setForeground(java.awt.Color.red);
247: String text = label.getText();
248: if (text != null)
249: label.setText("* " + text);
250: }
251: }
252: }
253:
254: public boolean isPkComponent() {
255: return isPKComponent;
256: }
257:
258: private void setColor(boolean b) {
259: if (b)
260: setBackground(WHITE);
261: else
262: setBackground(DISABLED);
263: }
264:
265: Border backupBorder = new ThinBevelBorder(ThinBevelBorder.LOWERED);
266:
267: private Border normalBorder() {
268: Border b = (Border) UIManager.getBorder("TextField.border");
269: if (b == null) {
270: return backupBorder;
271: } else {
272: return b;
273: }
274: }
275:
276: public void setValue(Object s) {
277:
278: // if the value to be displayed is null, we'll turn the label
279: // gray to tell the user it's null rather than an empty string
280: // or a string of blanks.
281: if (s == null) {
282: isNull = true;
283: if (label != null)
284: label.setEnabled(false);
285: } else {
286: isNull = false;
287: label.setEnabled(true);
288:
289: }
290:
291: // if the data type is displayable, display it.
292: if (isTypeDisplayable()) {
293: if (s != null) {
294: //s = s.trim();
295: super .setText(decode(s.toString()));
296: } else {
297: super .setText(null);
298: }
299: } else {
300: if (s == null) {
301: super .setText(null);
302: } else {
303: super .setText("<" + typeName + " value >");
304: }
305: }
306:
307: dirty = false;
308: }
309:
310: public void clear() {
311: super .setText(null);
312: label.setEnabled(true);
313: }
314:
315: public static String escapeQuotes(String s) {
316: if (s == null)
317: return s;
318: if (s.indexOf('\'') < 0)
319: return s;
320: StringBuffer buffer = new StringBuffer(s.length() + 10);
321: char[] chars = s.toCharArray();
322: for (int j = 0; j < chars.length; j++) {
323: if (chars[j] == '\'')
324: buffer.append('\'');
325: buffer.append(chars[j]);
326: }
327: return buffer.toString();
328: }
329:
330: public String getValueClause(boolean trim) {
331:
332: String s = getText();
333: if (s == null || s.length() == 0)
334: return null;
335:
336: if (trim)
337: s = s.trim();
338:
339: if (this .isTypeNumeric()) {
340: return s.trim();
341: } else {
342: switch (dataType.intValue()) {
343: case Types.CHAR:
344: case Types.VARCHAR:
345: return ("'" + escapeQuotes(encode(s)) + "'");
346: case 9:
347: case Types.DATE:
348: return ("{d '" + escapeQuotes(s) + "'}");
349: case 10:
350: case Types.TIME:
351: return ("{t '" + escapeQuotes(s) + "'}");
352: case 11:
353: case Types.TIMESTAMP:
354: return ("{ts '" + escapeQuotes(s) + "'}");
355: default:
356: return ("'" + escapeQuotes(encode(s)) + "'");
357: }
358: }
359: }
360:
361: private String columnNameForQuery = null;
362:
363: public String getColumnNameForQuery() {
364:
365: String temp = columnNameForQuery;
366: if (temp != null)
367: return temp;
368:
369: // check to see if the column name has embedded spaces or hyphens.
370: // if any are found, enclose the column name in double quotation marks.
371: temp = columnName;
372: if (columnName.indexOf(' ') > -1
373: || columnName.indexOf('-') > -1)
374: temp = "\"" + columnName + "\"";
375: columnNameForQuery = temp;
376: return temp;
377: }
378:
379: public String getCondition() {
380: return getCondition(true);
381: }
382:
383: public String getCondition(boolean useWildcards) {
384:
385: if (getText().trim().length() == 0
386: || isTypeDisplayable() == false) {
387: return null;
388: }
389:
390: String columnNameTemp = getColumnNameForQuery();
391:
392: String valueClause = getValueClause(true);
393:
394: if (useWildcards && isTypeNumeric() == false
395: && valueClause != null && valueClause.indexOf("%") > 0) {
396: return columnNameTemp + " LIKE " + valueClause;
397: } else if (useWildcards
398: && isTypeNumeric()
399: && valueClause != null
400: && (valueClause.indexOf(">") == 0
401: || valueClause.indexOf("<") == 0 || valueClause
402: .toUpperCase().indexOf("BETWEEN") == 0)) {
403: return columnNameTemp + " " + valueClause;
404: } else {
405: return columnNameTemp + " = " + valueClause;
406: }
407: }
408:
409: public String getSetClause() {
410:
411: return getColumnNameForQuery() + " = " + getValueClause(false);
412: }
413:
414: /**
415: * Overridden to always return false. In Java versiond 1.3 and prior, this
416: * causes the tab key to shift focus away from a JTextArea.
417: */
418: public boolean isManagingFocus() {
419: return managingFocus;
420: }
421:
422: public void scrollRectToVisible(Rectangle r) {
423: }
424:
425: public void setUI(javax.swing.plaf.TextUI ui) {
426:
427: boolean isEditingRequired = getBorder() instanceof RequiredFieldBorder;
428: super .setUI(ui);
429: if (isEditingRequired) {
430: setBorder(new RequiredFieldBorder(normalBorder()));
431: } else {
432: setBorder(normalBorder());
433: }
434: }
435:
436: /**
437: * This takes as its argument a HashSet of Integer objects that represent the SQL types
438: * that should be considered displayable and editable by this TextBox. This is for databases
439: * that have data types that are not one of the standard ones defined in java.sql.Types.
440: */
441: public void setEditableTypes(Set editableTypes) {
442: this.editableTypes = editableTypes;
443: }
444:
445: }
|