001: package com.xoetrope.swing;
002:
003: import java.awt.Color;
004: import java.awt.Dimension;
005: import java.awt.Font;
006: import java.awt.FontMetrics;
007: import java.awt.Graphics;
008: import java.awt.Graphics2D;
009: import java.awt.Image;
010: import javax.swing.JComponent;
011:
012: import com.xoetrope.event.XClickListener;
013: import com.xoetrope.event.XStateListener;
014: import com.xoetrope.util.XGraphicUtils;
015: import java.awt.Point;
016: import java.awt.Rectangle;
017: import java.awt.SystemColor;
018: import java.awt.event.KeyEvent;
019: import java.awt.event.KeyListener;
020: import java.util.Date;
021: import net.xoetrope.xui.XAttributedComponent;
022: import net.xoetrope.xui.XProject;
023: import net.xoetrope.xui.XProjectManager;
024: import net.xoetrope.xui.XTextHolder;
025: import net.xoetrope.xui.style.XStyle;
026: import net.xoetrope.xui.style.XStyleManager;
027:
028: /**
029: * An XKeyPad component is a visual representation of a numeric keypad.
030: *
031: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
032: * the GNU Public License (GPL), please see license.txt for more details. If
033: * you make commercial use of this software you must purchase a commercial
034: * license from Xoetrope.</p>
035: * <p> $Revision: 1.12 $</p>
036: */
037: public class XKeypad extends JComponent implements XStateListener,
038: XTextHolder, XAttributedComponent {
039: protected int borderHeight, borderWidth, keyHeight, keyWidth;
040: protected XClickListener clickListener;
041: protected XStyleManager styleManager;
042:
043: private String text;
044: private String enterText;
045:
046: private String style;
047: private String style3D;
048: private String styleShade;
049:
050: /**
051: * The button clicked. 100 = the enter button
052: */
053: private int maxLength, minLength;
054:
055: private XTextHolder outputField;
056: private String value;
057:
058: private static Color bkClr, highlight3dColor, frameClr,
059: shadow3dClr, textColor;
060:
061: private Rectangle[] buttonAreas;
062: private int selectedArea;
063:
064: private int keyCodes[] = { KeyEvent.VK_0, KeyEvent.VK_1,
065: KeyEvent.VK_2, KeyEvent.VK_3, KeyEvent.VK_4, KeyEvent.VK_5,
066: KeyEvent.VK_6, KeyEvent.VK_7, KeyEvent.VK_8, KeyEvent.VK_9,
067: KeyEvent.VK_ENTER };
068: private char keyChars[] = { '0', '1', '2', '3', '4', '5', '6', '7',
069: '8', '9', KeyEvent.CHAR_UNDEFINED };
070:
071: /**
072: * The owner project and the context in which this object operates.
073: */
074: protected XProject currentProject = XProjectManager
075: .getCurrentProject();
076:
077: /**
078: * Constructor for a new XKeypad. This control displays a numeric keypad
079: */
080: public XKeypad() {
081: minLength = maxLength = 3;
082:
083: value = new String("");
084: clickListener = new XClickListener(this , 0);
085: addMouseListener(clickListener);
086: addMouseMotionListener(clickListener);
087:
088: style = "base";
089: style3D = "base";
090: styleShade = "base";
091: styleManager = XProjectManager.getStyleManager();
092:
093: if (bkClr == null) {
094: XStyle threeDStyle = styleManager.getStyle(style3D);
095: XStyle shadeStyle = styleManager.getStyle(styleShade);
096: bkClr = SystemColor.control;
097: textColor = SystemColor.controlText;
098: highlight3dColor = SystemColor.controlLtHighlight;
099: frameClr = SystemColor.controlShadow;
100: shadow3dClr = SystemColor.controlDkShadow;
101: }
102: buttonAreas = null;
103: selectedArea = -1;
104: enterText = "ENTER";
105: }
106:
107: /**
108: * Refresh the display
109: * @param g the graphics context
110: */
111: public void update(Graphics g) {
112: paint(g);
113: }
114:
115: /**
116: * Renders the keypad
117: * @param sg the graphics context
118: */
119: public void paint(Graphics sg) {
120: Image offscreen = createImage(getSize().width, getSize().height);
121: Graphics g = offscreen.getGraphics();
122: super .paint(g);
123:
124: Dimension size = getSize();
125: int width = size.width;
126: int height = size.height;
127: g.setClip(0, 0, width, height);
128:
129: g.setColor(getBackground());
130: g.fillRect(0, 0, width, height);
131:
132: borderHeight = height / 17;
133: borderWidth = width / 13;
134: keyHeight = (height - borderHeight - borderHeight) / 5;
135: keyWidth = (width - borderWidth) / 4;
136:
137: int top = borderHeight;
138: int left = borderWidth;
139: int spacing = keyWidth + borderWidth;
140:
141: XStyle responseStyle = styleManager.getStyle(style3D);
142: Font f = styleManager.getFont(responseStyle);
143: if (f == null)
144: f = getFont();
145: FontMetrics fm = g.getFontMetrics(f);
146: int xTextInc = (keyWidth - fm.charWidth('8')) / 2;
147: int yTextInc = (fm.getAscent() + keyHeight) / 2;
148: g.setFont(f);
149:
150: g.setColor(bkClr);
151: g.draw3DRect(0, 0, width, height, true);
152:
153: if (buttonAreas == null) {
154: selectedArea = -1;
155: buttonAreas = new Rectangle[11];
156: buttonAreas[7] = new Rectangle(left + 1, top + 1,
157: keyWidth - 2, keyHeight - 2);
158: buttonAreas[8] = new Rectangle(left + 1 + spacing, top + 1,
159: keyWidth - 2, keyHeight - 2);
160: buttonAreas[9] = new Rectangle(
161: left + 1 + spacing + spacing, top + 1,
162: keyWidth - 2, keyHeight - 2);
163: top += borderHeight + keyHeight;
164: buttonAreas[4] = new Rectangle(left + 1, top + 1,
165: keyWidth - 2, keyHeight - 2);
166: buttonAreas[5] = new Rectangle(left + 1 + spacing, top + 1,
167: keyWidth - 2, keyHeight - 2);
168: buttonAreas[6] = new Rectangle(
169: left + 1 + spacing + spacing, top + 1,
170: keyWidth - 2, keyHeight - 2);
171: top += borderHeight + keyHeight;
172: buttonAreas[1] = new Rectangle(left + 1, top + 1,
173: keyWidth - 2, keyHeight - 2);
174: buttonAreas[2] = new Rectangle(left + 1 + spacing, top + 1,
175: keyWidth - 2, keyHeight - 2);
176: buttonAreas[3] = new Rectangle(
177: left + 1 + spacing + spacing, top + 1,
178: keyWidth - 2, keyHeight - 2);
179: top += borderHeight + keyHeight;
180: buttonAreas[0] = new Rectangle(left + 1, top + 1,
181: keyWidth - 2, keyHeight - 2);
182: buttonAreas[10] = new Rectangle(left + 1 + spacing,
183: top + 1, keyWidth + borderWidth + keyWidth - 2,
184: keyHeight - 2);
185: }
186: top = borderHeight;
187: XGraphicUtils.draw3dObject(g, (selectedArea == 7), left, top,
188: keyWidth, keyHeight, bkClr, highlight3dColor, frameClr,
189: shadow3dClr, highlight3dColor);
190: g.setColor(textColor);
191: g.drawString("7", left + xTextInc, top + yTextInc);
192:
193: XGraphicUtils.draw3dObject(g, (selectedArea == 8), left
194: + spacing, top, keyWidth, keyHeight, bkClr,
195: highlight3dColor, frameClr, shadow3dClr,
196: highlight3dColor);
197: g.setColor(textColor);
198: g.drawString("8", left + xTextInc + spacing, top + yTextInc);
199:
200: XGraphicUtils.draw3dObject(g, (selectedArea == 9), left
201: + spacing + spacing, top, keyWidth, keyHeight, bkClr,
202: highlight3dColor, frameClr, shadow3dClr,
203: highlight3dColor);
204: g.setColor(textColor);
205: g.drawString("9", left + xTextInc + spacing + spacing, top
206: + yTextInc);
207:
208: top += borderHeight + keyHeight;
209: XGraphicUtils.draw3dObject(g, (selectedArea == 4), left, top,
210: keyWidth, keyHeight, bkClr, highlight3dColor, frameClr,
211: shadow3dClr, highlight3dColor);
212: g.setColor(textColor);
213: g.drawString("4", left + xTextInc, top + yTextInc);
214:
215: XGraphicUtils.draw3dObject(g, (selectedArea == 5), left
216: + spacing, top, keyWidth, keyHeight, bkClr,
217: highlight3dColor, frameClr, shadow3dClr,
218: highlight3dColor);
219: g.setColor(textColor);
220: g.drawString("5", left + xTextInc + spacing, top + yTextInc);
221:
222: XGraphicUtils.draw3dObject(g, (selectedArea == 6), left
223: + spacing + spacing, top, keyWidth, keyHeight, bkClr,
224: highlight3dColor, frameClr, shadow3dClr,
225: highlight3dColor);
226: g.setColor(textColor);
227: g.drawString("6", left + xTextInc + spacing + spacing, top
228: + yTextInc);
229:
230: top += borderHeight + keyHeight;
231: XGraphicUtils.draw3dObject(g, (selectedArea == 1), left, top,
232: keyWidth, keyHeight, bkClr, highlight3dColor, frameClr,
233: shadow3dClr, highlight3dColor);
234: g.setColor(textColor);
235: g.drawString("1", left + xTextInc, top + yTextInc);
236:
237: XGraphicUtils.draw3dObject(g, (selectedArea == 2), left
238: + spacing, top, keyWidth, keyHeight, bkClr,
239: highlight3dColor, frameClr, shadow3dClr,
240: highlight3dColor);
241: g.setColor(textColor);
242: g.drawString("2", left + xTextInc + spacing, top + yTextInc);
243:
244: XGraphicUtils.draw3dObject(g, (selectedArea == 3), left
245: + spacing + spacing, top, keyWidth, keyHeight, bkClr,
246: highlight3dColor, frameClr, shadow3dClr,
247: highlight3dColor);
248: g.setColor(textColor);
249: g.drawString("3", left + xTextInc + spacing + spacing, top
250: + yTextInc);
251:
252: top += borderHeight + keyHeight;
253: XGraphicUtils.draw3dObject(g, (selectedArea == 0), left, top,
254: keyWidth, keyHeight, bkClr, highlight3dColor, frameClr,
255: shadow3dClr, highlight3dColor);
256: g.setColor(textColor);
257: g.drawString("0", left + xTextInc, top + yTextInc);
258:
259: int enterWidth = keyWidth + borderWidth + keyWidth;
260: XGraphicUtils.draw3dObject(g, (selectedArea == 10), left
261: + spacing, top, enterWidth, keyHeight, bkClr,
262: highlight3dColor, frameClr, shadow3dClr,
263: highlight3dColor);
264: g.setColor(textColor);
265:
266: if (currentProject.getTranslator() != null) {
267: enterText = currentProject.getTranslator().translate(
268: "ENTER");
269: }
270: g.drawString(enterText, left + spacing
271: + (enterWidth - fm.stringWidth(enterText)) / 2, top
272: + yTextInc);
273:
274: if ((selectedArea >= 0) && clickListener.getIsSelected()) {
275: g.setColor(new Color(highlight3dColor.getRed(),
276: highlight3dColor.getGreen(), highlight3dColor
277: .getBlue(), 128));
278: ((Graphics2D) g).fill(buttonAreas[selectedArea]);
279: }
280: sg.drawImage(offscreen, 0, 0, width, height, null);
281: g.dispose();
282: offscreen = null;
283: }
284:
285: /**
286: * Repaint the responses
287: */
288: public void paintStates() {
289: repaint();
290: }
291:
292: /**
293: * Find a response
294: * @param x the x coordinate of the mouse click
295: * @param y the y coordinate of the mouse click
296: * @param defResponse the default response
297: * @return true if a response was found
298: */
299: public boolean setState(int x, int y, int defResponse) {
300: int oldResponse = selectedArea;
301: selectedArea = findCurrentResponse(x, y);
302:
303: if (clickListener.getIsSelected()) {
304: if (selectedArea == clickListener.getActiveResponse())
305: return true;
306: else {
307: selectedArea = -1;
308: return true;
309: }
310: }
311: clickListener.setActiveResponse(selectedArea);
312: return (selectedArea != oldResponse);
313: }
314:
315: /**
316: * Find the response corresponding to the current point
317: * @param x the x coordinate of the mouse click
318: * @param y the y coordinate of the mouse click
319: * @return the response value if the mouse were click at the specified location,
320: * or -1 if not selection is available
321: */
322: public int findCurrentResponse(int x, int y) {
323: int selection = -1;
324: if (buttonAreas == null)
325: return -1;
326:
327: Point pt = new Point(x, y);
328: for (int i = 0; i < buttonAreas.length; i++) {
329: if (buttonAreas[i].contains(pt)) {
330: return i;
331: }
332: }
333: return -1;
334: }
335:
336: /**
337: * Fired the keyPressed event if a button has been pressed
338: */
339: public void updateSelectedState() {
340: if (selectedArea >= 0) {
341: KeyEvent ke = new KeyEvent(this , KeyEvent.KEY_PRESSED,
342: new Date().getTime(), 0, keyCodes[selectedArea],
343: keyChars[selectedArea]);
344: KeyListener[] listeners = getKeyListeners();
345: for (int i = 0; i < listeners.length; i++)
346: listeners[i].keyPressed(ke);
347: }
348: }
349:
350: /**
351: * Called by XClickListener to check if a response event should be sent to the
352: * parent form. The control can also use this event to do post click processing
353: * @return true if the parent is to be notified
354: */
355: public boolean respond() {
356: if (selectedArea < 10) {
357: if (value.length() >= maxLength)
358: value = "";
359: value += Integer.toString(selectedArea);
360: if (outputField != null) {
361: outputField.setText(value);
362: ((JComponent) outputField).invalidate();
363: ((JComponent) outputField).repaint();
364: }
365: } else
366: return true;
367:
368: return false;
369: }
370:
371: /**
372: * Gets an indexed color.
373: *
374: * @param idx The index of the color to get.
375: * @param callerClassId The ID of this calling class
376: * @return The color
377: * @see com.xoetrope.miniui.XFrame#X_BUTTON
378: */
379: public Color getColor(int idx, int callerClassId) {
380: return styleManager.getStyle("keypad").getStyleAsColor(
381: XStyle.COLOR_FORE);
382: }
383:
384: /**
385: * Get the style asociated with three dimensional objects/elements
386: * @return the style name
387: */
388: public String getStyle3D() {
389: return style3D;
390: }
391:
392: /**
393: * Get the style asociated with shaded elements
394: * @return the style name
395: */
396: public String getStyleShade() {
397: return styleShade;
398: }
399:
400: /**
401: * Set the style asociated with shaded elements, background and text colors
402: * @param newStyle the style name
403: */
404: public void setStyle(String newStyle) {
405: styleShade = newStyle;
406: XStyle style = styleManager.getStyle(styleShade);
407: bkClr = style.getStyleAsColor(XStyle.COLOR_BACK);
408: textColor = style.getStyleAsColor(XStyle.COLOR_FORE);
409: repaint();
410: }
411:
412: /**
413: * Get the style asociated with three dimensional objects/elements
414: * @param newStyle the style name
415: */
416: public void setStyle3D(String newStyle) {
417: style3D = newStyle;
418: XStyle threeDStyle = styleManager.getStyle(style3D);
419: highlight3dColor = threeDStyle
420: .getStyleAsColor(XStyle.COLOR_FORE);
421: shadow3dClr = threeDStyle.getStyleAsColor(XStyle.COLOR_BACK);
422: repaint();
423: }
424:
425: /**
426: * Set the style asociated with shaded elements, frame color
427: * @param newStyle the style name
428: */
429: public void setStyleShade(String newStyle) {
430: styleShade = newStyle;
431: XStyle shadeStyle = styleManager.getStyle(styleShade);
432: frameClr = shadeStyle.getStyleAsColor(XStyle.COLOR_FORE);
433: repaint();
434: }
435:
436: /**
437: * Sets the control's text. Used to localize the control.
438: * @param newText The new text to display.
439: */
440: public void setText(String newText) {
441: text = newText;
442: invalidate();
443: }
444:
445: /**
446: * Sets a text field in which to display the key value.
447: * @param of the output text field
448: */
449: public void setOutputField(XTextHolder of) {
450: outputField = of;
451: }
452:
453: /**
454: * Clears the output value.
455: */
456: public void clear() {
457: if (outputField != null)
458: outputField.setText("");
459:
460: value = "";
461: }
462:
463: /**
464: * Gets the output value
465: * @return the keyped value
466: */
467: public String getValue() {
468: return value;
469: }
470:
471: /**
472: * Gets the output text
473: * @return the keyped text
474: */
475: public String getText() {
476: return text;
477: }
478:
479: /**
480: * Sets the output value
481: * @param newValue the new keypad value
482: */
483: public void setValue(String newValue) {
484: value = newValue;
485: }
486:
487: /**
488: * Sets the maximum length of the output value
489: * @param len the new maximum length
490: */
491: public void setMaxLength(int len) {
492: maxLength = len;
493: }
494:
495: /**
496: * Sets the minimum length of the output value
497: * @param len the new minimum length
498: */
499: public void setMinLength(int len) {
500: minLength = len;
501: }
502:
503: /**
504: * Set one or more attributes of the component.
505: * @param attribName the name of the attribute
506: * @param attribValue the value of the attribute
507: * @return 0 for success, non zero otherwise
508: */
509: public int setAttribute(String attribName, Object attribValue) {
510: String attribNameLwr = attribName.toLowerCase();
511: String attribValueStr = (String) attribValue;
512: if (attribNameLwr.equals("style"))
513: setStyle(attribValueStr);
514: else if (attribNameLwr.equals("style3d"))
515: setStyle3D(attribValueStr);
516: else if (attribNameLwr.equals("styleshade"))
517: setStyleShade(attribValueStr);
518:
519: return 0;
520: }
521: }
|