diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..c465cdd
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,16 @@
+
+
+
+Although it is designed for console application (i.e. launched from the command.com shell prompt), it can launch standard GUI application. In such a case, any output of the java application (from System.out or System.err) is displayed in the a DOS Console.
+]]>
+
+
+Arguments can be passed to the application (either use the JSmooth default argument mechanism, or create a shortcut with arguments).]]>
+
Title: Egocentric Networks Client Program
+ *Description: Subject Interview Client
+ *Copyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * + * $Id: Answer.java,v 1.1 2005/08/02 19:36:02 samag Exp $ + */ +import com.endlessloopsoftware.ego.client.EgoClient; +import com.endlessloopsoftware.egonet.util.AnswerDataValue; + +import electric.xml.Element; +import electric.xml.Elements; +import java.util.Date; +import java.text.*; + +public class Answer implements Cloneable { + /** + * Unique ID for every question + */ + public Long questionId; + + private int[] alters; + + public boolean answered; + + public boolean adjacent; + + public int value; + + public int index; + + public String string; + + public String timestamp; + + public static final int NO_ANSWER = -1; + + public static final int ALL_ADJACENT = -2; + + private Answer() { + } + + public Answer(Long Id) { + this(Id, null); + } + + public Answer(Long Id, int[] alters) { + questionId = Id; + answered = false; + adjacent = false; + value = -1; + string = ""; + timestamp = DateFormat.getDateInstance().format(new Date()); + + if (alters == null) { + this.alters = new int[0]; + } else { + this.alters = alters; + } + } + + public Answer(AnswerDataValue data) { + questionId = data.getQuestionId(); + answered = data.getAnswered(); + adjacent = data.getAnswerAdjacent(); + value = data.getAnswerValue(); + string = data.getAnswerString(); + alters = data.getAlters().toArray(); + } + + public Object clone() throws CloneNotSupportedException { + return (super.clone()); + } + + /*************************************************************************** + * Add answer information to an xml structure for output to a file + * + * @param e + * XML Element, parent of answer tree + */ + public void writeAnswer(Element e) throws Exception { + Element answerElement = new Element("Answer"); + Element altersElement; + + try { + answerElement.addElement("QuestionId").setLong( + questionId.longValue()); + answerElement.addElement("Answered").setBoolean(answered); + + if (answered) { + answerElement.addElement("Value").setInt(value); + answerElement.addElement("Index").setInt(index); + answerElement.addElement("Adjacent").setBoolean(adjacent); + answerElement.addElement("String").setText(string); + answerElement.addElement("TimeStamp").setText(timestamp); + } + + if (alters.length > 0) { + altersElement = answerElement.addElement("Alters"); + for (int i = 0; i < alters.length; i++) { + altersElement.addElement("Index").setInt(alters[i]); + } + } + + e.addElement(answerElement); + } catch (Exception ex) { + System.err.println("Failure in Answer::writeAnswer; " + ex); + ex.printStackTrace(); + throw ex; + } + } + + /*************************************************************************** + * Read alter list from an xml tree + * + * @param interview + * Interview to read answers into + * @param e + * XML Element, parent of alter list + */ + public static Answer readAnswer(Element e) { + Answer r = null; + Elements alterElems = null; + int qAlters[] = null; + Long qId = new Long(e.getLong("QuestionId")); + Question q = (Question) EgoClient.study.getQuestions().getQuestion(qId); + Element alterElem = e.getElement("Alters"); + + if (alterElem != null) { + alterElems = alterElem.getElements("Index"); + qAlters = new int[alterElems.size()]; + + for (int i = 0; i < alterElems.size(); i++) { + qAlters[i] = alterElems.next().getInt(); + } + } + + r = new Answer(qId, qAlters); + + r.answered = e.getBoolean("Answered"); + + if (r.answered) { + r.string = e.getString("String"); + r.value = e.getInt("Value"); + r.index = e.getInt("Index"); + r.adjacent = q.selectionAdjacent(r.value); + } else { + r.string = null; + } + + return r; + } + + public int[] getAlters() { + return alters; + } + + public void setAlters(int[] alters) { + this.alters = alters; + } + + /* + * public AnswerDataValue getDataValue() { AnswerDataValue adv = new + * AnswerDataValue(); + * + * adv.setAnswered(this.answered); adv.setAnswerString(this.string); + * adv.setAnswerValue(this.value); adv.setAnswerAdjacent(this.adjacent); + * + * return adv; } + */ + public String toString() { + String str = null; + if (string == null) { + Integer val = value; + str = val.toString(); + ; + } else { + str = string; + } + return str; + } + + public String getString() { + String str = ""; + str = "Answered: " + answered + " string: " + string + " value : " + value; + return str; + + } +} \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/Question.java b/src/com/endlessloopsoftware/ego/Question.java new file mode 100644 index 0000000..c7bcb4c --- /dev/null +++ b/src/com/endlessloopsoftware/ego/Question.java @@ -0,0 +1,582 @@ +package com.endlessloopsoftware.ego; + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: Question.java,v 1.1 2005/08/02 19:36:02 samag Exp $ + * + */ + +import java.util.Date; + +import com.endlessloopsoftware.egonet.data.QuestionLinkDataValue; +import com.endlessloopsoftware.egonet.interfaces.QuestionEJBPK; +import com.endlessloopsoftware.egonet.util.QuestionDataValue; +import com.endlessloopsoftware.egonet.util.SelectionDataValue; + +import org.egonet.exceptions.MalformedQuestionException; +import org.egonet.util.listbuilder.Selection; + +import electric.xml.Element; +import electric.xml.Elements; + +/******************************************************************************* + * Routines for creating and handling atomic question elements + */ +public class Question implements Cloneable { + public boolean centralMarker = false; + + public boolean statable = false; + + public Long UniqueId = new Long(new Date().getTime()); + + public int questionType = Question.EGO_QUESTION; + + public String title = ""; + + public String text = ""; + + public String citation = ""; + + public int answerType = Question.TEXT; + + public int numQAlters = -1; + + public QuestionLink link = new QuestionLink(); + + /* + * public class selection extends Selection { public boolean modified=false; } + */ + + public Selection[] selections = new Selection[0]; + + public Answer answer = new Answer(new Long(-1)); + + /* Constants */ + public static final int MIN_QUESTION_TYPE = 1; + + public static final int STUDY_CONFIG = 0; + + public static final int EGO_QUESTION = 1; + + public static final int ALTER_PROMPT = 2; + + public static final int ALTER_QUESTION = 3; + + public static final int ALTER_PAIR_QUESTION = 4; + + public static final int NUM_QUESTION_TYPES = 5; + + public static final int ALL_QUESTION_TYPES = 5; + + public static final int MAX_QUESTION_TYPE = 4; + + public static final int MIN_ANSWER_TYPE = 0; + + public static final int CATEGORICAL = 0; + + public static final int NUMERICAL = 1; + + public static final int TEXT = 2; + + public static final int MAX_ANSWER_TYPE = 2; + + public static final int MAX_CATEGORICAL_CHOICES = 5; + + public static final String[] questionName = { "Study", "Ego", + "Alter Prompt", "Alter", "Alter Pair" }; + + /*************************************************************************** + * Creates question + * + * @return question new question + */ + public Question() { + } + + /*************************************************************************** + * Creates question with string as title + * + * @param s + * question title + * @return question new question + */ + public Question(String s) { + this.title = s; + } + + /*************************************************************************** + * Converts a QuestionDataValue to a question object + * + * @param question + * XML element of question + * @param base + * whether this is from the base file + * @throws MalformedQuestionException + * if theres is a problem with the XML representation + */ + public Question(QuestionDataValue data) { + this.UniqueId = data.getId(); + this.questionType = data.getQuestionType(); + this.answerType = data.getAnswerType(); + this.title = data.getTitle(); + this.text = data.getText(); + this.citation = data.getCitation(); + + SelectionDataValue[] selectionData = data.getSelectionDataValues(); + + /* Fix to properly display Apple UI interviews */ + if (this.questionType == Question.ALTER_PROMPT) { + this.answerType = Question.TEXT; + } + + /* + * temp vars for determining statable, a question must have at least one + * of each selection type to be statable + */ + boolean adjacent = false; + boolean nonadjacent = false; + + this.selections = new Selection[selectionData.length]; + for (int i = 0; i < selectionData.length; ++i) { + + Selection selection = new Selection(); + selection.setString(selectionData[i].getText()); + selection.setIndex(selectionData[i].getIndex()); + selection.setValue(selectionData[i].getValue()); + selection.setAdjacent(selectionData[i].getAdjacent()); + + /* + * selection selectionobj = new selection(); selectionobj.string = + * selectionData[i].getText(); selectionobj.index = + * selectionData[i].getIndex(); selectionobj.value = + * selectionData[i].getValue(); selectionobj.adjacent = + * selectionData[i].getAdjacent(); + */ + if (selection.isAdjacent()) + adjacent = true; + else + nonadjacent = true; + + selections[i] = selection; + } + + /* + * a question must have at least one of each selection type to be + * statable + */ + this.statable = adjacent && nonadjacent; + + if (data.getQuestionLinkDataValue() != null) { + QuestionLinkDataValue qlData = data.getQuestionLinkDataValue(); + + this.link.active = true; + this.link.answer = new Answer(qlData.getQuestionId()); + this.link.answer.value = qlData.getAnswerValue(); + this.link.answer.string = qlData.getAnswerString(); + } else { + this.link.active = false; + } + } + + /*************************************************************************** + * Reads a single question from an input stream + * + * @param question + * XML element of question + * @param base + * whether this is from the base file + * @throws MalformedQuestionException + * if theres is a problem with the XML representation + */ + public Question(Element question) throws MalformedQuestionException { + if ((question.getElement("QuestionTitle") == null) + || (question.getElement("QuestionText") == null) + || (question.getElement("Id") == null) + || (question.getElement("QuestionType") == null) + || (question.getElement("AnswerType") == null)) { + throw (new MalformedQuestionException()); + } + + this.title = question.getTextString("QuestionTitle"); + this.title = (this.title == null) ? "" : this.title; + + this.text = question.getTextString("QuestionText"); + this.text = (this.text == null) ? "" : this.text; + + this.citation = question.getTextString("Citation"); + this.citation = (this.citation == null) ? "" : this.citation; + + this.UniqueId = new Long(question.getLong("Id")); + this.questionType = question.getInt("QuestionType"); + this.answerType = question.getInt("AnswerType"); + + if (this.questionType == Question.ALTER_PROMPT) { + this.answerType = Question.TEXT; + } + + if (question.getAttribute("CentralityMarker") != null) { + boolean centrality = question.getAttribute("CentralityMarker") + .equals("true"); + + if (centrality + && (this.questionType != Question.ALTER_PAIR_QUESTION)) { + throw (new MalformedQuestionException()); + } + } + + Element link = question.getElement("Link"); + if (link != null) { + this.link.active = true; + this.link.answer = new Answer(new Long(link.getLong("Id"))); + this.link.answer.value = link.getInt("value"); + + /* Only support questions with single answers for link */ + this.link.answer.string = link.getTextString("string"); + } + + if (this.answerType == Question.CATEGORICAL) { + Element answerList = question.getElement("Answers"); + + if (answerList != null) { + Elements selections = answerList.getElements("AnswerText"); + + if (selections.size() == 0) { + throw (new MalformedQuestionException()); + } + + /* + * temp vars for determining statable, a question must have at + * least one of each selection type to be statable + */ + boolean adjacent = false; + boolean nonadjacent = false; + + this.selections = new Selection[selections.size()]; + + while (selections.hasMoreElements()) { + + Element selection = selections.next(); + int index = Integer.parseInt(selection + .getAttributeValue("index")); + + try { + this.selections[index] = new Selection(); + this.selections[index].setString(selection + .getTextString()); + this.selections[index] + .setValue(Integer.parseInt(selection + .getAttributeValue("value"))); + + this.selections[index].setAdjacent(Boolean.valueOf( + selection.getAttributeValue("adjacent")) + .booleanValue()); + this.selections[index].setIndex(index); + + } catch (NumberFormatException ex) { + this.selections[index].setValue(selections.size() + - (index + 1)); + this.selections[index].setAdjacent(false); + } + + if (this.selections[index].isAdjacent()) + adjacent = true; + else + nonadjacent = true; + } + + /* + * a question must have at least one of each selection type to + * be statable + */ + this.statable = adjacent && nonadjacent; + + /* Check to make sure all answers are contiguous */ + for (int i = 0; i < selections.size(); i++) { + if (this.selections[i] == null) { + throw (new MalformedQuestionException()); + } + } + } + } + } + + /*************************************************************************** + * Returns whether a given selection is adjacent based on the values stored + * in the question. Is used to override value found in an interview file + * + * @param value + * @return true iff that selection is marked as adjacent + */ + public boolean selectionAdjacent(int value) { + boolean rval = false; + + if (this.selections.length > 0) { + int size = this.selections.length; + + for (int i = 0; i < size; i++) { + if (value == this.selections[i].getValue()) { + rval = this.selections[i].isAdjacent(); + break; + } + } + } + + return rval; + } + + /*************************************************************************** + * Returns String representation of questionType + * + * @param type + * Question type to return as string + * @return string Question Type string + */ + public static String questionTypeString(int type) { + return (new String(questionName[type])); + } + + /*************************************************************************** + * Overrides toString method for question, returns title + * + * @return String title of question + */ + public String toString() { + if (title == null) { + return (new String("Untitled")); + } else { + return (title); + } + } + + /*************************************************************************** + * Writes a single question to an output stream + * + * @param w + * Print Writer of open output file + * @param q + * question + */ + public void writeQuestion(Element e, QuestionList list) { + if (this.centralMarker) { + e.setAttribute("CentralityMarker", "true"); + } + + e.addElement("Id").setLong(this.UniqueId.longValue()); + e.addElement("QuestionType").setInt(this.questionType); + e.addElement("AnswerType").setInt(this.answerType); + + if ((this.title != null) && (!this.title.equals(""))) { + e.addElement("QuestionTitle").setText(this.title); + } + + if ((this.text != null) && (!this.text.equals(""))) { + e.addElement("QuestionText").setText(this.text); + } + + if ((this.citation != null) && (!this.citation.equals(""))) { + e.addElement("Citation").setText(this.citation); + } + + if (this.selections.length > 0) { + int size = this.selections.length; + Element selections = e.addElement("Answers"); + + for (int i = 0; i < size; i++) { + Element answer = selections.addElement("AnswerText"); + answer.setText(this.selections[i].getString()); + answer.setAttribute("index", Integer.toString(i)); + answer.setAttribute("value", Integer + .toString(this.selections[i].getValue())); + answer.setAttribute("adjacent", + this.selections[i].isAdjacent() ? "true" : "false"); + } + } + + if (this.link.active + && (list.getQuestion(this.link.answer.questionId) != null)) { + try { + Element link = e.addElement("Link"); + link.addElement("Id").setLong( + this.link.answer.questionId.longValue()); + link.addElement("value").setInt(this.link.answer.value); + link.addElement("string").setText(this.link.answer.string); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + public QuestionDataValue getDataValue(QuestionList list, Long studyId) { + QuestionEJBPK pk = new QuestionEJBPK(this.UniqueId, studyId); + QuestionDataValue data = new QuestionDataValue(pk); + + data.setId(this.UniqueId); + data.setQuestionType(this.questionType); + data.setAnswerType(this.answerType); + data.setTitle(this.title); + data.setText(this.text); + data.setCitation(this.citation); + + if (this.selections.length > 0) { + int size = this.selections.length; + + for (int i = 0; i < size; i++) { + SelectionDataValue selectionData = new SelectionDataValue(); + selectionData.setText(this.selections[i].getString()); + selectionData.setIndex(i); + selectionData.setValue(this.selections[i].getValue()); + selectionData.setAdjacent(this.selections[i].isAdjacent()); + + data.addSelectionDataValue(selectionData); + } + } + + if (this.link.active + && (list.getQuestion(this.link.answer.questionId) != null)) { + try { + QuestionLinkDataValue qlData = new QuestionLinkDataValue(); + qlData.setActive(true); + qlData.setAnswerValue(this.link.answer.value); + qlData.setAnswerString(this.link.answer.string); + qlData.setQuestionId(this.link.answer.questionId); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + return data; + } + + /*************************************************************************** + * Implements Clone interface + * + * @return Clone of Question + */ + public Object clone() { + Question q; + + try { + q = (Question) super.clone(); + q.link = (QuestionLink) this.link.clone(); + + /******************************************************************* + * Dangerous to clone answers as multiple answers refer to same + * question Make sure they are assigned explicitly + */ + q.answer = null; + } catch (CloneNotSupportedException ex) { + q = null; + } + + return q; + } + + public String getString() { + String str = ""; + str = "ID : " + UniqueId + " Title : " + title + " text : " + text + + "\nAnswer : " + answer.getString(); + return str; + } +} + +/** + * $Log: Question.java,v $ Revision 1.1 2005/08/02 19:36:02 samag Initial + * checkin + * + * Revision 1.18 2004/04/11 00:24:48 admin Fixing headers + * + * Revision 1.17 2004/04/11 00:17:13 admin Improving display of Alter Prompt + * questions from Applet UI Interviews + * + * Revision 1.16 2004/04/06 20:29:22 admin First pass as supporting interactive + * applet linking interviews + * + * Revision 1.15 2004/04/06 14:56:02 admin Work to integrate with Applet Linking + * UI + * + * Revision 1.14 2004/04/01 15:11:16 admin Completing Original UI work + * + * Revision 1.13 2004/03/29 16:13:38 admin Fixed bug calculating statable + * questions + * + * Revision 1.12 2004/03/29 00:35:09 admin Downloading Interviews Fixing some + * bugs creating Interviews from Data Objects + * + * Revision 1.11 2004/03/28 17:31:31 admin More error handling when uploading + * study to server Server URL selection dialog for upload + * + * Revision 1.10 2004/03/22 00:00:34 admin Extended text entry area Started work + * on importing studies from server + * + * Revision 1.9 2004/03/21 14:00:38 admin Cleaned up Question Panel Layout using + * FOAM + * + * Revision 1.8 2004/03/10 14:32:39 admin Adding client library cleaning up code + * + * Revision 1.7 2004/02/10 20:10:42 admin Version 2.0 beta 3 + * + * Revision 1.6 2004/01/23 13:36:07 admin Updating Libraries Allowing upload to + * web server + * + * Revision 1.5 2003/12/18 19:30:05 admin Small mods to support EJB persistence + * + * Revision 1.4 2003/12/09 16:17:00 admin Fixing bug reading in adjacency + * selections Clearing identity diagonal of Weighted Adjacency Matrix + * + * Revision 1.3 2003/12/08 15:57:50 admin Modified to generate matrix files on + * survey completion or summarization Extracted statistics models + * + * Revision 1.2 2003/12/05 19:15:43 admin Extracting Study + * + * Revision 1.1 2003/12/04 15:14:08 admin Merging EgoNet and EgoClient projects + * so that they can share some common classes more easily. + * + * Revision 1.2 2003/11/25 19:25:43 admin Warn before closing window + * + * Revision 1.1.1.1 2003/06/08 15:09:40 admin Egocentric Network Survey + * Authoring Module + * + * Revision 1.16 2002/08/30 16:50:27 admin Using Selections + * + * Revision 1.15 2002/08/30 09:35:38 admin Using Selection Class + * + * Revision 1.14 2002/08/11 22:26:05 admin Final Statistics window, new file + * handling + * + * Revision 1.13 2002/08/08 17:07:25 admin Preparing to change file system + * + * Revision 1.12 2002/07/25 14:54:24 admin Question Links + * + * Revision 1.11 2002/07/24 14:17:51 admin new files + * + * Revision 1.9 2002/07/18 14:43:06 admin New Alter Prompt Panel, packages + * + * Revision 1.8 2002/06/30 15:59:18 admin Moving questions in lists, between + * lists Better category input + * + * Revision 1.7 2002/06/26 15:43:43 admin More selection dialog work File + * loading fixes + * + * Revision 1.6 2002/06/26 00:10:48 admin UI Work including base question + * coloring and category selections + * + * Revision 1.5 2002/06/25 15:41:02 admin Lots of UI work + * + * Revision 1.4 2002/06/21 21:52:50 admin Many changes to event handling, file + * handling + * + * Revision 1.3 2002/06/19 01:57:04 admin Much UI work done + * + * Revision 1.2 2002/06/16 17:53:10 admin Working with files + * + * Revision 1.1 2002/06/15 14:19:51 admin Initial Checkin of question and survey + * General file system work + * + */ + diff --git a/src/com/endlessloopsoftware/ego/QuestionLink.java b/src/com/endlessloopsoftware/ego/QuestionLink.java new file mode 100644 index 0000000..13e0135 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/QuestionLink.java @@ -0,0 +1,33 @@ +package com.endlessloopsoftware.ego; + + +/** + *Title: Egocentric Networks Client Program
+ *Description: Subject Interview Client
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * @version 1.0 + */ + +public class QuestionLink + implements Cloneable +{ + public boolean active = false; + public Answer answer = null; + + public Object clone() + throws CloneNotSupportedException + { + QuestionLink q; + + q = (QuestionLink) super.clone(); + + if (active) + { + q.answer = (Answer) this.answer.clone(); + } + + return(q); + } +} \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/QuestionList.java b/src/com/endlessloopsoftware/ego/QuestionList.java new file mode 100644 index 0000000..b69b51e --- /dev/null +++ b/src/com/endlessloopsoftware/ego/QuestionList.java @@ -0,0 +1,199 @@ +package com.endlessloopsoftware.ego; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Observable; +import java.util.Observer; +import java.util.Set; + + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * + * $Id: QuestionList.java,v 1.1 2005/08/02 19:36:02 samag Exp $ + */ + +public class QuestionList extends Observable + implements Observer +{ + private final MapExtWindowsLookAndFeel
on general Windows, and
+ * Plastic3DLookAndFeel
on Windows XP and all other OS.
+ *
+ * The JGoodies Swing Suite's ApplicationStarter
,
+ * ExtUIManager
, and LookChoiceStrategies
+ * classes provide a much more fine grained algorithm to choose and
+ * restore a look and theme.
+ */
+ /* Added by sonam : 08/20.2007 */
+
+ public static final String USE_SYSTEM_FONTS_APP_KEY =
+ "Application.useSystemFontSettings";
+
+ /* end of code added by sonam */
+ public static void configureUI()
+ {
+
+ /*
+ * Commented by sonam : 08/20/2007
+ * UIManager.put(Options.USE_SYSTEM_FONTS_APP_KEY, Boolean.TRUE);
+ * Options.setGlobalFontSizeHints(FontSizeHints.MIXED);
+ * Options.setDefaultIconSize(new Dimension(18, 18));
+ * String lafName = LookUtils.IS_OS_WINDOWS_XP ?
+ Options.getCrossPlatformLookAndFeelClassName() :
+ Options.getSystemLookAndFeelClassName();
+ */
+
+ /*
+ UIManager.put(USE_SYSTEM_FONTS_APP_KEY, Boolean.TRUE);
+ String lafName = (System.getProperty("os.name").toLowerCase()=="windows xp") ?
+ UIManager.getCrossPlatformLookAndFeelClassName() :
+ UIManager.getSystemLookAndFeelClassName();
+ try
+ {
+ UIManager.setLookAndFeel(lafName);
+ }
+ catch (Exception e)
+ {
+ System.err.println("Can't set look & feel:" + e);
+ }
+ */
+
+ }
+
+ public static void setWaitCursor(JFrame frame, boolean waitCursor)
+ {
+ if (waitCursor)
+ {
+ frame.getGlassPane().setVisible(true);
+ frame.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ }
+ else
+ {
+ frame.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ frame.getGlassPane().setVisible(false);
+ }
+ }
+
+}
diff --git a/src/com/endlessloopsoftware/ego/Study.java b/src/com/endlessloopsoftware/ego/Study.java
new file mode 100644
index 0000000..9be8f4c
--- /dev/null
+++ b/src/com/endlessloopsoftware/ego/Study.java
@@ -0,0 +1,1180 @@
+package com.endlessloopsoftware.ego;
+
+/**
+ *
Title: Egocentric Networks Client Program
+ *Description: Subject Interview Client
+ *Copyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * + * $Id: Study.java,v 1.1 2005/08/02 19:36:02 samag Exp $ + */ + +import java.io.IOException; +import java.util.*; + +import javax.ejb.CreateException; +import javax.swing.DefaultListModel; +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +import org.egonet.exceptions.DuplicateQuestionException; +import org.egonet.exceptions.MalformedQuestionException; + +import com.endlessloopsoftware.egonet.Shared; +import com.endlessloopsoftware.egonet.interfaces.StudySBRemote; +import com.endlessloopsoftware.egonet.interfaces.StudySBRemoteHome; +import com.endlessloopsoftware.egonet.interfaces.StudySBUtil; +import com.endlessloopsoftware.egonet.util.QuestionDataValue; +import com.endlessloopsoftware.egonet.util.StudyDataValue; +import electric.xml.Document; +import electric.xml.Element; +import electric.xml.Elements; + +/******************************************************************************* + * Stores basic configuration data for the study including question order lists + */ +public class Study extends Observable +{ + private long _uniqueId = -1L; + private String _uiType = Shared.TRADITIONAL_QUESTIONS; + private int _numAlters = -1; + private boolean _studyDirty = false; + private boolean _compatible = true; + private boolean _inUse = false; + private String _studyName = "New Study"; + private List[] _questionOrder = new List[Question.NUM_QUESTION_TYPES]; + private Question _firstQuestion = new Question("none"); + private QuestionList _questions = new QuestionList(); + private int _totalQuestions = -1; + private static Properties _prop = new Properties(); + + /** + * Instantiates Default Study + */ + public Study() + { + _studyName = "New Study"; + _uiType = Shared.TRADITIONAL_QUESTIONS; + _numAlters = 40; + _studyDirty = false; + _compatible = true; + _uniqueId = -1; + + // @TODO Move storage to parent package + // EgoNet.storage.setStudyFile(null); + this.getQuestions().removeAll(); + + for (int i = 0; i < _questionOrder.length; i++) + { + _questionOrder[i] = new ArrayList(); + } + } + + /** + * Instantiates Study based on a StudyDataValue downloaded from a survey server + */ + public Study(StudyDataValue data) + { + _uniqueId = data.getId().longValue(); + _uiType = data.getUIType(); + _numAlters = data.getNumAlters(); + _studyName = data.getStudyName(); + + Long[][] orders = data.getQuestionOrder(); + + for (int i = 0; i < Question.NUM_QUESTION_TYPES; ++i) + { + if (orders[i] != null) + { + _questionOrder[i] = Arrays.asList(orders[i]); + } + else + { + _questionOrder[i] = new ArrayList(); + } + } + + QuestionDataValue[] questionData = data.getQuestionDataValues(); + for (int i = 0; i < questionData.length; ++i) + { + Question question = new Question(questionData[i]); + + if ((question.questionType == Question.ALTER_PAIR_QUESTION) && isAppletUI()) + { + question.statable = true; + } + + _questions.addQuestion(question); + } + + verifyStudy(); + } + + /********** + * Instantiates study from an XML Document + * @param document + */ + public Study(Document document) + { + // Start with default study + this(); + + readPackageStudy(document); + readQuestions(document); + verifyStudy(); + } + + + /*************************************************************************** + * Returns UniqueId of study read from file + * + * @return long Unique Id of study + */ + public long getStudyId() + { + return (_uniqueId); + } + + /*************************************************************************** + * Notifies observers that a field in the study has changed + */ + public void notifyObservers() + { + setChanged(); + super.notifyObservers(this); + } + + /*************************************************************************** + * Returns name of study + * + * @return name name of study + */ + public String getStudyName() + { + return (_studyName); + } + + /*************************************************************************** + * Returns number of alters for which to prompt + * + * @return numAlters number of alters for which to prompt + */ + public int getNumAlters() + { + return (_numAlters); + } + + /*************************************************************************** + * Returns array of question order lists + * + * @return questionOrder array of lists + */ + public List[] getQuestionOrderArray() + { + return (_questionOrder); + } + + /** + * @return Returns the questions. + */ + public QuestionList getQuestions() + { + return _questions; + } + + /** + * @return Returns the questions. + */ + public Question getQuestion(Long id) + { + return getQuestions().getQuestion(id); + } + + + /** + * @return Returns the firstQuestion. + */ + public Question getFirstQuestion() + { + return _firstQuestion; + } + + /*************************************************************************** + * Returns array of questions for a specified category + * + * @param category + * category of questions to return + * @return questionOrder array of question Ids + * @throws NoSuchElementException + * for category out of range + */ + public List getQuestionOrder(int category) throws NoSuchElementException + { + if (category >= _questionOrder.length) + { + throw (new NoSuchElementException()); + } + + return (_questionOrder[category]); + } + + /*************************************************************************** + * Working forward from beginning, find first unanswered question + * + * @return index of first unanswered question + */ + public Question getFirstStatableQuestion() + { + Question statable = null; + Iterator questions; + + /** + * Try to find one all alters answer + */ + questions = getQuestionOrder(Question.ALTER_PAIR_QUESTION).iterator(); + while (questions.hasNext()) + { + Question q = (Question) getQuestions().getQuestion((Long) questions.next()); + + if (q.statable && !q.link.active) + { + statable = q; + break; + } + } + + /** + * Settle for any statable + */ + if (statable == null) + { + questions = getQuestionOrder(Question.ALTER_QUESTION).iterator(); + while (questions.hasNext()) + { + Question q = (Question) getQuestions().getQuestion((Long) questions.next()); + + if (q.statable) + { + statable = q; + } + } + } + + return (statable); + } + + /*************************************************************************** + * Returns UniqueId of study read from file + * + * @param long + * Unique Id of study + */ + public void setStudyId(long id) + { + _uniqueId = id; + } + + /*************************************************************************** + * Sets name of study + * + * @param name + * name of study + */ + public void setStudyName(String name) + { + if (!_studyName.equals(name)) + { + _studyName = name; + setModified(true); + } + } + + /*************************************************************************** + * Sets numAlters variable and notifies observers of change to study + * + * @param n + * number of alters for which to elicit + */ + public void setNumAlters(int n) + { + if (_numAlters != n) + { + _numAlters = n; + setModified(true); + } + } + + /*************************************************************************** + * Sets study dirty flag; generally done when the study is written to a + * file + */ + public void setModified(boolean dirty) + { + _studyDirty = dirty; + notifyObservers(); + } + + /*************************************************************************** + * gets dirty state of study + * + * @return dirty + */ + public boolean isModified() + { + return (_studyDirty); + } + + /** + * @return Returns the compatible. + */ + public boolean isCompatible() + { + return _compatible; + } + + /** + * @param compatible The compatible to set. + */ + public void setCompatible(boolean compatible) + { + this._compatible = compatible; + notifyObservers(); + } + + /** + * @return Returns the inUse. + */ + public boolean isInUse() + { + return _inUse; + } + + /** + * @param inUse The inUse to set. + */ + public void setInUse(boolean inUse) + { + this._inUse = inUse; + } + + /** + * @return Returns the uiType + */ + public String getUIType() + { + return _uiType; + } + + public boolean isAppletUI() + { + return (getUIType().equals(Shared.PAIR_ELICITATION) || getUIType().equals(Shared.THREE_STEP_ELICITATION)); + } + + /** + * Warn user this change will make study no longer compatible with previous interviews + * @param q + * @throws DuplicateQuestionException + */ + public boolean confirmIncompatibleChange(JFrame frame) + { + boolean ok = true; + if (isInUse() && isCompatible()) + { + int confirm = + JOptionPane.showConfirmDialog( + frame, + "This study has already been used for at least one interview.\n" + + "If you make this change you will have to save this as a new study and will \n" + + "no longer be able to access prior interviews with this study.\n" + + "Do you still wish to make this change?", + "Incompatible Study Modification", + JOptionPane.OK_CANCEL_OPTION); + + if (confirm != JOptionPane.OK_OPTION) + { + ok = false; + } + } + + return ok; + } + + /*************************************************************************** + * Adds a question to the full question list + * + * @param q + * question to add + */ + public void addQuestion(Question q) throws DuplicateQuestionException + { + if (!this.getQuestions().contains(q)) + { + this.getQuestions().addQuestion(q); + setModified(true); + } + else + { + throw new DuplicateQuestionException(); + } + + /* If not in appropriate array list, add to that list too */ + if (!_questionOrder[q.questionType].contains(q.UniqueId)) + { + _questionOrder[q.questionType].add(q.UniqueId); + } + } + + /*************************************************************************** + * Changes position of a question in an order list + * + * @param q + * question to move + * @param follow + * question q should follow + */ + public void moveQuestionAfter(Question q, Question follow) + { + int followloc; + + if (_questionOrder[q.questionType].contains(follow.UniqueId) || (follow == _firstQuestion)) + { + _questionOrder[q.questionType].remove(q.UniqueId); + + if (follow == _firstQuestion) + { + _questionOrder[q.questionType].add(0, q.UniqueId); + } + else + { + followloc = _questionOrder[q.questionType].indexOf(follow.UniqueId); + _questionOrder[q.questionType].add(followloc + 1, q.UniqueId); + } + + if (q.link.active) + { + if (!doesQuestionPreceed(q.link.answer.questionId, q.UniqueId)) + { + q.link.active = false; + q.link.answer = null; + } + } + + setModified(true); + } + } + + /*************************************************************************** + * moves question from one order list to another + * + * @param q + * question to move + * @param type + * new question type + */ + public void changeQuestionType(Question q, int type) + { + removeQuestion(q); + + q.questionType = type; + + try + { + addQuestion(q); + } + catch (DuplicateQuestionException e) + { + // This shouldn't happen + e.printStackTrace(); + } + + setModified(true); + } + + /*************************************************************************** + * Go through question list making sure any interquestion dependencies are + * met + * + * @param q + * question to move + * @param type + * new question type + */ + public void setCentralQuestion(Question q) + { + Long key; + Question listQ; + Iterator i = _questionOrder[Question.ALTER_PAIR_QUESTION].iterator(); + + while (i.hasNext()) + { + key = (Long) i.next(); + listQ = this.getQuestions().getQuestion(key); + + if (listQ != null) + { + if (listQ.equals(q)) + { + if (!listQ.centralMarker) + { + listQ.centralMarker = true; + setModified(true); + } + } + else + { + /* Only one centralMarker allowed */ + if (listQ.centralMarker) + { + listQ.centralMarker = false; + setModified(true); + } + } + } + } + } + + /*************************************************************************** + * Go through question list making sure any interquestion dependencies are + * met + * + * @param q + * question to move + * @param type + * new question type + */ + public void validateQuestions() + { + Long key; + Question q; + boolean foundCentral = false; + ; + Iterator i = _questionOrder[Question.ALTER_PAIR_QUESTION].iterator(); + + while (i.hasNext()) + { + key = (Long) i.next(); + q = this.getQuestions().getQuestion(key); + + if (q != null) + { + if (!foundCentral && q.centralMarker) + { + foundCentral = true; + } + else + { + /* Only one centralMarker allowed */ + q.centralMarker = false; + } + } + } + + if (!foundCentral) + { + /* Tag first Alter pair categorical question */ + i = _questionOrder[Question.ALTER_PAIR_QUESTION].iterator(); + + while (i.hasNext() && !foundCentral) + { + key = (Long) i.next(); + q = this.getQuestions().getQuestion(key); + + if ((q != null) && (q.answerType == Question.CATEGORICAL)) + { + q.centralMarker = true; + foundCentral = true; + } + } + } + } + + /*************************************************************************** + * Searches question list for all questions of a given tpe, places them in + * list + * + * @param questionType + * type filter for question list + * @param dlm + * list model to use in inserting questions + */ + public void fillList(int questionType, DefaultListModel dlm) + { + int startType, endType; + Iterator i; + Long key; + + if (questionType == Question.ALL_QUESTION_TYPES) + { + startType = Question.MIN_QUESTION_TYPE; + endType = Question.MAX_QUESTION_TYPE; + } + else + { + startType = questionType; + endType = questionType; + } + + for (int type = startType; type <= endType; type++) + { + if ((questionType != Question.ALL_QUESTION_TYPES) || (type != Question.ALTER_PROMPT)) + { + i = _questionOrder[type].iterator(); + while (i.hasNext()) + { + key = (Long) i.next(); + if (this.getQuestions().contains(key)) + { + dlm.addElement(this.getQuestions().getQuestion(key)); + } + } + } + } + } + + /*************************************************************************** + * Searches question list for all questions of a given tpe, places them in + * list until a given question is reached + * + * @param questionType + * type filter for question list + * @param dlm + * list model to use in inserting questions + * @param endId + * question list end, stop when you see this question + */ + public void fillList(int questionType, DefaultListModel dlm, Long endId) + { + int startType, endType; + Iterator i; + Long key; + boolean found = false; + + if (questionType == Question.ALL_QUESTION_TYPES) + { + startType = Question.MIN_QUESTION_TYPE; + endType = Question.MAX_QUESTION_TYPE; + } + else + { + startType = questionType; + endType = questionType; + } + + for (int type = startType;(type <= endType) && !found; type++) + { + if ((questionType != Question.ALL_QUESTION_TYPES) || (type != Question.ALTER_PROMPT)) + { + i = _questionOrder[type].iterator(); + while (i.hasNext() && !found) + { + key = (Long) i.next(); + if (key.equals(endId)) + { + found = true; + } + else if (this.getQuestions().contains(key)) + { + dlm.addElement(this.getQuestions().getQuestion(key)); + } + } + } + } + } + + /*************************************************************************** + * Returns true iff q1 preceeds q2 in study + * + * @param q1 + * Id of question which may preceed q2 + * @param q2 + * Id of question which may be preceeded by q1 + */ + public boolean doesQuestionPreceed(Long q1, Long q2) + { + int startType, endType; + Iterator i; + Long key; + boolean found = false; + + startType = Question.MIN_QUESTION_TYPE; + endType = Question.MAX_QUESTION_TYPE; + + for (int type = startType;(type <= endType) && !found; type++) + { + i = _questionOrder[type].iterator(); + while (i.hasNext() && !found) + { + key = (Long) i.next(); + if (key.equals(q1)) + { + return true; + } + else if (key.equals(q2)) + { + return false; + } + } + } + + return false; + } + + /*************************************************************************** + * Essentially makes sure order list matches question list + */ + public void verifyStudy() + { + for (int i = 0; i < Question.NUM_QUESTION_TYPES; i++) + { + Iterator it = getQuestionIterator(i); + + while (it.hasNext()) + { + Long qid = (Long) it.next(); + + if (getQuestions().getQuestion(qid) == null) + { + it.remove(); + } + } + } + } + + /*************************************************************************** + * Returns a bi-directional list iterator of questions for a category + * + * @param category + * category of question + * @return iterator list iterator or questions + */ + public ListIterator getQuestionIterator(int category) + { + return (_questionOrder[category].listIterator()); + } + + /*************************************************************************** + * Remove all base or custom Questions from question list and order lists + * + * @param base + * Remove questions from base file or custom file + */ + public void removeQuestions() + { + Question q; + + Iterator i = this.getQuestions().values().iterator(); + + while (i.hasNext()) + { + q = (Question) i.next(); + + i.remove(); + removeQuestion(q); + } + } + + /*************************************************************************** + * Remove one Question from question map and order lists + * + * @param q + * question to remove + */ + public void removeQuestion(Question q) + { + removeLinksToQuestion(q); + + for (int i = 0; i < _questionOrder.length; i++) + { + _questionOrder[i].remove(q.UniqueId); + } + + this.getQuestions().remove(q); + setModified(true); + } + + /*************************************************************************** + * Searches question list for any questions linked to a question about to + * be removed, and removes those question links. + * + * @param questionType + * type filter for question list + * @param dlm + * list model to use in inserting questions + */ + public void removeLinksToQuestion(Question lq) + { + Question q; + + Iterator i = this.getQuestions().values().iterator(); + + while (i.hasNext()) + { + q = (Question) i.next(); + + if (q.link.active && (q.link.answer.questionId.equals(lq.UniqueId))) + { + q.link.active = false; + q.link.answer = null; + } + } + } + + /*************************************************************************** + * Writes study specific information to xml output file + */ + public void writeInterviewStudy(Element e) + { + e.setInt("numalters", getNumAlters()); + } + + /*************************************************************************** + * Reads in study information from an XML input file Includes files paths + * and arrays of question orders + * + * @param studyFile + * File from which to read study + */ + public void readInterviewStudy(Element e) + { + // String data; + + try + { + if (e.getElement("numalters") != null) + { + setNumAlters(e.getInt("numalters")); + } + + } + catch (Exception ex) + { + /** @todo handle exception */ + ex.printStackTrace(); + } + } + + /*************************************************************************** + * Reads in study information from an XML input file Includes files paths + * and arrays of question orders + * + * @param studyFile + * File from which to read study + */ + public void readPackageStudy(Document document) + { + // String data; + + try + { + Element root = document.getRoot(); + setStudyId(Long.parseLong(root.getAttributeValue("Id"))); + + root = root.getElement("Study"); + + if (root.getElement("name") != null) + { + setStudyName(root.getTextString("name")); + } + + if (root.getElement("numalters") != null) + { + setNumAlters(root.getInt("numalters")); + } + + Elements elements = root.getElements("questionorder"); + while (elements.hasMoreElements()) + { + int qOrderId; + List questionOrder; + Elements ids; + + Element element = elements.next(); + qOrderId = Integer.parseInt(element.getAttribute("questiontype")); + questionOrder = (getQuestionOrderArray())[qOrderId]; + + ids = element.getElements("id"); + while (ids.hasMoreElements()) + { + questionOrder.add(new Long(ids.next().getLong())); + } + } + } + catch (Exception e) + { + /** @todo handle exception */ + e.printStackTrace(); + } + } + + /*************************************************************************** + * Reads all the questions from a file + * + * @param f + * File from which to read questions + */ + public void readQuestions(Document document) + { + Element root, question; + Elements questions; + + /** + * Parse XML file + */ + root = document.getRoot(); + root = root.getElement("QuestionList"); + questions = root.getElements("Question"); + + while (questions.hasMoreElements()) + { + try + { + /* Question complete, add it */ + Question q = new Question(questions.next()); + addQuestion(q); + } + catch (MalformedQuestionException e) + { + /* Don't create this question. Incomplete */ + System.err.println("Malformed Question in file."); + } + catch (DuplicateQuestionException e) + { + /* Don't create this question. Incomplete */ + System.err.println("Duplicate Question in file."); + } + } + } + + /************************************************************** + * Writes Study information to a file for later retrieval + * Includes files paths and arrays of question orders + * + * @param document XML element to which to add study information + * @todo prune order lists, possibly need to load question files to do this + */ + public void writeStudyData(Element document) + { + Iterator it; + int i; + + try + { + Element study = document.addElement("Study"); + + study.addElement("name").setText(getStudyName()); + study.addElement("numalters").setInt(getNumAlters()); + + for (i = 1; i < Question.NUM_QUESTION_TYPES; i++) + { + Element qorder = new Element("questionorder"); + it = (getQuestionOrderArray())[i].iterator(); + + if (it.hasNext()) + { + study.addElement(qorder).setAttribute("questiontype", Integer.toString(i)); + while (it.hasNext()) + { + qorder.addElement("id").setLong(((Long) it.next()).longValue()); + } + } + } + } + catch (Exception ex) + { + JOptionPane.showMessageDialog( + null, + "Unable to write to this study file", + "Study Writing Error", + JOptionPane.ERROR_MESSAGE); + + } + } + + /*********************************************************** + * Writes all questions to a package file for later use + * + * @param document + * XML tree to which to add question + * @throws IOException + */ + public void writeAllQuestionData(Element document) + throws IOException + { + Iterator it; + Element element; + + element = document.addElement("QuestionList"); + + it = getQuestions().getQuestionMap().values().iterator(); + + while (it.hasNext()) + { + Question q = (Question) it.next(); + q.writeQuestion(element.addElement("Question"), getQuestions()); + } + } + + /** + * @author Peter Schoaff + * + * Store study in selected server. + */ + public boolean writeDBStudy(JFrame frame, String server, char[] password) + { + boolean rval = true; + + try + { + _prop.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); + _prop.setProperty("java.naming.provider.url", server + ":1099"); + //System.out.println(_prop.getProperty("java.naming.provider.url")); + + StudySBRemoteHome studyHome = StudySBUtil.getHome(_prop); + StudySBRemote studySB = studyHome.create(); + StudyDataValue data = new StudyDataValue(); + + data.setUIType(com.endlessloopsoftware.egonet.Shared.THREE_STEP_ELICITATION); + data.setNumAlters(getNumAlters()); + data.setStudyName(getStudyName()); + + Long[][] questionOrder = new Long[Question.NUM_QUESTION_TYPES][]; + + for (int i = 1; i < Question.NUM_QUESTION_TYPES; ++i) + { + List qorder = getQuestionOrder(i); + questionOrder[i] = new Long[qorder.size()]; + qorder.toArray(questionOrder[i]); + } + + data.setQuestionOrder(questionOrder); + + Iterator it = getQuestions().getQuestionMap().values().iterator(); + + while (it.hasNext()) + { + Question q = (Question) it.next(); + data.addQuestionDataValue(q.getDataValue(this.getQuestions(), data.getId())); + } + + String epassword = "215-121-242-47-99-238-5-61-133-183-0-216-187-250-253-30-115-177-254-142-161-83-108-56";//SymmetricKeyEncryption.encrypt(new String(password)); + studySB.createStudy(data, epassword); + } + catch (CreateException e) + { + JOptionPane.showMessageDialog(frame, + "Unable to store study.\n" + e.getMessage(), + "Server error", + JOptionPane.ERROR_MESSAGE); + + rval = false; + } + catch (Exception e) + { + JOptionPane.showMessageDialog(frame, + "Unable to store study.\n", + "Server error", + JOptionPane.ERROR_MESSAGE); + + // TODO Auto-generated catch block + e.printStackTrace(); + rval = false; + } + + return rval; + } + +} + +/** + * $Log: Study.java,v $ + * Revision 1.1 2005/08/02 19:36:02 samag + * Initial checkin + * + * Revision 1.14 2004/04/11 15:19:28 admin + * Using password to access server + * + * Remote study summary in seperate thread with progress monitor + * + * Revision 1.13 2004/04/11 00:17:13 admin + * Improving display of Alter Prompt questions from Applet UI Interviews + * + * Revision 1.12 2004/04/07 00:08:31 admin + * updating manifests, jar creation. Removing author specific objects from + * client specific references + * + * Revision 1.11 2004/04/06 20:29:22 admin + * First pass as supporting interactive applet linking interviews + * + * Revision 1.10 2004/04/06 14:56:02 admin + * Work to integrate with Applet Linking UI + * + * Revision 1.9 2004/04/02 19:48:58 admin + * Keep Study Id when possible + * Store updated time in file + * + * Revision 1.8 2004/03/29 00:35:09 admin + * Downloading Interviews + * Fixing some bugs creating Interviews from Data Objects + * + * Revision 1.7 2004/03/28 17:31:31 admin + * More error handling when uploading study to server + * Server URL selection dialog for upload + * + * Revision 1.6 2004/03/23 14:58:47 admin + * Update UI + * Study creation now occurs in instantiators + * + * Revision 1.5 2004/03/21 20:29:37 admin + * Warn before making incompatible changes to in use study file + * + * Revision 1.4 2004/03/21 14:00:38 admin + * Cleaned up Question Panel Layout using FOAM + * + * Revision 1.3 2004/02/10 20:10:42 admin + * Version 2.0 beta 3 + * + * Revision 1.2 2004/01/23 13:36:07 admin + * Updating Libraries + * Allowing upload to web server + * + * Revision 1.1 2003/12/05 19:15:43 admin + * Extracting Study + * Revision 1.3 2003/12/04 15:14:08 admin Merging EgoNet + * and EgoClient projects so that they can share some common classes more + * easily. + * + * Revision 1.2 2003/11/25 19:25:44 admin Warn before closing window + * + * Revision 1.1.1.1 2003/06/08 15:09:40 admin Egocentric Network Survey + * Authoring Module + * + * Revision 1.10 2002/08/11 22:26:06 admin Final Statistics window, new file + * handling + * + * Revision 1.9 2002/08/08 17:07:26 admin Preparing to change file system + * + * Revision 1.8 2002/07/25 14:54:24 admin Question Links + * + * Revision 1.7 2002/07/24 14:17:10 admin xml files, links + * + * Revision 1.6 2002/07/18 14:43:06 admin New Alter Prompt Panel, packages + * + * Revision 1.5 2002/06/30 15:59:18 admin Moving questions in lists, between + * lists Better category input + * + * Revision 1.4 2002/06/26 15:43:43 admin More selection dialog work File + * loading fixes + * + * Revision 1.3 2002/06/25 15:41:02 admin Lots of UI work + * + * Revision 1.2 2002/06/21 22:47:12 admin question lists working again + * + * Revision 1.1 2002/06/21 21:53:29 admin new files + * + * Revision 1.2 2002/06/16 17:53:10 admin Working with files + * + * Revision 1.1 2002/06/15 14:19:51 admin Initial Checkin of question and + * survey General file system work + * + */ diff --git a/src/com/endlessloopsoftware/ego/author/AuthoringQuestionPanel.java b/src/com/endlessloopsoftware/ego/author/AuthoringQuestionPanel.java new file mode 100644 index 0000000..464c62e --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/AuthoringQuestionPanel.java @@ -0,0 +1,721 @@ +package com.endlessloopsoftware.ego.author; + +/** + *Title: Survey Center Database Client
+ *Description: Database Manipulation program for Survey Center Suite
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: QuestionPanel.java,v 1.1 2005/08/02 19:36:05 samag Exp $ + */ + + +import java.awt.*; +import java.awt.event.ActionEvent; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.egonet.exceptions.DuplicateQuestionException; + +import com.endlessloopsoftware.ego.Question; + +/** + * Generic Panel creation and handling routines for question editing + */ +public class AuthoringQuestionPanel extends EgoQPanel +{ + private final int questionType; + private boolean inUpdate; + + private final JSplitPane question_split = new JSplitPane(); + private final JList question_list = new JList(); + private final JScrollPane question_list_scroll = new JScrollPane(question_list); + private final JPanel question_panel_right = new RightPanel(); + private final JLabel question_title_label = new JLabel("Title:"); + private final JLabel question_question_label = new JLabel("Question:"); + private final JLabel question_citation_label = new JLabel("Citation:"); + private final JLabel question_type_label = new JLabel("Question Type:"); + private final JComboBox question_type_menu = new JComboBox(questionTypes); + private final JLabel question_answer_type_label = new JLabel("Answer Type:"); + private final JButton question_answer_type_button = new JButton("Selections"); + private final JLabel question_link_label = new JLabel("Question Link:"); + private final JLabel question_link_field = new JLabel("None"); + private final JLabel question_follows_label = new JLabel("Follows Question:"); + private final JComboBox question_answer_type_menu = new JComboBox(answerTypes); + private final JComboBox question_follows_menu = new JComboBox(); + private final JTextArea question_question_field = new NoTabTextArea(); + private final JTextArea question_citation_field = new NoTabTextArea(); + private final JTextField question_title_field = new JTextField(); + private final JButton question_new_button = new JButton("New"); + private final JButton question_link_button = new JButton("Set Link"); + private final JButton question_delete_button = new JButton("Delete"); + private final JLabel question_central_label = new JLabel(); + private final CategoryInputPane selectionsDialog; + private final QuestionLinkDialog questionLinkDialog; + private final Border listBorder; + + private final static String[] questionTypes = {Question.questionTypeString(1), Question.questionTypeString(2), + Question.questionTypeString(3), Question.questionTypeString(4)}; + private final static String[] answerTypes = {"Categorical", "Numerical", "Text"}; + + /** + * Generates Panel for question editing to insert in file tab window + * @param type Type of questions on Page (e.g. Alter Questions) + * @param parent parent frame for referencing composed objects + */ + public AuthoringQuestionPanel(int type) + { + questionType = type; + questionLinkDialog = new QuestionLinkDialog(); + selectionsDialog = new CategoryInputPane(question_list); + + listBorder = BorderFactory.createCompoundBorder( + new TitledBorder(new EtchedBorder(EtchedBorder.RAISED,Color.white,new Color(178, 178, 178)), + Question.questionTypeString(questionType)), + BorderFactory.createEmptyBorder(10,10,10,10)); + + try + { + jbInit(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + /** + * Component initialization + * @throws Exception + */ + private void jbInit() + throws Exception + { + inUpdate = true; + + // Configure Split Frame + question_split.setMinimumSize(new Dimension(430, 330)); + question_split.setPreferredSize(new Dimension(430, 330)); + question_split.setResizeWeight(.33); + question_split.setDividerLocation(.33); + question_list_scroll.setRequestFocusEnabled(false); + question_split.add(question_list_scroll, JSplitPane.LEFT); + question_split.add(question_panel_right, JSplitPane.RIGHT); + + this.setLayout(new GridLayout()); + + // Configure List + question_list_scroll.setBorder(listBorder); + question_list_scroll.setMinimumSize(new Dimension(150, 150)); + question_list_scroll.setPreferredSize(new Dimension(150, 150)); + question_list_scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + + question_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); +// question_list.setCellRenderer(new QuestionListCellRenderer()); + + // Configure question fields + question_panel_right.setLayout(new GridBagLayout()); + question_question_field.setMaximumSize(new Dimension(280, 64)); + question_question_field.setMinimumSize(new Dimension(72, 16)); + question_question_field.setPreferredSize(new Dimension(72, 16)); + question_question_field.setLineWrap(true); + question_question_field.setRows(1); + question_question_field.setTabSize(4); + question_question_field.setWrapStyleWord(true); + + question_citation_field.setMaximumSize(new Dimension(280, 64)); + question_citation_field.setMinimumSize(new Dimension(72, 16)); + question_citation_field.setPreferredSize(new Dimension(72, 16)); + question_citation_field.setLineWrap(true); + question_citation_field.setRows(1); + question_citation_field.setTabSize(4); + question_citation_field.setWrapStyleWord(true); + + /* Question Layout */ + question_panel_right.add(question_title_label, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_title_field, new GridBagConstraints(1, 0, 2, 1, 0.0, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 4)); + question_panel_right.add(question_question_label, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_question_field, new GridBagConstraints(1, 1, 2, 3, 0.0, 0.4 + ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_citation_label, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_citation_field, new GridBagConstraints(1, 4, 2, 3, 0.0, 0.3 + ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_type_label, new GridBagConstraints(0, 7, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_type_menu, new GridBagConstraints(1, 7, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_central_label, new GridBagConstraints(2, 7, 1, 1, 0.2, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_answer_type_label, new GridBagConstraints(0, 8, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_answer_type_menu, new GridBagConstraints(1, 8, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_answer_type_button, new GridBagConstraints(2, 8, 1, 1, 0.2, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_follows_label, new GridBagConstraints(0, 9, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_follows_menu, new GridBagConstraints(1, 9, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_link_label, new GridBagConstraints(0, 10, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_link_field, new GridBagConstraints(1, 10, 2, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_new_button, new GridBagConstraints(0, 11, 1, 1, 0.33, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_link_button, new GridBagConstraints(1, 11, 1, 1, 0.33, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_delete_button, new GridBagConstraints(2, 11, 1, 1, 0.33, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + + question_list.setModel(new DefaultListModel()); + EgoNet.study.fillList(questionType, (DefaultListModel) question_list.getModel()); + + question_list.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) { + question_list_selectionChanged(e); }}); + + question_new_button.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + question_new_button_actionPerformed(e);}}); + + question_delete_button.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + question_delete_button_actionPerformed(e);}}); + + question_link_button.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + question_link_button_actionPerformed(e);}}); + + question_follows_menu.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + question_follows_menu_actionPerformed(e);}}); + + question_type_menu.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + question_type_menu_actionPerformed(e);}}); + + question_answer_type_menu.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + question_answer_type_menu_actionPerformed(e);}}); + + question_answer_type_button.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + set_selections_button_actionPerformed(e);}}); + + question_title_field.getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { questionTitleEvent(); } + public void changedUpdate(DocumentEvent e) { questionTitleEvent(); } + public void removeUpdate(DocumentEvent e) { questionTitleEvent(); }}); + + question_question_field.getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { questionTextEvent(); } + public void changedUpdate(DocumentEvent e) { questionTextEvent(); } + public void removeUpdate(DocumentEvent e) { questionTextEvent(); }}); + + question_citation_field.getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { questionCitationEvent(); } + public void changedUpdate(DocumentEvent e) { questionCitationEvent(); } + public void removeUpdate(DocumentEvent e) { questionCitationEvent(); }}); + + this.add(question_split, null); + + inUpdate = false; + } + + /** + * Updates right side question fields when the selection changes + * @param e event generated by selection change. + */ + private void question_list_selectionChanged(ListSelectionEvent e) + { + if (!e.getValueIsAdjusting()) + { + if (!inUpdate) + { + questionUpdate(); + } + } + } + + /**** + * fill List with appropriate questions + * Set other fields to selected question + */ + public void fillPanel() + { + if (questionType == EgoNet.frame.curTab) + { + storageUpdate(); + questionUpdate(); + } + } + + /** + * Called when file changes to load new questions into list + */ + private void storageUpdate() + { + inUpdate = true; + + if (questionType == EgoNet.frame.curTab) + { + Object o = question_list.getSelectedValue(); + ((DefaultListModel) question_list.getModel()).removeAllElements(); + EgoNet.study.fillList(questionType, (DefaultListModel) question_list.getModel()); + question_list.setSelectedValue(o, true); + } + + inUpdate = false; + } + + private void questionUpdate() + { + Question q; + int index; + + inUpdate = true; + + if (questionType == EgoNet.frame.curTab) + { + /* If no element selected, assume first */ + index = question_list.getSelectedIndex(); + if ((index == -1) && (question_list.getModel().getSize() > 0)) + { + index = 0; + } + + /* Load questions from list into follows menu */ + question_follows_menu.removeAllItems(); + question_follows_menu.addItem(EgoNet.study.getFirstQuestion()); + for (int i = 0; i < question_list.getModel().getSize(); i++) + { + if (i != index) + { + question_follows_menu.addItem(question_list.getModel().getElementAt(i)); + } + } + + question_list.setSelectedIndex(index); + q = (Question) question_list.getSelectedValue(); + if (q != null) + { + question_type_menu.setSelectedIndex(questionType - 1); + question_answer_type_menu.setSelectedIndex(q.answerType); + question_question_field.setText(q.text); + question_citation_field.setText(q.citation); + question_title_field.setText(q.title); + question_follows_menu.setSelectedIndex(index); + + question_type_menu.setEnabled(true); + question_answer_type_menu.setEnabled(q.questionType != Question.ALTER_PROMPT); + + System.out.println("AnswerType : " + answerTypes[q.answerType]); + question_answer_type_button.setEnabled(q.answerType == Question.CATEGORICAL); + question_question_field.setEditable(true); + question_citation_field.setEditable(true); + question_title_field.setEditable(true); + question_delete_button.setEnabled(true); + question_link_button.setEnabled(true); + + /* Box only appears on alter pair page */ + question_central_label.setVisible(false); + if (q.answerType == Question.CATEGORICAL) + { + if (q.selections.length == 0) + { + question_central_label.setText("No Selections"); + question_central_label.setForeground(Color.red); + question_central_label.setVisible(true); + } + else if (questionType == Question.ALTER_PAIR_QUESTION) + { + question_central_label.setText("No Adjacency Selections"); + question_central_label.setForeground(Color.red); + + for (int i = 0; i < q.selections.length; i++) + { + if (q.selections[i].isAdjacent()) + { + question_central_label.setText("Adjacency Selections Set"); + question_central_label.setForeground(Color.black); + } + } + + question_central_label.setVisible(true); + } + } + + /* Fill in link field */ + if (q.link.active) + { + Question linkQuestion = EgoNet.study.getQuestions().getQuestion(q.link.answer.questionId); + + if (linkQuestion == null) + { + question_link_field.setText("< none >"); + } + else + { + if (linkQuestion.title.length() > 32) + { + question_link_field.setText(linkQuestion.title.substring(0, 32) + ": " + q.link.answer.string); + } + else + { + question_link_field.setText(linkQuestion.title + ": " + q.link.answer.string); + } + } + } + else + { + question_link_field.setText("< none >"); + } + } + else + { + question_answer_type_menu.setSelectedIndex(0); + question_question_field.setText(null); + question_citation_field.setText(null); + question_title_field.setText(null); + question_central_label.setVisible(false); + question_link_field.setText(""); + + question_type_menu.setEnabled(false); + question_answer_type_menu.setEnabled(false); + question_answer_type_button.setEnabled(false); + question_question_field.setEditable(false); + question_citation_field.setEditable(false); + question_title_field.setEditable(false); + question_delete_button.setEnabled(false); + question_link_button.setEnabled(false); + } + } + + inUpdate = false; + } + + + /**** + * Clear all on screen editable fields + * Generally called when a new survey is started + */ + public void clearPanel() + { + inUpdate = true; + ((DefaultListModel) question_list.getModel()).removeAllElements(); + inUpdate = false; + } + + /**** + * Document event handler used to read text fields + */ + private void questionTitleEvent() + { + Question q = (Question) question_list.getSelectedValue(); + String s; + + if ((q != null) && !inUpdate) + { + s = question_title_field.getText().trim(); + if ((q.title == null) || (!q.title.equals(s))) + { + q.title = question_title_field.getText().trim(); + EgoNet.study.setModified(true); + question_list.repaint(); + } + } + } + + + /**** + * Document event handler used to read text fields + */ + private void questionTextEvent() + { + Question q = (Question) question_list.getSelectedValue(); + String s; + + if ((q != null) && !inUpdate) + { + s = question_question_field.getText().trim(); + if ((q.text == null) || (!q.text.equals(s))) + { + q.text = question_question_field.getText().trim(); + EgoNet.study.setModified(true); + } + } + } + + + /**** + * Document event handler used to read text fields + */ + private void questionCitationEvent() + { + Question q = (Question) question_list.getSelectedValue(); + String s; + + if ((q != null) && !inUpdate) + { + s = question_citation_field.getText().trim(); + if ((q.citation == null) || (!q.citation.equals(s))) + { + q.citation = question_citation_field.getText().trim(); + EgoNet.study.setModified(true); + } + } + } + + + + /**** + * Event handler for new question button + * @param e Action Event + */ + private void question_new_button_actionPerformed(ActionEvent e) + { + if (EgoNet.study.confirmIncompatibleChange(EgoNet.frame)) + { + Question q = new Question(); + + q.questionType = questionType; + q.title = new String(Question.questionTypeString(questionType) + ":Untitled Question"); + + if (q.questionType == Question.ALTER_PROMPT) + { + q.answerType = Question.TEXT; + } + + try + { + EgoNet.study.addQuestion(q); + } + catch (DuplicateQuestionException e1) + { + e1.printStackTrace(); + } + + fillPanel(); + question_list.setSelectedValue(q, true); + + question_title_field.requestFocus(); + question_title_field.setSelectionStart(0); + question_title_field.setSelectionEnd(question_title_field.getText().length()); + + EgoNet.study.setModified(true); + EgoNet.study.setCompatible(false); + } + } + + + /**** + * Event handler for delete question button + * @param e Action Event + */ + private void question_delete_button_actionPerformed(ActionEvent e) + { + Question q = (Question) question_list.getSelectedValue(); + + if (q != null) + { + int confirm = JOptionPane.showConfirmDialog(EgoNet.frame, "Permanently remove this questions?", + "Delete Question", JOptionPane.OK_CANCEL_OPTION); + + if ((confirm == JOptionPane.OK_OPTION) && EgoNet.study.confirmIncompatibleChange(EgoNet.frame)) + { + EgoNet.study.removeQuestion(q); + EgoNet.study.setModified(true); + EgoNet.study.setCompatible(false); + fillPanel(); + } + } + } + + /** + * Opens Set Link Dialog + * @param e UI event + */ + void question_link_button_actionPerformed(ActionEvent e) + { + Question q = (Question) question_list.getSelectedValue(); + questionLinkDialog.pack(); + questionLinkDialog.activate(q); + } + + /** + * Change question type in question record, move to new ordering list + * @param e UI event + */ + void question_type_menu_actionPerformed(ActionEvent e) + { + if (!inUpdate) + { + if (EgoNet.study.confirmIncompatibleChange(EgoNet.frame)) + { + Question q = (Question) question_list.getSelectedValue(); + int type = question_type_menu.getSelectedIndex() + 1; + + EgoNet.study.changeQuestionType(q, type); + EgoNet.study.setCompatible(false); + fillPanel(); + } + else + { + questionUpdate(); + } + } + } + + /** + * Change answer type in pop up menu, save in question record + * @param e UI event + */ + void question_answer_type_menu_actionPerformed(ActionEvent e) + { + if (!inUpdate) + { + if (EgoNet.study.confirmIncompatibleChange(EgoNet.frame)) + { + int i = question_answer_type_menu.getSelectedIndex(); + Question q = (Question) question_list.getSelectedValue(); + + if (q != null) + { + if (q.answerType != i) + { + q.answerType = i; + EgoNet.study.setModified(true); + EgoNet.study.setCompatible(false); + questionUpdate(); + } + } + } + else + { + // Change back + questionUpdate(); + } + } + } + + /** + * Brings up category selection modal dialog box + * @param e UI event + */ + void set_selections_button_actionPerformed(ActionEvent e) + { + Point loc = getLocationOnScreen(); + + selectionsDialog.pack(); + selectionsDialog.setSize(300,300); + selectionsDialog.activate(); + } + + /** + * Changes order of questions + * @param e UI event + */ + void question_follows_menu_actionPerformed(ActionEvent e) + { + if (!inUpdate) + { + if (EgoNet.study.confirmIncompatibleChange(EgoNet.frame)) + { + Question follows = (Question) question_follows_menu.getSelectedItem(); + Question q = (Question) question_list.getSelectedValue(); + + EgoNet.study.moveQuestionAfter(q, follows); + EgoNet.study.setCompatible(false); + EgoNet.study.setModified(true); + fillPanel(); + } + else + { + questionUpdate(); + } + } + } + + void question_central_checkBox_actionPerformed(ActionEvent e) + { + Question q = (Question) question_list.getSelectedValue(); + EgoNet.study.setCentralQuestion(q); + } +} + + +/** + * Implements ListCellRenderer to differentiate between base and custom questions + */ +class QuestionListCellRenderer + implements ListCellRenderer +{ + protected final DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer(); + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) + { + JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + return renderer; + } +} + + +/** + * $Log: QuestionPanel.java,v $ + * Revision 1.1 2005/08/02 19:36:05 samag + * Initial checkin + * + * Revision 1.12 2004/04/11 00:24:48 admin + * Fixing headers + * + * Revision 1.11 2004/04/11 00:17:13 admin + * Improving display of Alter Prompt questions from Applet UI Interviews + * + * Revision 1.10 2004/04/07 00:08:31 admin + * updating manifests, jar creation. Removing author specific objects from + * client specific references + * + * Revision 1.9 2004/03/28 17:31:31 admin + * More error handling when uploading study to server + * Server URL selection dialog for upload + * + * Revision 1.8 2004/03/21 20:29:37 admin + * Warn before making incompatible changes to in use study file + * + * Revision 1.7 2004/03/21 14:00:38 admin + * Cleaned up Question Panel Layout using FOAM + * + * Revision 1.6 2004/02/10 20:10:43 admin + * Version 2.0 beta 3 + * + * Revision 1.5 2003/12/08 15:57:50 admin + * Modified to generate matrix files on survey completion or summarization + * Extracted statistics models + * + * Revision 1.4 2003/12/05 19:15:43 admin + * Extracting Study + * + * Revision 1.3 2003/12/04 15:14:08 admin + * Merging EgoNet and EgoClient projects so that they can share some + * common classes more easily. + * + * Revision 1.2 2003/11/25 19:25:44 admin + * Warn before closing window + * + * Revision 1.1.1.1 2003/06/08 15:09:40 admin + * Egocentric Network Survey Authoring Module + * + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/author/CategoryInputPane.java b/src/com/endlessloopsoftware/ego/author/CategoryInputPane.java new file mode 100644 index 0000000..54903ea --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/CategoryInputPane.java @@ -0,0 +1,251 @@ +package com.endlessloopsoftware.ego.author; + +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; + +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JList; + +import com.endlessloopsoftware.ego.Question; +import org.egonet.util.listbuilder.ListBuilder; +import org.egonet.util.listbuilder.Selection; + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: CategoryInputPane.java,v 1.1 2005/08/02 19:36:04 samag Exp $ + * + */ + +/** + * Dialog box for collecting categorical answer selections + */ +public class CategoryInputPane extends JDialog { + private final JList parentList; + + private final GridBagLayout gridBagLayout1 = new GridBagLayout(); + + // create list builder with preset values turned on. + private final ListBuilder listBuilder = new ListBuilder(); + + private final JButton jOKButton = new JButton("OK"); + + private final JButton jCancelButton = new JButton("Cancel"); + + private Box box1; + + /** + * Constructor for CategoryInputPane + * + * @param list + * question list from parent frame used to determine which + * question we are operating on + */ + public CategoryInputPane(JList list) { + parentList = list; + + try { + jbInit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Initializes layout and fields for the dialog + * + * @throws Exception + * No idea, sorry + */ + private void jbInit() throws Exception { + box1 = Box.createHorizontalBox(); + this.getContentPane().setLayout(gridBagLayout1); + + this.setModal(true); + this.setTitle("Category Options"); + this.setSize(400, 300); + + // Center the window + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension frameSize = this.getSize(); + if (frameSize.height > screenSize.height) { + frameSize.height = screenSize.height; + } + if (frameSize.width > screenSize.width) { + frameSize.width = screenSize.width; + } + this.setLocation((screenSize.width - frameSize.width) / 2, + (screenSize.height - frameSize.height) / 2); + + this.getContentPane().add( + listBuilder, + new GridBagConstraints(0, 0, 4, 1, 1.0, 0.9, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); + this.getContentPane().add( + jCancelButton, + new GridBagConstraints(3, 1, 1, 1, 0.2, 0.0, + GridBagConstraints.EAST, GridBagConstraints.NONE, + new Insets(10, 0, 10, 10), 0, 0)); + this.getContentPane().add( + jOKButton, + new GridBagConstraints(2, 1, 1, 1, 0.2, 0.0, + GridBagConstraints.EAST, GridBagConstraints.NONE, + new Insets(10, 20, 10, 0), 26, 0)); + this.getContentPane().add( + box1, + new GridBagConstraints(0, 1, 1, 1, 0.5, 0.0, + GridBagConstraints.CENTER, + GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), + 40, 0)); + + jOKButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + OKButton_actionPerformed(e); + } + }); + + jCancelButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + cancelButton_actionPerformed(e); + } + }); + + } + + void OKButton_actionPerformed(ActionEvent e) { + boolean changed = false; + boolean compatible = true; + // boolean abort = false; + + Question q = (Question) parentList.getSelectedValue(); + if (q != null) { + /* count choices */ + + Selection[] newSelections = listBuilder.getListSelections(); + + // code added 09/05/2007 sonam + // ask for values for each question + + /* + * for (int i = 0; i < newSelections.length; i++) { String + * inputValue = null; String extraInformation = ""; int + * intInputValue = -1; + * + * do { inputValue = JOptionPane.showInputDialog(this, + * extraInformation + " Please input a value for " + + * newSelections[i].getString() + ": ", new + * Integer(newSelections[i].getValue()) ); if (inputValue == null) { // + * if user actually selected cancel + * JOptionPane.showMessageDialog(this, "Your question weight will + * default to " + Integer.toString(i) + "!"); inputValue = + * Integer.toString(i); } try { intInputValue = + * Integer.parseInt(inputValue); } catch (NumberFormatException ex) { + * inputValue = null; extraInformation = "Sorry! That was not a + * valid value for :\"" + newSelections[i].getString() + "\""; + * continue; } } while (inputValue == null); + * newSelections[i].setValue(intInputValue); } + */ + + if (newSelections.length != q.selections.length) { + if (EgoNet.study.confirmIncompatibleChange(EgoNet.frame)) { + compatible = false; + changed = true; + + // If the number changed we know the list has changed, so + // just copy over + // the reference and let the loop trim the strings + q.selections = newSelections; + } else { + // Don't make this change + EgoNet.frame.fillCurrentPanel(); + this.hide(); + return; + } + } + + // Trim the strings, check for changes + for (int i = 0; i < q.selections.length; i++) { + if (!q.selections[i] + .equals(newSelections[i].getString().trim())) { + q.selections[i].setString(newSelections[i].getString() + .trim()); + changed = true; + } + // q.selections[i].value= newSelections[i].value; + } + + /* + * original code by Peter: // change all the values at once for (int + * i = 0; i < newWeights.length; i++) newSelections[i].value = + * newWeights[i]; + */ + // End of code change + EgoNet.study.setModified(changed); + EgoNet.study.setCompatible(compatible); + + EgoNet.frame.fillCurrentPanel(); + this.hide(); + } + + } + + void cancelButton_actionPerformed(ActionEvent e) { + this.hide(); + } + + void activate() { + Question q = (Question) parentList.getSelectedValue(); + + if (q != null) { + listBuilder.setListSelections(q.selections); + } else { + System.err.println("Parent list had no selections"); + } + + listBuilder.setEditable(true); + + listBuilder.setElementName("Option: "); + listBuilder.setTitle("Category Options"); + listBuilder + .setDescription("Enter possible answers to this question below. Press Return to add the option " + + "to the options list. Press OK to set options or Cancel to undo changes."); + listBuilder.setNameList(q.questionType == Question.ALTER_PROMPT); + listBuilder.setLetUserPickValues(true); + listBuilder + .setPresetListsActive(q.answerType == Question.CATEGORICAL); + +// boolean preset = (q.answerType == Question.CATEGORICAL) ? true : false; +// System.out.println("Is question categorical? " + preset); +// + listBuilder + .setAdjacencyActive(q.questionType == Question.ALTER_PAIR_QUESTION); + + this.setSize(450, 400); + jOKButton.setVisible(true); + jCancelButton.setText("Cancel"); + + /* Pack since we've modified the GUI elements */ + this.pack(); + this.setVisible(true); + } +} + +/** + * $Log: CategoryInputPane.java,v $ Revision 1.1 2005/08/02 19:36:04 samag + * Initial checkin + * + * Revision 1.11 2004/04/11 00:24:48 admin Fixing headers + * + */ diff --git a/src/com/endlessloopsoftware/ego/author/EgoFrame.java b/src/com/endlessloopsoftware/ego/author/EgoFrame.java new file mode 100644 index 0000000..21511c0 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/EgoFrame.java @@ -0,0 +1,570 @@ +package com.endlessloopsoftware.ego.author; + +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Observable; +import java.util.Observer; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.text.DefaultEditorKit; + +import com.endlessloopsoftware.ego.Question; +import com.endlessloopsoftware.ego.Shared; +import com.endlessloopsoftware.ego.Study; +import com.endlessloopsoftware.elsutils.AboutBox; + +/** + *+ * Title: Egocentric Network Researcher + *
+ *+ * Description: Configuration Utilities for an Egocentric network study + *
+ *+ * Copyright: Copyright (c) 2002 + *
+ *+ * Company: Endless Loop Software + *
+ * + * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: EgoFrame.java,v 1.1 2005/08/02 19:36:04 samag Exp $ + */ + +public class EgoFrame extends JFrame implements Observer { + int lastTab = 0; + int curTab = 0; + + private JPanel contentPane; + private boolean waitCursor = false; + + private final JMenuBar jEgonetMenuBar = new JMenuBar(); + private final JMenu jMenuFile = new JMenu("File"); + private final JMenuItem jMenuFileNew = new JMenuItem("New Study"); + private final JMenuItem jMenuFileOpen = new JMenuItem("Open Study"); + private final JMenuItem jMenuFileClose = new JMenuItem("Close Study"); + private final JMenuItem jMenuFileImport = new JMenuItem( + "Import Questions..."); + private final JMenuItem jMenuFileExport = new JMenuItem( + "Export Questions..."); + private final JMenuItem jMenuFileSaveAs = new JMenuItem("Save Study As..."); + private final JMenuItem jMenuFileSave = new JMenuItem("Save Study"); + private final JMenuItem jMenuFileUpload = new JMenuItem("Upload Study"); + private final JMenuItem jMenuFileSelectStudy = new JMenuItem( + "Select Active Study"); + private final JMenuItem jMenuFileExit = new JMenuItem("Quit"); + private final JMenu jMenuEdit = new JMenu("Edit"); + private final JMenuItem jMenuEditCut = new JMenuItem( + new DefaultEditorKit.CutAction()); + private final JMenuItem jMenuEditCopy = new JMenuItem( + new DefaultEditorKit.CopyAction()); + private final JMenuItem jMenuEditPaste = new JMenuItem( + new DefaultEditorKit.PasteAction()); + private final JMenu jMenuHelp = new JMenu("Help"); + private final JMenuItem jMenuHelpAbout = new JMenuItem("About"); + + private final JTabbedPane jTabbedPane = new JTabbedPane(); + private final BorderLayout borderLayout1 = new BorderLayout(); + + private final StudyPanel study_panel = new StudyPanel(this); + + private final EgoQPanel[] questionPanel = { + null, + (EgoQPanel) new AuthoringQuestionPanel(Question.EGO_QUESTION), + (EgoQPanel) new PromptPanel(Question.ALTER_PROMPT), + (EgoQPanel) new AuthoringQuestionPanel(Question.ALTER_QUESTION), + (EgoQPanel) new AuthoringQuestionPanel(Question.ALTER_PAIR_QUESTION), }; + + // Construct the frame + public EgoFrame() { + enableEvents(AWTEvent.WINDOW_EVENT_MASK); + try { + jbInit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Component initialization + private void jbInit() throws Exception { + // Listen for window closing + this.addWindowListener(new CloseListener()); + this.setDefaultCloseOperation(EXIT_ON_CLOSE); + + contentPane = (JPanel) this.getContentPane(); + contentPane.setLayout(borderLayout1); + this.setSize(new Dimension(815, 600)); + //this.setExtendedState(this.getExtendedState() | JFrame.MAXIMIZED_BOTH); + this.setTitle("Egocentric Network Study"); + + jMenuFileExit.setAccelerator(javax.swing.KeyStroke.getKeyStroke( + KeyEvent.VK_Q, Toolkit.getDefaultToolkit() + .getMenuShortcutKeyMask())); + jMenuFileNew.setAccelerator(javax.swing.KeyStroke.getKeyStroke( + KeyEvent.VK_N, Toolkit.getDefaultToolkit() + .getMenuShortcutKeyMask())); + jMenuFileOpen.setAccelerator(javax.swing.KeyStroke.getKeyStroke( + KeyEvent.VK_O, Toolkit.getDefaultToolkit() + .getMenuShortcutKeyMask())); + jMenuFileClose.setAccelerator(javax.swing.KeyStroke.getKeyStroke( + KeyEvent.VK_W, Toolkit.getDefaultToolkit() + .getMenuShortcutKeyMask())); + jMenuEditCopy.setAccelerator(javax.swing.KeyStroke.getKeyStroke( + KeyEvent.VK_C, Toolkit.getDefaultToolkit() + .getMenuShortcutKeyMask())); + jMenuEditCut.setAccelerator(javax.swing.KeyStroke.getKeyStroke( + KeyEvent.VK_X, Toolkit.getDefaultToolkit() + .getMenuShortcutKeyMask())); + jMenuEditPaste.setAccelerator(javax.swing.KeyStroke.getKeyStroke( + KeyEvent.VK_V, Toolkit.getDefaultToolkit() + .getMenuShortcutKeyMask())); + + jMenuEditCopy.setText("Copy"); + jMenuEditCut.setText("Cut"); + jMenuEditPaste.setText("Paste"); + + jMenuFile.add(jMenuFileNew); + jMenuFile.add(jMenuFileOpen); + jMenuFile.add(jMenuFileClose); + jMenuFile.addSeparator(); + jMenuFile.add(jMenuFileImport); + jMenuFile.add(jMenuFileExport); + jMenuFile.addSeparator(); + jMenuFile.add(jMenuFileSave); + jMenuFile.add(jMenuFileSaveAs); + jMenuFile.addSeparator(); + jMenuFile.add(jMenuFileUpload); + jMenuFile.add(jMenuFileSelectStudy); + jMenuFile.addSeparator(); + jMenuFile.add(jMenuFileExit); + + jMenuEdit.add(jMenuEditCut); + jMenuEdit.add(jMenuEditCopy); + jMenuEdit.add(jMenuEditPaste); + jMenuHelp.add(jMenuHelpAbout); + jEgonetMenuBar.add(jMenuFile); + jEgonetMenuBar.add(jMenuEdit); + jEgonetMenuBar.add(jMenuHelp); + this.setJMenuBar(jEgonetMenuBar); + + jTabbedPane.setTabPlacement(JTabbedPane.TOP); + jTabbedPane.add(study_panel, "Study"); + + for (int i = Question.MIN_QUESTION_TYPE; i <= Question.MAX_QUESTION_TYPE; i++) { + jTabbedPane.add(questionPanel[i], Question.questionTypeString(i)); + } + contentPane.add(jTabbedPane); + + /*********************************************************************** + * Action Listeners for Menu Events + */ + jMenuFileNew.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileNew_actionPerformed(e); + } + }); + + jMenuFileOpen.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileOpen_actionPerformed(e); + } + }); + + jMenuFileClose.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileClose_actionPerformed(e); + } + }); + + jMenuFileSave.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileSave_actionPerformed(e); + } + }); + + jMenuFileSaveAs.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileSaveAs_actionPerformed(e); + } + }); + + jMenuFileUpload.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileUpload_actionPerformed(e); + } + }); + + jMenuFileSelectStudy.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileSelectStudy_actionPerformed(e); + } + }); + + jMenuFileImport.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileImport_actionPerformed(e); + } + }); + + jMenuFileExport.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileExport_actionPerformed(e); + } + }); + + jMenuFileExit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileExit_actionPerformed(e); + } + }); + + jMenuHelpAbout.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuHelpAbout_actionPerformed(e); + } + }); + + /*********************************************************************** + * Change Listener for tabs + */ + jTabbedPane.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + jTabbedPane_stateChanged(e); + } + }); + + /* Fill panel, initialize frame */ + EgoNet.study = new Study(); + fillCurrentPanel(); + EgoNet.study.setModified(false); + updateMenus(); + } + + /*************************************************************************** + * Updates menus to take dirty question and study into account + */ + public void updateMenus() { + if (EgoNet.storage.getStudyFile() == null) { + jMenuFileImport.setEnabled(false); + jMenuFileClose.setEnabled(false); + jMenuFileSave.setEnabled(false); + jMenuFileSaveAs.setEnabled(false); + jMenuFileUpload.setEnabled(false); + jMenuFileSelectStudy.setEnabled(true); + jMenuFileExport.setEnabled(false); + jTabbedPane.setEnabledAt(1, false); + jTabbedPane.setEnabledAt(2, false); + jTabbedPane.setEnabledAt(3, false); + jTabbedPane.setEnabledAt(4, false); + jTabbedPane.setSelectedIndex(0); + } else { + jMenuFileImport.setEnabled(true); + jMenuFileClose.setEnabled(true); + jMenuFileSave.setEnabled(EgoNet.study.isCompatible() + && EgoNet.study.isModified()); + jMenuFileSaveAs.setEnabled(true); + jMenuFileUpload.setEnabled(true); + jMenuFileSelectStudy.setEnabled(true); + jMenuFileExport.setEnabled(true); + jTabbedPane.setEnabledAt(1, true); + jTabbedPane.setEnabledAt(2, true); + jTabbedPane.setEnabledAt(3, true); + jTabbedPane.setEnabledAt(4, true); + } + } + + /** + * New Study menu handler + * + * @param e + * Menu UI Event + */ + private void jMenuFileNew_actionPerformed(ActionEvent e) { + boolean ok = closeStudyFile(); + + if (ok) { + EgoNet.storage.newStudyFiles(); + fillCurrentPanel(); + EgoNet.study.setModified(false); + EgoNet.study.setCompatible(true); + EgoNet.study.addObserver(this); + updateMenus(); + } + } + + /*************************************************************************** + * Open Study menu handler + * + * @param e + * Menu UI Event + */ + private void jMenuFileOpen_actionPerformed(ActionEvent e) { + boolean ok = closeStudyFile(); + + if (ok) { + EgoNet.storage.selectStudy(); + fillCurrentPanel(); + EgoNet.study.setModified(false); + EgoNet.study.setCompatible(true); + EgoNet.study.addObserver(this); + updateMenus(); + } + } + + private void jMenuFileClose_actionPerformed(ActionEvent e) { + boolean ok = closeStudyFile(); + + if (ok) { + EgoNet.storage.setStudyFile(null); + EgoNet.study = new Study(); + fillCurrentPanel(); + EgoNet.study.addObserver(this); + EgoNet.study.setModified(false); + } + } + + private void jMenuFileImport_actionPerformed(ActionEvent e) { + EgoNet.storage.importQuestions(); + fillCurrentPanel(); + } + + private void jMenuFileExport_actionPerformed(ActionEvent e) { + EgoNet.storage.exportQuestions(); + } + + private void jMenuFileUpload_actionPerformed(ActionEvent e) { + JDialog storeDialog = new StoreStudyDialog(this); + storeDialog.pack(); + /* + * this.show(); Code above deprecated. Code change done Changed by sonam + * on 08/20/2007 + */ + storeDialog.setVisible(true); + } + + private void jMenuFileSelectStudy_actionPerformed(ActionEvent e) { + JDialog storeDialog = new SetActiveStudyDialog(this); + storeDialog.pack(); + /* + * this.show(); Code above deprecated. Code change done Changed by sonam + * on 08/20/2007 + */ + storeDialog.setVisible(true); + } + + private void jMenuFileSave_actionPerformed(ActionEvent e) { + if (EgoNet.storage.getStudyFile() == null) { + jMenuFileSaveAs_actionPerformed(e); + } else { + EgoNet.storage.saveStudyFile(); + EgoNet.study.setModified(false); + } + } + + private void jMenuFileSaveAs_actionPerformed(ActionEvent e) { + EgoNet.storage.saveAsStudyFile(); + fillStudyPanel(); + EgoNet.study.addObserver(this); + EgoNet.study.setModified(false); + EgoNet.study.setCompatible(true); + } + + // File | Exit action performed + private void jMenuFileExit_actionPerformed(ActionEvent e) { + boolean exit = closeStudyFile(); + + if (exit) { + System.exit(0); + } + } + + // Help | About action performed + public void jMenuHelpAbout_actionPerformed(ActionEvent e) { + + JOptionPane.showMessageDialog(this, + "Egonet is an egocentric network study tool." + + "\n\nThanks to: Dr. Chris McCarty, University of Florida", + "About Egonet", JOptionPane.PLAIN_MESSAGE); + + } + + /** + * Closes question file. If changes made gives user the option of saving. + * + * @return False iff user cancels save, True otherwise + */ + public boolean closeStudyFile() { + boolean exit = true; + + if (EgoNet.study.isModified()) { + int confirm = JOptionPane + .showConfirmDialog( + this, + "There are unsaved changes to the study. Would you like to save the study now?", + "Save Study Changes", + JOptionPane.YES_NO_CANCEL_OPTION); + + if (confirm == JOptionPane.YES_OPTION) { + jMenuFileSave_actionPerformed(null); + } else if (confirm == JOptionPane.CANCEL_OPTION) { + exit = false; + } + } + + return exit; + } + + public void fillCurrentPanel() { + boolean sd = EgoNet.study.isModified(); + boolean sc = EgoNet.study.isCompatible(); + + if (curTab == Question.STUDY_CONFIG) { + study_panel.fillPanel(); + } else if ((curTab >= Question.MIN_QUESTION_TYPE) + && (curTab <= Question.MAX_QUESTION_TYPE)) { + questionPanel[curTab].fillPanel(); + } + + EgoNet.study.setModified(sd); + EgoNet.study.setCompatible(sc); + } + + public void fillStudyPanel() { + boolean sd = EgoNet.study.isModified(); + + if (curTab == Question.STUDY_CONFIG) { + study_panel.fillPanel(); + } + + EgoNet.study.setModified(sd); + } + + private void jTabbedPane_stateChanged(ChangeEvent e) { + lastTab = curTab; + curTab = jTabbedPane.getSelectedIndex(); + + if ((lastTab == Question.STUDY_CONFIG) && (curTab != lastTab)) { + EgoNet.study.validateQuestions(); + } + + if ((curTab >= Question.MIN_QUESTION_TYPE) + && (curTab <= Question.MAX_QUESTION_TYPE)) { + questionPanel[curTab].fillPanel(); + } else if (curTab == Question.STUDY_CONFIG) { + study_panel.fillPanel(); + } + } + + protected void setWaitCursor(boolean waitCursor) { + this.waitCursor = waitCursor; + + if (waitCursor) { + this.getGlassPane().setVisible(true); + this.getGlassPane().setCursor( + Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + } else { + this.getGlassPane().setCursor( + Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + this.getGlassPane().setVisible(false); + } + } + + class CloseListener extends WindowAdapter { + /* + * (non-Javadoc) + * + * @see java.awt.event.WindowListener#windowClosed(java.awt.event.WindowEvent) + */ + public void windowClosing(WindowEvent arg0) { + jMenuFileExit_actionPerformed(null); + } + } + + /* + * (non-Javadoc) + * + * @see java.util.Observer#update(java.util.Observable, java.lang.Object) + */ + public void update(Observable o, Object arg) { + updateMenus(); + } +} + +/******************************************************************************* + * $Id: EgoFrame.java,v 1.1 2005/08/02 19:36:04 samag Exp $ + * + * $Log: EgoFrame.java,v $ Revision 1.1 2005/08/02 19:36:04 samag Initial + * checkin + * + * Revision 1.12 2004/04/11 00:24:48 admin Fixing headers + * + * Revision 1.11 2004/04/08 15:06:06 admin EgoClient now creates study summaries + * from Server EgoAuthor now sets active study on server + * + * Revision 1.10 2004/03/28 17:31:31 admin More error handling when uploading + * study to server Server URL selection dialog for upload + * + * Revision 1.9 2004/03/23 14:58:48 admin Update UI Study creation now occurs in + * instantiators + * + * Revision 1.8 2004/03/21 14:00:38 admin Cleaned up Question Panel Layout using + * FOAM + * + * Revision 1.7 2004/03/10 14:32:39 admin Adding client library cleaning up code + * + * Revision 1.6 2004/02/10 20:10:42 admin Version 2.0 beta 3 + * + * Revision 1.5 2004/01/23 13:36:07 admin Updating Libraries Allowing upload to + * web server + * + * Revision 1.4 2003/12/05 19:15:43 admin Extracting Study + * + * Revision 1.3 2003/12/04 15:14:08 admin Merging EgoNet and EgoClient projects + * so that they can share some common classes more easily. + * + * Revision 1.2 2003/11/25 19:25:43 admin Warn before closing window + * + * Revision 1.1.1.1 2003/06/08 15:09:40 admin Egocentric Network Survey + * Authoring Module + * + * Revision 1.13 2002/08/30 16:50:27 admin Using Selections + * + * Revision 1.12 2002/08/11 22:26:05 admin Final Statistics window, new file + * handling + * + * Revision 1.11 2002/08/08 17:07:24 admin Preparing to change file system + * + * Revision 1.10 2002/07/24 14:17:08 admin xml files, links + * + * Revision 1.9 2002/07/18 14:43:05 admin New Alter Prompt Panel, packages + * + * Revision 1.8 2002/06/26 15:43:42 admin More selection dialog work File + * loading fixes + * + * Revision 1.7 2002/06/25 15:41:01 admin Lots of UI work + * + * Revision 1.6 2002/06/21 22:47:12 admin question lists working again + * + * Revision 1.5 2002/06/21 21:52:50 admin Many changes to event handling, file + * handling + * + * Revision 1.4 2002/06/19 01:57:04 admin Much UI work done + * + * Revision 1.3 2002/06/16 17:53:10 admin Working with files + * + * Revision 1.2 2002/06/15 14:19:50 admin Initial Checkin of question and survey + * General file system work + * + */ diff --git a/src/com/endlessloopsoftware/ego/author/EgoNet.java b/src/com/endlessloopsoftware/ego/author/EgoNet.java new file mode 100644 index 0000000..220c4bf --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/EgoNet.java @@ -0,0 +1,96 @@ +package com.endlessloopsoftware.ego.author; + +import java.awt.Dimension; +import java.awt.Toolkit; + +import com.endlessloopsoftware.ego.Shared; +import com.endlessloopsoftware.ego.Study; + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: EgoNet.java,v 1.1 2005/08/02 19:36:04 samag Exp $ + */ + + +public class EgoNet +{ + public static final EgoStore storage = new EgoStore(); + public static Study study = new Study(); + public static final EgoFrame frame = new EgoFrame(); + + //Construct the application + public EgoNet() + { + frame.validate(); + + //Center the window + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension frameSize = frame.getSize(); + if (frameSize.height > screenSize.height) + { + frameSize.height = screenSize.height; + } + if (frameSize.width > screenSize.width) + { + frameSize.width = screenSize.width; + } + frame.setLocation( + (screenSize.width - frameSize.width) / 2, + (screenSize.height - frameSize.height) / 2); + frame.setVisible(true); + } + + //Main method + public static void main(String[] args) + { + Shared.configureUI(); + new EgoNet(); + } +} + +/** + * $Log: EgoNet.java,v $ + * Revision 1.1 2005/08/02 19:36:04 samag + * Initial checkin + * + * Revision 1.6 2004/04/11 00:24:48 admin + * Fixing headers + * + * Revision 1.5 2004/03/23 14:58:48 admin + * Update UI + * Study creation now occurs in instantiators + * + * Revision 1.4 2003/12/05 19:15:43 admin + * Extracting Study + * + * Revision 1.3 2003/12/04 15:14:08 admin + * Merging EgoNet and EgoClient projects so that they can share some + * common classes more easily. + * + * Revision 1.2 2003/11/25 19:25:44 admin + * Warn before closing window + * + * Revision 1.1.1.1 2003/06/08 15:09:40 admin + * Egocentric Network Survey Authoring Module + * + * Revision 1.5 2002/06/30 15:59:18 admin + * Moving questions in lists, between lists + * Better category input + * + * Revision 1.4 2002/06/26 00:10:48 admin + * UI Work including base question coloring and category selections + * + * Revision 1.3 2002/06/25 15:41:01 admin + * Lots of UI work + * + * Revision 1.2 2002/06/15 14:19:50 admin + * Initial Checkin of question and survey + * General file system work + * + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/author/EgoQPanel.java b/src/com/endlessloopsoftware/ego/author/EgoQPanel.java new file mode 100644 index 0000000..b4ec34c --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/EgoQPanel.java @@ -0,0 +1,17 @@ +package com.endlessloopsoftware.ego.author; + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + */ +import javax.swing.JPanel; + +public abstract class EgoQPanel extends JPanel +{ + abstract public void fillPanel(); + abstract public void clearPanel(); +} \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/author/EgoStore.java b/src/com/endlessloopsoftware/ego/author/EgoStore.java new file mode 100644 index 0000000..2c21ebe --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/EgoStore.java @@ -0,0 +1,764 @@ +package com.endlessloopsoftware.ego.author; + + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: EgoStore.java,v 1.1 2005/08/02 19:36:04 samag Exp $ + * + * + */ + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.prefs.Preferences; + +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.filechooser.FileFilter; + +import com.endlessloopsoftware.ego.Question; +import com.endlessloopsoftware.ego.Shared; +import com.endlessloopsoftware.ego.Study; +import com.endlessloopsoftware.elsutils.DateUtils; +import com.endlessloopsoftware.elsutils.files.DirList; +import com.endlessloopsoftware.elsutils.files.ExtensionFileFilter; +import com.endlessloopsoftware.elsutils.files.FileCreateException; +import com.endlessloopsoftware.elsutils.files.FileReadException; +import com.endlessloopsoftware.elsutils.files.FileWriteException; + +import electric.xml.Document; +import electric.xml.Element; +import electric.xml.Elements; + +/**** + * Handles IO for the EgoNet program + * Tracks data files and changes to those files + */ +public class EgoStore +{ + private File studyFile = null; + private boolean studyFileInUse = false; + + private static final String[] questionExtensions = { "qst", "qtp"}; + private static FileFilter readQuestionFilter = (FileFilter) new ExtensionFileFilter("Question Files", questionExtensions[0]); + private static FileFilter writeQuestionFilter = (FileFilter) new ExtensionFileFilter("Question Templates", questionExtensions); + private static FileFilter studyFilter = new ExtensionFileFilter("Study Files", "ego"); + + private static final String FILE_PREF = "FILE_PREF"; + + /** + * Sets parent frame + * + * @param frame + * parent + */ + public EgoStore() + { + } + + /************************************************************************************************************************************************************ + * Returns study file + * + * @return studyFile file containing study overview information + */ + public File getStudyFile() + { + return (studyFile); + } + + /************************************************************************************************************************************************************ + * Returns study file + * + * @return studyFile file containing study overview information + */ + public boolean getStudyInUse() + { + return (studyFileInUse); + } + + /************************************************************************************************************************************************************ + * Sets baseQuestionFile variable and notifies observers of change to study + * + * @param f + * question file + */ + public void setStudyFile(File f) + { + studyFile = f; + } + + /************************************************************************************************************************************************************ + * Select a directory in which to store project related files Create subdirectories if needed. + */ + public void newStudyFiles() + { + Preferences prefs = Preferences.userNodeForPackage(EgoNet.class); + JFileChooser jNewStudyChooser = new JFileChooser(); + File dirFile, newStudyFile; + String projectPath = null; + String projectName = null; + + jNewStudyChooser.addChoosableFileFilter(studyFilter); + jNewStudyChooser.setDialogTitle("Select Study Path"); + + if (getStudyFile() != null) + { + jNewStudyChooser.setCurrentDirectory(getStudyFile().getParentFile()); + } + else + { + File directory = new File(prefs.get(FILE_PREF, ".")); + jNewStudyChooser.setCurrentDirectory(directory); + } + + try + { + if (JFileChooser.APPROVE_OPTION == jNewStudyChooser.showSaveDialog(EgoNet.frame)) + { + projectPath = jNewStudyChooser.getSelectedFile().getParent(); + projectName = jNewStudyChooser.getSelectedFile().getName(); + + if (projectName.indexOf(".") != -1) + { + projectName = projectName.substring(0, projectName.indexOf(".")); + } + + try + { + String folder = projectPath.substring(projectPath.lastIndexOf(File.separator) + 1); + if (!folder.equals(projectName)) + { + dirFile = new File(projectPath, projectName); + dirFile.mkdir(); + projectPath = dirFile.getPath(); + } + } + catch (SecurityException e) + { + JOptionPane.showMessageDialog( + EgoNet.frame, + "Unable to create study directories.", + "New Study Error", + JOptionPane.ERROR_MESSAGE); + throw new FileCreateException(false); + } + + try + { + newStudyFile = new File(projectPath, projectName); + newStudyFile = ((ExtensionFileFilter) studyFilter).getCorrectFileName(newStudyFile); + if (!newStudyFile.createNewFile()) + { + int confirm = + JOptionPane.showConfirmDialog( + EgoNet.frame, + "Shall I overwrite it?
", + "Overwrite Study File", + JOptionPane.OK_CANCEL_OPTION); + + if (confirm != JOptionPane.OK_OPTION) + { + throw new FileCreateException(true); + } + } + + /* Clean out study variables */ + EgoNet.study = new Study(); + setStudyFile(newStudyFile); + EgoNet.study.setStudyName(projectName); + + /* Write out default info */ + writeStudy(newStudyFile, new Long(System.currentTimeMillis())); + studyFileInUse = false; + + // Store location in prefs file + prefs.put(FILE_PREF, newStudyFile.getParent()); + } + catch (java.io.IOException e) + { + JOptionPane.showMessageDialog( + EgoNet.frame, + "Unable to create study file.", + "File Error", + JOptionPane.ERROR_MESSAGE); + throw new FileCreateException(false); + } + + try + { + dirFile = new File(projectPath, "Statistics"); + dirFile.mkdir(); + + dirFile = new File(projectPath, "Interviews"); + dirFile.mkdir(); + } + catch (SecurityException e) + { + JOptionPane.showMessageDialog( + EgoNet.frame, + "Unable to create study directories.", + "New Study Error", + JOptionPane.ERROR_MESSAGE); + throw new FileCreateException(false); + } + } + } + catch (FileCreateException e) + { + if (e.report) + { + JOptionPane.showMessageDialog(EgoNet.frame, "Study not created."); + } + + setStudyFile(null); + } + } + + /************************************************************************************************************************************************************ + * Select a directory in which to store project related files Create subdirectories if needed. + */ + public void selectStudy() + { + Preferences prefs = Preferences.userNodeForPackage(EgoNet.class); + JFileChooser jNewStudyChooser = new JFileChooser(); + File f; + + jNewStudyChooser.addChoosableFileFilter(studyFilter); + jNewStudyChooser.setDialogTitle("Select Study"); + + if (getStudyFile() != null) + { + jNewStudyChooser.setCurrentDirectory(getStudyFile().getParentFile()); + } + else + { + jNewStudyChooser.setCurrentDirectory(new File(prefs.get(FILE_PREF, "."))); + } + + if (JFileChooser.APPROVE_OPTION == jNewStudyChooser.showOpenDialog(EgoNet.frame)) + { + f = jNewStudyChooser.getSelectedFile(); + + try + { + if (!f.canRead()) + { + throw new FileReadException(); + } + else + { + readStudy(f); + setStudyFile(f); + + // Store location in prefs file + prefs.put(FILE_PREF, f.getParent()); + } + } + catch (Exception e) + { + e.printStackTrace(); + + setStudyFile(null); + JOptionPane.showMessageDialog(null, "Unable to read study file.", "File Error", JOptionPane.ERROR_MESSAGE); + } + } + } + + /************************************************************************************************************************************************************ + * Select a question file to use for custom questions + */ + public void importQuestions() + { + JFileChooser jNewStudyChooser = new JFileChooser(); + File newFile; + // FileReader file = null; + Study newStudy = null; + + jNewStudyChooser.setCurrentDirectory(DirList.getLibraryDirectory()); + jNewStudyChooser.addChoosableFileFilter(readQuestionFilter); + jNewStudyChooser.setDialogTitle("Select Custom Questions File"); + + if (JFileChooser.APPROVE_OPTION == jNewStudyChooser.showOpenDialog(EgoNet.frame)) + { + newFile = jNewStudyChooser.getSelectedFile(); + + try + { + if (!newFile.canRead()) + { + throw (new FileReadException()); + } + + /* read question file here */ + Document document = new Document(newFile); + readQuestions(document); + } + catch (Exception e) + { + JOptionPane.showMessageDialog( + null, + "Unable to read question file.", + "File Error", + JOptionPane.ERROR_MESSAGE); + } + } + } + + /************************************************************************************************************************************************************ + * Save study information to a file with a new name + */ + public void saveStudyFile() + { + // FileWriter file = null; + PrintWriter out = null; + File studyFile = getStudyFile(); + + try + { + if (!studyFile.canWrite()) + { + throw (new FileWriteException()); + } + + writeStudy(studyFile, new Long(EgoNet.study.getStudyId())); + } + catch (Exception e) + { + JOptionPane.showMessageDialog(EgoNet.frame, "Unable to write to study file. Study not saved."); + } + } + + /************************************************************************************************************************************************************ + * Save question information to a file with a new name + */ + public void exportQuestions() + { + JFileChooser jNewQuestionsChooser = new JFileChooser(); + File newQuestionFile; + + jNewQuestionsChooser.setCurrentDirectory(new File(getStudyFile().getParent(), "/Questions/")); + jNewQuestionsChooser.addChoosableFileFilter(writeQuestionFilter); + jNewQuestionsChooser.setDialogTitle("Save Custom Questions As..."); + + if (JFileChooser.APPROVE_OPTION == jNewQuestionsChooser.showSaveDialog(EgoNet.frame)) + { + try + { + newQuestionFile = + ((ExtensionFileFilter) writeQuestionFilter).getCorrectFileName(jNewQuestionsChooser.getSelectedFile()); + if (!newQuestionFile.createNewFile()) + { + int confirm = + JOptionPane.showConfirmDialog( + EgoNet.frame, + "Shall I overwrite it?
", + "Overwrite Questions File", + JOptionPane.OK_CANCEL_OPTION); + + if (confirm != JOptionPane.OK_OPTION) + { + throw new FileCreateException(true); + } + } + + writeAllQuestions(newQuestionFile); + } + catch (Exception e) + { + JOptionPane.showMessageDialog( + EgoNet.frame, + "Unable to create question file.", + "File Error", + JOptionPane.ERROR_MESSAGE); + } + } + } + + /************************************************************************************************************************************************************ + * Save study info and questions as a package + */ + public void saveAsStudyFile() + { + JFileChooser jNewQuestionsChooser = new JFileChooser("Save Study As..."); + File newStudyFile; + // FileWriter file = null; + PrintWriter out = null; + boolean complete = false; + + jNewQuestionsChooser.setCurrentDirectory(getStudyFile().getParentFile()); + jNewQuestionsChooser.addChoosableFileFilter(studyFilter); + + while (!complete) + { + if (JFileChooser.APPROVE_OPTION == jNewQuestionsChooser.showSaveDialog(EgoNet.frame)) + { + try + { + int confirm = JOptionPane.OK_OPTION; + newStudyFile = ((ExtensionFileFilter) studyFilter).getCorrectFileName(jNewQuestionsChooser.getSelectedFile()); + + if (!newStudyFile.createNewFile()) + { + if (newStudyFile.canWrite()) + { + confirm = JOptionPane.showConfirmDialog(EgoNet.frame, + "Shall I overwrite it?
", "Overwrite Study Package File", + JOptionPane.OK_CANCEL_OPTION); + } + else + { + confirm = JOptionPane.showConfirmDialog(EgoNet.frame, + "If you overwrite it, any interviews created with it will be unreadable!
" + + "Shall I overwrite it?
", "Overwrite Study Package File", + JOptionPane.OK_CANCEL_OPTION); + } + } + + if (confirm == JOptionPane.OK_OPTION) + { + if (!newStudyFile.canWrite()) { throw (new FileWriteException()); } + + writeStudy(newStudyFile, new Long(System.currentTimeMillis())); + setStudyFile(newStudyFile); + studyFileInUse = false; + complete = true; + + // Store location in prefs file + Preferences prefs = Preferences.userNodeForPackage(EgoNet.class); + prefs.put(FILE_PREF, newStudyFile.getParent()); + } + } + catch (FileWriteException e) + { + JOptionPane.showMessageDialog(EgoNet.frame, "Unable to write to study file. Study not saved."); + } + catch (java.io.IOException e) + { + JOptionPane.showMessageDialog(EgoNet.frame, "Unable to write to study file. Study not saved."); + } + } + else + { + complete = true; + } + } + } + + /********************************************************************************* + * Reads in study information from an XML DOM + * and arrays of question orders + * + * @param document + * XML tree containing study data + */ + private void readStudyData(Document document) + { + // String data; + + Element root = document.getRoot(); + root = root.getElement("Study"); + + if (root.getElement("name") != null) + { + EgoNet.study.setStudyName(root.getTextString("name")); + } + + if (root.getElement("numalters") != null) + { + EgoNet.study.setNumAlters(root.getInt("numalters")); + } + + Elements elements = root.getElements("questionorder"); + while (elements.hasMoreElements()) + { + int qOrderId; + List questionOrder; + Elements ids; + + Element element = elements.next(); + qOrderId = Integer.parseInt(element.getAttribute("questiontype")); + questionOrder = (EgoNet.study.getQuestionOrderArray())[qOrderId]; + + ids = element.getElements("id"); + while (ids.hasMoreElements()) + { + questionOrder.add(new Long(ids.next().getLong())); + } + } + } + + /************************************************************************************************************************************************************ + * Writes Study information to a file for later retrieval Includes files paths and arrays of question orders + * + * @param f File into which to write study @todo prune order lists, possibly need to load question files to do this + * @throws IOException + */ + private void writeStudy(File f, Long id) throws IOException + { + Document document = new Document(); + + document.setEncoding("UTF-8"); + document.setVersion("1.0"); + Element studyElement = document.setRoot("Package"); + studyElement.setAttribute("Id", id.toString()); + studyElement.setAttribute("InUse", studyFileInUse ? "Y" : "N"); + studyElement.setAttribute("Creator", Shared.version); + studyElement.setAttribute("Updated", DateUtils.getDateString(Calendar.getInstance().getTime(), "dd/MM/yyyy hh:mm a")); + + EgoNet.study.writeStudyData(studyElement); + EgoNet.study.writeAllQuestionData(studyElement); + + document.write(f); + } + + /************************************************************************************************************************************************************ + * Reads in questions from an XML like input file Includes files paths and arrays of question orders + * + * @param document XML tree containing question list + */ + private void readQuestions(Document document) + { + // File f; + Element root, question; + Elements questions; + + /** + * Load new questions from array + */ + try + { + /** + * Parse XML file + */ + root = document.getRoot(); + root = root.getElement("QuestionList"); + questions = root.getElements("Question"); + + while (questions.hasMoreElements()) + { + try + { + Question q = new Question(questions.next()); + + if (q != null) + { + /* Question complete, add it */ + EgoNet.study.addQuestion(q); + } + } + catch (Exception ex) + { + // ex.printStackTrace(); + throw ex; + } + } + } + catch (Exception e) + { + JOptionPane.showMessageDialog( + EgoNet.frame, + "Unable to read question file", + "Question Reading Error", + JOptionPane.ERROR_MESSAGE); + } + } + + /************************************************************************************************************************************************************ + * Writes all questions to a package file for later use + * + * @param f + * File to write data to + * @throws IOException + */ + private void writeAllQuestions(File f) throws IOException + { + Document document = new Document(); + + //document.addChild( new XMLDecl( "1.0", "UTF-8" ) ); + document.setEncoding("UTF-8"); + document.setVersion("1.0"); + Element study = document.setRoot("QuestionFile"); + study.setAttribute("Id", Long.toString(new Date().getTime())); + + EgoNet.study.writeAllQuestionData(study); + + document.write(f); + } + + /************************************************************************************************************************************************************ + * Reads in study information from an XML like input file Includes files paths and arrays of question orders + * + * @param file + * XML file from which to read study + */ + public void readStudy(File file) + { + if (file != null) + { + try + { + Document document = new Document(file); + Element root = document.getRoot(); + String inUse = root.getAttribute("InUse"); + + if ((inUse != null) && inUse.equals("Y")) + { + studyFileInUse = true; + + JOptionPane.showMessageDialog( + EgoNet.frame, + "This study has already been used for at least one interview.\n" + + "You may change the text of questions while still using previously generated interview files. However, \n" + + "if you add, delete, reorder, or modify the answer types of any questions you will no longer be able to use \n" + + "it to view existing interview files.", + "File In Use", + JOptionPane.WARNING_MESSAGE); + } + + EgoNet.study = new Study(document); + EgoNet.study.setInUse(studyFileInUse); + } + catch (Exception e) + { + JOptionPane.showMessageDialog( + EgoNet.frame, + "Unable to read this study file", + "Study Reading Error", + JOptionPane.ERROR_MESSAGE); + + EgoNet.study = new Study(); + } + } + } +} + + +/******************** + * + * $Log: EgoStore.java,v $ + * Revision 1.1 2005/08/02 19:36:04 samag + * Initial checkin + * + * Revision 1.16 2004/04/11 00:24:48 admin + * Fixing headers + * + * Revision 1.15 2004/04/02 20:02:51 admin + * Maintaining InUse State in study files + * + * Revision 1.14 2004/04/02 19:48:58 admin + * Keep Study Id when possible + * Store updated time in file + * + * Revision 1.13 2004/04/01 21:50:52 admin + * Aborting interview if unable to write answers to file + * + * Revision 1.12 2004/03/23 14:58:48 admin + * Update UI + * Study creation now occurs in instantiators + * + * Revision 1.11 2004/03/22 00:00:34 admin + * Extended text entry area + * Started work on importing studies from server + * + * Revision 1.10 2004/03/21 20:29:37 admin + * Warn before making incompatible changes to in use study file + * + * Revision 1.9 2004/03/21 14:00:38 admin + * Cleaned up Question Panel Layout using FOAM + * + * Revision 1.8 2004/02/26 21:19:17 admin + * adding jardescs + * + * Revision 1.7 2004/02/10 20:10:43 admin + * Version 2.0 beta 3 + * + * Revision 1.6 2004/01/23 13:36:07 admin + * Updating Libraries + * Allowing upload to web server + * + * Revision 1.5 2003/12/05 19:15:43 admin + * Extracting Study + * + * Revision 1.4 2003/12/04 15:14:08 admin + * Merging EgoNet and EgoClient projects so that they can share some + * common classes more easily. + * + * Revision 1.3 2003/11/25 19:29:53 admin + * Formatting + * + * Revision 1.2 2003/11/25 19:25:44 admin + * Warn before closing window + * + * Revision 1.1.1.1 2003/06/08 15:09:40 admin + * Egocentric Network Survey Authoring Module + * + * Revision 1.17 2002/09/01 20:06:16 admin + * Structural question now selected in client. Visual feedback for alter pair + * categorical questions. + * + * Revision 1.16 2002/08/30 09:30:37 admin + * Allowing user to select study file name. Using it for study name. + * + * Revision 1.15 2002/08/11 22:26:05 admin + * Final Statistics window, new file handling + * + * Revision 1.14 2002/08/08 17:07:25 admin + * Preparing to change file system + * + * Revision 1.13 2002/07/25 14:54:24 admin + * Question Links + * + * Revision 1.12 2002/07/24 14:17:09 admin + * xml files, links + * + * Revision 1.11 2002/07/18 14:43:06 admin + * New Alter Prompt Panel, packages + * + * Revision 1.10 2002/06/30 15:59:18 admin + * Moving questions in lists, between lists + * Better category input + * + * Revision 1.9 2002/06/26 15:43:42 admin + * More selection dialog work + * File loading fixes + * + * Revision 1.8 2002/06/26 00:10:48 admin + * UI Work including base question coloring and category selections + * + * Revision 1.7 2002/06/25 15:41:01 admin + * Lots of UI work + * + * Revision 1.6 2002/06/21 22:47:12 admin + * question lists working again + * + * Revision 1.5 2002/06/21 21:52:50 admin + * Many changes to event handling, file handling + * + * Revision 1.4 2002/06/19 01:57:04 admin + * Much UI work done + * + * Revision 1.3 2002/06/16 17:52:01 admin + * New Project, Open Project methods + * DirList class w/method + * + * Revision 1.2 2002/06/15 14:19:50 admin + * Initial Checkin of question and survey + * General file system work + * + * Revision 1.1 2002/06/14 20:34:35 admin + * Created + * + */ diff --git a/src/com/endlessloopsoftware/ego/author/NoTabTextArea.java b/src/com/endlessloopsoftware/ego/author/NoTabTextArea.java new file mode 100644 index 0000000..a285ee9 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/NoTabTextArea.java @@ -0,0 +1,28 @@ +package com.endlessloopsoftware.ego.author; + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + */ + +import java.awt.KeyboardFocusManager; +import java.util.Collections; + +import javax.swing.JTextArea; + +/** + * Extends JTextArea to make tabs focus change events in question text areas + */ +public class NoTabTextArea extends JTextArea +{ + public NoTabTextArea() + { + super(); + setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET); + setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET); + } +} \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/author/PromptPanel.java b/src/com/endlessloopsoftware/ego/author/PromptPanel.java new file mode 100644 index 0000000..d8b88f3 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/PromptPanel.java @@ -0,0 +1,460 @@ +package com.endlessloopsoftware.ego.author; + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: PromptPanel.java,v 1.1 2005/08/02 19:36:03 samag Exp $ + * + * $Log: PromptPanel.java,v $ + * Revision 1.1 2005/08/02 19:36:03 samag + * Initial checkin + * + * Revision 1.6 2004/04/11 00:24:48 admin + * Fixing headers + * + * Revision 1.5 2004/03/21 14:00:38 admin + * Cleaned up Question Panel Layout using FOAM + * + * Revision 1.4 2003/12/05 19:15:43 admin + * Extracting Study + * + * Revision 1.3 2003/12/04 15:14:08 admin + * Merging EgoNet and EgoClient projects so that they can share some + * common classes more easily. + * + * Revision 1.2 2003/11/25 19:25:43 admin + * Warn before closing window + * + * Revision 1.1.1.1 2003/06/08 15:09:40 admin + * Egocentric Network Survey Authoring Module + * + * Revision 1.4 2002/08/11 22:26:05 admin + * Final Statistics window, new file handling + * + * Revision 1.3 2002/08/08 17:07:25 admin + * Preparing to change file system + * + * Revision 1.2 2002/07/24 14:17:08 admin + * xml files, links + * + * Revision 1.1 2002/07/18 14:43:06 admin + * New Alter Prompt Panel, packages + * + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.egonet.exceptions.DuplicateQuestionException; + +import com.endlessloopsoftware.ego.Question; + +/** + * Generic Panel creation and handling routines for question editing + */ +public class PromptPanel extends EgoQPanel +{ + private final int questionType; + private boolean inUpdate; + + private final JSplitPane question_split = new JSplitPane(); + private final JList question_list = new JList(); + private final JScrollPane question_list_scroll = new JScrollPane(question_list); + private final JPanel question_panel_right = new RightPanel(); + private final JLabel question_title_label = new JLabel("Title:"); + private final JLabel question_question_label = new JLabel("Question:"); + private final JLabel question_citation_label = new JLabel("Citation:"); + private final JLabel question_follows_label = new JLabel("Follows Question:"); + private final JTextArea question_question_field = new NoTabTextArea(); + private final JTextArea question_citation_field = new NoTabTextArea(); + private final JTextField question_title_field = new JTextField(); + private final JButton question_new_button = new JButton("New"); + private final JComboBox question_follows_menu = new JComboBox(); + private final JButton question_delete_button = new JButton("Delete"); + private final Border listBorder; + + /** + * Generates Panel for question editing to insert in file tab window + * @param type Type of questions on Page (e.g. Alter Questions) + * @param parent parent frame for referencing composed objects + */ + public PromptPanel(int type) + { + questionType = type; + listBorder = BorderFactory.createCompoundBorder( + new TitledBorder(new EtchedBorder(EtchedBorder.RAISED,Color.white,new Color(178, 178, 178)), + Question.questionTypeString(questionType)), + BorderFactory.createEmptyBorder(10,10,10,10)); + + try + { + jbInit(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + /** + * Component initialization + * @throws Exception + */ + private void jbInit() + throws Exception + { + inUpdate = true; + + // Configure Split Frame + question_split.setMinimumSize(new Dimension(430, 330)); + question_split.setPreferredSize(new Dimension(430, 330)); + question_split.setResizeWeight(.33); + question_split.setDividerLocation(.33); + question_list_scroll.setRequestFocusEnabled(false); + question_split.add(question_list_scroll, JSplitPane.LEFT); + question_split.add(question_panel_right, JSplitPane.RIGHT); + + this.setLayout(new GridLayout()); + + // Configure List + question_list_scroll.setBorder(listBorder); + question_list_scroll.setMinimumSize(new Dimension(150, 150)); + question_list_scroll.setPreferredSize(new Dimension(150, 150)); + question_list_scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + + question_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + question_list.setCellRenderer(new QuestionListCellRenderer()); + + // Configure question fields + question_panel_right.setLayout(new GridBagLayout()); + question_question_field.setMaximumSize(new Dimension(280, 64)); + question_question_field.setMinimumSize(new Dimension(72, 16)); + question_question_field.setPreferredSize(new Dimension(72, 16)); + question_question_field.setLineWrap(true); + question_question_field.setRows(1); + question_question_field.setTabSize(4); + question_question_field.setWrapStyleWord(true); + + question_citation_field.setMaximumSize(new Dimension(280, 64)); + question_citation_field.setMinimumSize(new Dimension(72, 16)); + question_citation_field.setPreferredSize(new Dimension(72, 16)); + question_citation_field.setLineWrap(true); + question_citation_field.setRows(1); + question_citation_field.setTabSize(4); + question_citation_field.setWrapStyleWord(true); + + /* Question Layout */ + question_panel_right.add(question_title_label, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_title_field, new GridBagConstraints(1, 0, 2, 1, 0.0, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 4)); + question_panel_right.add(question_question_label, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_question_field, new GridBagConstraints(1, 1, 2, 2, 0.0, 0.4 + ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_citation_label, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_citation_field, new GridBagConstraints(1, 3, 2, 2, 0.0, 0.3 + ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_new_button, new GridBagConstraints(0, 7, 1, 1, 0.33, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_delete_button, new GridBagConstraints(2, 7, 1, 1, 0.33, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_follows_label, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + question_panel_right.add(question_follows_menu, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)); + + question_list.setModel(new DefaultListModel()); + EgoNet.study.fillList(questionType, (DefaultListModel) question_list.getModel()); + + question_list.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) { + question_list_selectionChanged(e); }}); + + question_new_button.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + question_new_button_actionPerformed(e);}}); + + question_delete_button.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + question_delete_button_actionPerformed(e);}}); + + question_follows_menu.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + question_follows_menu_actionPerformed(e);}}); + + question_title_field.getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { questionTitleEvent(); } + public void changedUpdate(DocumentEvent e) { questionTitleEvent(); } + public void removeUpdate(DocumentEvent e) { questionTitleEvent(); }}); + + question_question_field.getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { questionTextEvent(); } + public void changedUpdate(DocumentEvent e) { questionTextEvent(); } + public void removeUpdate(DocumentEvent e) { questionTextEvent(); }}); + + question_citation_field.getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { questionCitationEvent(); } + public void changedUpdate(DocumentEvent e) { questionCitationEvent(); } + public void removeUpdate(DocumentEvent e) { questionCitationEvent(); }}); + + this.add(question_split, null); + + inUpdate = false; + } + + + /** + * Updates right side question fields when the selection changes + * @param e event generated by selection change. + */ + public void question_list_selectionChanged(ListSelectionEvent e) + { + if (!inUpdate) + { + questionUpdate(); + } + } + + /**** + * fill List with appropriate questions + * Set other fields to selected question + */ + public void fillPanel() + { + if (questionType == EgoNet.frame.curTab) + { + storageUpdate(); + questionUpdate(); + } + } + + /** + * Called when file changes to load new questions into list + */ + void storageUpdate() + { + inUpdate = true; + + if (questionType == EgoNet.frame.curTab) + { + ((DefaultListModel) question_list.getModel()).removeAllElements(); + EgoNet.study.fillList(questionType, (DefaultListModel) question_list.getModel()); + } + + inUpdate = false; + } + + void questionUpdate() + { + Question q; + int index; + + inUpdate = true; + + /** @todo Use List Data Listener? */ + if (questionType == EgoNet.frame.curTab) + { + index = question_list.getSelectedIndex(); + if ((question_list.getModel().getSize() > 0) && (index == -1)) + { + index = 0; + } + + question_follows_menu.removeAllItems(); + question_follows_menu.addItem(EgoNet.study.getFirstQuestion()); + for (int i = 0; i < question_list.getModel().getSize(); i++) + { + if (i != index) + { + question_follows_menu.addItem(question_list.getModel().getElementAt(i)); + } + } + + question_list.setSelectedIndex(index); + q = (Question) question_list.getSelectedValue(); + if (q != null) + { + question_question_field.setText(q.text); + question_citation_field.setText(q.citation); + question_title_field.setText(q.title); + question_follows_menu.setSelectedIndex(index); + + question_question_field.setEditable(true); + question_citation_field.setEditable(true); + question_title_field.setEditable(true); + question_delete_button.setEnabled(true); + question_follows_menu.setEnabled(true); + } + else + { + question_question_field.setText(null); + question_citation_field.setText(null); + question_title_field.setText(null); + + question_question_field.setEditable(false); + question_citation_field.setEditable(false); + question_title_field.setEditable(false); + question_delete_button.setEnabled(false); + question_follows_menu.setEnabled(false); + } + } + + inUpdate = false; + } + + + /**** + * Clear all on screen editable fields + * Generally called when a new survey is started + */ + public void clearPanel() + { + inUpdate = true; + ((DefaultListModel) question_list.getModel()).removeAllElements(); + inUpdate = false; + } + + /**** + * Document event handler used to read text fields + * @param e Document Event + */ + private void questionTitleEvent() + { + Question q = (Question) question_list.getSelectedValue(); + String s; + + if ((q != null) && !inUpdate) + { + s = question_title_field.getText().trim(); + if ((q.title == null) || (!q.title.equals(s))) + { + q.title = question_title_field.getText().trim(); + EgoNet.study.setModified(true); + question_list.repaint(); + } + } + } + + + /**** + * Document event handler used to read text fields + * @param e Document Event + */ + private void questionTextEvent() + { + Question q = (Question) question_list.getSelectedValue(); + String s; + + if ((q != null) && !inUpdate) + { + s = question_question_field.getText().trim(); + if ((q.text == null) || (!q.text.equals(s))) + { + q.text = question_question_field.getText().trim(); + EgoNet.study.setModified(true); + } + } + } + + + /**** + * Document event handler used to read text fields + * @param e Document Event + */ + private void questionCitationEvent() + { + Question q = (Question) question_list.getSelectedValue(); + String s; + + if ((q != null) && !inUpdate) + { + s = question_citation_field.getText().trim(); + if ((q.citation == null) || (!q.citation.equals(s))) + { + q.citation = question_citation_field.getText().trim(); + EgoNet.study.setModified(true); + } + } + } + + + void question_new_button_actionPerformed(ActionEvent e) + { + Question q = new Question(); + + q.questionType = questionType; + q.title = new String("Untitled Question"); + + try + { + EgoNet.study.addQuestion(q); + } + catch (DuplicateQuestionException e1) + { + } + + fillPanel(); + question_list.setSelectedValue(q, true); + + question_title_field.requestFocus(); + question_title_field.setSelectionStart(0); + question_title_field.setSelectionEnd(question_title_field.getText().length()); + } + + void question_delete_button_actionPerformed(ActionEvent e) + { + Question q = (Question) question_list.getSelectedValue(); + + if (q != null) + { + int confirm = JOptionPane.showConfirmDialog(EgoNet.frame, "Permanently remove this questions?", + "Delete Question", JOptionPane.OK_CANCEL_OPTION); + + if (confirm == JOptionPane.OK_OPTION) + { + EgoNet.study.removeQuestion(q); + fillPanel(); + } + } + } + + /** + * Changes order of questions + * @param e UI event + */ + void question_follows_menu_actionPerformed(ActionEvent e) + { + if (!inUpdate) + { + Question follows = (Question) question_follows_menu.getSelectedItem(); + Question q = (Question) question_list.getSelectedValue(); + + EgoNet.study.moveQuestionAfter(q, follows); + fillPanel(); + } + } +} + + + diff --git a/src/com/endlessloopsoftware/ego/author/QuestionLinkDialog.java b/src/com/endlessloopsoftware/ego/author/QuestionLinkDialog.java new file mode 100644 index 0000000..5c4a1e7 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/QuestionLinkDialog.java @@ -0,0 +1,720 @@ +package com.endlessloopsoftware.ego.author; + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: QuestionLinkDialog.java,v 1.1 2005/08/02 19:36:03 samag Exp $ + */ + + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Observable; +import java.util.Observer; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.text.PlainDocument; + +import com.endlessloopsoftware.ego.Answer; +import com.endlessloopsoftware.ego.Question; +import com.endlessloopsoftware.elsutils.documents.WholeNumberDocument; + +/** + * Generic Panel creation and handling routines for question editing + */ +public class QuestionLinkDialog extends JDialog + implements Observer +{ + private Question baseQuestion; + private Answer linkAnswer = new Answer(new Long(-1)); + + /* Containers */ + private final JSplitPane questionSplit = new JSplitPane(); + private final JList questionList = new JList(); + private final JScrollPane questionListScroll = new JScrollPane(questionList); + private final JPanel answerPanel = new JPanel(); + private final JPanel radioPanel = new JPanel(); + private final JPanel menuPanel = new JPanel(); + private final JPanel textPanel = new JPanel(); + private final JPanel questionPanelLeft = new JPanel(); + private final JPanel questionPanelRight = new RightPanel(); + private final GridBagLayout questionListLayout = new GridBagLayout(); + private final GridBagLayout answerRadioLayout = new GridBagLayout(); + private final GridBagLayout answerTextLayout = new GridBagLayout(); + private final GridBagLayout answerMenuLayout = new GridBagLayout(); + private final GridLayout answerPanelLayout = new GridLayout(); + + /* UI Elements */ + private final Border listBorder; + private final JLabel titleText = new JLabel(); + private final JTextArea questionText = new JTextArea(); + private final JTextArea answerTextField = new NoTabTextArea(); + private final JButton questionButtonOK = new JButton("OK"); + private final JButton questionButtonCancel = new JButton("Cancel"); + private final JButton questionButtonNone = new JButton("No Link"); + private final JLabel textAnswerLabel = new JLabel("Answer: "); + private final JLabel menuAnswerLabel = new JLabel("Answer: "); + private final JLabel radioAnswerLabel = new JLabel("Answer: "); + private final JComboBox answerMenu = new JComboBox(); + private final JCheckBox allAdjacentCheck = new JCheckBox("All Adjacent Selections"); + + private final ButtonGroup answerButtonGroup = new ButtonGroup(); + private ActionListener answerButtonListener; + private final WholeNumberDocument wholeNumberDocument = new WholeNumberDocument(); + private final PlainDocument plainDocument = new PlainDocument(); + + /* Lists */ + private final static int MAX_BUTTONS = 5; + private final JRadioButton[] answerButtons = { new JRadioButton(), new JRadioButton(), + new JRadioButton(), new JRadioButton(), new JRadioButton(), new JRadioButton()}; + + /* Question Iteration Variables */ + private Question question; + + + /** + * Generates Panel for question editing to insert in file tab window + * @param parent parent frame for referencing composed objects + */ + public QuestionLinkDialog() + { + listBorder = BorderFactory.createCompoundBorder( + new TitledBorder(new EtchedBorder(EtchedBorder.RAISED,Color.white,new Color(178, 178, 178)), "Questions"), + BorderFactory.createEmptyBorder(10,10,10,10)); + + try + { + jbInit(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + /** + * Component initialization + * @throws Exception + */ + private void jbInit() + throws Exception + { + /* Overview Layout */ + this.getContentPane().setLayout(new GridLayout()); + + // Configure Split Frame + questionSplit.setMinimumSize(new Dimension(430, 330)); + questionSplit.setPreferredSize(new Dimension(430, 330)); + questionSplit.setResizeWeight(.33); + questionSplit.setDividerLocation(.33); + questionText.setBackground(SystemColor.window); + questionText.setFont(new java.awt.Font("Serif", 0, 16)); + questionText.setLineWrap(true); + questionText.setTabSize(4); + questionText.setWrapStyleWord(true); + questionText.setEditable(false); + + questionSplit.add(questionPanelLeft, JSplitPane.LEFT); + questionSplit.add(questionPanelRight, JSplitPane.RIGHT); + + questionPanelLeft.setLayout(questionListLayout); + questionPanelLeft.setVisible(true); + + titleText.setFont(new java.awt.Font("Lucida Grande Bold", 0, 16)); + + // Configure List + questionListScroll.setBorder(listBorder); + questionListScroll.setMinimumSize(new Dimension(150, 150)); + questionListScroll.setPreferredSize(new Dimension(150, 150)); + questionListScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + + questionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + // Configure question fields + questionPanelRight.setLayout(new GridBagLayout()); + radioPanel.setLayout(answerRadioLayout); + textPanel.setLayout(answerTextLayout); + menuPanel.setLayout(answerMenuLayout); + + questionText.setBorder(BorderFactory.createLoweredBevelBorder()); + answerMenu.setOpaque(true); + answerPanel.setLayout(answerPanelLayout); + + answerTextField.setFont(new java.awt.Font("SansSerif", 0, 14)); + answerTextField.setMaximumSize(new Dimension(72, 64)); + answerTextField.setMinimumSize(new Dimension(72, 16)); + answerTextField.setPreferredSize(new Dimension(72, 16)); + answerTextField.setLineWrap(true); + answerTextField.setRows(1); + answerTextField.setTabSize(4); + answerTextField.setWrapStyleWord(true); + + /* List Layout */ + questionPanelLeft.add(questionListScroll, new GridBagConstraints(0, 0, 2, 1, 1.0, 1.0 + ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 29, 302)); + + /* Question Layout */ + questionPanelRight.add(titleText, new GridBagConstraints(0, 1, 4, 1, 0.0, 0.1 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + questionPanelRight.add(questionText, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.3 + ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 10, 10, 10), 0, 0)); + + /* Radio Panel Answer Layout */ + radioPanel.add(radioAnswerLabel, new GridBagConstraints(0, 0, 1, 1, 0.3, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); + + for (int i = 0; i < MAX_BUTTONS; i++) + { + radioPanel.add(answerButtons[i], new GridBagConstraints(1, i, 1, 1, 0.6, 0.2, + GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + } + + /* Text Answer Layout */ + textPanel.add(textAnswerLabel, new GridBagConstraints(0, 0, 1, 1, 0.3, 0.0 + ,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); + textPanel.add(answerTextField, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0 + ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); + + /* Popup Menu Answer Layout */ + menuPanel.add(menuAnswerLabel, new GridBagConstraints(0, 0, 1, 1, 0.3, 0.0 + ,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0)); + menuPanel.add(answerMenu, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0 + ,GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 0, 10), 0, 0)); + + /* Misc Button Layout */ + questionPanelRight.add(questionButtonOK, new GridBagConstraints(0, 11, 1, 1, 0.33, 0.1 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + questionPanelRight.add(questionButtonNone, new GridBagConstraints(2, 11, 1, 1, 0.33, 0.1 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + questionPanelRight.add(questionButtonCancel, new GridBagConstraints(3, 11, 1, 1, 0.33, 0.1 + ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); + questionPanelRight.add(answerPanel, new GridBagConstraints(0, 5, 4, 4, 1.0, 0.5 + ,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 0)); + questionPanelRight.add(allAdjacentCheck, new GridBagConstraints(0, 10, 4, 1, 0.0, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)); + + + /* Install event Handlers */ + questionList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) { + question_list_selectionChanged(e); }}); + + questionButtonOK.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + questionButtonOK_actionPerformed(e);}}); + + questionButtonNone.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + questionButtonNone_actionPerformed(e);}}); + + questionButtonCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + questionButtonCancel_actionPerformed(e);}}); + + answerButtonListener = new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + questionAnsweredEventHandler(e);}}; + + answerMenu.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + questionAnsweredEventHandler(e); }}); + + wholeNumberDocument.addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { answerTextEvent(e); } + public void changedUpdate(DocumentEvent e) { answerTextEvent(e); } + public void removeUpdate(DocumentEvent e) { answerTextEvent(e); }}); + + plainDocument.addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { answerTextEvent(e); } + public void changedUpdate(DocumentEvent e) { answerTextEvent(e); } + public void removeUpdate(DocumentEvent e) { answerTextEvent(e); }}); + + answerButtonListener = new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + questionAnsweredEventHandler(e);}}; + + allAdjacentCheck.addActionListener(new java.awt.event.ActionListener(){ + public void actionPerformed(ActionEvent e){ + allAdjacentCheck_actionPerformed(e);}}); + + for (int i = 0; i <= MAX_BUTTONS; i++) + { + answerButtonGroup.add(answerButtons[i]); + answerButtons[i].addActionListener(answerButtonListener); + } + + this.getContentPane().add(questionSplit, null); + } + + + void activate(Question q) + { + question = null; + linkAnswer = null; + baseQuestion = q; + + // Question vars + questionList.setModel(new DefaultListModel()); + EgoNet.study.fillList(Question.ALL_QUESTION_TYPES, (DefaultListModel) questionList.getModel(), q.UniqueId); + + // Set Selection + if (baseQuestion.link.active) + { + Question selected = EgoNet.study.getQuestions().getQuestion(baseQuestion.link.answer.questionId); + questionList.setSelectedValue(selected, true); + } + + if ((questionList.getSelectedIndex() == -1) && (questionList.getModel().getSize() > 0)) + { + questionList.setSelectedIndex(0); + } + + /* Prepare starting question and answer, fill with stored values */ + question = (Question) questionList.getSelectedValue(); + + if (question != null) + { + linkAnswer = new Answer(question.UniqueId); + + if (baseQuestion.link.active && (question.UniqueId.equals(baseQuestion.link.answer.questionId))) + { + linkAnswer.value = baseQuestion.link.answer.value; + linkAnswer.string = baseQuestion.link.answer.string; + linkAnswer.answered = true; + } + } + + + // Init + fillPanel(); + + this.setTitle("Set Link for Question \"" + q.title + "\""); + this.setSize(550, 500); + + //Center the window + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension frameSize = this.getSize(); + if (frameSize.height > screenSize.height) + { + frameSize.height = screenSize.height; + } + if (frameSize.width > screenSize.width) + { + frameSize.width = screenSize.width; + } + this.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); + + this.show(); + } + + + /** + * Updates right side question fields when the selection changes + * @param e event generated by selection change. + */ + public void question_list_selectionChanged(ListSelectionEvent e) + { + if (!e.getValueIsAdjusting() && !questionList.isSelectionEmpty()) + { + question = (Question) questionList.getSelectedValue(); + + if (question != null) + { + linkAnswer = new Answer(question.UniqueId); + + if (baseQuestion.link.active && (question.UniqueId.equals(baseQuestion.link.answer.questionId))) + { + linkAnswer.value = baseQuestion.link.answer.value; + linkAnswer.index = baseQuestion.link.answer.index; + linkAnswer.string = baseQuestion.link.answer.string; + linkAnswer.answered = true; + } + } + + setOKButtonState(); + fillPanel(); + } + } + + /**** + * fill List with appropriate questions + * Set other fields to selected question + */ + public void fillPanel() + { + allAdjacentCheck.setVisible(false); + + if (question != null) + { + titleText.setText(question.title); + + answerPanel.setVisible(false); + answerPanel.removeAll(); + questionText.setText("Please select a question and an answer which will trigger the inclusion of the current question"); + if (question.questionType == Question.ALTER_PROMPT) + { + // Should never be here + //assert(false); + } + else if (question.answerType == Question.TEXT) + { + answerPanel.add(textPanel); + answerPanel.validate(); + answerTextField.setDocument(plainDocument); + answerTextField.requestFocus(); + + if (linkAnswer.answered) + { + answerTextField.setText(linkAnswer.string); + } + else + { + answerTextField.setText(""); + } + } + else if (question.answerType == Question.NUMERICAL) + { + answerPanel.add(textPanel); + answerTextField.setDocument(wholeNumberDocument); + answerTextField.requestFocus(); + + if (linkAnswer.answered) + { + answerTextField.setText(linkAnswer.string); + } + else + { + answerTextField.setText(""); + } + } + else if (question.selections.length <= 5) + { + allAdjacentCheck.setVisible(question.questionType == Question.ALTER_PAIR_QUESTION); + questionText.setText(question.text); + + answerPanel.add(radioPanel); + + if (linkAnswer.answered) + { + if (linkAnswer.value == Answer.ALL_ADJACENT) + { + allAdjacentCheck.setSelected(true); + answerButtons[MAX_BUTTONS].setSelected(true); + } + else + { + allAdjacentCheck.setSelected(false); + answerButtons[question.selections.length - (linkAnswer.value + 1)].setSelected(true); + } + } + else + { + answerButtons[MAX_BUTTONS].setSelected(true); + } + + for (int i = 0; i < question.selections.length; i++) + { + answerButtons[i].setText(question.selections[i].getString()); + answerButtons[i].setVisible(true); + answerButtons[i].setEnabled(linkAnswer.value != Answer.ALL_ADJACENT); + } + + for (int i = question.selections.length; i < MAX_BUTTONS; i++) + { + answerButtons[i].setVisible(false); + } + } + else + { + allAdjacentCheck.setVisible(question.questionType == Question.ALTER_PAIR_QUESTION); + questionText.setText(question.text); + answerPanel.add(menuPanel); + + answerMenu.removeAllItems(); + + answerMenu.addItem("Select an answer"); + for (int i = 0; i < question.selections.length; i++) + { + answerMenu.addItem(question.selections[i]); + } + + if (linkAnswer.value == Answer.ALL_ADJACENT) + { + allAdjacentCheck.setSelected(true); + answerMenu.setEnabled(false); + } + else if (linkAnswer.value != Answer.NO_ANSWER) + { + allAdjacentCheck.setSelected(false); + answerMenu.setEnabled(true); + answerMenu.setSelectedIndex(question.selections.length - linkAnswer.value); + } + else + { + allAdjacentCheck.setSelected(false); + answerMenu.setEnabled(true); + answerMenu.setSelectedIndex(0); + } + } + + answerPanel.validate(); + answerPanel.setVisible(true); + } + } + + /**** + * Clear all on screen editable fields + * Generally called when a new survey is started + */ + public void clearPanel() + { + ((DefaultListModel) questionList.getModel()).removeAllElements(); + } + + /**** + * Parses answer fields to retrieve answer to question + * @param answer Answer from interview to fill with correct values + */ + void fillAnswer() + { + linkAnswer.string = null; + + switch (question.answerType) + { + case Question.NUMERICAL: + if (answerTextField.getText().length() > 0) + { + linkAnswer.string = answerTextField.getText(); + linkAnswer.value = Integer.valueOf(linkAnswer.string).intValue(); + linkAnswer.answered = true; + } + else + { + linkAnswer.value = Answer.NO_ANSWER; + linkAnswer.answered = false; + } + break; + + case Question.TEXT: + linkAnswer.string = answerTextField.getText(); + linkAnswer.value = linkAnswer.string.length(); + linkAnswer.answered = (linkAnswer.value != 0); + break; + + case Question.CATEGORICAL: + if (question.selections.length <= 5) + { + if (allAdjacentCheck.isSelected()) + { + linkAnswer.value = Answer.ALL_ADJACENT; + linkAnswer.string = "All Adjacent"; + linkAnswer.answered = true; + } + else + { + int button = selectedButtonIndex(answerButtons); + linkAnswer.answered = (button != MAX_BUTTONS); + + if (linkAnswer.answered) + { + linkAnswer.value = question.selections[button].getValue(); + linkAnswer.index = question.selections[button].getIndex(); + linkAnswer.string = answerButtons[button].getActionCommand(); + } + else + { + linkAnswer.value = Answer.NO_ANSWER; + linkAnswer.index = Answer.NO_ANSWER; + linkAnswer.string = ""; + } + } + } + else + { + if (allAdjacentCheck.isSelected()) + { + linkAnswer.value = Answer.ALL_ADJACENT; + linkAnswer.string = "All Adjacent"; + linkAnswer.answered = true; + } + else if (answerMenu.getSelectedIndex() > 0) + { + linkAnswer.value = question.selections[answerMenu.getSelectedIndex() - 1].getValue(); + linkAnswer.string = answerMenu.getSelectedItem().toString(); + linkAnswer.answered = (linkAnswer.value < question.selections.length); + } + else + { + linkAnswer.value = Answer.NO_ANSWER; + linkAnswer.string = ""; + linkAnswer.answered = false; + } + } + break; + } + } + + void jShowListButton_actionPerformed(ActionEvent e) + { + questionPanelLeft.setVisible(!questionPanelLeft.isVisible()); + questionSplit.setDividerLocation(.33); + questionSplit.repaint(); + } + + void questionButtonNone_actionPerformed(ActionEvent e) + { + if (EgoNet.study.confirmIncompatibleChange(EgoNet.frame)) + { + baseQuestion.link.active = false; + baseQuestion.link.answer = null; + EgoNet.study.setModified(true); + EgoNet.study.setCompatible(false); + } + + EgoNet.frame.fillCurrentPanel(); + this.hide(); + } + + void questionButtonCancel_actionPerformed(ActionEvent e) + { + this.hide(); + } + + void questionButtonOK_actionPerformed(ActionEvent e) + { + if ((linkAnswer != null) && (linkAnswer.answered) && EgoNet.study.confirmIncompatibleChange(EgoNet.frame)) + { + baseQuestion.link.active = true; + baseQuestion.link.answer = linkAnswer; + EgoNet.study.setModified(true); + EgoNet.study.setCompatible(false); + } + + this.hide(); + EgoNet.frame.fillCurrentPanel(); + } + + int selectedButtonIndex(JRadioButton[] group) + { + int ri = -1; + + for (int i = 0; i < group.length; i++) + { + if (group[i].isSelected()) + { + ri = i; + break; + } + } + + return (ri); + } + + void setOKButtonState() + { + questionButtonOK.setEnabled((question != null) && linkAnswer.answered); + } + + + void questionAnsweredEventHandler(ActionEvent e) + { + if (e.getActionCommand() != "Initialization") + { + fillAnswer(); + setOKButtonState(); + } + } + + void answerTextEvent(DocumentEvent e) + { + fillAnswer(); + setOKButtonState(); + } + + public void update(Observable o, Object arg) + { + fillAnswer(); + setOKButtonState(); + } + + void allAdjacentCheck_actionPerformed(ActionEvent e) + { + fillAnswer(); + fillPanel(); + setOKButtonState(); + } +} + +/** + * $Log: QuestionLinkDialog.java,v $ + * Revision 1.1 2005/08/02 19:36:03 samag + * Initial checkin + * + * Revision 1.12 2004/04/11 00:24:48 admin + * Fixing headers + * + * Revision 1.11 2004/04/07 00:08:31 admin + * updating manifests, jar creation. Removing author specific objects from + * client specific references + * + * Revision 1.10 2004/03/28 17:31:31 admin + * More error handling when uploading study to server + * Server URL selection dialog for upload + * + * Revision 1.9 2004/03/21 20:29:37 admin + * Warn before making incompatible changes to in use study file + * + * Revision 1.8 2004/03/21 14:00:38 admin + * Cleaned up Question Panel Layout using FOAM + * + * Revision 1.7 2004/03/05 19:47:20 admin + * Fixing problem with links from popup menu questions + * + * Revision 1.6 2004/02/10 20:10:43 admin + * Version 2.0 beta 3 + * + * Revision 1.5 2003/12/08 15:57:50 admin + * Modified to generate matrix files on survey completion or summarization + * Extracted statistics models + * + * Revision 1.4 2003/12/05 19:15:43 admin + * Extracting Study + * + * Revision 1.3 2003/12/04 15:14:08 admin + * Merging EgoNet and EgoClient projects so that they can share some + * common classes more easily. + * + * Revision 1.2 2003/11/25 19:25:43 admin + * Warn before closing window + * + * Revision 1.1.1.1 2003/06/08 15:09:40 admin + * Egocentric Network Survey Authoring Module + * + * Revision 1.6 2002/08/30 16:50:27 admin + * Using Selections + * + * Revision 1.5 2002/08/26 16:01:11 admin + * UI fixes + * + * Revision 1.4 2002/08/11 22:26:05 admin + * Final Statistics window, new file handling + * + * Revision 1.3 2002/08/08 17:07:25 admin + * Preparing to change file system + * + * Revision 1.2 2002/07/25 14:54:24 admin + * Question Links + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/author/RightPanel.java b/src/com/endlessloopsoftware/ego/author/RightPanel.java new file mode 100644 index 0000000..f935461 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/RightPanel.java @@ -0,0 +1,23 @@ +package com.endlessloopsoftware.ego.author; + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + */ + +import javax.swing.JPanel; + +/** + * Extends JPanel class to keep focus in right panel of split question panel + */ +public class RightPanel extends JPanel +{ + public boolean isFocusCycleRoot() + { + return (true); + } +} diff --git a/src/com/endlessloopsoftware/ego/author/SelectStudyDialog.gui_xml b/src/com/endlessloopsoftware/ego/author/SelectStudyDialog.gui_xml new file mode 100644 index 0000000..5a2b7f3 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/SelectStudyDialog.gui_xml @@ -0,0 +1,341 @@ + +Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: SetActiveStudyDialog.java,v 1.1 2005/08/02 19:36:04 samag Exp $ + * + */ + +import java.awt.Cursor; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; +import java.util.prefs.Preferences; + +import javax.swing.*; + +import com.cim.dlgedit.loader.DialogResource; +import com.cim.util.swing.DlgUtils; +import com.endlessloopsoftware.egonet.interfaces.ConfigurationSBRemote; +import com.endlessloopsoftware.egonet.interfaces.ConfigurationSBRemoteHome; +import com.endlessloopsoftware.egonet.interfaces.ConfigurationSBUtil; +import com.endlessloopsoftware.egonet.interfaces.StudySBRemote; +import com.endlessloopsoftware.egonet.interfaces.StudySBRemoteHome; +import com.endlessloopsoftware.egonet.interfaces.StudySBUtil; +import com.endlessloopsoftware.elsutils.security.SymmetricKeyEncryption; + +public class SetActiveStudyDialog + extends JDialog + implements ActionListener +{ + // Declare beans. + private JButton loadStudies; + private JButton select; + private JList surveyNameList; + private JTextField serverURL; + private JPasswordField password; + + // Get default values + private Preferences prefs = Preferences.userNodeForPackage(this.getClass()); + + Properties prop = new Properties(); + { + prop.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); + } + + private static final String SERVER_URL = "ServerURL"; + + // Constructor. + public SetActiveStudyDialog(Frame owner) + { + // This dialog is modal. + super(owner, "Select Active Survey", true); + + // Load User Interface + JPanel panel = DialogResource.load("com/endlessloopsoftware/ego/author/SelectStudyDialog.gui_xml"); + + setContentPane(panel); + + // Attach beans to fields. + loadStudies = (JButton) DialogResource.getComponentByName(panel, "loadStudies"); + select = (JButton) DialogResource.getComponentByName(panel, "select"); + surveyNameList = (JList) DialogResource.getComponentByName(panel, "surveyNames"); + password = (JPasswordField) DialogResource.getComponentByName(panel, "password"); + serverURL = (JTextField) DialogResource.getComponentByName(panel, "serverURL"); + + // Set default value + serverURL.setText(prefs.get(SERVER_URL, "")); + password.setText(null); + surveyNameList.setModel(new DefaultListModel()); + + // Fill In Survey List + + // Add dialog as ActionListener. + loadStudies.addActionListener(this); + select.addActionListener(this); + + pack(); + setLocationRelativeTo(owner); + + // Set Enter and Escape keys as default keys. + //getRootPane().setDefaultButton(store); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } + + /** + * Invoke the onXxx() action handlers. + * + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + public void actionPerformed(ActionEvent e) + { + DlgUtils.invokeHandler(this, e); + } + + public void onloadStudies() + { + surveyNameList.setModel(getList()); + } + + public void onselect() + { + String message = ""; + boolean success = false; + setWaitCursor(true); + + String studyName = (String) surveyNameList.getSelectedValue(); + + if (!("".equals(studyName) || (studyName == null))) + { + try + { + String epassword = "215-121-242-47-99-238-5-61-133-183-0-216-187-250-253-30-115-177-254-142-161-83-108-56";//SymmetricKeyEncryption.encrypt(new String(password.getPassword())); + + ConfigurationSBRemoteHome configurationSBHome = ConfigurationSBUtil.getHome(prop); + ConfigurationSBRemote configurationSession = configurationSBHome.create(); + configurationSession.setActiveStudy(studyName, epassword); + + success = true; + } + catch (Exception ex) + { + message = ex.getMessage(); + } + } + else + { + JOptionPane.showMessageDialog(this, "No Survey Selected"); + } + + prefs.put(SERVER_URL, serverURL.getText()); + + if (success) + { + JOptionPane.showMessageDialog(this, studyName + " is now the active survey."); + } + else + { + JOptionPane.showMessageDialog(this, "Unable to set active survey.\n" + message, "Server Error", JOptionPane.ERROR_MESSAGE); + } + + setWaitCursor(false); + + this.hide(); + } + + protected void setWaitCursor(boolean waitCursor) + { + if (waitCursor) + { + this.getGlassPane().setVisible(true); + this.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + } + else + { + this.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + this.getGlassPane().setVisible(false); + } + } + + /** + * @author admin + * + * To change the template for this generated type comment go to + * Window - Preferences - Java - Code Generation - Code and Comments + */ + public ListModel getList() + { + DefaultListModel listModel = new DefaultListModel(); + + if ("".equals(serverURL.getText())) + return listModel; + + try + { + setWaitCursor(true); + + prop.setProperty("java.naming.provider.url", serverURL.getText()+":1099"); + + StudySBRemoteHome studySBHome = StudySBUtil.getHome(prop); + StudySBRemote studySession = studySBHome.create(); + Set studyNames = studySession.getStudyNames(); + + for (Iterator it = studyNames.iterator(); it.hasNext();) + { + listModel.addElement(it.next()); + } + } + catch (Exception e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + finally + { + setWaitCursor(false); + } + + return (ListModel) listModel; + } + + public String encryptPassword(String password) + { + return SymmetricKeyEncryption.encrypt(password); + } +} + +/** + * $Log: SetActiveStudyDialog.java,v $ + * Revision 1.1 2005/08/02 19:36:04 samag + * Initial checkin + * + * Revision 1.3 2004/04/11 15:19:28 admin + * Using password to access server + * + * Remote study summary in seperate thread with progress monitor + * + * Revision 1.2 2004/04/11 00:24:48 admin + * Fixing headers + * + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/author/StoreStudyDialog.java b/src/com/endlessloopsoftware/ego/author/StoreStudyDialog.java new file mode 100644 index 0000000..3aa0297 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/StoreStudyDialog.java @@ -0,0 +1,135 @@ +package com.endlessloopsoftware.ego.author; + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: StoreStudyDialog.java,v 1.1 2005/08/02 19:36:05 samag Exp $ + * + */ + +import java.awt.Cursor; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.prefs.Preferences; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JTextField; + +import com.cim.dlgedit.loader.DialogResource; +import com.cim.util.swing.DlgUtils; + +public class StoreStudyDialog + extends JDialog + implements ActionListener +{ + // Declare beans. + private JButton cancel; + private JButton store; + private JLabel surveyName; + private JTextField serverURL; + private JPasswordField password; + + // Get default values + private Preferences prefs = Preferences.userNodeForPackage(this.getClass()); + + private static final String SERVER_URL = "ServerURL"; + + // Constructor. + public StoreStudyDialog(Frame owner) + { + // This dialog is modal. + super(owner, "Upload Survey to Server", true); + + // Load User Interface + JPanel panel = DialogResource.load("com/endlessloopsoftware/ego/author/StoreSurvey.gui_xml"); + + setContentPane(panel); + + // Attach beans to fields. + cancel = (JButton) DialogResource.getComponentByName(panel, "cancel"); + store = (JButton) DialogResource.getComponentByName(panel, "store"); + surveyName = (JLabel) DialogResource.getComponentByName(panel, "surveyName"); + password = (JPasswordField) DialogResource.getComponentByName(panel, "password"); + serverURL = (JTextField) DialogResource.getComponentByName(panel, "serverURL"); + + // Set default value + surveyName.setText(EgoNet.study.getStudyName()); + serverURL.setText(prefs.get(SERVER_URL, "")); + + // Add dialog as ActionListener. + cancel.addActionListener(this); + store.addActionListener(this); + + pack(); + setLocationRelativeTo(owner); + + // Set Enter and Escape keys as default keys. + //getRootPane().setDefaultButton(store); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } + + /** + * Invoke the onXxx() action handlers. + * + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + public void actionPerformed(ActionEvent e) + { + DlgUtils.invokeHandler(this, e); + } + + public void oncancel() + { + this.hide(); + } + + public void onstore() + { + setWaitCursor(true); + boolean success = EgoNet.study.writeDBStudy(EgoNet.frame, serverURL.getText(), password.getPassword()); + + if (success) + { + prefs.put(SERVER_URL, serverURL.getText()); + } + setWaitCursor(false); + + this.hide(); + } + + protected void setWaitCursor(boolean waitCursor) + { + if (waitCursor) + { + this.getGlassPane().setVisible(true); + this.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + } + else + { + this.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + this.getGlassPane().setVisible(false); + } + } + + +} + +/** + * $Log: StoreStudyDialog.java,v $ + * Revision 1.1 2005/08/02 19:36:05 samag + * Initial checkin + * + * Revision 1.3 2004/04/11 00:24:48 admin + * Fixing headers + * + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/author/StoreSurvey.gui_xml b/src/com/endlessloopsoftware/ego/author/StoreSurvey.gui_xml new file mode 100644 index 0000000..4fa3b48 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/author/StoreSurvey.gui_xml @@ -0,0 +1,288 @@ + +Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: StudyPanel.java,v 1.1 2005/08/02 19:36:05 samag Exp $ + */ +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.io.File; +import java.io.IOException; + +import javax.swing.BorderFactory; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.JTextPane; +import javax.swing.SwingConstants; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.Document; + +import com.endlessloopsoftware.ego.client.EgoClient; +import com.endlessloopsoftware.elsutils.documents.WholeNumberDocument; + +/** + * Generic Panel creation and handling routines for question editing + */ +public class StudyPanel extends JPanel +{ + private final EgoFrame frame; + private final GridBagLayout study_layout = new GridBagLayout(); + private final JLabel study_path_label = new JLabel("Study Path:"); + private final JLabel study_path_field = new JLabel("< none selected >"); + private final JLabel study_name_label = new JLabel("Study Name:"); + private final JTextField study_name_field = new JTextField("< none selected >"); + private final JLabel study_num_alters_label = new JLabel("Number of Alters:"); + private final JTextField study_num_alters_field = new JTextField(); + private final JLabel titleLabel = new JLabel("EgoCentric Network Study Configuration"); + private final JTextPane instructionPane = new JTextPane(); + private final Document altersDocument = new WholeNumberDocument(); + + private final String[] instructionStrings = { + "Start by selecting a study or choosing \"New Study\" from the file menu.", "Please name the study.", + "You may add predefined questions to the study by selecting Import Questions from the file menu"}; + + + /** + * Generates Panel for study configuration info + * @param parent parent frame for this panel + */ + public StudyPanel(EgoFrame parent) + { + frame = parent; + + try + { + jbInit(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + /** + * Component initialization + */ + private void jbInit() + { + this.setLayout(study_layout); + this.setMinimumSize(new Dimension(300, 200)); + this.setPreferredSize(new Dimension(400, 400)); + + study_num_alters_field.setDocument(altersDocument); + + /* Question Layout */ + titleLabel.setBorder(BorderFactory.createEtchedBorder()); + titleLabel.setHorizontalAlignment(SwingConstants.CENTER); + instructionPane.setBackground(Color.lightGray); + instructionPane.setBorder(BorderFactory.createLoweredBevelBorder()); + instructionPane.setEditable(false); + instructionPane.setText(instructionStrings[0]); + + add(titleLabel, new GridBagConstraints(0, 0, 4, 1, 1.0, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 0, 10), 0, 0)); + add(study_name_label, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.1 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 4)); + add(study_name_field, new GridBagConstraints(1, 1, 2, 1, 0.33, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 6)); + add(study_path_label, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.1 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 4)); + add(study_path_field, new GridBagConstraints(1, 2, 2, 1, 0.33, 0.0 + ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 4)); + add(study_num_alters_label, new GridBagConstraints(0, 4, 2, 1, 0.0, 0.1 + ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0)); + add(study_num_alters_field, new GridBagConstraints(2, 4, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 50, 8)); + add(instructionPane, new GridBagConstraints(0, 5, 4, 1, 1.0, 0.15 + ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 4)); + + /**** + * Action Listeners for buttons and other UI elements + * @param e event to be handled + */ + study_name_field.getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { studyNameTextEvent(); } + public void changedUpdate(DocumentEvent e) { studyNameTextEvent(); } + public void removeUpdate(DocumentEvent e) { studyNameTextEvent(); }}); + + study_num_alters_field.getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { studyAltersTextEvent(); } + public void changedUpdate(DocumentEvent e) { studyAltersTextEvent(); } + public void removeUpdate(DocumentEvent e) { studyAltersTextEvent(); }}); + } + + + /**** + * Clear all on screen editable fields + * Generally called when a new survey is started + */ + public void clearPanel() + { + study_name_field.setText(""); + study_path_field.setText("< none selected >"); + } + + /**** + * Clear all on screen editable fields + * Generally called when a new survey is started + */ + public void fillPanel() + { + boolean hasStudy = (EgoNet.storage.getStudyFile() != null); + + try + { + study_name_field. setEnabled(hasStudy); + study_name_label. setEnabled(hasStudy); + study_num_alters_label. setEnabled(hasStudy); + study_num_alters_field. setEnabled(hasStudy && !EgoNet.storage.getStudyInUse()); + study_path_label. setEnabled(hasStudy); + study_path_field. setEnabled(hasStudy); + + study_name_field. setText(EgoNet.study.getStudyName()); + study_path_field. setText(filename(EgoNet.storage.getStudyFile())); + + study_num_alters_field.setText(Integer.toString(EgoNet.study.getNumAlters())); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + private String filename(File f) + throws IOException + { + if (f == null) + { + return("< none selected >"); + } + else + { + return(f.getPath().toString()); + } + } + + private void studyNameTextEvent() + { + String s = study_name_field.getText(); + + if (!EgoNet.study.getStudyName().equals(s)) + { + EgoNet.study.setStudyName(s); + } + } + + private void studyAltersTextEvent() + { + String s = study_num_alters_field.getText(); + int i = 0; + + if (!s.equals("")) + { + i = Integer.parseInt(s); + } + + if (i != EgoNet.study.getNumAlters()) + { + EgoNet.study.setNumAlters(i); + //EgoNet.study.setCompatible(false); + } + } + +} + +/** + * $Log: StudyPanel.java,v $ + * Revision 1.1 2005/08/02 19:36:05 samag + * Initial checkin + * + * Revision 1.9 2004/03/22 18:01:28 admin + * Fixed problem confirming alterNums by simply making it non-editable when + * the study is in use + * + * Now confirming changes to number of selections + * + * Revision 1.8 2004/03/21 20:29:37 admin + * Warn before making incompatible changes to in use study file + * + * Revision 1.7 2004/03/21 14:00:38 admin + * Cleaned up Question Panel Layout using FOAM + * + * Revision 1.6 2004/02/26 21:19:17 admin + * adding jardescs + * + * Revision 1.5 2004/02/10 20:10:43 admin + * Version 2.0 beta 3 + * + * Revision 1.4 2003/12/05 19:15:44 admin + * Extracting Study + * + * Revision 1.3 2003/12/04 15:14:09 admin + * Merging EgoNet and EgoClient projects so that they can share some + * common classes more easily. + * + * Revision 1.2 2003/11/25 19:25:44 admin + * Warn before closing window + * + * Revision 1.1.1.1 2003/06/08 15:09:40 admin + * Egocentric Network Survey Authoring Module + * + * Revision 1.12 2002/08/30 16:50:28 admin + * Using Selections + * + * Revision 1.11 2002/08/11 22:26:06 admin + * Final Statistics window, new file handling + * + * Revision 1.10 2002/08/08 17:07:26 admin + * Preparing to change file system + * + * Revision 1.9 2002/07/24 14:17:10 admin + * xml files, links + * + * Revision 1.7 2002/06/30 15:59:18 admin + * Moving questions in lists, between lists + * Better category input + * + * Revision 1.6 2002/06/26 15:43:43 admin + * More selection dialog work + * File loading fixes + * + * Revision 1.5 2002/06/25 15:41:02 admin + * Lots of UI work + * + * Revision 1.4 2002/06/21 22:47:13 admin + * question lists working again + * + * Revision 1.3 2002/06/21 21:52:50 admin + * Many changes to event handling, file handling + * + * Revision 1.2 2002/06/19 01:57:05 admin + * Much UI work done + * + * Revision 1.1 2002/06/16 17:53:31 admin + * new File + * + * Revision 1.2 2002/06/15 14:19:51 admin + * Initial Checkin of question and survey + * General file system work + * + */ + diff --git a/src/com/endlessloopsoftware/ego/client/ClientFrame.java b/src/com/endlessloopsoftware/ego/client/ClientFrame.java new file mode 100644 index 0000000..7ce335d --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/ClientFrame.java @@ -0,0 +1,263 @@ +package com.endlessloopsoftware.ego.client; + +import java.awt.AWTEvent; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.PrintWriter; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import com.endlessloopsoftware.elsutils.files.ExtensionFileFilter; +import com.endlessloopsoftware.elsutils.files.FileCreateException; + +import com.endlessloopsoftware.ego.Shared; +import com.endlessloopsoftware.elsutils.AboutBox; +import com.endlessloopsoftware.elsutils.files.FileHelpers; +import com.endlessloopsoftware.ego.client.graph.GraphData; + +/** + *+ * Title: Egocentric Network Researcher + *
+ *+ * Description: Configuration Utilities for an Egocentric network study + *
+ *+ * Copyright: Copyright (c) 2004 + *
+ *+ * Company: Endless Loop Software + *
+ * + * @author Peter C. Schoaff + * @version 2.1 + */ + +public class ClientFrame extends JFrame { + private final JMenuBar jMenuBar1 = new JMenuBar(); + + private final JMenu jMenuFile = new JMenu("File"); + + private final JMenu jMenuHelp = new JMenu("Help"); + + private final JMenuItem jMenuHelpAbout = new JMenuItem("About"); + + private final JMenuItem saveStudySummary = new JMenuItem( + "Save Study Summary"); + + private final JMenuItem exit = new JMenuItem("Exit"); + + public final JMenuItem saveAlterSummary = new JMenuItem( + "Save Alter Summary"); + + public final JMenuItem saveTextSummary = new JMenuItem( + "Save Text Answer Summary"); + + public final JMenuItem saveAdjacencyMatrix = new JMenuItem( + "Save Adjacency Matrix"); + + public final JMenuItem saveWeightedAdjacencyMatrix = new JMenuItem( + "Save Weighted Adjacency Matrix"); + + public final JMenuItem saveGraph = new JMenuItem("Save Graph as JPEG image"); + + public final JMenuItem saveInterview = new JMenuItem("Save Interview"); + + public final JMenuItem recalculateStatistics = new JMenuItem("Recalculate Statistics"); + + public final JMenuItem close = new JMenuItem("Return to Main Menu"); + + public final JMenuItem saveInterviewStatistics = new JMenuItem( + "Save Interview Statistics"); + + // Construct the frame + public ClientFrame() { + enableEvents(AWTEvent.WINDOW_EVENT_MASK); + + try { + jbInit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Component initialization + private void jbInit() throws Exception { + this.setSize(new Dimension(700, 600)); + this.setTitle("Egocentric Networks Study Tool"); + + createMenuBar(EgoClient.SELECT); + + this.setContentPane(new JPanel()); + + jMenuHelpAbout.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuHelpAbout_actionPerformed(e); + } + }); + + exit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + jMenuFileExit_actionPerformed(e); + } + }); + + saveStudySummary.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + saveStudySummary_actionPerformed(e); + } + }); + + saveGraph.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + saveGraph_actionPerformed(e); + } + }); + + saveInterview.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + EgoClient.interview.completeInterview(); + } catch (FileCreateException ex) { + ex.printStackTrace(); + } + } + }); + + recalculateStatistics.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + EgoClient.interview = EgoClient.storage.readInterview(); + if(EgoClient.interview != null) + ViewInterviewPanel.gotoPanel(); + } + }); + + close + .addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + SourceSelectPanel.gotoPanel(false); + } + }); + } + + public void flood() { + Dimension size = this.getSize(); + this.pack(); + this.setSize(size); + this.validate(); + } + + // File | Exit action performed + public void jMenuFileExit_actionPerformed(ActionEvent e) { + if (EgoClient.interview != null) { + EgoClient.interview.exit(); + } + + System.exit(0); + } + + // Help | About action performed + public void jMenuHelpAbout_actionPerformed(ActionEvent e) { + JOptionPane.showMessageDialog(this, + "Egonet is an egocentric network study tool." + + "\n\nThanks to: Dr. Chris McCarty, University of Florida", + "About Egonet", JOptionPane.PLAIN_MESSAGE); + } + + // Overridden so we can exit when window is closed + protected void processWindowEvent(WindowEvent e) { + super.processWindowEvent(e); + if (e.getID() == WindowEvent.WINDOW_CLOSING) { + jMenuFileExit_actionPerformed(null); + } + } + + public void createMenuBar(int mode) { + jMenuBar1.removeAll(); + jMenuFile.removeAll(); + jMenuHelp.removeAll(); + + // File Menu + if (mode == EgoClient.VIEW_SUMMARY) { + jMenuFile.add(saveStudySummary); + jMenuFile.add(close); + jMenuFile.addSeparator(); + jMenuFile.add(exit); + } else if (mode == EgoClient.VIEW_INTERVIEW) { + /******************************************************************* + * Create Menu Bar + ******************************************************************/ + jMenuFile.add(saveAlterSummary); + jMenuFile.add(saveTextSummary); + jMenuFile.add(saveAdjacencyMatrix); + jMenuFile.add(saveWeightedAdjacencyMatrix); + jMenuFile.add(saveGraph); + jMenuFile.add(saveInterview); + jMenuFile.add(recalculateStatistics); + jMenuFile.addSeparator(); + jMenuFile.add(close); + } else { + jMenuFile.add(exit); + } + jMenuBar1.add(jMenuFile); + + // Help Menu + jMenuHelp.add(jMenuHelpAbout); + jMenuBar1.add(jMenuHelp); + + this.setJMenuBar(jMenuBar1); + } + + void saveStudySummary_actionPerformed(ActionEvent e) { + String name = FileHelpers.formatForCSV(EgoClient.study.getStudyName()); + String filename = name + "_Summary"; + PrintWriter w = EgoClient.storage.newStatisticsPrintWriter( + "Study Summary", "csv", filename); + + if (w != null) { + try { + ((SummaryPanel) EgoClient.frame.getContentPane()) + .writeStudySummary(w); + } finally { + w.close(); + } + } + } + + void saveGraph_actionPerformed(ActionEvent e) { + String fileName; + fileName = EgoClient.interview.getName() + "_graph"; + File currentDirectory = new File(EgoClient.storage.getPackageFile() + .getParent() + + "/Graphs"); + currentDirectory.mkdir(); + + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setCurrentDirectory(currentDirectory); + fileChooser.setSelectedFile(new File(fileName + ".jpeg")); + fileChooser.setDialogTitle("Save Graph"); + fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + + // ExtensionFileFilter jpegFilter = new ExtensionFileFilter("JPEG + // Files",".jpeg"); + FileFilter imageFilter = new ImageFilter(); + fileChooser.addChoosableFileFilter(imageFilter); + + int returnValue = fileChooser.showSaveDialog(this); + if (returnValue == JFileChooser.APPROVE_OPTION) { + File imageFile = fileChooser.getSelectedFile(); + System.out.println(imageFile.getName()); + GraphData.writeJPEGImage(imageFile); + } + + } +} \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/ClientPanel.java b/src/com/endlessloopsoftware/ego/client/ClientPanel.java new file mode 100644 index 0000000..d8f279f --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/ClientPanel.java @@ -0,0 +1,204 @@ +package com.endlessloopsoftware.ego.client; + +/** + *Copyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * + * $Id: ClientPanel.java,v 1.1 2005/08/02 19:36:01 samag Exp $ + */ + +import java.awt.Color; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +import org.egonet.exceptions.CorruptedInterviewException; + +import com.cim.dlgedit.loader.DialogResource; +import com.endlessloopsoftware.ego.Study; + +public class ClientPanel + extends JPanel +{ + + private final GridBagLayout gridBagLayout1 = new GridBagLayout(); + + + private JLabel titleLabel; + private JButton selectStudyButton; + private JButton statisticsButton; + private JButton gradientStatisticsButton; + private JButton viewInterviewButton; + private JButton startInterviewButton; + + private JLabel studyNameLabel = new JLabel(); + + public ClientPanel() + { + try + { +// Load up the dialog contents. + java.io.InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/endlessloopsoftware/ego/client/localSelect.gui_xml"); + JPanel panel = DialogResource.load(is); + //JPanel panel = DialogResource.load("com/endlessloopsoftware/ego/client/localSelect.gui_xml"); + +// Attach beans to fields. + selectStudyButton = (JButton) DialogResource.getComponentByName(panel, "SelectStudy"); + viewInterviewButton = (JButton) DialogResource.getComponentByName(panel, "ViewInterview"); + statisticsButton = (JButton) DialogResource.getComponentByName(panel, "SummaryStatistics"); + gradientStatisticsButton = (JButton)DialogResource.getComponentByName(panel,"GradientStatistics"); + startInterviewButton = (JButton) DialogResource.getComponentByName(panel, "StartInterview"); + titleLabel = (JLabel) DialogResource.getComponentByName(panel, "Title"); + studyNameLabel = (JLabel) DialogResource.getComponentByName(panel, "StudyName"); + + jbInit(); + + this.setLayout(new GridLayout(1, 1)); + this.add(panel); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + //Component initialization + private void jbInit() throws Exception + { + titleLabel.setBackground(Color.lightGray); + titleLabel.setBorder(BorderFactory.createRaisedBevelBorder()); + titleLabel.setHorizontalAlignment(SwingConstants.CENTER); + + studyNameLabel.setBorder(BorderFactory.createLoweredBevelBorder()); + studyNameLabel.setHorizontalAlignment(SwingConstants.CENTER); + studyNameLabel.setText(" "); + + selectStudyButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + doSelectStudy(e);}}); + + viewInterviewButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + doViewInterview(e);}}); + + statisticsButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + doSummaryStatistics(e);}}); + + startInterviewButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + doStartInterview(e);}}); + + fillPanel(); + } + + void fillPanel() + { + startInterviewButton.setEnabled(EgoClient.storage.getStudyLoaded()); + viewInterviewButton.setEnabled(EgoClient.storage.getStudyLoaded()); + statisticsButton.setEnabled(EgoClient.storage.getStudyLoaded()); + + studyNameLabel.setText(EgoClient.study.getStudyName()); + if (studyNameLabel.getText() == null) + { + studyNameLabel.setText(" "); + } + + if (EgoClient.storage.getStudyLoaded()) + { + + } + } + + private void doSelectStudy(ActionEvent e) + { + /* Clear out old data */ + EgoClient.study = new Study(); + EgoClient.storage = new EgoStore(); + EgoClient.interview = null; + + /* Read new study */ + EgoClient.storage.selectStudy(); + EgoClient.storage.readPackage(); + studyNameLabel.setText(EgoClient.study.getStudyName()); + + fillPanel(); + } + + private void doStartInterview(ActionEvent e) + { + EgoClient.uiPath = EgoClient.DO_INTERVIEW; + EgoClient.storage.setPackageInUse(); + try + { + EgoClient.interview = new Interview(EgoClient.study); + if (!EgoClient.interview._statisticsAvailable) + { + /* No Structural question for this study, warn user */ + int option = JOptionPane.showConfirmDialog(EgoClient.frame, "This study has no questions with specified adjacency selections.
" + + "You will be unable to generate any structural statistics for it.
" + + "Continue anyway?
", + "No Statistics Available", JOptionPane.YES_NO_OPTION); + + if (option == JOptionPane.NO_OPTION) + { + EgoClient.interview = null; + } + } + } + catch (CorruptedInterviewException ex) { + /* No Structural question for this study, warn user */ + JOptionPane.showMessageDialog(EgoClient.frame, "Unable to create an interview from this file", + "No Statistics Available", JOptionPane.ERROR_MESSAGE); + EgoClient.interview = null; + } + + if (EgoClient.interview != null) + { + StartPanel.gotoPanel(); + } + } + + private void doViewInterview(ActionEvent e) + { + EgoClient.uiPath = EgoClient.VIEW_INTERVIEW; + + EgoClient.storage.setInterviewFile(null); + EgoClient.interview = null; + EgoClient.storage.selectInterview(); + } + + private void doSummaryStatistics(ActionEvent e) + { + /* Warn User this could take awhile */ + int ok = JOptionPane.showConfirmDialog(EgoClient.frame, "This operation could take over a minute. Should I continue?", + "Load Interview Statistics", JOptionPane.OK_CANCEL_OPTION); + + if (ok == JOptionPane.OK_OPTION) + { + SummaryPanel.gotoPanel(); + } + } +} + +/** + * $Log: ClientPanel.java,v $ + * Revision 1.1 2005/08/02 19:36:01 samag + * Initial checkin + * + * Revision 1.10 2004/04/08 15:06:06 admin + * EgoClient now creates study summaries from Server + * EgoAuthor now sets active study on server + * + * Revision 1.9 2004/04/06 15:46:11 admin + * cvs tags in headers + * + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/ClientQuestionPanel.java b/src/com/endlessloopsoftware/ego/client/ClientQuestionPanel.java new file mode 100644 index 0000000..ef19ed7 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/ClientQuestionPanel.java @@ -0,0 +1,1017 @@ +package com.endlessloopsoftware.ego.client; + +/** + *+ * Title: Egocentric Network Researcher + *
+ *+ * Description: Configuration Utilities for an Egocentric network study + *
+ *+ * Copyright: Copyright (c) 2002 + *
+ *+ * Company: Endless Loop Software + *
+ * + * @author Peter C. Schoaff + * @version 1.0 $Id: QuestionPanel.java,v 1.1 2005/08/02 19:36:00 samag Exp $ + */ + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.util.Collections; +import java.util.Observable; +import java.util.Observer; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.text.PlainDocument; + +import com.cim.dlgedit.loader.DialogResource; +import com.endlessloopsoftware.ego.Answer; +import com.endlessloopsoftware.ego.Question; +import com.endlessloopsoftware.egonet.Shared; +import com.endlessloopsoftware.elsutils.documents.WholeNumberDocument; +import com.endlessloopsoftware.elsutils.files.FileCreateException; +import com.endlessloopsoftware.elsutils.layout.CardPanel; +import org.egonet.util.listbuilder.ListBuilder; +import org.egonet.util.listbuilder.Selection; +import com.jgoodies.forms.builder.PanelBuilder; +import com.jgoodies.forms.layout.CellConstraints; +import com.jgoodies.forms.layout.FormLayout; + +// import java.text.*; +import java.util.Date; + +/** + * Generic Panel creation and handling routines for question editing + */ +public class ClientQuestionPanel extends JPanel implements Observer { + /* Lists */ + private final static int MAX_BUTTONS = 5; + + private final JRadioButton[] answerButtons = { new JRadioButton(), + new JRadioButton(), new JRadioButton(), new JRadioButton(), + new JRadioButton(), new JRadioButton() }; + + private final KeyStroke enter = KeyStroke + .getKeyStroke(KeyEvent.VK_ENTER, 0); + + private final KeyStroke[] numKey = { + KeyStroke.getKeyStroke(KeyEvent.VK_0, 0), + KeyStroke.getKeyStroke(KeyEvent.VK_1, 0), + KeyStroke.getKeyStroke(KeyEvent.VK_2, 0), + KeyStroke.getKeyStroke(KeyEvent.VK_3, 0), + KeyStroke.getKeyStroke(KeyEvent.VK_4, 0), + KeyStroke.getKeyStroke(KeyEvent.VK_5, 0), + KeyStroke.getKeyStroke(KeyEvent.VK_6, 0), + KeyStroke.getKeyStroke(KeyEvent.VK_7, 0), + KeyStroke.getKeyStroke(KeyEvent.VK_8, 0), + KeyStroke.getKeyStroke(KeyEvent.VK_9, 0) }; + + private final ActionListener keyActionListener = new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + numberKey_actionPerformed(e); + } + }; + + private final String ALTER_CARD = "ALTER"; + + private final String TEXT_CARD = "TEXT"; + + private final String NUMERICAL_CARD = "NUMERICAL"; + + private final String RADIO_CARD = "RADIO"; + + private final String MENU_CARD = "MENU"; + + /* UI Elements */ + private final Border listBorder; + + private JLabel titleText = new JLabel(); + + private JTextArea questionText = new JTextArea(); + + private final JTextArea answerTextField = new NoTabTextArea(); + + private final JTextArea numericalTextField = new NoTabTextArea(); + + private JButton questionButtonPrevious; + + private JButton questionButtonNext; + + private JProgressBar questionProgress; + + private final JComboBox answerMenu = new JComboBox(); + + private final ListBuilder alterList = new ListBuilder(); + + private final JCheckBox noAnswerBox = new JCheckBox("Don't Know"); + + /* Containers */ + private final JSplitPane questionSplit = new JSplitPane(); + + private final JList questionList = new JList(); + + private CardPanel answerPanel = new CardPanel(); + + private final JPanel radioPanel = new RadioPanel(); + + private final JPanel menuPanel = new MenuAnswerPanel(); + + private final JPanel textPanel = new TextAnswerPanel(); + + private final JPanel numericalPanel = new NumericalAnswerPanel(); + + private final JPanel questionPanelLeft; + + private final JPanel questionPanelRight; + + private final ButtonGroup answerButtonGroup = new ButtonGroup(); + + private ActionListener answerButtonListener; + + private final WholeNumberDocument wholeNumberDocument = new WholeNumberDocument(); + + private final PlainDocument plainDocument = new PlainDocument(); + + /* Question Iteration Variables */ + private Question question; + + private String alterName, pairName; + + /** + * Generates Panel for question editing to insert in file tab window + * + * @param parent + * parent frame for referencing composed objects + */ + public ClientQuestionPanel() { + listBorder = BorderFactory.createCompoundBorder(new TitledBorder( + new EtchedBorder(EtchedBorder.RAISED, Color.white, new Color( + 178, 178, 178)), "Questions"), BorderFactory + .createEmptyBorder(10, 10, 10, 10)); + + questionPanelLeft = getLeftPanel(); + questionPanelRight = getRightPanel(); + + try { + jbInit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Component initialization + * + * @throws Exception + */ + private void jbInit() throws Exception { + // Question vars + question = EgoClient.interview.setInterviewIndex(EgoClient.interview + .getFirstUnansweredQuestion(), false); + + this.setMinimumSize(new Dimension(330, 330)); + this.setLayout(new GridLayout()); + + // Configure Split Frame + questionSplit.add(questionPanelLeft, JSplitPane.LEFT); + questionSplit.add(questionPanelRight, JSplitPane.RIGHT); + + questionSplit.setOneTouchExpandable(false); + questionSplit.setDividerLocation(0.33); + + // Provide minimum sizes for the two components in the split pane + Dimension minimumSize = new Dimension(100, 100); + questionPanelLeft.setMinimumSize(minimumSize); + questionPanelRight.setMinimumSize(minimumSize); + + /* Install event Handlers */ + questionList.getSelectionModel().addListSelectionListener( + new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) { + question_list_selectionChanged(e); + } + }); + + questionButtonPrevious + .addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + questionButtonPrevious_actionPerformed(e); + } + }); + + questionButtonNext + .addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + questionButtonNext_actionPerformed(e); + } + }); + + answerButtonListener = new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + questionAnsweredEventHandler(e); + } + }; + + answerMenu.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + questionAnsweredEventHandler(e); + } + }); + + wholeNumberDocument.addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { + answerTextEvent(e); + } + + public void changedUpdate(DocumentEvent e) { + answerTextEvent(e); + } + + public void removeUpdate(DocumentEvent e) { + answerTextEvent(e); + } + }); + + plainDocument.addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { + answerTextEvent(e); + } + + public void changedUpdate(DocumentEvent e) { + answerTextEvent(e); + } + + public void removeUpdate(DocumentEvent e) { + answerTextEvent(e); + } + }); + + noAnswerBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + noAnswerBox_actionPerformed(e); + } + }); + + for (int i = 0; i <= MAX_BUTTONS; i++) { + answerButtonGroup.add(answerButtons[i]); + answerButtons[i].addActionListener(answerButtonListener); + } + + // register all number buttons instead of till MAX_BUTTONS alone + // for (int i = 0; i <= MAX_BUTTONS; i++) + for (int i = 0; i <= 9; i++) { + this.registerKeyboardAction(keyActionListener, Integer + .toString(i + 1), numKey[i], + JComponent.WHEN_IN_FOCUSED_WINDOW); + } + this.registerKeyboardAction(keyActionListener, Integer.toString(0), + enter, JComponent.WHEN_IN_FOCUSED_WINDOW); + numericalTextField.registerKeyboardAction(keyActionListener, Integer + .toString(0), enter, JComponent.WHEN_FOCUSED); + answerTextField.registerKeyboardAction(keyActionListener, Integer + .toString(0), enter, JComponent.WHEN_FOCUSED); + answerMenu.registerKeyboardAction(keyActionListener, Integer + .toString(0), enter, JComponent.WHEN_FOCUSED); + + alterList.addListObserver(this); + + questionProgress.setMaximum(EgoClient.interview.getNumQuestions()); + questionProgress.setValue(EgoClient.interview.getQuestionIndex()); + + questionList.setModel(new DefaultListModel()); + EgoClient.interview + .fillList((DefaultListModel) questionList.getModel()); + + if (EgoClient.uiPath == EgoClient.VIEW_INTERVIEW) + questionList.setSelectedIndex(0); + + this.add(questionSplit, null); + + /* Differences in UI in conducting interview vs. viewing it */ + questionPanelLeft + .setVisible(EgoClient.uiPath == EgoClient.VIEW_INTERVIEW); + + fillPanel(); + } + + /** + * Hides the static frame EgoClient.frame and initializes it with an + * entirely new QuestionPanel + */ + static void gotoPanel() { + /* Return to first screen */ + EgoClient.frame.setVisible(false); + EgoClient.frame.setContentPane(new ClientQuestionPanel()); + EgoClient.frame.pack(); + + if (EgoClient.uiPath == EgoClient.DO_INTERVIEW) { + // EgoClient.frame.setSize(600, 530); + EgoClient.frame.setExtendedState(EgoClient.frame.getExtendedState() + | JFrame.MAXIMIZED_BOTH); + } else { + // EgoClient.frame.setSize(640, 530); + EgoClient.frame.setExtendedState(EgoClient.frame.getExtendedState() + | JFrame.MAXIMIZED_BOTH); + } + + EgoClient.frame.setVisible(true); + } + + private JPanel getLeftPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new GridBagLayout()); + + // Configure List + JScrollPane questionListScroll = new JScrollPane(questionList); + questionListScroll.setBorder(listBorder); + questionListScroll.setMinimumSize(new Dimension(150, 150)); + questionListScroll + .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + questionListScroll.setAutoscrolls(true); + + questionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + /* List Layout */ + panel.add(questionListScroll, new GridBagConstraints(0, 0, 2, 1, 1.0, + 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 29, 302)); + + return panel; + } + + private JPanel getRightPanel() { + // Load up the dialog contents. + JPanel panel = DialogResource + .load("com/endlessloopsoftware/ego/client/QuestionPanel.gui_xml"); + + // Attach beans to fields. + questionButtonPrevious = (JButton) DialogResource.getComponentByName( + panel, "questionButtonPrevious"); + questionButtonNext = (JButton) DialogResource.getComponentByName(panel, + "questionButtonNext"); + titleText = (JLabel) DialogResource.getComponentByName(panel, + "titleText"); + answerPanel = (CardPanel) DialogResource.getComponentByName(panel, + "answerPanel"); + questionProgress = (JProgressBar) DialogResource.getComponentByName( + panel, "questionProgress"); + questionText = (JTextArea) DialogResource.getComponentByName(panel, + "questionText"); + + /* Set up answer panel cards */ + answerPanel.add(new JScrollPane(alterList), ALTER_CARD); + answerPanel.add(new JScrollPane(textPanel), TEXT_CARD); + answerPanel.add(new JScrollPane(numericalPanel), NUMERICAL_CARD); + answerPanel.add(new JScrollPane(radioPanel), RADIO_CARD); + answerPanel.add(new JScrollPane(menuPanel), MENU_CARD); + + titleText.setFont(new java.awt.Font("Lucida Grande Bold", 0, 15)); + + questionText.setBackground(SystemColor.window); + questionText.setFont(new java.awt.Font("Serif", 0, 16)); + questionText.setLineWrap(true); + questionText.setTabSize(4); + questionText.setWrapStyleWord(true); + questionText.setEditable(false); + questionText.setMargin(new Insets(4, 4, 4, 4)); + questionText.setBorder(BorderFactory.createLoweredBevelBorder()); + + answerMenu.setOpaque(true); + + answerTextField.setFont(new java.awt.Font("SansSerif", 0, 14)); + answerTextField.setLineWrap(true); + answerTextField.setRows(1); + answerTextField.setTabSize(4); + answerTextField.setWrapStyleWord(true); + + numericalTextField.setFont(new java.awt.Font("SansSerif", 0, 14)); + numericalTextField.setLineWrap(true); + numericalTextField.setRows(1); + numericalTextField.setTabSize(4); + numericalTextField.setWrapStyleWord(false); + + return panel; + } + + /** + * Updates right side question fields when the selection changes + * + * @param e + * event generated by selection change. + */ + public void question_list_selectionChanged(ListSelectionEvent e) { + question = EgoClient.interview.setInterviewIndex(questionList + .getSelectedIndex(), true); + fillPanel(); + } + + /*************************************************************************** + * fill List with appropriate questions Set other fields to selected + * question + */ + public void fillPanel() { + if (question != null) { + String[] alterNames = EgoClient.interview.getAlterStrings(question); + setButtonNextState(); + questionButtonPrevious + .setEnabled(EgoClient.interview.hasPrevious()); + + switch (question.questionType) { + case Question.EGO_QUESTION: + titleText.setText("Questions About You"); + break; + + case Question.ALTER_PROMPT: + titleText.setText("Whom do you know?"); + break; + + case Question.ALTER_QUESTION: + titleText.setText("Questions About
Questions About
Title: Egocentric Networks Client Program
+ *Description: Subject Interview Client.
+ *Copyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * + * $Id: EgoClient.java,v 1.1 2005/08/02 19:36:01 samag Exp $ + */ + +public class EgoClient +{ + public static Study study = new Study(); + public static EgoStore storage = new EgoStore(); + public static ClientFrame frame = new ClientFrame(); + public static Interview interview = null; + public static int uiPath; + + /** + * Used to create drop down menus of different "modes" + */ + public static final int SELECT = 0; + public static final int DO_INTERVIEW = 1; + public static final int VIEW_INTERVIEW = 2; + public static final int VIEW_SUMMARY = 3; + + private boolean packFrame = false; + + //Construct the application + public EgoClient() + { + SourceSelectPanel.gotoPanel(true); + + frame.setVisible(true); + frame.setExtendedState(frame.getExtendedState()|JFrame.MAXIMIZED_BOTH); + + } + + public static ClientFrame getFrame() + { + return (frame); + } + + //Main method + public static void main(String[] args) + { + // save this -- it might be useful for the web part later + /*System.setProperty("java.security.policy", "security.policy"); + if(System.getSecurityManager() == null) { + System.setSecurityManager(new java.rmi.RMISecurityManager()); + }*/ + + //if(true) return; + Shared.configureUI(); + new EgoClient(); + } +} \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/EgoStore.java b/src/com/endlessloopsoftware/ego/client/EgoStore.java new file mode 100644 index 0000000..5774dd6 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/EgoStore.java @@ -0,0 +1,854 @@ +package com.endlessloopsoftware.ego.client; + +/** + *Title: Egocentric Network Researcher
+ *Description: Configuration Utilities for an Egocentric network study
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter C. Schoaff + * @version 1.0 + * + * $Id: EgoStore.java,v 1.1 2005/08/02 19:36:01 samag Exp $ + */ + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.*; +import java.util.prefs.Preferences; + +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.filechooser.FileFilter; +import javax.swing.ProgressMonitor; +import javax.swing.SwingWorker; + +import org.egonet.exceptions.CorruptedInterviewException; +import org.egonet.exceptions.FileMismatchException; + +import com.endlessloopsoftware.ego.Shared; +import com.endlessloopsoftware.ego.Study; +import com.endlessloopsoftware.ego.client.statistics.Statistics; +import com.endlessloopsoftware.elsutils.files.ExtensionFileFilter; +import com.endlessloopsoftware.elsutils.files.FileCreateException; +import com.endlessloopsoftware.elsutils.files.FileHelpers; +import com.endlessloopsoftware.elsutils.files.FileReadException; + +import electric.xml.Document; +import electric.xml.Element; +import electric.xml.ParseException; + +/******************************************************************************* + * Handles IO for the EgoNet program Tracks data files and changes to those + * files + */ +public class EgoStore extends Observable { + private File packageFile = null; + + private File interviewFile = null; + + private boolean loaded = false; + + private boolean interviewLoaded = false; + + private Document packageDocument = null; + + private static final FileFilter packageFilter = new ExtensionFileFilter( + "Study Definition Files", "ego"); + + private static final FileFilter interviewFilter = new ExtensionFileFilter( + "Interview Files", "int"); + + private static final String FILE_PREF = "FILE_PREF"; + + + + /** + * Sets parent frame + * + * @param g + * EgoClient + */ + public EgoStore() { + } + + /*************************************************************************** + * Notifies observers that a field in the study has changed + */ + public void notifyObservers() { + setChanged(); + super.notifyObservers(this); + } + + /*************************************************************************** + * Returns study file + * + * @return studyFile file containing study overview information + */ + public boolean getStudyLoaded() { + return (loaded); + } + + /*************************************************************************** + * Returns study file + * + * @return studyFile file containing study overview information + */ + public File getPackageFile() { + return (packageFile); + } + + /*************************************************************************** + * Returns interview file + * + * @return interview file containing answers + */ + public File getInterviewFile() { + return (interviewFile); + } + + /*************************************************************************** + * Sets interview file variable and notifies observers of change to study + * + * @param f + * question file + */ + public void setInterviewFile(File f) { + interviewFile = f; + notifyObservers(); + } + + /*************************************************************************** + * Sets baseQuestionFile variable and notifies observers of change to study + * + * @param f + * question file + */ + public void setPackageFile(File f) { + packageFile = f; + notifyObservers(); + } + + /*************************************************************************** + * Select a directory in which to store project related files Create + * subdirectories if needed. + */ + public void selectStudy() { + + JFileChooser jNewStudyChooser = new JFileChooser(); + File f, directory; + + Preferences prefs = null; + try { + prefs = Preferences.userNodeForPackage(EgoClient.class); + } catch (Throwable t) { + // eat this exception + } + + + jNewStudyChooser.addChoosableFileFilter(packageFilter); + jNewStudyChooser.setDialogTitle("Select Study Definition File"); + + if (getPackageFile() != null) { + jNewStudyChooser.setCurrentDirectory(getPackageFile().getParentFile()); + } else { + if(prefs!=null) + directory = new File(prefs.get(FILE_PREF, ".")); + directory = new File("."); + jNewStudyChooser.setCurrentDirectory(directory); + } + + if (JFileChooser.APPROVE_OPTION == jNewStudyChooser.showOpenDialog(EgoClient.getFrame())) { + f = jNewStudyChooser.getSelectedFile(); + + if (f != null) { + try { + if (!f.canRead()) { + throw new FileReadException(); + } else { + setPackageFile(f); + + // Store location in prefs file + if(prefs!=null) + prefs.put(FILE_PREF, f.getParent()); + } + } catch (Exception e) { + JOptionPane.showMessageDialog(null, + "Unable to read study file.", "File Error", + JOptionPane.ERROR_MESSAGE); + } + } + } + } + + /** + * File filter to filter the interview files based on selected study The + * file chooser displays only the interview files compatible with the + * currently chosen study + * + * @author sonam + * + */ + public class VersionFileFilter extends ExtensionFileFilter { + MapCopyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * + * $Id: Interview.java,v 1.1 2005/08/02 19:35:59 samag Exp $ + */ + +import java.util.Collection; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.logging.Logger; + +import javax.swing.DefaultListModel; +import javax.swing.JOptionPane; + +import org.egonet.exceptions.CorruptedInterviewException; +import org.egonet.exceptions.MissingPairException; + +import com.endlessloopsoftware.ego.Answer; +import com.endlessloopsoftware.ego.Question; +import com.endlessloopsoftware.ego.Study; +import com.endlessloopsoftware.ego.client.StatRecord.EgoAnswer; +import com.endlessloopsoftware.ego.client.statistics.Statistics; +import com.endlessloopsoftware.egonet.Shared; +import com.endlessloopsoftware.egonet.util.AnswerDataValue; +import com.endlessloopsoftware.egonet.util.InterviewDataValue; +import com.endlessloopsoftware.elsutils.ELSMath; +import com.endlessloopsoftware.elsutils.files.FileCreateException; + +import electric.xml.Element; +import electric.xml.Elements; + +public class Interview +{ + private final static Logger logger = Logger.getLogger("Interview"); + + private final Answer[] _answers; + private final Study _study; + private int[][] _matrix; + private Statistics _stats = null; + private String[] _egoName = { "", ""}; + private boolean _complete; + private String[] _alterList = new String[0]; + + private int _qIndex = 0; + private final int _numAlterPairs; + private int _numAnswers; + private int _numAlters; + + boolean _statisticsAvailable = false; + + /******** + * Create interview from question list + * @param client parent object for globals + * @param numAlters number of alters to be elicited + * @throws CorruptedInterviewException if unable to read interview + */ + public Interview(Study study) + throws CorruptedInterviewException + { + /* Locals */ + int j, k; + Iterator questions; + + /* Calculate some interview values */ + _study = study; + _numAlters = study.getNumAlters(); + _numAlterPairs = ELSMath.summation(_numAlters - 1); + _numAnswers = + EgoClient.study.getQuestionOrder(Question.EGO_QUESTION).size() + + EgoClient.study.getQuestionOrder(Question.ALTER_PROMPT).size() + + (_numAlters * EgoClient.study.getQuestionOrder(Question.ALTER_QUESTION).size()) + + (_numAlterPairs * EgoClient.study.getQuestionOrder(Question.ALTER_PAIR_QUESTION).size()); + _answers = new Answer[_numAnswers]; + + /* Generate answer instances */ + _qIndex = 0; + + /* Ego Questions */ + questions = EgoClient.study.getQuestionOrder(Question.EGO_QUESTION).iterator(); + while (questions.hasNext()) + { + Long questionId = (Long) questions.next(); + Question question = _study.getQuestions().getQuestion(questionId); + + if (question == null) + { + throw new CorruptedInterviewException(); + } + else + { + _answers[_qIndex++] = new Answer(question.UniqueId, null); + } + } + + /* Alter Prompt Questions */ + questions = EgoClient.study.getQuestionOrder(Question.ALTER_PROMPT).iterator(); + while (questions.hasNext()) + { + Long questionId = (Long) questions.next(); + Question question = _study.getQuestions().getQuestion(questionId); + + if (question == null) + { + throw new CorruptedInterviewException(); + } + else + { + _answers[_qIndex++] = new Answer(question.UniqueId, null); + } + } + + /* Alter Questions */ + for (j = 0; j < _numAlters; j++) + { + questions = EgoClient.study.getQuestionOrder(Question.ALTER_QUESTION).iterator(); + int[] alter = { j }; + while (questions.hasNext()) + { + Long questionId = (Long) questions.next(); + Question question = _study.getQuestions().getQuestion(questionId); + if (question == null) + { + throw new CorruptedInterviewException(); + } + else + { + _answers[_qIndex++] = new Answer(question.UniqueId, alter); + } + } + } + + /* Alter Pair Questions */ + for (k = 0; k < _numAlters; k++) + { + for (j = (k + 1); j < _numAlters; j++) + { + questions = EgoClient.study.getQuestionOrder(Question.ALTER_PAIR_QUESTION).iterator(); + int[] alters = { k, j }; + while (questions.hasNext()) + { + Question question = _study.getQuestions().getQuestion((Long) questions.next()); + + if (question == null) + { + throw new CorruptedInterviewException(); + } + else + { + if (question.statable) + { + _statisticsAvailable = true; + } + + _answers[_qIndex++] = new Answer(question.UniqueId, alters); + } + } + } + } + } + + /***************************************** + * Generate an interview from a datavalue downloaded from a server + * @param data + */ + public Interview(Study study, InterviewDataValue data) + { + System.out.println("Creating Interview from data object"); + _study = study; + _numAlters = study.getNumAlters(); + _statisticsAvailable = true; + + _matrix = data.getAdjacencyMatrix(); + _egoName = new String[] {data.getFirstName(), data.getLastName()}; + _complete = data.getComplete().booleanValue(); + _alterList = data.getAlters(); + _numAnswers = data.getAnswerDataValues().length; + + _numAlterPairs = ELSMath.summation(_alterList.length - 1); + _numAnswers = data.getAnswerDataValues().length; + _answers = new Answer[_numAnswers]; + + //System.out.println(_study.getQuestions().size()); + //System.out.println(_study.getQuestions().dump()); + + for (int i = 0; i < data.getAnswerDataValues().length; ++i) + { + AnswerDataValue answerData = data.getAnswerDataValues()[i]; + _answers[i] = new Answer(answerData); + + //System.out.println("Answer for: " + _study.getQuestion(_answers[i].questionId)); + } + } + + /**** + * Called when user shutting down program + */ + public void exit() + { + if (!_complete) + { + try + { + EgoClient.storage.writeInterviewFile(); + } + catch (FileCreateException ignored) + { + System.err.println("Unable to write Interview File"); + } + } + } + + /**** + * Searches question list for all questions and places them in list + * @param dlm list model to use in inserting questions + */ + public void fillList(DefaultListModel dlm) + { + dlm.removeAllElements(); + + for (int i = 0; i < _numAnswers; i++) + { + //Question q = getQuestion(i); + + Question q = _study.getQuestions().getQuestion(_answers[i].questionId); + + if (q.questionType == Question.ALTER_PAIR_QUESTION && + (_study.getUIType().equals(Shared.PAIR_ELICITATION) || + _study.getUIType().equals(Shared.THREE_STEP_ELICITATION))) + { + /* Skip Alter Pair Questions for Interactive Linking Studies */ + } + else + { + String s = q.toString(); + + if (q.questionType == Question.ALTER_QUESTION) + { + s = s + "; alter " + _answers[i].getAlters()[0]; + } + else if (q.questionType == Question.ALTER_PAIR_QUESTION) + { + s = s + "; alters " + _answers[i].getAlters()[0] + "& " + _answers[i].getAlters()[1]; + } + + s = Question.questionTypeString(q.questionType) + ": " + s; + + dlm.addElement(s); + } + } + } + + /**** + * Returns total number of questions in an interview + * @return i number of questions + */ + public int getNumQuestions() + { + return _numAnswers; + } + + /**** + * Returns current answer from an interview + * Note, multiple answers may refer to same question + * @return i question index + */ + private Answer getCurrentAnswer() + { + return _answers[_qIndex]; + } + + /**** + * Sets current answer from an interview + * @param a new Answer + */ + private void setCurrentAnswer(Answer a) + { + /** @todo Validate answer */ + _answers[_qIndex] = a; + } + + /**** + * Returns current question from an interview + * @return i question index + */ + public int getQuestionIndex() + { + return _qIndex; + } + + /**** + * Returns current list of alters + * @return s String Array of alters + */ + public String[] getAlterList() + { + return _alterList; + } + + /**** + * Sets current list of alters + * @param s String Array of alters + */ + public void setAlterList(String[] s) + { + _alterList = s; + } + + /**** + * Gets a set containing all the answers which use a selected question + * @param qId Unique Identifier of question + * @return Set of answers using this question + */ + public Set getAnswerSubset(Long qId) + { + Set s = new HashSet(_numAlterPairs); + + for (int i = 0; i < _answers.length; i++) + { + if (_answers[i].questionId.equals(qId)) + { + s.add(_answers[i]); + } + } + + return (s); + } + + /**** + * Gets a List containing all the answers to ego questions + * @return List of answers using this question + */ + public List getEgoAnswers() + { + List l = new ArrayList(); + int index = 0; + Question q = _study.getQuestions().getQuestion(_answers[index].questionId); + + while (q.questionType == Question.EGO_QUESTION) + { + l.add(_answers[index]); + q = _study.getQuestions().getQuestion(_answers[++index].questionId); + } + + return (l); + } + + /**** + * Gets a List containing all the answers to alter questions + * @return List of answers using this question + */ + public ListCopyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * + * $Id: ServerInterviewChooser.java,v 1.1 2005/08/02 19:36:00 samag Exp $ + */ +package com.endlessloopsoftware.ego.client; + +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; + +import javax.ejb.FinderException; +import javax.swing.JButton; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JTextField; +import javax.swing.JTree; +import javax.swing.ProgressMonitor; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeSelectionModel; + +import com.cim.dlgedit.loader.DialogResource; +import com.cim.util.swing.DlgUtils; +import com.endlessloopsoftware.ego.Question; +import com.endlessloopsoftware.ego.Shared; +import com.endlessloopsoftware.ego.Study; +import com.endlessloopsoftware.ego.client.statistics.Statistics; +import com.endlessloopsoftware.egonet.interfaces.InterviewSBRemote; +import com.endlessloopsoftware.egonet.interfaces.InterviewSBRemoteHome; +import com.endlessloopsoftware.egonet.interfaces.InterviewSBUtil; +import com.endlessloopsoftware.egonet.interfaces.StudySBRemote; +import com.endlessloopsoftware.egonet.interfaces.StudySBRemoteHome; +import com.endlessloopsoftware.egonet.interfaces.StudySBUtil; +import com.endlessloopsoftware.egonet.util.InterviewDataValue; +import com.endlessloopsoftware.egonet.util.InterviewIdentifier; +import com.endlessloopsoftware.egonet.util.StudyAndInterviewTransfer; +import com.endlessloopsoftware.egonet.util.StudyDataValue; +import com.endlessloopsoftware.elsutils.SwingWorker; + +public class ServerInterviewChooser + extends JPanel + implements ActionListener, TreeSelectionListener +{ + // Types + private final int DECORATION = 0; + private final int STUDY = 1; + private final int INTERVIEW = 2; + + // Declare beans. + private JButton loadInterviews; + private JButton select; + private JPasswordField serverPassword; + private JTextField serverURL; + private JTree interviewTree; + + // Tree handling variables + private DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(); + private DefaultTreeModel treeModel = new DefaultTreeModel(rootNode); + + // Study Server Communication + StudySBRemote studySession; + InterviewSBRemote interviewSession; + + // Constructor. + public ServerInterviewChooser() + { + // Load up the dialog contents. + //JPanel panel = DialogResource.load("com/endlessloopsoftware/ego/client/ServerInterviewChooser.gui_xml"); + java.io.InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/endlessloopsoftware/ego/client/ServerInterviewChooser.gui_xml"); + JPanel panel = DialogResource.load(is); + + // Attach beans to fields. + loadInterviews = (JButton) DialogResource.getComponentByName(panel, "LoadInterviews"); + select = (JButton) DialogResource.getComponentByName(panel, "Select"); + serverPassword = (JPasswordField) DialogResource.getComponentByName(panel, "serverPassword"); + serverURL = (JTextField) DialogResource.getComponentByName(panel, "serverURL"); + interviewTree = (JTree) DialogResource.getComponentByName(panel, "interviewTree"); + + // Clear out Tree to start + interviewTree.addTreeSelectionListener(this); + interviewTree.setModel(treeModel); + rootNode.setUserObject(new TreeSelection("No Server Selected", DECORATION)); + interviewTree.setEditable(false); + interviewTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + interviewTree.setShowsRootHandles(false); + treeModel.reload(); + + select.setEnabled(false); + + // Add dialog as ActionListener. + loadInterviews.setText("Load Studies"); + loadInterviews.addActionListener(this); + select.addActionListener(this); + + this.setLayout(new GridLayout(1, 1)); + this.add(panel); + } + + /** + * Invoke the onXxx() action handlers. + * + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + public void actionPerformed(ActionEvent e) + { + DlgUtils.invokeHandler(this, e); + } + + public void onLoadInterviews() + { + fillTree(); + } + + public void onSelect() + { + Properties prop = new Properties(); + prop.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); + prop.setProperty("java.naming.provider.url", serverURL.getText()+":1099"); + + final DefaultMutableTreeNode node = (DefaultMutableTreeNode) interviewTree.getLastSelectedPathComponent(); + + if (node == null) + { + return; + } + + final String epassword = "215-121-242-47-99-238-5-61-133-183-0-216-187-250-253-30-115-177-254-142-161-83-108-56"; + //SymmetricKeyEncryption.encrypt(new String(serverPassword.getPassword())); + final TreeSelection selection = (TreeSelection) node.getUserObject(); + + int type = selection.getType(); + + switch (type) + { + case STUDY: + { + try + { + final StatRecord[] statRecords = new StatRecord[node.getChildCount()]; + Shared.setWaitCursor(EgoClient.frame, true); + StudyDataValue data = studySession.fetchDataByStudyName(selection.toString(), epassword); + final Study study = new Study(data); + + final ProgressMonitor progressMonitor = new ProgressMonitor(EgoClient.frame, + "Calculating Statistics", "", 0, + node.getChildCount()); + final SwingWorker worker = new SwingWorker() + { + public Object construct() + { + for (int i = 0; i < node.getChildCount(); ++i) + { + DefaultMutableTreeNode interviewNode = (DefaultMutableTreeNode) node.getChildAt(i); + TreeSelection interviewSelection = (TreeSelection) interviewNode.getUserObject(); + + System.out.println("Loading " + interviewSelection.getIdentifier()); + + InterviewIdentifier id = (InterviewIdentifier) interviewSelection.getIdentifier(); + InterviewDataValue interviewData; + try + { + interviewData = interviewSession.fetchUserInterviewData(selection.toString(), + id.getFirstName(), + id.getLastName(), + epassword); + + System.out.println("Creating Interview " + interviewSelection.getIdentifier()); + Interview interview = new Interview(study, interviewData); + + System.out.println("Generating Statistics " + interviewSelection.getIdentifier()); + Question q = study.getFirstStatableQuestion(); + Statistics statistics = interview.generateStatistics(q); + + System.out.println("Most Central Degree Alter " + statistics.mostCentralBetweenAlterName); + + System.out.println("To StatRecord " + interviewSelection.getIdentifier()); + + statRecords[i] = new StatRecord(statistics); + } + catch (Exception e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + //System.out.println("Complete " + interviewSelection.getIdentifier()); + progressMonitor.setProgress(i); + } + + return statRecords; + } + + public void finished() + { + Shared.setWaitCursor(EgoClient.frame, false); + progressMonitor.close(); + SummaryPanel.gotoPanel(statRecords); + } + }; + + progressMonitor.setProgress(0); + progressMonitor.setMillisToDecideToPopup(0); + progressMonitor.setMillisToPopup(0); + + worker.start(); + + } + catch (FinderException e) + { + e.printStackTrace(); + } + catch(java.lang.reflect.UndeclaredThrowableException e) + { + e.printStackTrace(); + System.out.println(e.getUndeclaredThrowable()); + } + catch (Exception e) + { + JOptionPane.showMessageDialog(this, "Unable to load study.\n" + e.getMessage(), "Server Error", + JOptionPane.ERROR_MESSAGE); + e.printStackTrace(); + } + finally + { + Shared.setWaitCursor(EgoClient.frame, false); + } + } + break; + + case INTERVIEW: + { + DefaultMutableTreeNode studyNode = (DefaultMutableTreeNode) node.getParent(); + TreeSelection studySelect = (TreeSelection) studyNode.getUserObject(); + + try + { + Shared.setWaitCursor(EgoClient.frame, true); + + StudyDataValue studyData = studySession.fetchDataByStudyName(studySelect.toString(), epassword); + + InterviewIdentifier id = (InterviewIdentifier) selection.getIdentifier(); + InterviewDataValue interviewData = interviewSession.fetchUserInterviewData(studySelect.toString(), + id.getFirstName(), + id.getLastName(), + epassword); + + EgoClient.uiPath = EgoClient.VIEW_INTERVIEW; + + EgoClient.storage.setInterviewFile(null); + EgoClient.interview = null; + + Study study = new Study(studyData); + EgoClient.study = study; + +// System.out.println(EgoClient.study.getQuestions().size()); +// System.out.println(EgoClient.study.getQuestions().dump()); +// + EgoClient.interview = new Interview(study, interviewData); + + if (EgoClient.interview != null) + { + ViewInterviewPanel.gotoPanel(); + } + } + catch (FinderException e) + { + JOptionPane.showMessageDialog(this, "Unable to load interview.", "Server Error", + JOptionPane.ERROR_MESSAGE); + } + catch (Exception e) + { + JOptionPane.showMessageDialog(this, "Unable to load interview.\n" + e.getMessage(), "Server Error", + JOptionPane.ERROR_MESSAGE); + e.printStackTrace(); + } + finally + { + Shared.setWaitCursor(EgoClient.frame, false); + } + + } + + default: + break; + } + } + + /** + * @author admin + * + * To change the template for this generated type comment go to + * Window - Preferences - Java - Code Generation - Code and Comments + */ + public void fillTree() + { + try + { + Shared.setWaitCursor(EgoClient.frame, true); + + Properties prop = new Properties(); + prop.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); + prop.setProperty("java.naming.provider.url", serverURL.getText()+":1099"); + + StudySBRemoteHome studySBHome = StudySBUtil.getHome(prop); + studySession = studySBHome.create(); + InterviewSBRemoteHome interviewSBHome = InterviewSBUtil.getHome(prop); + interviewSession = interviewSBHome.create(); + Set studyNames = studySession.getStudyAndInterviewNames(); + + //System.out.println("Found " + studyNames.size() + " studies."); + + rootNode.removeAllChildren(); + + for (Iterator it = studyNames.iterator(); it.hasNext();) + { + StudyAndInterviewTransfer xfer = (StudyAndInterviewTransfer) it.next(); + + DefaultMutableTreeNode studyNode = new DefaultMutableTreeNode(new TreeSelection(xfer.studyName, STUDY)); + + for (Iterator ints = xfer.interviewIdentifiers.iterator(); ints.hasNext();) + { + InterviewIdentifier id = (InterviewIdentifier) ints.next(); + studyNode.add(new DefaultMutableTreeNode(new TreeSelection(id, INTERVIEW))); + } + + rootNode.add(studyNode); + } + + if (studyNames.size() > 0) rootNode.setUserObject(new TreeSelection("Studies", DECORATION)); + else rootNode.setUserObject(new TreeSelection("No Studies Found", DECORATION)); + + treeModel.reload(); + } + catch (Exception e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + finally + { + Shared.setWaitCursor(EgoClient.frame, false); + } + } + + /* (non-Javadoc) + * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent) + */ + public void valueChanged(TreeSelectionEvent e) + { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) interviewTree.getLastSelectedPathComponent(); + + if (node == null) + { + select.setEnabled(false); + return; + } + + TreeSelection selection = (TreeSelection) node.getUserObject(); + + if (select != null) + { + if (selection.getType() == STUDY) + { + select.setText("View Study Summary"); + select.setEnabled(true); + } + else if (selection.getType() == INTERVIEW) + { + select.setText("View Interview"); + select.setEnabled(true); + } + else + { + select.setEnabled(false); + } + } + else + { + select.setEnabled(false); + } + select.setEnabled((selection != null) && ((selection.getType() == STUDY) || (selection.getType() == INTERVIEW))); + } + + private class TreeSelection + { + private Object _id; + private int _type; + + public TreeSelection(Object id, int type) + { + _id = id; + _type = type; + } + + public String toString() + { + return _id.toString(); + } + + public int getType() + { + return _type; + } + + public Object getIdentifier() + { + return _id; + } + } + +} + +/** + * $Log: ServerInterviewChooser.java,v $ + * Revision 1.1 2005/08/02 19:36:00 samag + * Initial checkin + * + * Revision 1.11 2004/04/11 15:19:28 admin + * Using password to access server + * + * Remote study summary in seperate thread with progress monitor + * + * Revision 1.10 2004/04/08 15:06:07 admin + * EgoClient now creates study summaries from Server + * EgoAuthor now sets active study on server + * + * Revision 1.9 2004/04/07 00:08:31 admin + * updating manifests, jar creation. Removing author specific objects from + * client specific references + * + * Revision 1.8 2004/04/06 15:43:26 admin + * Moving matrix generation into interview to support Applet Linking UI. + * An interview generated with applet linking will have no meaningful alter pair + * questions. The adjacency matrix will be returned in an Athenian manner from + * the server. + * + * Revision 1.7 2004/04/06 14:56:02 admin + * Work to integrate with Applet Linking UI + * + * Revision 1.6 2004/03/29 00:35:09 admin + * Downloading Interviews + * Fixing some bugs creating Interviews from Data Objects + * + * Revision 1.5 2004/03/28 17:31:32 admin + * More error handling when uploading study to server + * Server URL selection dialog for upload + * + * Revision 1.4 2004/03/23 14:58:48 admin + * Update UI + * Study creation now occurs in instantiators + * + * Revision 1.3 2004/03/22 20:09:17 admin + * Includes interviews in selection box + * + * Revision 1.2 2004/03/22 00:00:34 admin + * Extended text entry area + * Started work on importing studies from server + * + * Revision 1.1 2004/03/20 18:13:59 admin + * Adding remote selection dialog + * + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/SourceSelectPanel.java b/src/com/endlessloopsoftware/ego/client/SourceSelectPanel.java new file mode 100644 index 0000000..373f33e --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/SourceSelectPanel.java @@ -0,0 +1,80 @@ +/** + *Copyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * + * $Id: SourceSelectPanel.java,v 1.1 2005/08/02 19:36:01 samag Exp $ + */ +package com.endlessloopsoftware.ego.client; + +import java.awt.Dimension; +import java.awt.Toolkit; + +import javax.swing.JFrame; +import javax.swing.JTabbedPane; + +/** + * @author admin + * + * To change the template for this generated type comment go to + * Window - Preferences - Java - Code Generation - Code and Comments + */ +public class SourceSelectPanel + extends JTabbedPane +{ + public SourceSelectPanel() + { + super(); + this.addTab("Local Files", new ClientPanel()); + // this.addTab("Remote Server", new ServerInterviewChooser()); + //this.addTab("Test Panel", new TestPanel()); + } + + public static void gotoPanel(boolean center) + { + /* Return to first screen */ +// EgoClient.frame.setVisible(false); + EgoClient.frame.setContentPane(new SourceSelectPanel()); + EgoClient.frame.createMenuBar(EgoClient.SELECT); + EgoClient.frame.pack(); + //EgoClient.frame.setSize(600, 500); + EgoClient.frame.setExtendedState(EgoClient.frame.getExtendedState()|JFrame.MAXIMIZED_BOTH); + + if (center) + { + //Center the window + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension frameSize = EgoClient.frame.getSize(); + if (frameSize.height > screenSize.height) + { + frameSize.height = screenSize.height; + } + if (frameSize.width > screenSize.width) + { + frameSize.width = screenSize.width; + } + EgoClient.frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); + + } + + EgoClient.frame.setVisible(true); + } +} + + +/** + * $Log: SourceSelectPanel.java,v $ + * Revision 1.1 2005/08/02 19:36:01 samag + * Initial checkin + * + * Revision 1.2 2004/03/21 14:00:39 admin + * Cleaned up Question Panel Layout using FOAM + * + * Revision 1.1 2004/03/20 18:13:59 admin + * Adding remote selection dialog + * + * Revision 1.1 2004/03/19 20:28:45 admin + * Converted statistics frome to a panel. Incorporated in a tabbed panel + * as part of main frame. + * + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/StartPanel.java b/src/com/endlessloopsoftware/ego/client/StartPanel.java new file mode 100644 index 0000000..da3d561 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/StartPanel.java @@ -0,0 +1,295 @@ +package com.endlessloopsoftware.ego.client; + +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingConstants; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +import com.endlessloopsoftware.elsutils.documents.AlphaDocument; +import com.endlessloopsoftware.elsutils.files.FileCreateException; +import com.endlessloopsoftware.elsutils.files.FileReadException; + +/** + *Title: Egocentric Networks Client Program
+ *Description: Subject Interview Client
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * @version 1.0 + */ + +public class StartPanel extends JPanel +{ + private final GridBagLayout gridBagLayout1 = new GridBagLayout(); + private final JLabel titleLabel = new JLabel("What is your name?"); + private final JLabel firstNameLabel = new JLabel("First: "); + private final JTextField firstNameField = new JTextField(); + private final JLabel lastNameLabel = new JLabel("Last: "); + private final JTextField lastNameField = new JTextField(); + private final JButton startInterviewButton = new JButton("Start Interview"); + private final AlphaDocument firstNameDocument = new AlphaDocument(); + private final AlphaDocument lastNameDocument = new AlphaDocument(); + + public StartPanel() + { + try + { + jbInit(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + private void jbInit() throws Exception + { + this.setLayout(gridBagLayout1); + + titleLabel.setFont(new java.awt.Font("Lucida Grande", 1, 16)); + titleLabel.setHorizontalAlignment(SwingConstants.CENTER); + titleLabel.setHorizontalTextPosition(SwingConstants.CENTER); + firstNameLabel.setHorizontalTextPosition(SwingConstants.RIGHT); + lastNameLabel.setHorizontalTextPosition(SwingConstants.RIGHT); + startInterviewButton.setEnabled(false); + + this.setBorder(BorderFactory.createEtchedBorder()); + this.add( + titleLabel, + new GridBagConstraints( + 0, + 0, + 2, + 1, + 1.0, + 0.2, + GridBagConstraints.CENTER, + GridBagConstraints.HORIZONTAL, + new Insets(0, 0, 0, 0), + 0, + 0)); + this.add( + firstNameLabel, + new GridBagConstraints( + 0, + 1, + 1, + 1, + 0.3, + 0.1, + GridBagConstraints.CENTER, + GridBagConstraints.NONE, + new Insets(0, 0, 0, 0), + 0, + 0)); + this.add( + firstNameField, + new GridBagConstraints( + 1, + 1, + 1, + 1, + 0.7, + 0.0, + GridBagConstraints.CENTER, + GridBagConstraints.HORIZONTAL, + new Insets(10, 10, 10, 10), + 0, + 6)); + this.add( + lastNameLabel, + new GridBagConstraints( + 0, + 2, + 1, + 1, + 0.0, + 0.1, + GridBagConstraints.CENTER, + GridBagConstraints.NONE, + new Insets(0, 0, 0, 0), + 0, + 0)); + this.add( + lastNameField, + new GridBagConstraints( + 1, + 2, + 1, + 1, + 0.0, + 0.0, + GridBagConstraints.CENTER, + GridBagConstraints.HORIZONTAL, + new Insets(10, 10, 10, 10), + 0, + 6)); + this.add( + startInterviewButton, + new GridBagConstraints( + 0, + 3, + 2, + 1, + 0.0, + 0.0, + GridBagConstraints.CENTER, + GridBagConstraints.HORIZONTAL, + new Insets(20, 80, 20, 80), + 0, + 0)); + + startInterviewButton.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(ActionEvent e) + { + startInterviewButton_actionPerformed(e); + } + }); + + firstNameField.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(ActionEvent e) + { + firstNameField_actionPerformed(e); + } + }); + + lastNameField.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(ActionEvent e) + { + lastNameField_actionPerformed(e); + } + }); + + firstNameField.setDocument(firstNameDocument); + firstNameDocument.addDocumentListener(new DocumentListener() + { + public void insertUpdate(DocumentEvent e) + { + textEvent(e); + } + public void changedUpdate(DocumentEvent e) + { + textEvent(e); + } + public void removeUpdate(DocumentEvent e) + { + textEvent(e); + } + }); + + lastNameField.setDocument(lastNameDocument); + lastNameDocument.addDocumentListener(new DocumentListener() + { + public void insertUpdate(DocumentEvent e) + { + textEvent(e); + } + public void changedUpdate(DocumentEvent e) + { + textEvent(e); + } + public void removeUpdate(DocumentEvent e) + { + textEvent(e); + } + }); + } + + static void gotoPanel() + { + /* Return to first screen */ + EgoClient.frame.setVisible(false); + EgoClient.frame.setContentPane(new StartPanel()); + EgoClient.frame.pack(); + EgoClient.frame.setSize(350, 350); + //EgoClient.frame.setExtendedState(EgoClient.frame.getExtendedState()|JFrame.MAXIMIZED_BOTH); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension frameSize = EgoClient.frame.getSize(); + if (frameSize.height > screenSize.height) + { + frameSize.height = screenSize.height; + } + if (frameSize.width > screenSize.width) + { + frameSize.width = screenSize.width; + } + EgoClient.frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); + EgoClient.frame.setVisible(true); + } + + void startInterviewButton_actionPerformed(ActionEvent e) + { + boolean success = false; + + /* Logic */ + try + { + EgoClient.interview.setName(firstNameField.getText(), lastNameField.getText()); + + success = EgoClient.storage.saveInterview(); + } + catch (FileCreateException ex) + { + success = false; + } + catch (FileReadException ex) + { + success = false; + } + + /* UI */ + if (success) + { + ClientQuestionPanel.gotoPanel(); + } + else + { + SourceSelectPanel.gotoPanel(false); + } + } + + protected void lastNameField_actionPerformed(ActionEvent e) + { + if (firstNameField.getText().length() == 0) + { + firstNameField.requestFocus(); + } + else + { + startInterviewButton_actionPerformed(e); + } + } + + protected void firstNameField_actionPerformed(ActionEvent e) + { + if (lastNameField.getText().length() == 0) + { + lastNameField.requestFocus(); + } + else + { + startInterviewButton_actionPerformed(e); + } + } + + protected void textEvent(DocumentEvent e) + { + startInterviewButton.setEnabled( + (firstNameField.getText().length() > 0) && (lastNameField.getText().length() > 0)); + } +} \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/StatRecord.java b/src/com/endlessloopsoftware/ego/client/StatRecord.java new file mode 100644 index 0000000..cdbb303 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/StatRecord.java @@ -0,0 +1,215 @@ +/** + *Copyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * + * $Id: StatRecord.java,v 1.1 2005/08/02 19:36:00 samag Exp $ + */ +package com.endlessloopsoftware.ego.client; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.endlessloopsoftware.ego.client.statistics.AlterStats; +import com.endlessloopsoftware.ego.client.statistics.Statistics; + +import electric.xml.Element; +import electric.xml.Elements; + +public class StatRecord +{ + String name = ""; + String degreeName = ""; + Integer degreeValue = new Integer(0); + Float degreeMean = new Float(0); + Float degreeNC = new Float(0); + + String betweenName = ""; + Float betweenValue = new Float(0); + Float betweenMean = new Float(0); + Float betweenNC = new Float(0); + + String closenessName = ""; + Float closenessValue = new Float(0); + Float closenessMean = new Float(0); + Float closenessNC = new Float(0); + + Integer numCliques = new Integer(0); + Integer numComponents = new Integer(0); + Integer numIsolates = new Integer(0); + Integer numDyads = new Integer(0); + + List egoAnswers = new ArrayList(); + List alterAnswers = new ArrayList(); + + + public List getEgoAnswers() + { + return egoAnswers; + } + public List getAlterAnswers() + { + return alterAnswers; + } + + public StatRecord(Element e) + { + Element nameElem = e.getElement("EgoName"); + if (nameElem != null) + { + name = nameElem.getString("First") + " " + nameElem.getString("Last"); + } + + degreeName = e.getString("DegreeName"); + degreeValue = new Integer(e.getInt("DegreeValue")); + degreeMean = new Float(e.getFloat("DegreeMean")); + degreeNC = new Float(e.getFloat("DegreeNC")); + + closenessName = e.getString("ClosenessName"); + closenessValue = new Float(e.getFloat("ClosenessValue")); + closenessMean = new Float(e.getFloat("ClosenessMean")); + closenessNC = new Float(e.getFloat("ClosenessNC")); + + betweenName = e.getString("BetweenName"); + betweenValue = new Float(e.getFloat("BetweenValue")); + betweenMean = new Float(e.getFloat("BetweenMean")); + betweenNC = new Float(e.getFloat("BetweenNC")); + + numCliques = new Integer(e.getInt("NumCliques")); + numComponents = new Integer(e.getInt("NumComponents")); + numIsolates = new Integer(e.getInt("NumIsolates")); + numDyads = new Integer(e.getInt("NumDyads")); + + Elements egoList = e.getElement("EgoAnswers").getElements("EgoAnswer"); + while (egoList.hasMoreElements()) + { + egoAnswers.add(new EgoAnswer(egoList.next())); + } + + Elements alterList = e.getElement("AlterQuestionSummaries").getElements("AlterQuestionSummary"); + while (alterList.hasMoreElements()) + { + alterAnswers.add(new AlterAnswer(alterList.next())); + } + } + + public StatRecord(Statistics stats) + { + name = stats.getInterview().getName()[0] + " " + stats.getInterview().getName()[1]; + + degreeName = stats.mostCentralDegreeAlterName; + degreeValue = new Integer(stats.mostCentralDegreeAlterValue); + degreeMean = new Float(stats.meanCentralDegreeValue); + degreeNC = new Float(stats.degreeNC); + + closenessName = stats.mostCentralClosenessAlterName; + closenessValue = new Float(stats.mostCentralClosenessAlterValue); + closenessMean = new Float(stats.meanCentralClosenessValue); + closenessNC = new Float(stats.closenessNC); + + betweenName = stats.mostCentralBetweenAlterName; + betweenValue = new Float(stats.mostCentralBetweenAlterValue); + betweenMean = new Float(stats.meanCentralBetweenAlterValue); + betweenNC = new Float(stats.betweenNC); + + numCliques = new Integer(stats.cliqueSet.size()); + numComponents = new Integer(stats.componentSet.size() - stats.isolates - stats.dyads); + numIsolates = new Integer(stats.isolates); + numDyads = new Integer(stats.dyads); + + egoAnswers = Arrays.asList(stats.getInterview().getEgoAnswerArray(this)); + + for (int i = 0; i < stats.alterStatArray.length; ++i) + { + alterAnswers.add(new AlterAnswer(stats.alterStatArray[i])); + } + } + + public class EgoAnswer + { + String title; + String answer; + int index; + + protected EgoAnswer(Element e) + { + title = e.getString("Title"); + answer = e.getString("Answer"); + index = e.getInt("AnswerIndex"); + } + + public EgoAnswer(String title, String answer, int index) + { + this.title = title; + this.answer = answer; + this.index = index; + } + } + + public class AlterAnswer + { + String title; + int count; + String[] selections; + int[] totals; + //code added + int[] AnswerIndex; + //end of add + + protected AlterAnswer(Element e) + { + int index=0; + + title = e.getString("Title"); + count = e.getInt("Count"); + + + Elements answerList = e.getElement("Answers").getElements("Answer"); + selections = new String[answerList.size()]; + totals = new int[answerList.size()]; + //added by sonam 08/24/07 + AnswerIndex = new int[answerList.size()]; + //end + while (answerList.hasMoreElements()) + { + Element a = answerList.next(); + + index = a.getInt("AnswerIndex"); + selections[index] = a.getString("Text"); + totals[index] = a.getInt("Total"); + //added by sonam 08/24/07 + AnswerIndex[index] = a.getInt("AnswerIndex"); + //end + } + } + + protected AlterAnswer(AlterStats alterStats) + { + title = alterStats.qTitle; + count = alterStats.answerCount; + selections = (String[]) alterStats.answerText.clone(); + totals = (int[]) alterStats.answerTotals.clone(); + } + + public String[] getSelections() { + return selections; + } + + public String getTitle() { + return title; + } + + } +} + +/** + * $Log: StatRecord.java,v $ + * Revision 1.1 2005/08/02 19:36:00 samag + * Initial checkin + * + * Revision 1.1 2004/04/08 15:06:07 admin + * EgoClient now creates study summaries from Server + * EgoAuthor now sets active study on server + * + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/SummaryPanel.java b/src/com/endlessloopsoftware/ego/client/SummaryPanel.java new file mode 100644 index 0000000..fe8a1c0 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/SummaryPanel.java @@ -0,0 +1,555 @@ + +package com.endlessloopsoftware.ego.client; + +/** + *Copyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * + * $Id: SummaryPanel.java,v 1.1 2005/08/02 19:36:00 samag Exp $ + */ +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.PrintWriter; +import java.text.DecimalFormat; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.ProgressMonitor; + +import com.endlessloopsoftware.ego.Shared; +import com.endlessloopsoftware.ego.client.statistics.StatisticsArrayPanel; +import com.endlessloopsoftware.ego.client.statistics.models.StatTableModel; +import com.endlessloopsoftware.elsutils.SwingWorker; +import com.endlessloopsoftware.elsutils.files.DirList; +import com.endlessloopsoftware.elsutils.files.FileHelpers; + +import electric.xml.Document; +import electric.xml.Element; + +public class SummaryPanel extends JPanel +{ + private final JButton _finishedButton = new JButton("Finished"); + private JPanel _summaryPanel; + + private StatRecord[] _stats = new StatRecord[0]; + private int _recordCount = 0; + + + public SummaryPanel(StatRecord[] stats) + { + setLayout(new GridBagLayout()); + + /* Get data to display */ + _stats = stats; + _recordCount = stats.length; + + /* Load table */ + _summaryPanel = new StatisticsArrayPanel(new SummaryModel(this)); + + add(_summaryPanel, + new GridBagConstraints( 0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); + add(_finishedButton, + new GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, + GridBagConstraints.EAST, GridBagConstraints.NONE, + new Insets(5, 5, 5, 5), 0, 0)); + + _finishedButton.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(ActionEvent e) + { + finishedButton_actionPerformed(e); + } + }); + } + + public SummaryPanel(ProgressMonitor progress) + { + setLayout(new GridBagLayout()); + + /* Get data to display */ + loadInterviewArray(progress); + + /* Load table */ + _summaryPanel = new StatisticsArrayPanel(new SummaryModel(this)); + + add(_summaryPanel, + new GridBagConstraints( 0, 0, 1, 1, 1.0, 1.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); + add(_finishedButton, + new GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, + GridBagConstraints.EAST, GridBagConstraints.NONE, + new Insets(5, 5, 5, 5), 0, 0)); + + _finishedButton.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(ActionEvent e) + { + finishedButton_actionPerformed(e); + } + }); + } + + static void gotoPanel(StatRecord[] stats) + { + // Build Screen + EgoClient.frame.setVisible(false); + Shared.setWaitCursor(EgoClient.frame, true); + EgoClient.frame.setContentPane(new SummaryPanel(stats)); + EgoClient.frame.createMenuBar(EgoClient.VIEW_SUMMARY); + EgoClient.frame.pack(); + // EgoClient.frame.setSize(640, 530); + EgoClient.frame.setExtendedState(EgoClient.frame.getExtendedState()|JFrame.MAXIMIZED_BOTH); + Shared.setWaitCursor(EgoClient.frame, false); + EgoClient.frame.setVisible(true); + } + + static void gotoPanel() + { + final ProgressMonitor progressMonitor = new ProgressMonitor(EgoClient.frame, "Calculating Statistics", "", 0, 100); + final SwingWorker worker = new SwingWorker() + { + public Object construct() + { + // Build Screen + EgoClient.frame.setVisible(false); + Shared.setWaitCursor(EgoClient.frame, true); + EgoClient.frame.setContentPane(new SummaryPanel(progressMonitor)); + EgoClient.frame.createMenuBar(EgoClient.VIEW_SUMMARY); + EgoClient.frame.pack(); + //EgoClient.frame.setSize(640, 530); + EgoClient.frame.setExtendedState(EgoClient.frame.getExtendedState()|JFrame.MAXIMIZED_BOTH); + return EgoClient.frame; + } + + public void finished() + { + Shared.setWaitCursor(EgoClient.frame, false); + EgoClient.frame.setVisible(true); + + if (progressMonitor.isCanceled()) + { + SourceSelectPanel.gotoPanel(false); + } + progressMonitor.close(); + } + }; + + progressMonitor.setProgress(0); + progressMonitor.setMillisToDecideToPopup(0); + progressMonitor.setMillisToPopup(0); + + worker.start(); + } + + private void finishedButton_actionPerformed(ActionEvent e) + { + SourceSelectPanel.gotoPanel(false); + } + + private void loadInterviewArray(ProgressMonitor progress) + { + File intPath = new File(EgoClient.storage.getPackageFile().getParent(), "/Interviews/"); + File istPath = new File(EgoClient.storage.getPackageFile().getParent(), "/Statistics/"); + String[] intFiles = DirList.getDirList(intPath, "int"); + Set istFileSet = new HashSet(); + int i = 0, p = 0; + + istPath.mkdir(); + + progress.setMinimum(0); + progress.setMaximum(intFiles.length * 2); + + for (i = 0; (i < intFiles.length) && !progress.isCanceled(); i++) + { + progress.setProgress(++p); + + String thisIntFileName = intFiles[i]; + File intFile = new File(intPath, thisIntFileName); + File thisIstFile, thisMatrixFile, thisWeightedMatrixFile; + + // Check that this has the correct Study Id + try + { + String istPathString = istPath.getCanonicalPath(); + thisIstFile = EgoStore.int2ist(istPathString, intFiles[i]); + thisMatrixFile = EgoStore.int2matrix(istPathString, intFiles[i]); + thisWeightedMatrixFile = EgoStore.int2weightedmatrix(istPathString, intFiles[i]); + + if (!(thisIstFile.exists() && thisMatrixFile.exists() && thisWeightedMatrixFile.exists())) + { + Document document = new Document(intFile); + Element root = document.getRoot(); + long id = Long.parseLong(root.getAttribute("StudyId")); + + if (id == EgoClient.study.getStudyId()) + { + EgoClient.storage.generateStatisticsFile(intFile); + istFileSet.add(thisIstFile); + } + } + else + { + // IST files exists, check for compliance + Document document = new Document(thisIstFile); + Element root = document.getRoot(); + long id = Long.parseLong(root.getAttribute("StudyId")); + String creator = root.getAttribute("Creator"); + + if (id == EgoClient.study.getStudyId()) + { + //Commented this out because it would not create a new IST file when new measures are added + if (creator.equals(Shared.version)) + { + istFileSet.add(thisIstFile); + } + else + { + EgoClient.storage.generateStatisticsFile(intFile); + istFileSet.add(thisIstFile); + } + } + } + } + catch (Exception ignored) + { + } + } + + _stats = new StatRecord[istFileSet.size()]; + + progress.setMaximum(intFiles.length + istFileSet.size()); + for (Iterator it = istFileSet.iterator(); it.hasNext() && !progress.isCanceled();) + { + progress.setProgress(++p); + + try + { + Document document = new Document((File) it.next()); + Element root = document.getRoot(); + + StatRecord rec = new StatRecord(root); + + if (rec != null) + { + _stats[_recordCount++] = rec; + } + } + catch (Exception ignored) + { + ignored.printStackTrace(); + } + } + } + + public void writeStudySummary(PrintWriter w) + { + Iterator it; + StatRecord stat = _stats[0]; + DecimalFormat percentFormatter = new DecimalFormat("#.##"); + + if (_stats.length == 0) + { + return; + } + + /******* + * Column Headers + */ + w.print("Respondant_Name"); + it = stat.egoAnswers.iterator(); + while (it.hasNext()) + { + w.print(", " + FileHelpers.formatForCSV(((StatRecord.EgoAnswer) it.next()).title)); + } + + it = stat.alterAnswers.iterator(); + while (it.hasNext()) + { + StatRecord.AlterAnswer answer = (StatRecord.AlterAnswer) it.next(); + String title = FileHelpers.formatForCSV(answer.title); + + if (answer.selections.length == 1) + { + w.print(", " + title + "_mn"); + } + else + { + + //Code commented and changed by sonam 08/24/07 + /*for (int i = 0; i < answer.selections.length; i++) + { + w.print(", " + title + i + "N"); + w.print(", " + title + i + "P"); + }*/ + + for (int i = 0; i < answer.selections.length; i++) + { + + w.print(", " + title + "|Answer:" + answer.selections[i] + + "|Value:" + answer.AnswerIndex[i] + "|Count"); + w.print(", " + title + "|Answer:" + answer.selections[i] + + "|Value:" + answer.AnswerIndex[i] + "|Percentage"); + + } + //end of code modify + } + } + /*w.println( + ", Max_Deg_Name, Max_Deg_Value, Max_Close_Name, Max_Close_Value" + + ", Max_Between_Name, Max_Between_Value, #_Cliques, #_Components");*/ + w.println( + ", Max_Deg_Name, Max_Deg_Value, Max_Close_Name, Max_Close_Value" + + ", Max_Between_Name, Max_Between_Value, N_Cliques, N_Components, Degree_Mean" + + ", Closeness_Mean, Between_Mean, DegreeNC, ClosenessNC, BetweenNC" + + ", N_Isolates, N_Dyads"); + + /******* + * Data Lines + */ + for (int i = 0; i < _recordCount; i++) + { + stat = _stats[i]; + + w.print(FileHelpers.formatForCSV(stat.name)); + + it = stat.egoAnswers.iterator(); + while (it.hasNext()) + { + w.print(", " + ((StatRecord.EgoAnswer) it.next()).index); + } + + it = stat.alterAnswers.iterator(); + while (it.hasNext()) + { + StatRecord.AlterAnswer answer = (StatRecord.AlterAnswer) it.next(); + + if (answer.selections.length == 1) + { + if ((answer.count == 0) || (answer.totals[0] == 0)) + { + w.print(", " + 0); + } + else + { + w.print(", " + ((float) answer.totals[0] / answer.count)); + } + } + else + { + for (int j = 0; j < answer.selections.length; j++) + { + w.print(", " + answer.totals[j]); + + if ((answer.count == 0) || (answer.totals[j] == 0)) + { + w.print(", " + 0); + } + else + { + w.print(", " + percentFormatter.format((double) answer.totals[j] / answer.count)); + } + } + } + } + + w.println( + ", " + + FileHelpers.formatForCSV(stat.degreeName) + + ", " + + stat.degreeValue + + ", " + + FileHelpers.formatForCSV(stat.closenessName) + + ", " + + stat.closenessValue + + ", " + + FileHelpers.formatForCSV(stat.betweenName) + + ", " + + stat.betweenValue + + ", " + + stat.numCliques + + ", " + + stat.numComponents + + ", " + + stat.degreeMean + + ", " + + (stat.closenessMean.floatValue()== -1 ? ".":stat.closenessMean.toString()) + + ", " + + stat.betweenMean + + ", " + + stat.degreeNC + + ", " + + stat.closenessNC + + ", " + + stat.betweenNC + + "," + + stat.numIsolates + + "," + + stat.numDyads); + } + } + + class SummaryModel extends StatTableModel + { + private final SummaryPanel summaryPanel; + SummaryModel(SummaryPanel parent) + { + summaryPanel = parent; + } + + public int getColumnCount() + { + if (summaryPanel._recordCount > 0) + { + return 17; + } + else + { + return 1; + } + } + + public Object getValueAt(int rowIndex, int columnIndex) + { + if (rowIndex < summaryPanel._recordCount) + { + try + { + switch (columnIndex) + { + case 0 : + return (summaryPanel._stats[rowIndex].name); /* Name */ + case 1 : + return (summaryPanel._stats[rowIndex].degreeName); /* Max Degree Name */ + case 2 : + return (summaryPanel._stats[rowIndex].degreeValue); + case 3 : + return (summaryPanel._stats[rowIndex].closenessName); /* Max Closeness Name */ + case 4 : + return (summaryPanel._stats[rowIndex].closenessValue); + case 5 : + return (summaryPanel._stats[rowIndex].betweenName); /* Max Betweenness Name */ + case 6 : + return (summaryPanel._stats[rowIndex].betweenValue); + case 7 : + return (summaryPanel._stats[rowIndex].numCliques); /* # Cliques */ + case 8 : + return (summaryPanel._stats[rowIndex].numComponents); /* # Components */ + case 9 : + return (summaryPanel._stats[rowIndex].degreeMean); + case 10 : + return (summaryPanel._stats[rowIndex].closenessMean); + case 11 : + return (summaryPanel._stats[rowIndex].betweenMean); + case 12 : + return (summaryPanel._stats[rowIndex].degreeNC); + case 13 : + return (summaryPanel._stats[rowIndex].closenessNC); + case 14 : + return (summaryPanel._stats[rowIndex].betweenNC); + case 15 : + return (summaryPanel._stats[rowIndex].numIsolates); /* Components size 1 */ + case 16 : + return (summaryPanel._stats[rowIndex].numDyads); /* Components size 2*/ + default : + return (null); + } + } + catch (Exception ex) + { + ex.printStackTrace(); + return (null); + } + } + else + { + return (null); + } + } + + public int getRowCount() + { + if (summaryPanel._recordCount > 0) + { + return summaryPanel._recordCount; + } + else + { + return 0; + } + } + + public String getColumnName(int column) + { + if (summaryPanel._recordCount > 0) + { + switch (column) + { + case 0 : + return ("Name"); + case 1 : + return ("Degree Max"); + case 3 : + return ("Closeness Max"); + case 5 : + return ("Betweenness Max"); + case 7 : + return ("# Cliques"); + case 8 : + return ("# Components"); + case 9 : + return ("Degree Mean"); + case 10: + return ("Closeness Mean"); + case 11: + return ("Betweenness Mean"); + case 12: + return ("Degree NC"); + case 13: + return ("Closeness NC"); + case 14: + return ("Betweenness NC"); + case 15: + return ("# Isolates"); + case 16: + return ("# Dyads"); + default : + return (null); + } + } + else + { + return ("No matching interviews found"); + } + } + + public int getResizeMode() + { + return JTable.AUTO_RESIZE_OFF; + } + } + +} + + +/** + * $Log: SummaryPanel.java,v $ + * Revision 1.1 2005/08/02 19:36:00 samag + * Initial checkin + * + * Revision 1.11 2004/04/08 15:06:07 admin + * EgoClient now creates study summaries from Server + * EgoAuthor now sets active study on server + * + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/TestPanel.java b/src/com/endlessloopsoftware/ego/client/TestPanel.java new file mode 100644 index 0000000..b220969 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/TestPanel.java @@ -0,0 +1,29 @@ +package com.endlessloopsoftware.ego.client; + +import com.cim.dlgedit.loader.DialogResource; + +import java.awt.GridBagLayout; +import java.awt.GridLayout; + +import javax.swing.JPanel; +import javax.swing.JButton; + +public class TestPanel +extends JPanel{ + private final GridBagLayout gblayout2 = new GridBagLayout(); + private JButton JB1; + public TestPanel(){ + try{ + JPanel panel = DialogResource.load("com/endlessloopsoftware/ego/client/localSelect.gui_xml"); + JB1 = (JButton)DialogResource.getComponentByName(panel,"Test Button"); + jbInit(); + this.setLayout(new GridLayout()); + this.add(panel); + } + catch(Exception e){} + } + + private void jbInit() throws Exception{ + + } +} \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/ViewInterviewPanel.java b/src/com/endlessloopsoftware/ego/client/ViewInterviewPanel.java new file mode 100644 index 0000000..be26e1d --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/ViewInterviewPanel.java @@ -0,0 +1,94 @@ +/** + *Copyright: Copyright (c) 2002 - 2004
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * + * $Id: ViewInterviewPanel.java,v 1.1 2005/08/02 19:36:00 samag Exp $ + */ +package com.endlessloopsoftware.ego.client; + +import javax.swing.JFrame; +import javax.swing.JTabbedPane; +import javax.swing.ProgressMonitor; + +import com.endlessloopsoftware.ego.Shared; +import com.endlessloopsoftware.ego.client.statistics.StatisticsFrame; +import com.endlessloopsoftware.elsutils.SwingWorker; +import com.endlessloopsoftware.ego.client.graph.*; + +public class ViewInterviewPanel + extends JTabbedPane +{ + public ViewInterviewPanel(ProgressMonitor progress) + { + super(); + progress.setProgress(10); + this.addTab("Interview", new ClientQuestionPanel()); + progress.setProgress(15); + this.addTab("Statistics", new StatisticsFrame()); + this.addTab("Graph", new GraphPanel()); + progress.setProgress(70); + } + + static void gotoPanel() + { + final ProgressMonitor progressMonitor = new ProgressMonitor(EgoClient.frame, "Calculating Statistics", "", 0, 100); + final SwingWorker worker = new SwingWorker() + { + public Object construct() + { + // Build Screen + EgoClient.frame.setVisible(false); + Shared.setWaitCursor(EgoClient.frame, true); + progressMonitor.setProgress(5); + EgoClient.frame.setContentPane(new ViewInterviewPanel(progressMonitor)); + progressMonitor.setProgress(75); + EgoClient.frame.createMenuBar(EgoClient.VIEW_INTERVIEW); + EgoClient.frame.pack(); + // EgoClient.frame.setSize(640, 530); + EgoClient.frame.setExtendedState(EgoClient.frame.getExtendedState()|JFrame.MAXIMIZED_BOTH); + + return EgoClient.frame; + } + + public void finished() + { + Shared.setWaitCursor(EgoClient.frame, false); + progressMonitor.close(); + EgoClient.frame.setVisible(true); + } + }; + + progressMonitor.setProgress(0); + progressMonitor.setMillisToDecideToPopup(0); + progressMonitor.setMillisToPopup(0); + + worker.start(); + } +} + + +/** + * $Log: ViewInterviewPanel.java,v $ + * Revision 1.1 2005/08/02 19:36:00 samag + * Initial checkin + * + * Revision 1.5 2004/03/29 00:35:10 admin + * Downloading Interviews + * Fixing some bugs creating Interviews from Data Objects + * + * Revision 1.4 2004/03/28 17:31:32 admin + * More error handling when uploading study to server + * Server URL selection dialog for upload + * + * Revision 1.3 2004/03/21 15:38:08 admin + * Using progress bar while bringing up Summary Panel + * + * Revision 1.2 2004/03/21 15:17:42 admin + * Using progress Bar while bringing up question panel + * + * Revision 1.1 2004/03/19 20:28:45 admin + * Converted statistics frome to a panel. Incorporated in a tabbed panel + * as part of main frame. + * + */ \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/WorkingDialog.java b/src/com/endlessloopsoftware/ego/client/WorkingDialog.java new file mode 100644 index 0000000..10447fe --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/WorkingDialog.java @@ -0,0 +1,53 @@ +package com.endlessloopsoftware.ego.client; + +import java.awt.BorderLayout; + +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** + *Title: Egocentric Networks Client Program
+ *Description: Subject Interview Client
+ *Copyright: Copyright (c) 2002
+ *Company: Endless Loop Software
+ * @author Peter Schoaff + * @version 1.0 + */ + +public class WorkingDialog extends JDialog +{ + private JPanel panel1 = new JPanel(); + private BorderLayout borderLayout1 = new BorderLayout(); + private JLabel jLabel1 = new JLabel(); + + public WorkingDialog(JFrame frame, String title, boolean modal) + { + super(frame, title, modal); + try + { + jbInit(); + pack(); + } + catch(Exception ex) + { + ex.printStackTrace(); + } + } + + public WorkingDialog() + { + this(null, "", false); + } + + private void jbInit() throws Exception + { + panel1.setLayout(borderLayout1); + jLabel1.setFont(new java.awt.Font("Dialog", 1, 16)); + jLabel1.setToolTipText(""); + jLabel1.setText("Working..."); + getContentPane().add(panel1); + panel1.add(jLabel1, BorderLayout.CENTER); + } +} \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/graph/ELSFRLayout.java b/src/com/endlessloopsoftware/ego/client/graph/ELSFRLayout.java new file mode 100644 index 0000000..04283e9 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/graph/ELSFRLayout.java @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2003, the JUNG Project and the Regents of the University of + * California All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or http://jung.sourceforge.net/license.txt for a description. + */ +package com.endlessloopsoftware.ego.client.graph; + +import java.util.Iterator; + +import cern.colt.matrix.DoubleMatrix1D; +import cern.colt.matrix.impl.DenseDoubleMatrix1D; +import edu.uci.ics.jung.exceptions.FatalException; +//import edu.uci.ics.jung.graph.ArchetypeVertex; +import edu.uci.ics.jung.graph.Edge; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Vertex; +import edu.uci.ics.jung.utils.Pair; +import edu.uci.ics.jung.utils.UserData; +import edu.uci.ics.jung.visualization.AbstractLayout; +import edu.uci.ics.jung.visualization.Coordinates; +import edu.uci.ics.jung.visualization.LayoutMutable; + +/** + * Implements the Fruchterman-Reingold algorithm for node layout. + * + * @author Scott White, Yan-Biao Boey, Danyel Fisher + */ +public class ELSFRLayout + extends AbstractLayout + implements LayoutMutable +{ + + private static final Object FR_KEY = "edu.uci.ics.jung.FR_Visualization_Key"; + private double forceConstant; + private double temperature; + private int currentIteration; + private String status = null; + private int mMaxIterations = 700; + + public ELSFRLayout(Graph g) + { + super(g); + // currentIteration = 0; + } + + /* + * new function for handling updates and changes to the graph + */ + public void update() + { + for (Iterator iter = getGraph().getVertices().iterator(); iter.hasNext();) + { + Vertex v = (Vertex) iter.next(); + Coordinates coord = (Coordinates) v.getUserDatum(getBaseKey()); + if (coord == null) + { + coord = new Coordinates(); + v.addUserDatum(getBaseKey(), coord, UserData.REMOVE); + initializeLocation(v, coord, getCurrentSize()); + initialize_local_vertex(v); + } + } + } + + /** + * Returns the current temperature and number of iterations elapsed, as a + * string. + */ + public String getStatus() + { + return status; + } + + public void forceMove(Vertex picked, int x, int y) + { + super.forceMove(picked, x, y); + } + + protected void initialize_local() + { + currentIteration = 0; + temperature = getCurrentSize().getWidth() / 10; + forceConstant = 0.75 * Math.sqrt(getCurrentSize().getHeight() * getCurrentSize().getWidth() + / getVisibleGraph().numVertices()); + } + + private Object key = null; + + private double EPSILON = 0.000001D; + + /** + * Returns a visualization-specific key (that is, specific both to this + * instance and AbstractLayout) that can be used to access + * UserData related to the AbstractLayout. + */ + public Object getKey() + { + if (key == null) + key = new Pair(this, FR_KEY); + return key; + } + + protected void initialize_local_vertex(Vertex v) + { + if (v.getUserDatum(getKey()) == null) + { + v.addUserDatum(getKey(), new FRVertexData(), UserData.REMOVE); + } + } + + /** + * Moves the iteration forward one notch, calculation attraction and + * repulsion between vertices and edges and cooling the temperature. + */ + public void advancePositions() + { + currentIteration++; + status = "VV: " + getVisibleVertices().size() + " IT: " + currentIteration + " temp: " + temperature; + /** + * Calculate repulsion + */ + for (Iterator iter = getVisibleVertices().iterator(); iter.hasNext();) + { + Vertex v1 = (Vertex) iter.next(); + if (dontMove(v1)) + continue; + calcRepulsion(v1); + } + + /** + * Calculate attraction + */ + for (Iterator iter = getVisibleEdges().iterator(); iter.hasNext();) + { + Edge e = (Edge) iter.next(); + + calcAttraction(e); + } + + // double cumulativeChange = 0; + + for (Iterator iter = getVisibleVertices().iterator(); iter.hasNext();) + { + Vertex v = (Vertex) iter.next(); + if (dontMove(v)) + continue; + calcPositions(v); + } + + cool(); + } + + public void calcPositions(Vertex v) + { + FRVertexData fvd = getFRData(v); + Coordinates xyd = super.getCoordinates(v); + double deltaLength = Math.max(EPSILON, Math.sqrt(fvd.disp.zDotProduct(fvd.disp))); + + double newXDisp = fvd.getXDisp() / deltaLength * Math.min(deltaLength, temperature); + + if (Double.isNaN(newXDisp)) { throw new FatalException("Unexpected mathematical result"); } + + double newYDisp = fvd.getYDisp() / deltaLength * Math.min(deltaLength, temperature); + xyd.addX(newXDisp); + xyd.addY(newYDisp); + + double borderWidth = getCurrentSize().getWidth() / 50.0; + double maxborder = getCurrentSize().getWidth() / 8; + borderWidth = Math.max(borderWidth, 30); + borderWidth = Math.min(borderWidth, maxborder); + + double newXPos = xyd.getX(); + if (newXPos < borderWidth) + { + newXPos = borderWidth + Math.random() * borderWidth * 2.0; + } + else if (newXPos > (getCurrentSize().getWidth() - borderWidth)) + { + newXPos = getCurrentSize().getWidth() - borderWidth - Math.random() * borderWidth * 2.0; + } + //double newXPos = Math.min(getCurrentSize().getWidth() - 20.0, + // Math.max(20.0, xyd.getX())); + + double newYPos = xyd.getY(); + if (newYPos < borderWidth) + { + newYPos = borderWidth + Math.random() * borderWidth * 2.0; + } + else if (newYPos > (getCurrentSize().getHeight() - borderWidth)) + { + newYPos = getCurrentSize().getHeight() - borderWidth - Math.random() * borderWidth * 2.0; + } + //double newYPos = Math.min(getCurrentSize().getHeight() - 20.0, + // Math.max(20.0, xyd.getY())); + + xyd.setX(newXPos); + xyd.setY(newYPos); + } + + public void calcAttraction(Edge e) + { + Vertex v1 = (Vertex) e.getIncidentVertices().iterator().next(); + Vertex v2 = e.getOpposite(v1); + + double xDelta = getX(v1) - getX(v2); + double yDelta = getY(v1) - getY(v2); + + double deltaLength = Math.max(EPSILON, Math.sqrt((xDelta * xDelta) + (yDelta * yDelta))); + + double force = (deltaLength * deltaLength) / forceConstant; + + if (Double.isNaN(force)) { throw new FatalException("Unexpected mathematical result"); } + + FRVertexData fvd1 = getFRData(v1); + FRVertexData fvd2 = getFRData(v2); + + fvd1.decrementDisp((xDelta / deltaLength) * force, (yDelta / deltaLength) * force); + fvd2.incrementDisp((xDelta / deltaLength) * force, (yDelta / deltaLength) * force); + } + + public void calcRepulsion(Vertex v1) + { + FRVertexData fvd1 = getFRData(v1); + fvd1.setDisp(0, 0); + + for (Iterator iter2 = getVisibleVertices().iterator(); iter2.hasNext();) + { + Vertex v2 = (Vertex) iter2.next(); + if (dontMove(v2)) + continue; + if (v1 != v2) + { + double xDelta = getX(v1) - getX(v2); + double yDelta = getY(v1) - getY(v2); + + double deltaLength = Math.max(EPSILON, Math.sqrt((xDelta * xDelta) + (yDelta * yDelta))); + + double force = (forceConstant * forceConstant) / deltaLength; + + if (Double.isNaN(force)) { throw new FatalException("Unexpected mathematical result"); } + + fvd1.incrementDisp((xDelta / deltaLength) * force, (yDelta / deltaLength) * force); + } + } + } + + private void cool() + { + temperature *= (1.0 - currentIteration / (double) mMaxIterations); + } + + public void setMaxIterations(int maxIterations) + { + mMaxIterations = maxIterations; + } + + public FRVertexData getFRData(Vertex v) + { + return (FRVertexData) (v.getUserDatum(getKey())); + } + + /** + * This one is an incremental visualization. + */ + public boolean isIncremental() + { + return true; + } + + /** + * Returns true once the current iteration has passed the maximum count, MAX_ITERATIONS. + */ + public boolean incrementsAreDone() + { + if (currentIteration > mMaxIterations) { return true; } + return false; + } + + public static class FRVertexData + { + private DoubleMatrix1D disp; + + public FRVertexData() + { + initialize(); + } + + public void initialize() + { + disp = new DenseDoubleMatrix1D(2); + } + + public double getXDisp() + { + return disp.get(0); + } + + public double getYDisp() + { + return disp.get(1); + } + + public void setDisp(double x, double y) + { + disp.set(0, x); + disp.set(1, y); + } + + public void incrementDisp(double x, double y) + { + disp.set(0, disp.get(0) + x); + disp.set(1, disp.get(1) + y); + } + + public void decrementDisp(double x, double y) + { + disp.set(0, disp.get(0) - x); + disp.set(1, disp.get(1) - y); + } + } +} \ No newline at end of file diff --git a/src/com/endlessloopsoftware/ego/client/graph/ELSRenderer.java b/src/com/endlessloopsoftware/ego/client/graph/ELSRenderer.java new file mode 100644 index 0000000..c85c386 --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/graph/ELSRenderer.java @@ -0,0 +1,181 @@ +/* +* Copyright (c) 2003, the JUNG Project and the Regents of the University +* of California +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* http://jung.sourceforge.net/license.txt for a description. +*/ +package com.endlessloopsoftware.ego.client.graph; + +import java.awt.Color; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.Graphics; + +import edu.uci.ics.jung.graph.Edge; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Vertex; +import edu.uci.ics.jung.graph.decorators.StringLabeller; +import edu.uci.ics.jung.visualization.AbstractRenderer; + +/** + * @author Scott White + */ +public class ELSRenderer extends AbstractRenderer +{ + private String mSizeKey; + + private GradientPaint paint = null; + private int mDefaultNodeSize; + private double maxRank = -1; + private double minRank = -1; + + public ELSRenderer() + { + mDefaultNodeSize = 8; + maxRank = 0; + } + + public void paintEdge(Graphics g, Edge e, int x1, int y1, int x2, int y2) + { + Color c = g.getColor(); + g.setColor(Color.LIGHT_GRAY); + g.drawLine(x1, y1, x2, y2); + g.setColor(c); + } + + public void paintVertex(Graphics g, Vertex v, int x, int y) + { + + String label = null; + if (getLabel() != null) + { + // label = (String) v.getUserDatum(getLabel()); + label = StringLabeller.getLabeller((Graph) v.getGraph()).getLabel(v); + } + + if (label == null) + { + label = v.toString(); + } + + if (label.length() > 15) + { + label = label.substring(0, 14); + } + + int nodeSize = mDefaultNodeSize; + if (mSizeKey != null) + { + // for (Iterator it = v.getUserDatumKeyIterator(); it.hasNext();) + // System.out.println(it.next()); + + try + { + Number decoratedNodeSize = (Number) v.getUserDatum(mSizeKey); + int red = 0; + + if (decoratedNodeSize.doubleValue() > 0) + { + // red = (int) Math.ceil((double) 255 * (Math.log(decoratedNodeSize.doubleValue()) / + // Math.log(getMaxDegreeRank()))); + red = (int) Math.ceil((double) 255 * (decoratedNodeSize.doubleValue() / + getMaxDegreeRank())); + } + + // System.out.println(decoratedNodeSize.doubleValue()); + // System.out.println(Math.log(decoratedNodeSize.doubleValue())); + // System.out.println(getMaxDegreeRank()); + // System.out.println(Math.log(getMaxDegreeRank())); + // System.out.println(red); + + Color c = new Color(255, 255 - red, 64 - (red / 4)); + g.setColor(c); + } + catch (Exception e) + { + e.printStackTrace(); + System.exit(-1); + } + } + + int labelSize = g.getFontMetrics().stringWidth(label); + nodeSize = Math.max(nodeSize, 10); + nodeSize = Math.min(nodeSize, 150); + + g.fillOval(x - nodeSize / 2, y - nodeSize / 2, nodeSize, nodeSize); + g.setColor(Color.GRAY); + g.drawOval(x - nodeSize / 2, y - nodeSize / 2, nodeSize, nodeSize); + g.setColor(Color.BLACK); + Font font = new Font("Arial", Font.PLAIN, 12); + Font f = g.getFont(); + g.setFont(font); + if (nodeSize > labelSize) + { + g.drawString(label, x - labelSize / 2, y + 4); + } + else + { + g.drawString(label, x - labelSize / 2 + 20, y + 15); + + } + g.setFont(f); + } + + public String getSizeKey() + { + return mSizeKey; + } + + public void setSizeKey(String decorationKey) + { + this.mSizeKey = decorationKey; + } + + String mLabel; + + public String getLabel() + { + return mLabel; + } + + public void setLabel(String label) + { + this.mLabel = label; + } + + /** + * @return + */ + public double getMaxDegreeRank() + { + return maxRank; + } + + /** + * @param i + */ + public void setMaxDegreeRank(double d) + { + maxRank = d; + } + + /** + * @return + */ + public double getMinRank() + { + return minRank; + } + + /** + * @param d + */ + public void setMinRank(double d) + { + minRank = d; + } + +} diff --git a/src/com/endlessloopsoftware/ego/client/graph/EdgePanel.java b/src/com/endlessloopsoftware/ego/client/graph/EdgePanel.java new file mode 100644 index 0000000..e13573b --- /dev/null +++ b/src/com/endlessloopsoftware/ego/client/graph/EdgePanel.java @@ -0,0 +1,400 @@ +package com.endlessloopsoftware.ego.client.graph; + +import java.awt.Color; +import java.awt.Dimension; +import java.util.*; +import java.awt.event.ItemEvent; +import javax.swing.table.*; + +import org.egonet.util.table.*; + +import javax.swing.GroupLayout; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableModel; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.*; + +import com.endlessloopsoftware.ego.Question; +import com.endlessloopsoftware.ego.QuestionList; +import com.endlessloopsoftware.ego.Study; +import com.endlessloopsoftware.ego.client.EgoClient; +import com.endlessloopsoftware.ego.client.graph.GraphQuestion; +import org.egonet.util.listbuilder.Selection; +import edu.uci.ics.jung.utils.Pair; + +public class EdgePanel extends JPanel implements TableModelListener { + + private GroupLayout layout; + + GraphRenderer graphRenderer; + + List+// * By default, with FlowLayout the ImageLabel takes its minimum size (just enclosing the image). The default with BorderLayout is to expand to fill the region +// * in width (North/South), height (East/West) or both (Center). This is the same behavior as with the builtin Label class. If you give an explicit resize or +// * reshape call before adding the ImageLabel to the Container, this size will override the defaults. +// *
+// * Here is an example of its use: +// *
+// * +// *
+// * +// * public class ShowImages extends Applet { private ImageLabel image1, image2; +// * +// * public void init() { image1 = new ImageLabel(getCodeBase(), "some-image.gif"); image2 = new ImageLabel(getCodeBase(), "other-image.jpg"); add(image1); +// * add(image2); } } +// * +// *+// * +// * @author Marty Hall (hall@apl.jhu.edu) +// * @see Icon +// * @see ImageButton +// * @version 1.0 (1997) +// */ +// +public class ImageLabel extends Canvas +{ +// //---------------------------------------------------- +// // Instance variables. +// +// // The actual Image drawn on the canvas. +// private Image image; +// +// // A String corresponding to the URL of the image +// // you will get if you call the constructor with +// // no arguments. +// private static String defaultImageString = "http://www.endlessloopsoftware.com/eLoop_web.png"; +// +// // The URL of the image. But sometimes we will use +// // an existing image object (e.g. made by +// // createImage) for which this info will not be +// // available, so a default string is used here. +// private String imageString = "
+// * Note: The effects of this could be undone by the LayoutManager of the parent Container, if it is using one. So this is normally only used in +// * conjunction with a null LayoutManager. +// * +// * @param x +// * The X coord of center of the image (in parent's coordinate system) +// * @param y +// * The Y coord of center of the image (in parent's coordinate system) +// * @see java.awt.Component#move +// */ +// +// public void centerAt(int x, int y) +// { +// debug("Placing center of " + imageString + " at (" + x + "," + y + ")"); +// move(x - width / 2, y - height / 2); +// } +// +// //---------------------------------------------------- +// /** +// * Determines if the x and y (in the ImageLabel's own coordinate system) is inside the ImageLabel. Put here because Netscape 2.02 has a bug in +// * which it doesn't process inside() and locate() tests correctly. +// */ +// public synchronized boolean inside(int x, int y) +// { +// return ((x >= 0) && (x <= width) && (y >= 0) && (y <= height)); +// } +// +// //---------------------------------------------------- +// /** +// * Draws the image. If you override this in a subclass, be sure to call super.paint. +// */ +// public void paint(Graphics g) +// { +// if (!doneLoading) +// waitForImage(true); +// else +// { +// if (explicitSize) +// g.drawImage(image, border, border, width - 2 * border, height - 2 * border, this); +// else +// g.drawImage(image, border, border, this); +// drawRect(g, 0, 0, width - 1, height - 1, border, borderColor); +// } +// } +// +// //---------------------------------------------------- +// /** +// * Used by layout managers to calculate the usual size allocated for the Component. Since some layout managers (e.g. BorderLayout) may call this before +// * paint is called, you need to make sure that the image is done loading, which will force a resize, which determines the values returned. +// */ +// public Dimension preferredSize() +// { +// if (!doneLoading) +// waitForImage(false); +// return (super.preferredSize()); +// } +// +// //---------------------------------------------------- +// /** +// * Used by layout managers to calculate the smallest size allocated for the Component. Since some layout managers (e.g. BorderLayout) may call this before +// * paint is called, you need to make sure that the image is done loading, which will force a resize, which determines the values returned. +// */ +// public Dimension minimumSize() +// { +// if (!doneLoading) +// waitForImage(false); +// return (super.minimumSize()); +// } +// +// //---------------------------------------------------- +// // LayoutManagers (such as BorderLayout) might call +// // resize or reshape with only 1 dimension of +// // width/height non-zero. In such a case, you still +// // want the other dimension to come from the image +// // itself. +// +// /** +// * Resizes the ImageLabel. If you don't resize the label explicitly, then what happens depends on the layout manager. With FlowLayout, as with FlowLayout +// * for Labels, the ImageLabel takes its minimum size, just enclosing the image. With BorderLayout, as with BorderLayout for Labels, the ImageLabel is +// * expanded to fill the section. Stretching GIF/JPG files does not always result in clear looking images. So just as with builtin Labels and Buttons, +// * don't use FlowLayout if you don't want the Buttons to get resized. If you don't use any LayoutManager, then the ImageLabel will also just fit the +// * image. +// *
+// * Note that if you resize explicitly, you must do it before the ImageLabel is added to the Container. In such a case, the explicit size overrides +// * the image dimensions. +// * +// * @see #reshape +// */ +// public void resize(int width, int height) +// { +// if (!doneLoading) +// { +// explicitSize = true; +// if (width > 0) +// explicitWidth = width; +// if (height > 0) +// explicitHeight = height; +// } +// super.resize(width, height); +// } +// +// /** +// * Resizes the ImageLabel. If you don't resize the label explicitly, then what happens depends on the layout manager. With FlowLayout, as with FlowLayout +// * for Labels, the ImageLabel takes its minimum size, just enclosing the image. With BorderLayout, as with BorderLayout for Labels, the ImageLabel is +// * expanded to fill the section. Stretching GIF/JPG files does not always result in clear looking images. So just as with builtin Labels and Buttons, +// * don't use FlowLayout if you don't want the Buttons to get resized. If you don't use any LayoutManager, then the ImageLabel will also just fit the +// * image. +// *
+// * Note that if you resize explicitly, you must do it before the ImageLabel is added to the Container. In such a case, the explicit size overrides
+// * the image dimensions.
+// *
+// * @see #resize
+// */
+// public void reshape(int x, int y, int width, int height)
+// {
+// if (!doneLoading)
+// {
+// explicitSize = true;
+// if (width > 0)
+// explicitWidth = width;
+// if (height > 0)
+// explicitHeight = height;
+// }
+// super.reshape(x, y, width, height);
+// }
+//
+// //----------------------------------------------------
+// // You can't just set the background color to
+// // the borderColor and skip drawing the border,
+// // since it messes up transparent gifs. You
+// // need the background color to be the same as
+// // the container.
+//
+// /**
+// * Draws a rectangle with the specified OUTSIDE left, top, width, and height. Used to draw the border.
+// */
+// protected void drawRect(
+// Graphics g,
+// int left,
+// int top,
+// int width,
+// int height,
+// int lineThickness,
+// Color rectangleColor)
+// {
+// g.setColor(rectangleColor);
+// for (int i = 0; i < lineThickness; i++)
+// {
+// g.drawRect(left, top, width, height);
+// if (i < lineThickness - 1)
+// { // Skip last iteration
+// left = left + 1;
+// top = top + 1;
+// width = width - 2;
+// height = height - 2;
+// }
+// }
+// }
+//
+// //----------------------------------------------------
+// /**
+// * Calls System.out.println if the debug variable is true; does nothing otherwise.
+// *
+// * @param message
+// * The String to be printed.
+// */
+// protected void debug(String message)
+// {
+// if (debug)
+// System.out.println(message);
+// }
+//
+// //----------------------------------------------------
+// // Creates the URL with some error checking.
+//
+// private static URL makeURL(String s)
+// {
+// URL u = null;
+// try
+// {
+// u = new URL(s);
+// }
+// catch (MalformedURLException mue)
+// {
+// System.out.println("Bad URL " + s + ": " + mue);
+// mue.printStackTrace();
+// }
+// return (u);
+// }
+//
+// private static URL makeURL(URL directory, String file)
+// {
+// URL u = null;
+// try
+// {
+// u = new URL(directory, file);
+// }
+// catch (MalformedURLException mue)
+// {
+// System.out.println("Bad URL " + directory.toExternalForm() + ", " + file + ": " + mue);
+// mue.printStackTrace();
+// }
+// return (u);
+// }
+//
+// //----------------------------------------------------
+// // Loads the image. Needs to be static since it is
+// // called by the constructor.
+//
+// private static Image loadImage(URL url)
+// {
+// return (Toolkit.getDefaultToolkit().getImage(url));
+// }
+//
+// //----------------------------------------------------
+// /** The Image associated with the ImageLabel. */
+//
+// public Image getImage()
+// {
+// return (image);
+// }
+//
+// //----------------------------------------------------
+// /** Gets the border width. */
+//
+// public int getBorder()
+// {
+// return (border);
+// }
+//
+// /** Sets the border thickness. */
+//
+// public void setBorder(int border)
+// {
+// this.border = border;
+// }
+//
+// //----------------------------------------------------
+// /** Gets the border color. */
+//
+// public Color getBorderColor()
+// {
+// return (borderColor);
+// }
+//
+// /** Sets the border color. */
+//
+// public void setBorderColor(Color borderColor)
+// {
+// this.borderColor = borderColor;
+// }
+//
+// //----------------------------------------------------
+// // You could just call size().width and size().height,
+// // but since we've overridden resize to record
+// // this, we might as well use it.
+//
+// /** Gets the width (image width plus twice border). */
+//
+// public int getWidth()
+// {
+// return (width);
+// }
+//
+// /** Gets the height (image height plus 2x border). */
+//
+// public int getHeight()
+// {
+// return (height);
+// }
+//
+// //----------------------------------------------------
+// /**
+// * Has the ImageLabel been given an explicit size? This is used to decide if the image should be stretched or not. This will be true if you call resize or
+// * reshape on the ImageLabel before adding it to a Container. It will be false otherwise.
+// */
+// protected boolean hasExplicitSize()
+// {
+// return (explicitSize);
+// }
+//
+// //----------------------------------------------------
+// /**
+// * Returns the string representing the URL that will be used if none is supplied in the constructor.
+// */
+// public static String getDefaultImageString()
+// {
+// return (defaultImageString);
+// }
+//
+// /**
+// * Sets the string representing the URL that will be used if none is supplied in the constructor. Note that this is static, so is shared by all ImageLabels.
+// * Using this might be convenient in testing, but "real" applications should avoid it.
+// */
+// public static void setDefaultImageString(String file)
+// {
+// defaultImageString = file;
+// }
+//
+// //----------------------------------------------------
+// /**
+// * Returns the string representing the URL of image.
+// */
+// protected String getImageString()
+// {
+// return (imageString);
+// }
+//
+// //----------------------------------------------------
+// /** Is the debugging flag set? */
+//
+// public boolean isDebugging()
+// {
+// return (debug);
+// }
+//
+// /**
+// * Set the debugging flag. Verbose messages will be printed to System.out if this is true.
+// */
+// public void setIsDebugging(boolean debug)
+// {
+// this.debug = debug;
+// }
+//
+ //----------------------------------------------------
+}
diff --git a/src/com/endlessloopsoftware/ego/client/graph/NodeColorPanel.java b/src/com/endlessloopsoftware/ego/client/graph/NodeColorPanel.java
new file mode 100644
index 0000000..280a66c
--- /dev/null
+++ b/src/com/endlessloopsoftware/ego/client/graph/NodeColorPanel.java
@@ -0,0 +1,195 @@
+package com.endlessloopsoftware.ego.client.graph;
+
+import javax.swing.*;
+import javax.swing.table.*;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.util.*;
+import java.awt.event.*;
+
+import org.egonet.util.listbuilder.Selection;
+import org.egonet.util.table.*;
+
+import com.endlessloopsoftware.ego.*;
+import com.endlessloopsoftware.ego.client.EgoClient;
+import com.endlessloopsoftware.ego.client.graph.NodeProperty.NodeShape;
+
+public class NodeColorPanel extends JPanel {
+
+ private JLabel questionLabel;
+
+ private JComboBox questionCombo;
+
+ ColorChooserEditor colorChooser;
+
+ private PropertyTableModel tableModel;
+
+ private JTable table;
+
+ private GroupLayout layout;
+
+ private GraphRenderer graphRenderer;
+
+ private GraphData graphData;
+
+ private JButton applyButton;
+
+ List Title: Egocentric Network Researcher Description: Configuration Utilities for an Egocentric network study Copyright: Copyright (c) 2003 Company: Endless Loop Software Copyright: Copyright (c) 2002 - 2004, Endless Loop Software, Inc. Company: Endless Loop Software, Inc. Title: Egocentric Networks Client Program Description: Subject Interview Client Copyright: Copyright (c) 2002 Company: Endless Loop Software Title: Egocentric Network Researcher Description: Configuration Utilities for an Egocentric network study Copyright: Copyright (c) 2002 Company: Endless Loop Software Title: Egocentric Network Researcher Description: Configuration Utilities for an Egocentric network study Copyright: Copyright (c) 2003 Company: Endless Loop Software Title: Egocentric Network Researcher Description: Configuration Utilities for an Egocentric network study Copyright: Copyright (c) 2003 Company: Endless Loop Software Title: Egocentric Network Researcher Description: Configuration Utilities for an Egocentric network study Copyright: Copyright (c) 2003 Company: Endless Loop Software Title: Egocentric Network Researcher Description: Configuration Utilities for an Egocentric network study Copyright: Copyright (c) 2003 Company: Endless Loop Software Title: Egocentric Network Researcher Description: Configuration Utilities for an Egocentric network study Copyright: Copyright (c) 2003 Company: Endless Loop Software Title: Egocentric Network Researcher Description: Configuration Utilities for an Egocentric network study Copyright: Copyright (c) 2003 Company: Endless Loop Software Title: Egocentric Network Researcher Description: Configuration Utilities for an Egocentric network study Copyright: Copyright (c) 2003 Company: Endless Loop Software Endless Loop Software Abstract Statistics Table Model Copyright: Copyright (c) 2003 Company: Endless Loop Software, Inc.