001: package com.xoetrope.carousel.survey;
002:
003: import com.xoetrope.survey.Condition;
004: import com.xoetrope.survey.Question;
005: import java.awt.Color;
006: import java.awt.Font;
007: import java.awt.Graphics;
008: import java.awt.Graphics2D;
009: import java.awt.RenderingHints;
010: import java.awt.event.ActionEvent;
011: import java.awt.event.ActionListener;
012: import java.awt.event.MouseEvent;
013: import java.awt.geom.Rectangle2D;
014: import java.awt.geom.RoundRectangle2D;
015: import java.util.Enumeration;
016: import javax.swing.BorderFactory;
017: import javax.swing.JLabel;
018: import javax.swing.JMenuItem;
019: import javax.swing.JPopupMenu;
020:
021: /**
022: * A view of the question in graphic editor.
023: *
024: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
025: * the GNU Public License (GPL), please see license.txt for more details. If
026: * you make commercial use of this software you must purchase a commercial
027: * license from Xoetrope.</p>
028: * <p> $Revision: 1.5 $</p>
029: */
030: public class XQuestionView extends XSurveyComponentSmall {
031: public static Color BACKGROUND_COLOR = new Color(213, 247, 255);
032: public static Color BORDER_COLOR = Color.BLACK;
033: public static int WIDTH = 100;
034: public static int HEIGHT = 20;
035: public static int LEFT_GAP = 2;
036: public static int RIGHT_GAP = 2;
037: public static int ARC = 10;
038: public static int ID_WIDTH = 20;
039: public static int TYPE_WIDTH = 20;
040: public static int FIELD_GAP = 3;
041: public static int TEXT_GAP = 3;
042: public static int FONT_STYLE = 0;
043: public static int FONT_SIZE = 12;
044: public static String FONT_NAME = "Dialog";
045: public static Color FONT_COLOR;
046:
047: protected int arc, idWidth, typeWidth, fieldGap, textGap;
048: protected String fontName;
049:
050: protected Question question;
051: protected XConditionView newConditionView;
052:
053: public XQuestionView(Question q, XRulesEditorPane ep, XGroupView gv) {
054: super (ep, gv);
055: question = q;
056: newConditionView = null;
057: }
058:
059: public XQuestionView(XRulesEditorPane ep) {
060: super (ep);
061: }
062:
063: protected void initVariables() {
064: super .initVariables();
065: width = WIDTH;
066: height = HEIGHT;
067: backgroundColor = BACKGROUND_COLOR;
068: borderColor = BORDER_COLOR;
069: arc = ARC;
070: idWidth = ID_WIDTH;
071: typeWidth = TYPE_WIDTH;
072: fieldGap = FIELD_GAP;
073: textGap = TEXT_GAP;
074: fontName = FONT_NAME;
075: fontStyle = FONT_STYLE;
076: fontSize = FONT_SIZE;
077: fontColor = FONT_COLOR;
078: leftGap = LEFT_GAP;
079: rightGap = RIGHT_GAP;
080: topGap = TOP_GAP;
081: bottomGap = BOTTOM_GAP;
082: }
083:
084: protected void createPopupMenu() {
085: JMenuItem menuItem;
086: popupMenu = new JPopupMenu();
087: JLabel header = new JLabel(" Question Options");
088: header.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
089: popupMenu.add(header);
090: popupMenu.addSeparator();
091: menuItem = new JMenuItem("add new question");
092: popupMenu.add(menuItem);
093: menuItem.addActionListener(new ActionListener() {
094: public void actionPerformed(ActionEvent e) {
095: XQuestionGroup group = (XQuestionGroup) question
096: .getGroup();
097: group.addNewQuestion();
098: }
099: });
100: popupMenu.addSeparator();
101: menuItem = new JMenuItem("change id");
102: popupMenu.add(menuItem);
103: menuItem.addActionListener(new ActionListener() {
104: public void actionPerformed(ActionEvent e) {
105: editorPane.showQuestionIdField(XQuestionView.this );
106: }
107: });
108: menuItem = new JMenuItem("change text");
109: popupMenu.add(menuItem);
110: menuItem.addActionListener(new ActionListener() {
111: public void actionPerformed(ActionEvent e) {
112: editorPane.showQuestionTextField(XQuestionView.this );
113: }
114: });
115: menuItem = new JMenuItem("change type");
116: popupMenu.add(menuItem);
117: menuItem.addActionListener(new ActionListener() {
118: public void actionPerformed(ActionEvent e) {
119: editorPane.showQuestionTypeField(XQuestionView.this );
120: }
121: });
122: popupMenu.addSeparator();
123: menuItem = new JMenuItem("delete question");
124: popupMenu.add(menuItem);
125: menuItem.addActionListener(new ActionListener() {
126: public void actionPerformed(ActionEvent e) {
127: XQuestionGroup group = (XQuestionGroup) question
128: .getGroup();
129: group.deleteQuestion(question);
130: }
131: });
132: menuItem = new JMenuItem("show table");
133: popupMenu.add(menuItem);
134: menuItem.addActionListener(new ActionListener() {
135: public void actionPerformed(ActionEvent e) {
136: editorFrame.showQuestion(question);
137: }
138: });
139: }
140:
141: protected void updateModel(XSurveyComponentBig oldOwner,
142: XSurveyComponentBig newOwner) {
143: XGroupView oldGroupView = (XGroupView) oldOwner;
144: XGroupView newGroupView = (XGroupView) newOwner;
145: if (oldGroupView != null) {
146: XQuestionGroup group = oldGroupView.getGroup();
147: group.getQuestions().removeAllElements();
148: Enumeration enumQuestionViews = oldGroupView
149: .getXComponents().elements();
150: while (enumQuestionViews.hasMoreElements()) {
151: XQuestionView questionView = (XQuestionView) enumQuestionViews
152: .nextElement();
153: Question question = questionView.getQuestion();
154: group.getQuestions().add(question);
155: }
156: }
157:
158: if (oldGroupView != null && oldGroupView.equals(newGroupView)
159: || oldGroupView == null && newGroupView == null) {
160: editorFrame.getRulesEditorPanel().refreshTables();
161: return;
162: }
163:
164: if (newGroupView != null) {
165: XQuestionGroup group = newGroupView.getGroup();
166: group.getQuestions().removeAllElements();
167: Enumeration enumQuestionViews = newGroupView
168: .getXComponents().elements();
169: while (enumQuestionViews.hasMoreElements()) {
170: XQuestionView questionView = (XQuestionView) enumQuestionViews
171: .nextElement();
172: Question question = questionView.getQuestion();
173: group.getQuestions().add(question);
174: question.setGroup(group);
175: }
176: }
177: editorFrame.getRulesEditorPanel().refreshTables();
178: }
179:
180: public Class getOwnerClass() {
181: return XGroupView.class;
182: }
183:
184: protected void createShape() {
185: int w = getWidth() - 1;
186: int h = getHeight() - 1;
187: int arc = getArc();
188: shape = new RoundRectangle2D.Double(0, 0, w, h, arc, arc);
189: }
190:
191: public void paintQuestion(Graphics2D g) {
192: int x, y = 0, w, h = getHeight() - 1;
193: int arc = getArc();
194:
195: Color backgroundColor = getBackgroundColor();
196: Color borderColor = getBorderColor();
197:
198: g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
199: RenderingHints.VALUE_ANTIALIAS_ON);
200: x = 0;
201: w = getIdWidth() - 1;
202: g.setColor(backgroundColor);
203: g.fillRoundRect(x, y, w, h, arc, arc);
204: g.setColor(borderColor);
205: g.drawRoundRect(x, y, w, h, arc, arc);
206:
207: x = getIdWidth() + getFieldGap();
208: w = getNameWidth() - 1;
209: g.setColor(backgroundColor);
210: g.fillRoundRect(x, y, w, h, arc, arc);
211: g.setColor(borderColor);
212: g.drawRoundRect(x, y, w, h, arc, arc);
213:
214: x = getIdWidth() + getNameWidth() + 2 * getFieldGap();
215: w = getTypeWidth() - 1;
216: g.setColor(backgroundColor);
217: g.fillRoundRect(x, y, w, h, arc, arc);
218: g.setColor(borderColor);
219: g.drawRoundRect(x, y, w, h, arc, arc);
220:
221: g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
222: RenderingHints.VALUE_ANTIALIAS_OFF);
223: Font font = getFont();
224: Color fontColor = getFontColor();
225: int idWidth = getIdWidth();
226: int nameWidth = getNameWidth();
227: int typeWidth = getTypeWidth();
228: int fieldGap = getFieldGap();
229: int textGap = getTextGap();
230:
231: g.setFont(font);
232: g.setColor(fontColor);
233: Rectangle2D rc = null;
234:
235: String id = String.valueOf(question.getId());
236: String truncId = getTruncatedText(id, idWidth - 2 * textGap, g,
237: font);
238: rc = font.getStringBounds(truncId, g.getFontRenderContext());
239: x = (int) (idWidth - rc.getWidth()) / 2;
240: y = (int) (rc.getHeight());
241: g.drawString(truncId, x, y);
242:
243: String name = String.valueOf(question.getText());
244: String truncName = getTruncatedText(name, nameWidth - 2
245: * textGap, g, font);
246: rc = font.getStringBounds(truncName, g.getFontRenderContext());
247: x = idWidth + fieldGap + textGap;
248: y = (int) (rc.getHeight());
249: g.drawString(truncName, x, y);
250:
251: String type = null;
252: switch (question.getQuestionType()) {
253: case Question.MUTUALLY_EXCLUSIVE:
254: type = "E";
255: break;
256: case Question.MULTIPLE_CHOICE:
257: type = "M";
258: break;
259: case Question.FREE_TEXT:
260: type = "F";
261: break;
262: }
263: rc = font.getStringBounds(type, g.getFontRenderContext());
264: x = (int) (idWidth + fieldGap + nameWidth + fieldGap + (typeWidth - rc
265: .getWidth()) / 2);
266: y = (int) (rc.getHeight());
267: g.drawString(type, x, y);
268: }
269:
270: protected static final int ID_FIELD = 1;
271: protected static final int NAME_FIELD = 2;
272: protected static final int TYPE_FIELD = 3;
273:
274: protected int getClickedRegion(MouseEvent e) {
275: int region = 0;
276: int x = e.getPoint().x;
277: int y = e.getPoint().y;
278: if (x >= 0 && x <= getIdWidth())
279: region = ID_FIELD;
280: else if (x >= getIdWidth() + getFieldGap()
281: && x <= getIdWidth() + getFieldGap() + getNameWidth())
282: region = NAME_FIELD;
283: else if (x >= getIdWidth() + 2 * getFieldGap() + getNameWidth()
284: && x <= getWidth())
285: region = TYPE_FIELD;
286: return region;
287: }
288:
289: public void mouseClicked(MouseEvent e) {
290: if (e.getClickCount() == 2)
291: editorFrame.showQuestion(question);
292: }
293:
294: protected void startDragging(MouseEvent e) {
295: if (e.isShiftDown()) {
296: super .startDragging(e);
297: } else {
298: newConditionView = new XConditionView(new Condition(
299: question), editorPane, null);
300: newConditionView.setLocation(getLocation());
301: newConditionView.moveToFront();
302: newConditionView.setFirstMouseEvent(e);
303: newConditionView.startDragging(e);
304: }
305: }
306:
307: protected void endDragging(MouseEvent e) {
308: if (newConditionView == null) {
309: super .endDragging(e);
310: } else {
311: newConditionView.endDragging(e);
312: newConditionView = null;
313: }
314: }
315:
316: protected void drag(MouseEvent e) {
317: if (newConditionView == null) {
318: super .drag(e);
319: } else {
320: newConditionView.drag(e);
321: newConditionView.setFirstMouseEvent(e);
322: }
323: }
324:
325: public void paint(Graphics g) {
326: Graphics2D g2d = (Graphics2D) g;
327: paintQuestion(g2d);
328: }
329:
330: public Question getQuestion() {
331: return question;
332: }
333:
334: public int getArc() {
335: return (int) (getScale() * arc);
336: }
337:
338: public void setArc(int a) {
339: arc = (int) ((double) a / getScale());
340: }
341:
342: public int getIdWidth() {
343: return (int) (getScale() * idWidth);
344: }
345:
346: public void setIdWidth(int iw) {
347: idWidth = (int) ((double) iw / getScale());
348: }
349:
350: public int getTypeWidth() {
351: return (int) (getScale() * typeWidth);
352: }
353:
354: public void setTypeWidth(int tw) {
355: typeWidth = (int) ((double) tw / getScale());
356: }
357:
358: public int getFieldGap() {
359: return (int) (getScale() * fieldGap);
360: }
361:
362: public void setFieldGap(int fg) {
363: fieldGap = (int) ((double) fg / getScale());
364: }
365:
366: public int getTextGap() {
367: return (int) (getScale() * textGap);
368: }
369:
370: public void setTextGap(int tg) {
371: textGap = (int) ((double) tg / getScale());
372: }
373:
374: public int getNameWidth() {
375: int width = getWidth();
376: int fieldGap = getFieldGap();
377: int idWidth = getIdWidth();
378: int typeWidth = getTypeWidth();
379: return (width - idWidth - typeWidth - 2 * fieldGap);
380: }
381: }
|