001: package com.xoetrope.awt.survey;
002:
003: import com.xoetrope.awt.*;
004: import java.awt.Dimension;
005: import java.awt.Font;
006: import java.awt.FontMetrics;
007: import java.awt.Graphics;
008:
009: import com.xoetrope.util.XGraphicUtils;
010: import net.xoetrope.xui.style.XStyle;
011:
012: /**
013: * <p>Description: Extends XQuestion by rendering text in a form suitable for a
014: * kiosk displaying one question at a time</p>
015: * <p>The following color indexes are used</p>
016: * <p>0 - The color for the top and bottom bands</p>
017: * <p>2 - The background color</p>
018: * <p>3 - The text color and option text color</p>
019: * <p>4 - The check mark surround color</p>
020: * <p>5 - The check mark background color</p>
021: * <p>6 - The check mark shadow color</p>
022: * <p>7 - The check mark frame color</p>
023: * <p>8 - The selected check mark shadow color</p>
024: * <p>9 - The selected check mark tick color</p>
025: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
026: * the GNU Public License (GPL), please see license.txt for more details. If
027: * you make commercial use of this software you must purchase a commercial
028: * license from Xoetrope.</p>
029: * <p>$Revision: 1.3 $</p>
030: */
031: public class XKioskQuestion extends XQuestion {
032: int woffset = 0;
033: int responseHeight;
034:
035: /**
036: * Sets the scale for question layout
037: * @param newScale the new scale
038: */
039: public void setScale(int newScale) {
040: //setBackground( null );//frame.getColor( 2, classId ));
041:
042: scale = newScale;
043: xScale = (getSize().width - woffset * 2) / scale;
044: responseHeight = 1;
045:
046: clickListener.setOffset(woffset);
047: }
048:
049: /**
050: * Renders the question. Renders question text as a single strip wrapped
051: * over multiple lines and without using a header. The responses/options are
052: * then spaced horizontally with a block/shadow behind the check marks.
053: * @param g
054: */
055: public void paint(Graphics g) {
056: Font f;
057: FontMetrics fm;
058:
059: String questionText = question.getText().toLowerCase();
060: Dimension d = getSize();
061:
062: XStyle questionStyle = styleManager.getStyle("Question");
063: f = styleManager.getFont(questionStyle);
064: g.setFont(f);
065: fm = g.getFontMetrics(f);
066:
067: // Draw the question text over multiple lines
068: g.setColor(questionTextColor);
069: int start = 0;
070: int end = 0;
071: String line;
072: int lineNum = 1;
073: do {
074: boolean drawLine = false;
075:
076: // Extend the string by a word (to the next space, if any)
077: end = questionText.indexOf(' ', end + 1);
078: String ss;
079: if (end > 0)
080: ss = questionText.substring(start, end);
081: else {
082: ss = questionText.substring(start);
083: drawLine = true;
084: }
085:
086: // Does the next word fit in?
087: int sWidth = fm.stringWidth(ss);
088: if (sWidth < (d.width - 120))
089: line = ss;
090: else
091: drawLine = true;
092:
093: if (drawLine) {
094: g.drawString(ss, woffset + (d.width - sWidth) / 2,
095: lineNum * fm.getAscent() + 20);
096: lineNum++;
097: start = end + 1;
098: }
099: } while (end >= 0);
100:
101: // If no text drawn, then do it now
102: if ((start == 0) && (lineNum == 1))
103: g.drawString(questionText, woffset, fm.getAscent() + 10);
104:
105: XStyle responseStyle = styleManager
106: .getStyle("Question/Response");
107: f = styleManager.getFont(responseStyle);
108: g.setFont(f);
109: fm = g.getFontMetrics(f);
110:
111: int responses = question.getNumOptions();
112: if (responses == 0)
113: return;
114: responseHeight = (d.height - 155) / responses;
115: int ctop = 100;
116:
117: int activeResponse = clickListener.getActiveResponse();
118: int selectedResponse = clickListener.getSelectedResponse();
119: int indent = (responseHeight - 20) / 4;
120: int blockWidth = 460;
121: int stringWidth = 0;
122: int leftEdgeInc = 0;
123: for (int i = 0; i < responses; i++) {
124: stringWidth = Math.max(stringWidth, fm.stringWidth(question
125: .getOptionText(i).toUpperCase()));
126: }
127: blockWidth = Math.max(blockWidth, stringWidth + 100);
128: if (blockWidth > 610) {
129: leftEdgeInc = (610 - blockWidth);///2;
130: blockWidth = Math.min(700, blockWidth);
131: }
132:
133: for (int i = 0; i < responses; i++) {
134: // Draw the text
135: g.setColor(responseTextBkColor);
136: drawOptionBackground(g, 170 + leftEdgeInc, ctop,
137: blockWidth, responseHeight - indent - indent);
138: g.setColor(responseTextColor);
139: String optionText = question.getOptionText(i).toUpperCase();
140: int textWidth = fm.stringWidth(optionText);
141: int textLeft = 250 + leftEdgeInc;
142: if (stringWidth >= 150)
143: textLeft += (blockWidth - 100 - textWidth) / 2;
144: else
145: textLeft += (300 - textWidth) / 2;
146: g.drawString(optionText, textLeft, fm.getAscent() + ctop
147: + indent);
148: XGraphicUtils.draw3dObject(g, activeResponse == i,
149: 200 + leftEdgeInc, ctop + indent, 20, fm
150: .getAscent(), cueBkColor,
151: responseTextBkColor, responseTextColor,
152: questionBkColor, responseTextBkColor);
153: if (isOptionSelected(i)) {
154: g.setColor(responseTextColor);
155: g.fillRect(203 + leftEdgeInc, ctop + 3 + indent, 15, fm
156: .getAscent() - 5);
157: }
158: ctop += responseHeight;
159: }
160: }
161:
162: /**
163: * Draws the background for each option.
164: * @param g the graphics context
165: * @param x the left edge
166: * @param y the top
167: * @param w the width
168: * @param h the height
169: */
170: public void drawOptionBackground(Graphics g, int x, int y, int w,
171: int h) {
172: g.fillRect(x, y, w, h);
173: }
174:
175: public boolean setState(int x, int y, int defResponse) {
176: int oldResponse = defResponse;
177: int activeResponse = (y - 100) / responseHeight;
178: if ((activeResponse == 0) && (x < 0))
179: activeResponse = oldResponse;
180: else if (activeResponse >= numResponses)
181: activeResponse = oldResponse;
182:
183: clickListener.setActiveResponse(activeResponse);
184: return (defResponse != activeResponse);
185: }
186:
187: /**
188: * Called by XClickListener to check if a response event should be sent to the
189: * parent form. The control can also use this event to do post click processing
190: * @return true if the parent is to be notified
191: */
192: public boolean respond() {
193: return true;
194: }
195:
196: /**
197: * Repaint the responses
198: */
199: public void paintResponses() {
200: repaint();
201: }
202:
203: /**
204: * Clear the screen
205: */
206: public void invalidate() {
207: super .invalidate();
208: }
209:
210: /**
211: * Update the screen
212: * @param g
213: */
214: public void update(Graphics g) {
215: paint(g);
216: }
217:
218: /**
219: * Is the prepared image drawn off screen?
220: * @return The double buffered flag
221: */
222: public boolean isDoubleBuffered() {
223: return false;
224: }
225: }
|