// ConceptWebClient.java - a web applet for the development of concept maps // A concept map drawing applet. Scott Harrison 2001-2007 // Scott Harrison, harris41@msu.edu // Project investigators: Douglas Luckie, Diane Ebert-May // Copyright 2001-2007 Michigan State University Board of Trustees // =============================================================== INSTALLATION // // ConceptWebClient can be installed with the rest of // the C-TOOLS software package. For information, see // sourcetreepath/build/README // cd sourcetreepath/build; aap install-javaclient // // The ConceptWebClient also supports a standalone mode, and the // web page code in ctoolsapplet.html demonstrates basic deployment of // the applet. // ================================================================ COMPILATION // For purposes of browser compatibility, JDK 1.3 (from Sun) is recommended. // javac ConceptWebClient.java // ==================================================================== LICENSE // // This software is eventually to be released under the General // Public License, Version 2, June 1991. (It will be released // when there is a "Gold Master" version ready.) // // Until then, if you would like to use this software, you should // contact Dr. Douglas Luckie, luckie@msu.edu. // // Development of this software was funded by the National Science Foundation. // // Copyright 2001-2007 Michigan State University Board of Trustees // ================================================================ DESCRIPTION // This code allows students in a classroom setting to generate concept maps. // Instructors are given significant flexibility for the modification of // concept map assignments and exercises that are delivered through this // software. Instructors can choose to enable or disable certain features // of this applet, which is key for having this tool run in standalone mode // versus integration with a courseware management system (like moodle). // Instructors can also choose to define the concept // map that students first begin to work with. For instance, an instructor // might want the students to all start with three major concepts already // present on a concept map. // // This is a "web client"; it is a java applet that is meant to run on a wide // variety of browsers. // // Concept maps are made of "concept words", "linking words", and "links". // For C-TOOLS, the term "words" is inclusive of both "concept words" and // "linking words". Also, the term "concept word" is meant to be identical // to the notion of a "concept phrase". Thus, "Pizza Hut" is considered // to be a concept word (for the variable names inside this source code). // ============================================================ DEVELOPER NOTES // Also, for reasons of browser and compiler compatibility (JDK1.3) // the goal with this code has been to keep the objects, processing, // interface layout, and event handling simple so as to ensure robustness // across diverse operating systems and browsers (e.g., a set // of remotely connecting students). Additional considerations // include promoting a common look and feel (something which differing AWT or // Swing implementations can interfere with). Also, I want things to be // kept "mobile" in the sense that the software can be modestly extended // and enhanced in most any direction for special needs (without assuming // in advance what those special user needs might be). The overall goal of // this technology is not "a huge extensible basket of concept mapping // features", but rather "a common browser-compatible billboard" for getting // started with concept mapping in a classroom setting that can be configured // to work in many different institutional scenarios. So, for the brave few // who look at this code, prior to contorting its simplicity, please // take time to consider that there may be reasons (and benefits) as // to why the softwawre is structured the way it is. // // That said, the "VIEW" menu is being currently prototyped, and this // is distorting the class structure a bit (BubbleMenuHelp, SubOption, etc). // // Also, Safari with JDK 1.4.1 is quite buggy and does not always read in the // parameters correctly (i.e., getParameter). Therefore, after a getParameter // is called, I need to check if it is null, and if so, do additional logic // such as assigning a default value or sending a retry (rtry) request // to the server. // =========================================================== ACKNOWLEDGEMENTS // The applet code emerged at Michigan State University (MSU) supported in // large part by an NSF funded grant project. I would like to thank the // following for helpful comments and contributions to help guide the // ultimate outcome of this applet: // Douglas Luckie, Diane Ebert-May, Janet Batzli, Duncan Sibley, Rett Weber, // Joshua Wallace, Crystal Tobin, students of MSU's Lyman Briggs School as // well as the variety of java applet coding tutorials and examples that // other software developers have made publicly available over the internet. // =============================================================== JAVA CLASSES // ConceptWebClient // | // | +------- ConceptWebClient.class : main class for the web client // | +------- MoveableWord.class : implement the "magnetic rectangle" // | concept which can be dragged around // | +------- Link.class : ordered pair structure by which one // | concept is attached to another concept // | +------- MenuButton.class : a menu button that can be clicked on; // | menu buttons appear on the left side of // | the applet // | +------- BubbleMenuHelp.class : shows list of actions (SubOptions) // | whenever a menu button is pressed; // | brief help text is displayed for // | each SubOption // | +------- SubOption.class : a choice that is available after a // | menu button is pressed; usually // | there are multiple SubOptions associated // | with each menu button // | +------- Message.class : brief help messages which are displayed; // | especially in concert with SubOptions // | which are selected // | +------- StatusMessage.class : status of concept map; SAVED, NOT // | SAVED, or AUTOSAVED // | +------- TargetArea.class : a set of coordinates // | defining a target area (used to // | interactively respond to events // | on the user interface) // | +------- ServerTalker.class : support capability to talk to server // ========================================================= NECESSARY PACKAGES import java.applet.*; import java.awt.*; import java.awt.event.*; import java.util.Vector; import java.util.Enumeration; import java.net.*; import java.io.*; /** * The GeneralThread class is the main background process for the applet. * It was developed to support autosaving off of the applet. * Its usage is presently disabled however since a variety of browsers and * applet runtime environments seem to crash or be unstable with autonomous * processes. */ class GeneralThread extends Thread { AppletContext ac; URL url; String mapname; String expiration_key; String sid; MoveableWord words[]; Link links[]; int number_words; int number_links; String disable_string; String gallery; ServerTalker server_talker; Graphics g; String teststring; /** * Constructor. Set the parameters for running the background autosaving * thread. * (Parameters not yet listed.) */ GeneralThread(URL u, AppletContext a, MoveableWord[] w, Link[] l, int num_w, int num_l, ServerTalker st, Graphics graphics, String ekey) { url = u; ac = a; words = w; links = l; number_words = num_w; number_links = num_l; server_talker = st; g = graphics; expiration_key = ekey; } // END GeneralThread constructor /** * Run the thread. (Turns on every 20 seconds.) */ public void run() { while (true) { try {sleep(20000);} catch (Exception e) {} // System.out.println("TESTSTR: "+teststring); String data = new String(); String winfo = new String(); data += "command=AUTOSAVE&"; for (int j = 0; j < number_links; j++) { data += "c"+j+"="+ links[j].getIndex1()+"+"+ links[j].getIndex2()+"&"; } for (int i = number_words - 1; i >= 0; i--) { if (words[i].word_type.equals("LINKINGWORD")) { winfo = words[i].info(g)+"+n"; } else { winfo = words[i].info(g) + "+w"; } data += "w" + i + "=" + winfo + "&"; } if (disable_string != null) { data += "DISABLE="+disable_string; } if (disable_string != null && gallery != null) { data += "&gallery="+gallery; } // Authentication data for the CGI/Servlet. data += "&mapname="+mapname; data += "&expiration_key="+expiration_key; data += "&sid="+sid; // Cannot trust cookie data to // be available from applet. // CGI/Servlet uniform resource locator // is the url variable already manifest for this // thread. server_talker.put(url,data); // The "official" url connection object. // If the user tries to save an applet outside // of user authentication, the page needs to // be reloaded (and the CGI servlet layer // subsequently takes the user through a // login or registration process prior to // the save procedure). if (expiration_key.equals("NA")) { // ac.showDocument(url); } } } } // END GeneralThread /** * The ConceptWebClient class is the main class for the web client. * It presents a concept map drawing tool similar in functionality * to Dia, Visio (tm) or other schematic tools. The feature set * implemented by this class is not as exhaustive as standard schematic * tools; rather, it is limited to those features necessary to draw * a concept map generally involving ten words or less. This reduces * the size of the applet so as to be realistic in terms of network * bandwidth as well as simplifying users' ability to understand * and work with the applet interface. *

* Technical Notes

* *
 *Description of pixel-based, graphical layout:
 *          <----------- applet_width ----------->
 *       
 *       ^   ------------------------------------
 *       |  |    ^                        ^      |
 *       |  |    |         top_space      |      |
 *       a  |    V                        V      |
 *       p  |------------------------------------|
 *       p  |<->|<------- space_width ------>|<->|
 *       l  | l |      ^                     | r |
 *       e  | e |      |                     | g |
 *       t  | f | space_height               | h |
 *       _  | t |      |                     | t |
 *       h  | s |      |                     | s |
 *       e  | p |      |                     | p |
 *       i  | a |      |                     | a |
 *       g  | c |      |                     | c |
 *       h  | e |      V                     | e |
 *       t  |------------------------------------|
 *       |  |    ^                        ^      |
 *       |  |    |       bottom_space     |      |
 *       |  |    V                        V      |
 *       V   ------------------------------------
 *
* @author Programmer: Scott Harrison, 2001-2007, harris41@msu.edu; * Project investigators: Douglas Luckie, Diane Ebert-May; * Copyright 2001-2007 Michigan State University Board of Trustees * @since JDK 1.3.1 */ public class ConceptWebClient extends Applet implements MouseListener, MouseMotionListener, ActionListener { // --------------------------------------------------------- Class variables. private static int rtry; /** The object which talks to the server. */ private static ServerTalker server_talker; /** The robo object helps scribble suggestions on top * of a concept map. */ private static Robograde robo; // A number of configuration settings occur in this section, but // many other configuration settings also occur inside the "init" method // of this class. /** The DocumentBase for this applet (because getDocumentBase causes * security exceptions, we must have it passed as a parameter). */ private static String document_base; /** The expiration key for this applet. The servlet must know that the * applet session is not bogus. */ private static String expiration_key; /** The session id for this applet (and the surrounding web pages). * (Not every browser/OS passes on cookie data from the applet.) */ private static String sid; /** The mapname for this concept map. (The suffix .cmap should not be * included.) */ private static String mapname; // The text entry feature consists of a text box and a submit button. // This feature allows users to add new concepts and linking words to // the developing concept map. /** Text entry box for specifying concept and linking words. */ private static TextField text_entry_box; /** "Null" text to be on submit button. */ private static String text_entry_null_submit_label; /** Both color mode and black-and-white mode are supported. * The web client will start by running in color mode (this * value is initially set to true). */ private static boolean color = true; /** A value to control how many screen redraws occur. * (Allows for animated drawing during stages of saving. */ private static boolean mode_cycle = false; // There are different events which influence the web client's // state of operation. /** Status flag for the mouse button. */ private static boolean mousedown = false; /** Flag to indicate if a word was selected. */ private static boolean selected_word = false; /** Flag to indicate if an image was selected. */ private static boolean selected_image = false; // Tracking, guiding, and controlling user activity is done with the mode, // submode, and event_counter variables. /** Tracks the selection of a menu button; * e.g. MOVE, ADD, DELETE, VIEW, SAVE, and GRADE. */ private static String mode; /** Tracks the selection of a menu button's suboptions. * e.g. ADD_CONCEPT, ADD_LINKINGWORD; or * DELETE_WORD, DELETE_LINES. */ private static String submode; /** Event counter: when a mode and submode are * activated from the navigation menu, the user is * guided through a series of steps through which to * complete the task. The series of steps is counted * by the event_counter variable. */ private static int event_counter = 1; // **** Applet and drawing space dimensions **** // (These should match the HTML code tags.) // Defined in exact pixel units to improve appearance on a large variety // of browsers. /** Helpful instructions to user are shown here. */ private static final int top_space = 25; /** The software description is here. */ private static final int bottom_space = 25; /** Padding on the right side of the applet. */ private static final int right_space = 0; /** The menu buttons are placed here. */ private static final int left_space = 70; /** The width of the concept map canvas. */ // private static final int space_width = 480; private static int space_width = 768; /** The height of the concept map canvas. */ // private static final int space_height = 300; private static int space_height = 480; /** Font size. */ private static int font_size = 10; /** The width of the bubble menu. */ private static final int bubble_width = 400; /** The width of the entire applet. */ private static int applet_width = left_space+space_width+right_space; /** The height of the entire applet. */ private static int applet_height = top_space+space_height+bottom_space; /** Standard icon width. */ private static final int image_width = 100; private static final int image_height = 100; private static int image_x = 60+left_space; private static int image_y = 40+top_space; private Image image_icon1 = null; // Color values and color variables. /** Major background color in colormode, RGB value. */ private static final int background_color = 0x336699; /** Major background color object, colormode. */ private static Color Background_Color; /** Major background color in graymode, RGB value. */ private static final int background_gray = 0xFFFFFF; /** Major background color object, graymode. */ private static Color Background_Gray; /** Footer foreground color in colormode, RGB value. */ private static final int footer_fg_color = 0x336699; /** Footer foreground color object, colormode. */ private static Color Footer_Fg_Color; /** Footer foreground color in graymode, RGB value. */ private static final int footer_fg_gray = 0x000000; /** Footer foreground color object, graymode. */ private static Color Footer_Fg_Gray; /** Foreground color, RGB value, of "incorrect" scribbling, colormode. */ private static final int incorrect_fg_color = Color.red.getRGB(); /** Foreground color, color object, of "incorrect" scribbling,colormode. */ private static Color Incorrect_Fg_Color; /** Foreground color, RGB value, of "incorrect" scribbling, graymode. */ private static final int incorrect_fg_gray = Color.black.getRGB(); /** Foreground color, color object, of "incorrect" scribbling, graymode. */ private static Color Incorrect_Fg_Gray; /** Foreground color, RGB value, of "neutral" scribbling, colormode. */ private static final int neutral_fg_color = Color.yellow.getRGB(); /** Foreground color, color object, of "neutral" scribbling,colormode. */ private static Color Neutral_Fg_Color; /** Foreground color, RGB value, of "neutral" scribbling, graymode. */ private static final int neutral_fg_gray = Color.black.getRGB(); /** Foreground color, color object, of "neutral" scribbling, graymode. */ private static Color Neutral_Fg_Gray; /** Foreground color, RGB value, of "correct" scribbling, colormode. */ private static final int correct_fg_color = Color.green.getRGB(); /** Foreground color, color object, of "correct" scribbling,colormode. */ private static Color Correct_Fg_Color; /** Foreground color, RGB value, of "correct" scribbling, graymode. */ private static final int correct_fg_gray = Color.black.getRGB(); /** Foreground color, color object, of "correct" scribbling, graymode. */ private static Color Correct_Fg_Gray; /** Background color (colormode) of concept words, RGB value. */ private static final int conceptword_bg_color = 0xFF9933; /** Background color (colormode) of concept words, color object. */ private static Color Conceptword_Bg_Color; /** Foreground color (colormode) of concept words, RGB value. */ private static final int conceptword_fg_color = 0x000000; /** Foreground color (colormode) of concept words, color object. */ private static Color Conceptword_Fg_Color; /** Background color (graymode) of concept words, RGB value. */ private static final int conceptword_bg_gray = Color.lightGray.getRGB(); /** Background color (graymode) of concept words, color object. */ private static Color Conceptword_Bg_Gray; /** Foreground color (graymode) of concept words, RGB value. */ private static final int conceptword_fg_gray = 0x000000; /** Foreground color (graymode) of concept words, color object. */ private static Color Conceptword_Fg_Gray; /** Foreground color (graymode) of concept word border, RGB value. */ private static final int conceptword_fg_brd_gray = 0x000000; /** Foreground color (graymode) of concept word border, color object. */ private static Color Conceptword_Fg_Brd_Gray; /** Background color (colormode) of linking words, RGB value. */ private static final int linkingword_bg_color = 0xFFFFCC; /** Background color (colormode) of linking words, color object. */ private static Color Linkingword_Bg_Color; /** Foreground color (colormode) of linking words, RGB value. */ private static final int linkingword_fg_color = 0x000000; /** Foreground color (colormode) of linking words, color object. */ private static Color Linkingword_Fg_Color; /** Background color (graymode) of linking words, RGB value. */ private static final int linkingword_bg_gray = 0xFFFFFF; /** Background color (graymode) of linking words, color object. */ private static Color Linkingword_Bg_Gray; /** Foreground color (graymode) of linking words, RGB value. */ private static final int linkingword_fg_gray = 0x000000; /** Foreground color (graymode) of linking words, color object. */ private static Color Linkingword_Fg_Gray; /** Foreground color (graymode) of linking word border, RGB value. */ private static final int linkingword_fg_brd_gray = 0x000000; /** Foreground color (graymode) of linking word border, color object. */ private static Color Linkingword_Fg_Brd_Gray; /** Foreground color (colormode) of link, RGB value. */ private static final int link_fg_color = 0xFFFFFF; /** Foreground color (colormode) of link, color object. */ private static Color Link_Fg_Color; /** Foreground color (graymode) of link, RGB value. */ private static final int link_fg_gray = 0x000000; /** Foreground color (graymode) of link, color object. */ private static Color Link_Fg_Gray; /** Foreground color (colormode) of link, RGB value. */ private static final int link_targetbox_fg_color = Color.pink.getRGB(); /** Foreground color (colormode) of link, color object. */ private static Color Link_Targetbox_Fg_Color; /** Foreground color (graymode) of link, RGB value. */ private static final int link_targetbox_fg_gray = Color.black.getRGB(); /** Foreground color (graymode) of link, color object. */ private static Color Link_Targetbox_Fg_Gray; /** Background color (colormode) of buttons, RGB value. */ private static final int button_bg_color = 0x336699; /** Background color (colormode) of buttons, color object. */ private static Color Button_Bg_Color; /** Foreground color (colormode) of not-selected button, RGB value. */ private static final int button_fg_off_color = 0xFF9933; /** Foreground color (colormode) of not-selected button, color * object. */ private static Color Button_Fg_Off_Color; /** Foreground color (colormode) of selected button, RGB value. */ private static final int button_fg_on_color = 0xFFFFCC; /** Foreground color (colormode) of selected button, color object. */ private static Color Button_Fg_On_Color; /** Background color (graymode) of buttons, RGB value. */ private static final int button_bg_gray = Color.lightGray.getRGB(); /** Background color (graymode) of buttons, color object. */ private static Color Button_Bg_Gray; /** Foreground color (graymode) of selected button, RGB value. */ private static final int button_fg_off_gray = Color.darkGray.getRGB(); /** Foreground color (graymode) of selected button, color * object. */ private static Color Button_Fg_Off_Gray; /** Foreground color (graymode) of not-selected button, RGB value. */ private static final int button_fg_on_gray = 0x000000; /** Foreground color (graymode) of not-selected button, color object. */ private static Color Button_Fg_On_Gray; /** Background color (colormode) of bubbles, RGB value. */ private static final int bubble_bg_color = 0xFFFFCC; /** Background color (colormode) of bubbles, color object. */ private static Color Bubble_Bg_Color; /** Foreground color (colormode) of bubble, RGB value. */ private static final int bubble_fg_color = 0x000000; /** Foreground color (colormode) of bubble, color object. */ private static Color Bubble_Fg_Color; /** Background color (graymode) of bubbles, RGB value. */ private static final int bubble_bg_gray = 0xFFFFFF; /** Background color (graymode) of bubbles, color object. */ private static Color Bubble_Bg_Gray; /** Foreground color (graymode) of bubble, RGB value. */ private static final int bubble_fg_gray = 0x000000; /** Foreground color (graymode) of bubble, color object. */ private static Color Bubble_Fg_Gray; /** Foreground color (colormode) of bubble border, RGB value. */ private static final int bubble_border_color = 0x000000; /** Foreground color (colormode) of bubble border, color object. */ private static Color Bubble_Border_Color; /** Foreground color (graymode) of bubble border, RGB value. */ private static final int bubble_border_gray = 0x000000; /** Foreground color (graymode) of bubble border, color object. */ private static Color Bubble_Border_Gray; /** Foreground color (colormode) of bubble highlight, RGB value. */ private static final int bubble_highlight_color = 0xFF9933; /** Foreground color (colormode) of bubble highlight, color object. */ private static Color Bubble_Highlight_Color; /** Foreground color (graymode) of bubble highlight, RGB value. */ private static final int bubble_highlight_gray = 0x000000; /** Foreground color (graymode) of bubble highlight, color object. */ private static Color Bubble_Highlight_Gray; /** Background color (colormode) for selection of suboptions, RGB value. */ private static final int suboption_bg_color = 0x336699; /** Background color (colormode) for selection of suboptions, * color object. */ private static Color SubOption_Bg_Color; /** Foreground color (colormode) for selection of suboptions, RGB value. */ private static final int suboption_fg_color = 0xFFFFCC; /** Foreground color (colormode) for selection of suboptions, * color object. */ private static Color SubOption_Fg_Color; /** Background color (graymode) for selection of suboptions, RGB value. */ private static final int suboption_bg_gray = Color.lightGray.getRGB(); /** Background color (graymode) for selection of suboptions, * color object. */ private static Color SubOption_Bg_Gray; /** Foreground color (graymode) for selection of suboptions, RGB value. */ private static final int suboption_fg_gray = 0x000000; /** Foreground color (graymode) for selection of suboptions, * color object. */ private static Color SubOption_Fg_Gray; /** Background color (colormode) for a dialog message, RGB value. */ private static final int dialog_bg_color = 0xAAAAFF; /** Background color (colormode) for a dialog message, color object. */ private static Color Dialog_Bg_Color; /** Foreground color (colormode) for a dialog message, RGB value. */ private static final int dialog_fg_color = 0x000000; /** Foreground color (colormode) for a dialog message, color object. */ private static Color Dialog_Fg_Color; /** Background color (graymode) for a dialog message, RGB value. */ private static final int dialog_bg_gray = 0xAAAAAA; /** Background color (graymode) for a dialog message, color object. */ private static Color Dialog_Bg_Gray; /** Foreground color (graymode) for a dialog message, RGB value. */ private static final int dialog_fg_gray = 0x000000; /** Foreground color (graymode) for a dialog message, color object. */ private static Color Dialog_Fg_Gray; /** Background color (colormode) for a dialog message, RGB value. */ private static final int dialogalert_bg_color = 0xAAAAFF; /** Background color (colormode) for a dialog message, color object. */ private static Color DialogAlert_Bg_Color; /** Foreground color (colormode) for a dialog alert message, RGB value. */ private static final int dialogalert_fg_color = 0xFF0000; /** Foreground color (colormode) for a dialog message, color object. */ private static Color DialogAlert_Fg_Color; /** Background color (graymode) for a dialog message, RGB value. */ private static final int dialogalert_bg_gray = 0xAAAAAA; /** Background color (graymode) for a dialog message, color object. */ private static Color DialogAlert_Bg_Gray; /** Foreground color (graymode) for a dialog message, RGB value. */ private static final int dialogalert_fg_gray = 0x000000; /** Foreground color (graymode) for a dialog message, color object. */ private static Color DialogAlert_Fg_Gray; /** Background color (colormode) for text entry, RGB value. */ private static final int entry_bg_color = 0xAAAAFF; /** Background color (colormode) for text entry, color object. */ private static Color Entry_Bg_Color; /** Background color (graymode) for text entry, RGB value. */ private static final int entry_bg_gray = 0xAAAAAA; /** Background color (graymode) for text entry, color object. */ private static Color Entry_Bg_Gray; /** Part of a buffer used to avoid flicker. */ private static Image temp_screen_image; /** Part of a buffer used to avoid flicker. */ private static Graphics temp_screen; /** Font for banner. */ private static Font font_banner; /** Font metrics for banner. */ private static FontMetrics metrics_banner; /** Font for buttons. */ private static Font font_button; /** Font metrics for buttons. */ private static FontMetrics metrics_button; /** Superscript font for buttons. */ private static Font font_button_sup; /** Superscript metrics for buttons. */ private static FontMetrics metrics_button_sup; /** Font for status text on buttons. */ private static Font small_font_button; /** Font metrics for status text on buttons. */ private static FontMetrics small_metrics_button; /** Font for dialog message. */ private static Font font_message; /** Font metrics for dialog message. */ private static FontMetrics metrics_message; /** Font for dialog message. */ private static Font font_bmessage; /** Font metrics for dialog message. */ private static FontMetrics metrics_bmessage; /** Font for dialog message. */ private static Font font_status; /** Font metrics for dialog message. */ private static FontMetrics metrics_status; /** Font for linking words. */ private static Font font_linkingword; /** Font metrics for linking words. */ private static FontMetrics metrics_linkingword; /** Font for concept words. */ private static Font font_concept; /** Font metrics for concept words. */ private static FontMetrics metrics_concept; // Concept map metrics. /** Number of concepts and linking words. */ private static int number_words = 0; /** Number of concepts and linking words. */ private static boolean one_word_flag = false; /** Number of concepts. */ private static int number_conceptwords = 0; /** Number of linking words. */ private static int number_linkingwords = 0; /** Number of connections (links). */ private static int number_links; // Arrays which store concepts, linking words, and connections. /** holds both concepts and linking words */ private static MoveableWord words[]; /** An array of ordered pairs. */ private static Link links[]; /** Action button (helps for a browser compatible non-AWT solution). */ private static ActionButton text_entry_button; // Menu buttons (when they are pressed, the "mode" variable changes). /** MOVE a concept word. */ private static MenuButton move_button; /** ADD to the concept map. */ private static MenuButton add_button; /** DELETE from the concept map. */ private static MenuButton edit_button; /** VIEW the concept map. */ private static MenuButton view_button; /** SAVE the concept map. */ private static MenuButton save_button; /** GRADE the concept map. */ private static MenuButton grade_button; /** The text suboption that is to be highlighted. */ private static String Bubble_Highlight_TextPattern; /** The menu features which are to be hidden/disabled * on the web client. */ private static String disable_string; /** The canvas size for the applet (space_width x space_height). */ private static String canvassize_string; /** The font size for the concept and linking words. */ private static String fontsize_string; /** The set of concept maps the given web client refers to. */ private static String gallery; /** The message to display during saving. */ private static String save_banner_text; /** The message to display during robograding. */ private static String robograder_banner_text; /** The message to display during robograding. */ private static String resize_banner_text; /** Default button width dimension */ private static final int button_width = 70; /** Default button height dimension */ private static final int button_height = 25; // Dimensions for the connecting links' arrowheads. /** Length of a connecting link's arrowhead. */ private static final int link_arrowhead_length = 12; /** Width of a connecting link's arrowhead. */ private static final int link_arrowhead_width = 5; /** Thickening of link. */ private static final int link_linkthickener_width = 1; /** Offset text rightwards in menu buttons. */ private static final int menu_button_text_offset = 0; /** Index used for parsing canvassize_string. */ private static int x_index = 0; /** * Unescape string. A '@' ("at" sign) + ';' * ("semicolon" sign) combination is used since * java's getParameter method can pre-empt processing * of ampersand-semicolon escaping. * @param word The word to substitute escaped values with "real" values. */ public String unescape (String word) { String newword; // Used to temporarily store fixing of word. String escapefrag; // Escaped fragment of the word. int atsign_index = -2; int semicolon_index = 0; int atstring_index = 0; int semiback = 0; atstring_index = 0; atsign_index = 0; while (atsign_index != -1 && atsign_index != -2) { atsign_index = word.indexOf("@",atstring_index); semicolon_index = word.indexOf(";",atstring_index); while (semicolon_index < atsign_index && semicolon_index != -1) { semicolon_index = word.indexOf(";",semicolon_index+1); } semiback = 0; if (atsign_index != -1 && semicolon_index != -1 && atsign_index < semicolon_index) { escapefrag = word.substring(atsign_index + 1, semicolon_index); if (escapefrag.equals("comma")) { newword = word.substring(0,atsign_index) + "," + word.substring(semicolon_index+1, word.length()); word = newword; semiback = 6; } else if (escapefrag.equals("amp")) { newword = word.substring(0,atsign_index) + "&" + word.substring(semicolon_index+1,word.length()); word = newword; semiback = 4; } else if (escapefrag.equals("nbsp")) { newword = word.substring(0,atsign_index) + " " + word.substring(semicolon_index+1,word.length()); word = newword; semiback = 5; } else if (escapefrag.equals("at")) { newword = word.substring(0,atsign_index) + "@" + word.substring(semicolon_index+1,word.length()); word = newword; semiback = 3; } else if (escapefrag.equals("quote")) { newword = word.substring(0,atsign_index) + "\"" + word.substring(semicolon_index+1, word.length()); word = newword; semiback = 6; } else if (escapefrag.equals("single")) { newword = word.substring(0,atsign_index) + "'" + word.substring(semicolon_index+1, word.length()); word = newword; semiback = 7; } else if (escapefrag.equals("back")) { newword = word.substring(0,atsign_index) + "\\" + word.substring(semicolon_index+1, word.length()); word = newword; semiback = 7; } else if (escapefrag.equals("gt")) { newword = word.substring(0,atsign_index) + ">" + word.substring(semicolon_index+1, word.length()); word = newword; semiback = 7; } else if (escapefrag.equals("lt")) { newword = word.substring(0,atsign_index) + "<" + word.substring(semicolon_index+1, word.length()); word = newword; semiback = 7; } else { word = "&" + escapefrag + ";"; } } atstring_index = semicolon_index + 1 - semiback; if (semicolon_index == -1) { atsign_index = -2; } } return word; } // END unescape /** * Constructor. Things to do before launching applet in runtime * environment. */ public ConceptWebClient() { // Don't look for BeanInfo or $COMClassObject (prevent error_log spam). try { java.beans.Introspector.setBeanInfoSearchPath(null); } catch (Exception e) { } } // END ConceptWebClient constructor /** * Take a list of strings and shuffle them. * @param string_list The list to shuffle. */ public static void stringlist_shuffle(String[] string_list) { String tempstring = new String(); for (int idx1 = string_list.length; idx1 > 0; idx1--) { int idx2 = (int)(Math.random()*string_list.length); tempstring = string_list[idx1 - 1]; string_list[idx1-1] = new String(string_list[idx2]); string_list[idx2] = new String(tempstring); } } /** * Run once at beginning of program. * Initializes values with various predefined constants. * (Note that this is a very lengthy method.) */ public void init () { try {Thread.sleep(500);} catch (Exception e) {} rtry = 1; // Don't look for BeanInfo or $COMClassObject (prevent error_log spam). try { java.beans.Introspector.setBeanInfoSearchPath(null); } catch (Exception e) { } /* try { image_icon1 = getImage(new URL("http://ctools.msu.edu/ctools/ctools_images/newscience.gif")); } catch (IOException e) { } */ // Define the server talker object. this.server_talker = new ServerTalker(); // Define the robograding object. this.robo = new Robograde(); // Tell applet that it is to listen for mouse-related events. this.addMouseListener(this); this.addMouseMotionListener(this); this.color = true; ActionButton.colormode_on(); MenuButton.colormode_on(); MoveableWord.colormode_on(); Link.colormode_on(); BubbleMenuHelp.colormode_on(); Message.colormode_on(); Robograde.colormode_on(); // Initialize background color values. this.Background_Color = new Color(this.background_color); this.Background_Gray = new Color(this.background_gray); this.setBackground(Background_Gray); // Set default background color. // Initialize other color values. this.Footer_Fg_Color = new Color(this.footer_fg_color); this.Footer_Fg_Gray = new Color(this.footer_fg_gray); this.Incorrect_Fg_Color = new Color(this.incorrect_fg_color); this.Incorrect_Fg_Gray = new Color(this.incorrect_fg_gray); this.Neutral_Fg_Color = new Color(this.neutral_fg_color); this.Neutral_Fg_Gray = new Color(this.neutral_fg_gray); this.Correct_Fg_Color = new Color(this.correct_fg_color); this.Correct_Fg_Gray = new Color(this.correct_fg_gray); this.Conceptword_Fg_Color = new Color(this.conceptword_fg_color); this.Conceptword_Bg_Color = new Color(this.conceptword_bg_color); this.Conceptword_Fg_Gray = new Color(this.conceptword_fg_gray); this.Conceptword_Bg_Gray = new Color(this.conceptword_bg_gray); this.Conceptword_Fg_Brd_Gray = new Color(this.conceptword_fg_brd_gray); this.Linkingword_Fg_Color = new Color(this.linkingword_fg_color); this.Linkingword_Bg_Color = new Color(this.linkingword_bg_color); this.Linkingword_Fg_Gray = new Color(this.linkingword_fg_gray); this.Linkingword_Bg_Gray = new Color(this.linkingword_bg_gray); this.Linkingword_Fg_Brd_Gray = new Color(this.linkingword_fg_brd_gray); this.Link_Fg_Color = new Color(this.link_fg_color); this.Link_Fg_Gray = new Color(this.link_fg_gray); this.Link_Targetbox_Fg_Color = new Color(this.link_targetbox_fg_color); this.Link_Targetbox_Fg_Gray = new Color(this.link_targetbox_fg_gray); this.Button_Fg_On_Color = new Color(this.button_fg_on_color); this.Button_Fg_Off_Color = new Color(this.button_fg_off_color); this.Button_Bg_Color = new Color(this.button_bg_color); this.Button_Fg_On_Gray = new Color(this.button_fg_on_gray); this.Button_Fg_Off_Gray = new Color(this.button_fg_off_gray); this.Button_Bg_Gray = new Color(this.button_bg_gray); this.Bubble_Fg_Color = new Color(this.bubble_fg_color); this.Bubble_Bg_Color = new Color(this.bubble_bg_color); this.Bubble_Fg_Gray = new Color(this.bubble_fg_gray); this.Bubble_Bg_Gray = new Color(this.bubble_bg_gray); this.Bubble_Border_Color = new Color(this.bubble_border_color); this.Bubble_Border_Gray = new Color(this.bubble_border_gray); this.Bubble_Highlight_Color = new Color(this.bubble_highlight_color); this.Bubble_Highlight_Gray = new Color(this.bubble_highlight_gray); this.SubOption_Fg_Color = new Color(this.suboption_fg_color); this.SubOption_Bg_Color = new Color(this.suboption_bg_color); this.SubOption_Fg_Gray = new Color(this.suboption_fg_gray); this.SubOption_Bg_Gray = new Color(this.suboption_bg_gray); this.Dialog_Fg_Color = new Color(this.dialog_fg_color); this.Dialog_Bg_Color = new Color(this.dialog_bg_color); this.Dialog_Fg_Gray = new Color(this.dialog_fg_gray); this.Dialog_Bg_Gray = new Color(this.dialog_bg_gray); this.DialogAlert_Fg_Color = new Color(this.dialogalert_fg_color); this.DialogAlert_Bg_Color = new Color(this.dialogalert_bg_color); this.DialogAlert_Fg_Gray = new Color(this.dialogalert_fg_gray); this.DialogAlert_Bg_Gray = new Color(this.dialogalert_bg_gray); this.Entry_Bg_Color = new Color(this.entry_bg_color); this.Entry_Bg_Gray = new Color(this.entry_bg_gray); this.Bubble_Highlight_TextPattern = new String("SUBMIT"); this.save_banner_text = new String("SAVING..."); this.robograder_banner_text = new String("ROBOGRADING..."); this.resize_banner_text = new String("RESIZING..."); // Get the expiration key for this session. // Get the document base for this server. this.document_base = this.getParameter("DOCUMENTBASE"); this.expiration_key = this.getParameter("EXPIRATION_KEY"); try {Thread.sleep(500);} catch (Exception e) {} // Safari w/ jdk1.4.1 does not always get the applet params // (safari jdk1.4.1 glitch that needs to be programmed around). // make safari w/ jdk1.4.1 happy... if (document_base == null) { try {Thread.sleep(500);} catch (Exception e) {} System.out.println("Glitch: no documentbase parameter"); document_base = new String("http://ctools.msu.edu/ctools"); /* try {rtry = 1; URL url = new URL(document_base+"/ConceptServerScript.cgi"+"?rtry=1"); getAppletContext().showDocument(url);} catch (Exception e) {} */ } rtry = 0; if (expiration_key == null) { try {Thread.sleep(500);} catch (Exception e) {} this.expiration_key = this.getParameter("EXPIRATION_KEY"); } if (expiration_key == null && rtry != 1) { System.out.println("Glitch: no expiration_key parameter"); try {rtry = 1; URL url = new URL(document_base+"/ConceptServerScript.cgi"+"?rtry=1"); getAppletContext().showDocument(url);} catch (Exception e) {} } // font size for concept and linking words this.fontsize_string = this.getParameter("FONTSIZE"); // make safari w/ jdk1.4.1 happy... if (this.fontsize_string == null && rtry != 1) { System.out.println("Glitch: no fontsize parameter"); try {rtry = 1; URL url = new URL(document_base+"/ConceptServerScript.cgi"+"?rtry=1"); getAppletContext().showDocument(url);} catch (Exception e) {} } if (this.fontsize_string == null) { this.fontsize_string = new String(" default "); } if (this.fontsize_string != null) { if (fontsize_string.indexOf("-1",0) != -1) { this.font_size = 8; } else if (fontsize_string.indexOf("default",0) != -1) { this.font_size = 10; } else if (fontsize_string.indexOf("+1",0) != -1) { this.font_size = 12; } else if (fontsize_string.indexOf("+2",0) != -1) { this.font_size = 16; } else if (fontsize_string.indexOf("+3",0) != -1) { this.font_size = 30; } } // The drawing area dimensions (user-specified) for the concept map. this.canvassize_string = this.getParameter("CANVASSIZE"); // make safari w/ jdk1.4.1 happy... if (canvassize_string == null && rtry != 1) { System.out.println("Glitch: no canvassize parameter"); try {rtry = 1; URL url = new URL(document_base+"/ConceptServerScript.cgi"+"?rtry=1"); getAppletContext().showDocument(url);} catch (Exception e) {} } if (canvassize_string == null) { canvassize_string = "768x480"; } if (canvassize_string != null) { x_index = canvassize_string.indexOf("x",0); space_width = Integer.parseInt(canvassize_string.substring(0,x_index)); space_height = Integer.parseInt(canvassize_string.substring(x_index+1, canvassize_string.length())); // Recompute the width of the entire applet. applet_width = left_space+space_width+right_space; // Recompute the height of the entire applet. applet_height = top_space+space_height+bottom_space; } this.resize(this.applet_width, this.applet_height); // Specify applet dimensions. // Set up buffer if available (so as to reduce screen flickering). try { this.temp_screen_image = this.createImage(this.applet_width, this.applet_height); this.temp_screen = this.temp_screen_image.getGraphics(); } catch (Exception e) { // double-buffering not available this.temp_screen = null; } // Specify fonts. // The font used for large banner text (for saving status). this.font_banner = new Font("Helvetica", Font.BOLD, 30); if (this.font_banner == null) { this.font_banner = this.getFont(); } this.metrics_banner = this.getFontMetrics(this.font_banner); // The font used for menu buttons and also BubbleMenuHelp SubOptions. this.font_button = new Font("Helvetica", Font.BOLD, 10); if (this.font_button == null) { this.font_button = this.getFont(); } this.metrics_button = this.getFontMetrics(this.font_button); // The font used for menu buttons and also BubbleMenuHelp SubOptions. this.font_button_sup = new Font("Helvetica", Font.PLAIN, 8); if (this.font_button_sup == null) { this.font_button_sup = this.getFont(); } this.metrics_button_sup = this.getFontMetrics(this.font_button_sup); // The font used to add status entries to menu buttons (deprecated). this.small_font_button = new Font("Helvetica", Font.PLAIN, 8); if (this.small_font_button == null) { this.small_font_button = this.getFont(); } this.small_metrics_button = this.getFontMetrics(this.small_font_button); // The font used to display info in the top and bottom applet regions. this.font_message = new Font("Helvetica", Font.PLAIN, 10); if (this.font_message == null) { this.font_message = this.getFont(); } this.metrics_message = this.getFontMetrics(this.font_message); // The font used to label the lower left entry box. this.font_bmessage = new Font("Helvetica", Font.BOLD, 10); if (this.font_bmessage == null) { this.font_bmessage = this.getFont(); } this.metrics_bmessage = this.getFontMetrics(this.font_bmessage); // The font used to display status info in the top applet region. this.font_status = new Font("Helvetica", Font.PLAIN, 10); if (this.font_status == null) { this.font_status = this.getFont(); } this.metrics_status = this.getFontMetrics(this.font_status); // The font used for linking words. this.font_linkingword = new Font("Helvetica", Font.PLAIN, this.font_size); if (this.font_linkingword == null) { this.font_linkingword = this.getFont(); } this.metrics_linkingword = this.getFontMetrics(this.font_linkingword); // The font used for concept words. this.font_concept = new Font("Helvetica", Font.BOLD, this.font_size); if (this.font_concept == null) { this.font_concept = this.getFont(); } this.metrics_concept = this.getFontMetrics(this.font_concept); // Initialize concept words with spatial offsets, fonts, and colors. MoveableWord.conceptword_configure(this.left_space, this.top_space, this.font_concept, this.metrics_concept, this.Conceptword_Fg_Color, this.Conceptword_Bg_Color, this.Conceptword_Fg_Gray, this.Conceptword_Bg_Gray, this.Conceptword_Fg_Brd_Gray); // Initialize linking words with spatial offsets, fonts, and colors. MoveableWord.linkingword_configure(this.left_space, this.top_space, this.font_linkingword, this.metrics_linkingword, this.Linkingword_Fg_Color, this.Linkingword_Bg_Color, this.Linkingword_Fg_Gray, this.Linkingword_Bg_Gray, this.Linkingword_Fg_Brd_Gray); // Initialize connecting line characteristics. Robograde.configure(this.Incorrect_Fg_Color, this.Incorrect_Fg_Gray, this.Neutral_Fg_Color, this.Neutral_Fg_Gray, this.Correct_Fg_Color, this.Correct_Fg_Gray ); // Initialize connecting line characteristics. Link.configure(this.link_arrowhead_length, this.link_arrowhead_width, this.link_linkthickener_width, this.Link_Fg_Color,this.Link_Fg_Gray, this.Link_Targetbox_Fg_Color,this.Link_Targetbox_Fg_Gray ); this.number_links = 0; // The map starts with zero links (connections). this.words = new MoveableWord[100]; // 100 words maximum. this.links = new Link[100]; // 100 links maximum. // Instantiate 100 possible links. for (int i = 0; i < 100; i++) { this.links[i] = new Link(); } // Getting the **** APPLET PARAMETERS **** (specified in HTML code). // Note, getParameter(CANVASSIZE) is not processed here, but is // processed above in this code, so is FONTSIZE. // (appropriately prior to the resize() function) // Get the session id key for this session. this.sid = this.getParameter("sid"); // make safari w/ jdk1.4.1 happy... if (sid == null && rtry != 1) { try {rtry = 1; URL url = new URL(document_base+"/ConceptServerScript.cgi"+"?rtry=1"); getAppletContext().showDocument(url);} catch (Exception e) {} } // Get the map name for this map. this.mapname = this.getParameter("MAPNAME"); // Determine which menu buttons, if any, should be disabled. this.disable_string = this.getParameter("DISABLE"); // make safari w/ jdk1.4.1 happy... if (disable_string == null && rtry != 1) { try {rtry = 1; URL url = new URL(document_base+"/ConceptServerScript.cgi"+"?rtry=1"); getAppletContext().showDocument(url);} catch (Exception e) {} } // The set of maps a concept map refers to. this.gallery = this.getParameter("GALLERY"); // Read the parameters of concepts and linking words // (e.g. An instructor might want to have the applet // start with a pre-existing set of concept words and // linking words). String conceptword_string = this.getParameter("CONCEPTWORDS"); String linkingword_string = this.getParameter("LINKINGWORDS"); // If concept and linkingword parameters are defined. if (conceptword_string != null && linkingword_string != null) { // Perform comma-based parsing apart of fields within strings. int last_string_index = 0; int string_index = conceptword_string.indexOf(",",0); // These arrays will hold the fields within the string. // Lists of Concepts and Linking Words. String conceptword_list[] = new String[200]; String linkingword_list[] = new String[200]; String word; // Current field within string being considered. this.number_words = 0; // Set the number of words to be // zero. this.number_conceptwords = 0; // Set the number of concept words // to be zero. this.number_linkingwords = 0; // Set the number of linking words // to be zero. // Parse the conceptword_string for comma-separated fields. while (string_index != -1) { word = conceptword_string.substring(last_string_index, string_index); last_string_index = string_index+1; string_index = conceptword_string.indexOf(",", last_string_index); conceptword_list[number_conceptwords] = word; number_words++; number_conceptwords++; } if (number_conceptwords > 0) // Then grab last field. { word = conceptword_string.substring(last_string_index, conceptword_string.length()); /* System.out.println( "numword: "+number_words+"; "+ "conceptword: "+number_conceptwords+"; "+ "word: "+word+"; " );*/ conceptword_list[number_conceptwords] = word; number_words++; number_conceptwords++; } // Parse the linkingword_string for comma-separated fields. last_string_index = 0; string_index = linkingword_string.indexOf(",",0); while (string_index != -1) { word = linkingword_string.substring(last_string_index, string_index); last_string_index = string_index+1; string_index = linkingword_string.indexOf(",", last_string_index); linkingword_list[number_linkingwords] = new String(word); number_words++; number_linkingwords++; } if (number_linkingwords > 0) // Then grab last field. { word = linkingword_string.substring(last_string_index, linkingword_string.length()); linkingword_list[number_linkingwords] = new String(word); number_words++; number_linkingwords++; } // Shuffle concept word list. String tempstring = new String(); for (int idx1 = number_conceptwords; idx1 > 0; idx1--) { int idx2 = (int)(Math.random()*number_conceptwords); tempstring = conceptword_list[idx1-1]; conceptword_list[idx1-1] = new String(conceptword_list[idx2]); conceptword_list[idx2] = new String(tempstring); } // Translate concept word data into MoveableWord objects and store // inside the "words" array. for (int i = 0; i < number_conceptwords; i++) { words[i] = new MoveableWord(conceptword_list[i],"CONCEPT"); // Potential X location for new word. int Xnewloc = left_space+space_width-100; // Potential Y location for new word. int Ynewloc = (int)(Math.random() * (float)(this.space_height*1/8)) + this.top_space; int j2 = i-1; dfs: while (j2 > -1) { if ((words[j2].Y > this.top_space) && (words[j2].Y <= (this.top_space+(this.space_height*1/8))) ) { if ( words[j2].X <= (Xnewloc+words[i].width) ) { Xnewloc = words[j2].X-30; } while ( words[j2].X <= (Xnewloc+words[i].width) ) { Xnewloc -= 30; } } if (Xnewloc < (left_space+10)) { Ynewloc = (int)(Math.random() * (float)(this.space_height*1/8)) + (this.top_space+ (int)(float)(this.space_height*1/8))+15; Xnewloc = left_space+space_width-100; break dfs; } j2--; } j2 = i-1; dfs2: while (j2 > -1) { if ( (words[j2].Y > (this.top_space+(this.space_height*1/8))+15) && (words[j2].Y < (this.top_space+(this.space_height*2/8))+15) ) { if ( words[j2].X <= (Xnewloc+words[i].width) ) { Xnewloc = words[j2].X-30; } while ( words[j2].X <= (Xnewloc+words[i].width) ) { Xnewloc -= 30; } } if (Xnewloc < (left_space+10)) { Ynewloc = (int)(Math.random() * (float)(this.space_height*1/8)) + (this.top_space+ (int)(float)(this.space_height*2/8))+30; Xnewloc = (int)(Math.random() * (float)(space_width - words[i].width) )+left_space; break dfs2; } j2--; } if ((Xnewloc+words[i].width)>(left_space+space_width)) { Xnewloc = left_space+space_width-words[i].width-10; } if (Xnewloc<(left_space+10)) { Xnewloc = left_space+10; } this.words[i].X = Xnewloc; this.words[i].Y = Ynewloc; this.words[i].set_center(); } // Shuffle linking word list. for (int idx1 = number_linkingwords; idx1 > 0; idx1--) { int idx2 = (int)(Math.random()*number_linkingwords); tempstring = linkingword_list[idx1-1]; linkingword_list[idx1-1] = new String(linkingword_list[idx2]); linkingword_list[idx2] = new String(tempstring); } // Translate linking word data into MoveableWord objects and store // inside the "words" array. for (int ip = 0; ip < number_linkingwords; ip++) { int i = number_conceptwords+ip; words[i] = new MoveableWord(linkingword_list[ip],"LINKINGWORD"); // Potential X location for new word. int Xnewloc = left_space+space_width-100; // Potential Y location for new word. int Ynewloc = this.top_space+this.space_height- 15 - (int)(Math.random() * (float)(this.space_height*1/8)); int j2 = i-1; dfs3: while (j2>(number_conceptwords-1)) { if ( (words[j2].Y > (this.top_space+this.space_height- (this.space_height*1/8+15))) && (words[j2].Y < (this.top_space+this.space_height)) ) { if ( words[j2].X <= (Xnewloc+words[i].width) ) { Xnewloc = words[j2].X-30; } while ( words[j2].X <= (Xnewloc+words[i].width) ) { Xnewloc -= 30; } } if (Xnewloc < (left_space+10)) { Ynewloc = this.top_space + this.space_height - 30 - (int)(Math.random() * (float)(this.space_height*1/8)) - (int)(this.space_height*1/8); Xnewloc = left_space+space_width-100; break dfs3; } j2--; } j2 = i-1; dfs4: while (j2 > (number_conceptwords-1)) { if ( (words[j2].Y < (this.top_space+this.space_height- (this.space_height*1/8+15))) && (words[j2].Y > (this.top_space+this.space_height- (this.space_height*2/8+30))) ) { if ( words[j2].X <= (Xnewloc+words[i].width) ) { Xnewloc = words[j2].X-30; } while ( words[j2].X <= (Xnewloc+words[i].width) ) { Xnewloc -= 30; } } if (Xnewloc < (left_space+10)) { Ynewloc = this.top_space + this.space_height - 45 - (int)(Math.random() * (float)(this.space_height*1/8)) - (int)(this.space_height*2/8); Xnewloc = (int)(Math.random() * (float)(space_width - words[i].width) )+left_space; break dfs4; } j2--; } if ((Xnewloc+words[i].width)>(left_space+space_width)) { Xnewloc = left_space+space_width-words[i].width-10; } if (Xnewloc<(left_space+10)) { Xnewloc = left_space+10; } if ((Ynewloc+words[i].height)>(top_space+space_height)) { Ynewloc = top_space+space_height-words[i].height-10; } this.words[i].X = Xnewloc; this.words[i].Y = Ynewloc; this.words[i].set_center(); } } /* BTL="block top left". * * Note, most of the time, when users start a concept map exercise, * BTLx, BTLy, WORDS, TYPES, and LINKS strings are left blank. * * BTLx, BTLy, WORDS, TYPES, and LINKS strings are meant to help * retrieve saved concept maps that the user may have worked on in the * past. * * These four strings (not including LINKS) are in a parallel * structure: * e.g. The first element of BTLx_string, BTLy_string, WORDS_string, * and TYPES_string, all describe the first concept map word; * e.g. The second element of BTLx_string, BTLy_string, WORDS_string, * and TYPES_string, all describe the second concept map word; * etc. * * Another usage of these values would be to help customize * the initial concept map that is presented to the user. */ String BTLx_string = getParameter("BTLx"); // Top left x of words. String BTLy_string = getParameter("BTLy"); // Top left y of words String WORDS_string = getParameter("WORDS"); // Text of words. String TYPES_string = getParameter("TYPES"); // CONCEPT or LINKINGWORD. // LINKS exist between the enumerated concept objects above. // LINKS is a list of ordered pairs where each pair consists of // two integers pointing to locations in the BTLx/BTLy/WORDS/TYPES // strings. String LINKS_string = getParameter("LINKS"); if (BTLx_string != null && BTLy_string != null && WORDS_string != null && TYPES_string!=null) // If these all exist. { // For debugging. // System.out.println(BTLx_string); // System.out.println(BTLy_string); // System.out.println(WORDS_string); // System.out.println(TYPES_string); // System.out.println(LINKS_string); // Only accept up to 200 words maximum into the applet from the // HTML parameters. String word_list[] = new String[200]; // 200 word maximum array. String word; // Used to temporarily store substrings. number_words = 0; // Initialize the number of words to be zero. // Parse the applet parameter WORDS (if exists). // Also, determine a total count of concept map words. int last_string_index = 0; int string_index = WORDS_string.indexOf(",",0); if (string_index == -1 && WORDS_string.length() > 0) { one_word_flag = true; } while (string_index != -1) { word = WORDS_string.substring(last_string_index,string_index); word = unescape(word); last_string_index = string_index+1; string_index = WORDS_string.indexOf(",",last_string_index); word_list[number_words] = word; number_words++; } if (number_words>0 || one_word_flag) // Then grab last field. { // Specify string substring region having last WORDS value. word = WORDS_string.substring(last_string_index, WORDS_string.length()); word = unescape(word); word_list[number_words] = word; number_words++; } // Parse the applet parameter TYPES (if exists). // Also, determine a total count of "concept words" // and "linking words" // (i.e. concept_map_words = concept_words + linking_words). String type_list[] = new String[200]; last_string_index = 0; string_index = TYPES_string.indexOf(",",0); int count = 0; while (string_index != -1) { word = TYPES_string.substring(last_string_index,string_index); last_string_index = string_index+1; string_index = TYPES_string.indexOf(",",last_string_index); if (word.equals("CONCEPT")) { type_list[count] = "CONCEPT"; number_conceptwords++; } else { type_list[count] = "LINKINGWORD"; number_linkingwords++; } count++; } if (number_words > 0 || one_word_flag) // Then grab last field. { // Specify string substring region having last TYPES value. word = TYPES_string.substring(last_string_index, TYPES_string.length()); if (word.equals("CONCEPT")) { type_list[count] = "CONCEPT"; number_conceptwords++; } else { type_list[count] = "LINKINGWORD"; number_linkingwords++; } } // Parse the applet parameter BTLx (if exists). int btlx_list[] = new int[200]; last_string_index = 0; string_index = BTLx_string.indexOf(",",0); count = 0; while (string_index != -1) { word = BTLx_string.substring(last_string_index,string_index); last_string_index = string_index+1; string_index = BTLx_string.indexOf(",",last_string_index); btlx_list[count] = Integer.parseInt(word); count++; } if (number_words > 0 || one_word_flag) // Then grab last field. { // Specify string substring region having last BTLx value. word = BTLx_string.substring(last_string_index, BTLx_string.length()); btlx_list[count] = Integer.parseInt(word); } // Parse the applet parameter BTLy (if exists). int btly_list[] = new int[200]; last_string_index = 0; string_index = BTLy_string.indexOf(",",0); count = 0; while (string_index != -1) { // Specify string substring region having last BTLy value. word = BTLy_string.substring(last_string_index,string_index); last_string_index = string_index+1; string_index = BTLy_string.indexOf(",",last_string_index); btly_list[count] = Integer.parseInt(word); count++; } if (number_words > 0 || one_word_flag) // Then grab last field. { // Specify string substring region having last BTLy value. word = BTLy_string.substring(last_string_index, BTLy_string.length()); btly_list[count] = Integer.parseInt(word); } // Parse the applet parameter LINKS (if exists). if (LINKS_string != null && LINKS_string.length() > 0) { last_string_index = 0; string_index = LINKS_string.indexOf(",",0); count = 0; int sloc; String word1; String word2; while (string_index != -1) { word = LINKS_string.substring(last_string_index, string_index); last_string_index = string_index+1; string_index = LINKS_string.indexOf(",",last_string_index); sloc = word.indexOf(" ",0); word1 = word.substring(0,sloc); word2 = word.substring(sloc+1,word.length()); links[count].setValue(Integer.parseInt(word1), Integer.parseInt(word2)); number_links++; count++; } if (LINKS_string.length() > 0) // Get the last unprocessed link { // Specify string substring region having last LINKS value. word = LINKS_string.substring(last_string_index, LINKS_string.length()); sloc = word.indexOf(" ",0); word1 = word.substring(0,sloc); word2 = word.substring(sloc+1,word.length()); links[count].setValue(Integer.parseInt(word1), Integer.parseInt(word2)); number_links++; } } // Calculate dimensions and positions of concept and linking words. for (int i = 0; i < number_words; i++) { // For debugging // System.out.println(word_list[i] + type_list[i] + // btlx_list[i] + btly_list[i]); words[i] = new MoveableWord(word_list[i],type_list[i]); int wordX = left_space+space_width/2; int wordY = top_space+space_height/2; while (wordY > (top_space+(space_height*1/8))) { wordX = (int)(Math.random() * (float)(space_width - words[i].width) )+left_space; wordY = (int)(Math.random () * (float)(space_height - words[i].height) )+top_space; } words[i].X = wordX; words[i].Y = wordY; words[i].X = btlx_list[i]+left_space; words[i].Y = btly_list[i]+top_space; words[i].set_center(); } } // Dialog message coordinates. Message.configure(font_message,metrics_message, Dialog_Fg_Color,Dialog_Bg_Color, Dialog_Fg_Gray,Dialog_Bg_Gray, left_space+5,15,left_space,0,space_width-100, top_space); // Dialog status message coordinates. StatusMessage.configure(font_status,metrics_status, Dialog_Fg_Color,Dialog_Bg_Color, Dialog_Fg_Gray,Dialog_Bg_Gray, DialogAlert_Fg_Color,DialogAlert_Bg_Color, DialogAlert_Fg_Gray,DialogAlert_Bg_Gray, left_space+space_width-95,15, space_width+left_space-100,0,100, top_space); // Set initial mode to move. if (!is_disabled(1)) { mode = new String("MOVE"); } else { mode = new String(""); } // Set initial submode to nothing. submode = new String(""); // Set event counter to 1 (used for multiple-step-guidance such // as with connecting links). event_counter = 1; // Set dimensions, fonts, and colors of the menu buttons. MenuButton.configure(button_width,button_height, font_button,small_font_button, metrics_button, menu_button_text_offset, Button_Fg_On_Color,Button_Fg_Off_Color, Button_Bg_Color, Button_Fg_On_Gray,Button_Fg_Off_Gray, Button_Bg_Gray ); // Set dimensions, fonts, and colors of the action buttons. ActionButton.configure(button_width,button_height, font_button,small_font_button, metrics_button, menu_button_text_offset, Button_Fg_On_Color,Button_Fg_Off_Color, Button_Bg_Color, Button_Fg_On_Gray,Button_Fg_Off_Gray, Button_Bg_Gray ); // Configure BubbleMenuHelp objects (these pop-up when a menu button // is pressed). BubbleMenuHelp.configure( font_button,metrics_button, font_button_sup,metrics_button_sup, font_message,metrics_message, bubble_width, Bubble_Fg_Color,Bubble_Bg_Color, Bubble_Fg_Gray,Bubble_Bg_Gray, SubOption_Fg_Color,SubOption_Bg_Color, SubOption_Fg_Gray,SubOption_Bg_Gray, Bubble_Border_Color,Bubble_Border_Gray, Bubble_Highlight_Color,Bubble_Highlight_Gray, Bubble_Highlight_TextPattern ); // Construct the text entry action button. text_entry_button = new ActionButton(new String("add to map"),0, 230+top_space); // Construct the menu buttons with the text that should appear on them // as well as their coordinates. move_button = new MenuButton(new String("MOVE"),0, top_space+button_height*0); add_button = new MenuButton(new String("ADD"),0, top_space+button_height*1); edit_button = new MenuButton(new String("EDIT"),0, top_space+button_height*2); view_button = new MenuButton(new String("VIEW"),0, top_space+button_height*3); save_button = new MenuButton(new String("SAVE"),0, top_space+button_height*4); grade_button = new MenuButton(new String("GRADE"),0, top_space+button_height*5); // Set the pop-out for the MOVE menu button. move_button.setPopOut(new BubbleMenuHelp("Use your mouse to move concepts and linking words", 20,top_space,false), new Message(new String("Move concepts and linking words."))); // Set the pop-out for the ADD menu button. add_button.setPopOut(new BubbleMenuHelp("Press a button below",100, top_space+button_height*1-15,true), new Message(new String("Select add choice"))); // Set suboptions for the ADD menu button. add_button.addSubOption( new String("CONCEPT WORD"), new String("i.e. \"Earth\""), new Message(new String( "Enter your new concept word or phrase in the Text Box.")), !is_disabled(3) ); add_button.addSubOption( new String("LINKING WORD"), new String("i.e. \"rotates\""), new Message(new String( "Enter your new linking word or phrase in the Text Box.")), !is_disabled(4) ); add_button.addSubOption( new String("CONNECTING LINE"), new String("generate line between 2 words"), new Message(new String( "Click on the two concepts you wish to connect with a line link.")), new Message(new String( "Click on the second of the two concepts you are connecting.")), !is_disabled(5) ); // Set the pop-out for the EDIT menu button. edit_button.setPopOut(new BubbleMenuHelp("Press a button below",100, top_space+button_height*2-15,true), new Message(new String("Select edit choice"))); // Set suboptions for the EDIT menu button. edit_button.addSubOption( new String("DELETE WORD"), new String("remove word"), new Message(new String( "Select the concept or linking word you wish to remove.")), !is_disabled(8) ); edit_button.addSubOption( new String("DELETE LINES"), new String("remove line links"), new Message(new String( "Click on a line's box to remove, "+ "or click on a "+ "word to remove adjoining lines.")), !is_disabled(9) ); edit_button.addSubOption( new String("EDIT WORD"), new String("change the contents of a word"), new Message(new String( "Click on a concept or linking word to "+ "alter its text.")), new Message(new String( "Change the text and click \"change word\" "+ "button.")), !is_disabled(8) ); // Define the VIEW menu button attributes. view_button.setMode("basic"); view_button.setPopOut( new BubbleMenuHelp("Press a button below",100, top_space+button_height*3-15,true), new Message(new String("Select view option "+ "(current canvas size is "+ space_width+"x"+space_height+")")) ); // Set suboptions for the VIEW menu button. /* view_button.addSubOption( new String("EXPORT GRAPHIC"), new String( "create graphic image to print, save or send"), new Message(new String( "A GIF is being compiled and will be displayed shortly")), !is_disabled(11) );*/ view_button.addPrintSubOption( new String("LANDSCAPE"), new String("PORTRAIT"), new String("TOGGLE COLOR"), new String("Print Preview:"), new Message(new String( "A graphics image is being compiled and will be displayed shortly")), !is_disabled(11) ); /* view_button.addSubOption( new String("TOGGLE COLOR"), new String("switch applet between COLORS and GRAYMODE"), new Message(new String("Colors are switched")), !is_disabled(12) );*/ view_button.addComplexSizeSubOption( new String("480x300"), new String("768x480"), new String("960x600"), new String("1119x669"), new String("1282x801"), new String("1440x900"), new String("SMALL"), new String("MEDIUM"), new String("LARGE"), new String("Advanced"), new String(canvassize_string), new String("Resize:"), new Message(new String("Applet resized")), !is_disabled(12) ); // new String(canvassize_string), /* view_button.addSizeSubOption( new String("480x300"), new String("768x480"), new String("960x600"), new String("1119x669"), new String("1282x801"), new String("1440x900"), new String(canvassize_string), new String("Resize:"), new Message(new String("Applet resized")), !is_disabled(12) );*/ view_button.addSizeSubOption( new String("TOGGLE COLOR"), new String(" -1 "), new String(" default "), new String(" +1 "), new String(" +2 "), new String(" +3 "), new String(fontsize_string), new String("Select font size:"), new Message(new String("Concept map font size is changed")), !is_disabled(12) ); // Define the SAVE menu button attributes. save_button.setPopOut(new BubbleMenuHelp("Press a button below",100, top_space+button_height*4-15,true), new Message(new String("Select save choice"))); // Set suboptions for the SAVE menu button. save_button.addSubOption( new String("SAVE NOW"), new String("store map into your Map Gallery"), new Message(new String("Data is being generated on the server")), new Message(new String("Saving is complete")), !is_disabled(14) ); save_button.addSubOption( new String("RECOVER"), new String("try to recover autosaved work"), new Message(new String("Server side data is being generated")), !is_disabled(44) ); save_button.addSubOption( new String("EXPORT DATA"), new String("download data for future import"), new Message(new String("Export data is being compiled")), !is_disabled(15) ); // Define the GRADE menu button attributes. grade_button.setPopOut(new BubbleMenuHelp("Press a button below",100, top_space+button_height*5-15,true), new Message(new String("Press a button below"))); // Set suboptions for the GRADE menu button. if (!is_disabled(17)) { grade_button.setPopOut(new BubbleMenuHelp("Select SUBMIT to complete the assignment", 100,top_space+button_height*5-15,true), new Message(new String("You must select SUBMIT in order to complete this assignment"))); } grade_button.addSubOption(new String("SUBMIT"), new String("go to submit page"), new Message( new String("Assignment is being submitted to the instructor")), !is_disabled(17) ); // Need to add superscripted TM grade_button.addSubOption(new String("SHOW ROBOGRADER"), new String ("view an automatic assessment of your map"), new Message( new String("Robograder is "+ "currently under "+ "development")), !is_disabled(18) ); setLayout(null); // Avoiding AWT layouts for the sake of browser // compatibility as well as standardizing the // space that students have available to generate // a concept map. Since geometric distance cannot // be reliably specified for diverse browser AWT // implementations, space will be standardized // with pixels. // Add in AWT components for the keyboard entry of new words. text_entry_box = new TextField(6);//text_entry_box.setEditable(false); text_entry_box.setBounds(0,top_space+190,button_width,35); this.add(text_entry_box); /* try { URL url = new URL(document_base+"/ConceptServerScript.cgi?action="); // Start the general background thread (implements autosaving). Thread gt = new GeneralThread(url, getAppletContext(), words,links, number_words, number_links, server_talker, getGraphics(), expiration_key); gt.setDaemon(true); gt.start(); } catch (Exception e) { } */ } // END init /** * Pushes information.

* Currently a lot of logic occurs inside here. This function brings * together the pushing of information onto the: *

* Other interface state changes also occur here such as drawing * in color mode versus gray mode. * The strategic idea regarding this function was inspired by the * fact that different java virtual machines invoke the * the paint and update methods at irreconcilably different times. * Thus, the goal is to synchronize the pushing of information * in one function as opposed to relying on paint, update, or repaint * to do everything consistently.

* In some respects, an additional advantage to this strategy is that * it makes the code organization less diffuse and, for the programmer, * helps process all information that needs to be passed to the user in * a concerted manner. */ public void push_information_everywhere (Graphics g, Rectangle clip) { AppletContext ac = getAppletContext(); // Note to self: this should probably be removed or commented out. if (clip.x == Integer.MIN_VALUE) { clip = new Rectangle(0, 0, getSize().width, getSize().height); } // Consider the whole applet as a clipping area (for browser compatibility). clip = new Rectangle (0, 0, getSize().width, getSize().height); // Evaluate a color toggle action. if (mode.equals("VIEW")) { if (submode.equals("TOGGLE COLOR")) { ActionButton.color_toggle(); MenuButton.color_toggle(); MoveableWord.color_toggle(); Link.color_toggle(); BubbleMenuHelp.color_toggle(); Message.color_toggle(); Robograde.color_toggle(); if (color == true) {color = false;} else {color = true;} } else if (submode.equals("More Options")) { MenuButton.setMode("advanced"); } else if (submode.equals("Fewer Options")) { MenuButton.setMode("basic"); } } // Determine the map space background color. if (color == true) { g.setColor(Background_Color); } else { g.setColor(Background_Gray); } // Draw the map space (boundaried subspace inside applet space). g.fillRect(left_space, top_space, space_width, space_height); // Draw the left, top, and bottom portions of the applet. // (These surround the map space above.) if (color == true) { g.setColor(Entry_Bg_Color); } else { g.setColor(Entry_Bg_Gray); } g.fillRect(0,0,left_space,applet_height); g.fillRect(0,0,applet_width,top_space); g.fillRect(0,top_space+space_height,applet_width,bottom_space); /* g.setColor(Color.white); g.fillRect(image_x, image_y, image_width, image_height); g.setColor(Color.red); g.setFont(font_message); g.drawString("Test Icon",image_x+10,image_y+10); */ if (image_icon1 != null) { g.drawImage(image_icon1,image_x,image_y,this); } // (There currently is not any right space that needs to be drawn.) // Draw connecting lines. if (submode.equals("ENACT ROBOGRADER")) { for (int j = 0; j < number_links; j++) { links[j].draw(robo,j,g, words[links[j].getIndex1()], words[links[j].getIndex2()], false); } } else { for (int j = 0; j < number_links; j++) { links[j].draw(g,words[links[j].getIndex1()], words[links[j].getIndex2()], ((selected_word && !mode.equals("ADD")) && (selected_word && !(mode.equals("EDIT") && !submode.equals("DELETE LINES"))) ) || (mode.equals("EDIT") && submode.equals("DELETE LINES")) ); } } // Draw the words (so that the words that were last added appear at // the front). for (int i = number_words - 1; i >= 0; i--) { // Only redraw the word if it exists inside the clipping region // (but the clipping region is the entire applet...). // the null thing makes safari w/ jdk1.4.1 happy if (words[i] == null && rtry != 1) { System.out.println("Glitch: Word is null; #"+i); try {rtry = 1; URL url = new URL(document_base+"/ConceptServerScript.cgi"+"?rtry=1"); getAppletContext().showDocument(url);} catch (Exception e) {} } if (words[i] != null && words[i].inside_clip(clip.x, clip.y, clip.width, clip.height)) { if (submode.equals("ENACT ROBOGRADER")) { // words[i].draw(robo,i,g); // Draw normally for now. words[i].draw(g); } else { words[i].draw(g); } } } // Set the font in the graphics context. g.setFont(font_message); if (color == true) { g.setColor(Entry_Bg_Color); } else { g.setColor(Entry_Bg_Gray); } g.fillRect(0,top_space+160,button_width,100); // Draw the menu buttons based on the "mode" and on the disabled // feature settings. Also evaluate URL requests. if (mode.equals("")) { if (!is_disabled(1)) {move_button.draw(g,true);} if (!is_disabled(2)) {add_button.draw(g,true);} if (!is_disabled(7)) {edit_button.draw(g,true);} if (!is_disabled(10)) {view_button.draw(g,true);} if (!is_disabled(13)) {save_button.draw(g,true);} if (!is_disabled(16)) {grade_button.draw(g,true);} } else if (mode.equals("MOVE")) { mode_cycle = false; // This marks the end of the save animation. move_button.draw(g,false); if (!is_disabled(2)) {add_button.draw(g,true);} if (!is_disabled(7)) {edit_button.draw(g,true);} if (!is_disabled(10)) {view_button.draw(g,true);} if (!is_disabled(13)) {save_button.draw(g,true);} if (!is_disabled(16)) {grade_button.draw(g,true);} if (event_counter == 1 && submode.equals("ON")) { if (mousedown == true) { move_button.drawPopOut(g); } } move_button.drawPopOutMessage(g); } else if (mode.equals("ADD")) { if (!is_disabled(1)) {move_button.draw(g,true);} if (!is_disabled(7)) {edit_button.draw(g,true);} if (!is_disabled(10)) {view_button.draw(g,true);} if (!is_disabled(13)) {save_button.draw(g,true);} if (!is_disabled(16)) {grade_button.draw(g,true);} if (color == true) { g.setColor(Dialog_Bg_Color); } else { g.setColor(Dialog_Bg_Gray); } g.fillRect(left_space, top_space+space_height, space_width, 25); if (submode.equals("")) { add_button.draw(g,false); add_button.drawPopOut(g); add_button.drawPopOutMessage(g); } else { add_button.draw_with_blerb(g,false,submode); if (submode.equals("CONCEPT WORD")) { add_button.drawSubOptionMessage1(0,g); if (event_counter == 1) { this.add(text_entry_box); text_entry_box.setEditable(true); if (text_entry_box.getText().length() == 0) { text_entry_box.setText("enter"); } text_entry_box.setVisible(true); event_counter = 2; } g.setColor(MoveableWord.conceptword_bg); g.fillRect(0,top_space+160,button_width,100); g.setColor(MoveableWord.conceptword_fg); g.setFont(font_bmessage); g.drawString("Concept",10,top_space+175); text_entry_button.changeText("add to map"); text_entry_button.draw(g,true); if (color == false) { g.setColor(Bubble_Border_Gray); g.drawRect(0,top_space+160,button_width,100); } } else if (submode.equals("LINKING WORD")) { add_button.drawSubOptionMessage1(1,g); if (event_counter == 1) { this.add(text_entry_box); text_entry_box.setEditable(true); if (text_entry_box.getText().length()==0) { text_entry_box.setText("enter"); } text_entry_box.setVisible(true); event_counter = 2; } g.setColor(MoveableWord.linkingword_bg); g.fillRect(0,top_space+160,button_width,100); g.setColor(MoveableWord.linkingword_fg); g.setFont(font_bmessage); g.drawString("Linking",10,top_space+175); text_entry_button.changeText("add to map"); text_entry_button.draw(g,true); if (color == false) { g.setColor(Bubble_Border_Color); g.drawRect(0,top_space+160,button_width,100); } } else if (submode.equals("CONNECTING LINE")) { if (event_counter == 1) { add_button.drawSubOptionMessage1(2,g); } else { add_button.drawSubOptionMessage2(2,g); } } } } else if (mode.equals("EDIT")) { if (!is_disabled(1)) {move_button.draw(g,true);} if (!is_disabled(2)) {add_button.draw(g,true);} if (!is_disabled(10)) {view_button.draw(g,true);} if (!is_disabled(13)) {save_button.draw(g,true);} if (!is_disabled(16)) {grade_button.draw(g,true);} if (submode.equals("")) { edit_button.draw(g,false); edit_button.drawPopOut(g); edit_button.drawPopOutMessage(g); } else { edit_button.draw_with_blerb(g,false,submode); if (submode.equals("DELETE WORD")) { edit_button.drawSubOptionMessage1(0,g); } else if (submode.equals("DELETE LINES")) { edit_button.drawSubOptionMessage1(1,g); } else if (submode.equals("EDIT WORD")) { if (event_counter == 2) { edit_button.drawSubOptionMessage2(2,g); this.add(text_entry_box); text_entry_box.setEditable(true); if (text_entry_box.getText().length() == 0) { text_entry_box.setText(words[0].word); } text_entry_box.setVisible(true); if (words[0].word_type.equals("CONCEPT")) { g.setColor(MoveableWord.conceptword_bg); } else { g.setColor(MoveableWord.linkingword_bg); } g.fillRect(0,top_space+160,button_width,100); if (words[0].word_type.equals("CONCEPT")) { g.setColor(MoveableWord.conceptword_fg); } else { g.setColor(MoveableWord.linkingword_fg); } g.setFont(font_bmessage); g.drawString("Edit Word",10,top_space+175); text_entry_button.changeText("alter word"); text_entry_button.draw(g,true); event_counter = 3; } else if (event_counter == 3) { if (words[0].word_type.equals("CONCEPT")) { g.setColor(MoveableWord.conceptword_bg); } else { g.setColor(MoveableWord.linkingword_bg); } g.fillRect(0,top_space+160,button_width,100); if (words[0].word_type.equals("CONCEPT")) { g.setColor(MoveableWord.conceptword_fg); } else { g.setColor(MoveableWord.linkingword_fg); } g.setFont(font_concept); g.drawString("Edit Word",10,top_space+175); text_entry_button.draw(g,true); edit_button.drawSubOptionMessage2(2,g); } else { edit_button.drawSubOptionMessage1(2,g); } } } } else if (mode.equals("VIEW")) { if (!is_disabled(1)) {move_button.draw(g,true);} if (!is_disabled(2)) {add_button.draw(g,true);} if (!is_disabled(7)) {edit_button.draw(g,true);} if (!is_disabled(13)) {save_button.draw(g,true);} if (!is_disabled(16)) {grade_button.draw(g,true);} if (submode.equals("")) { view_button.draw(g,false); view_button.drawPopOut(g); view_button.drawPopOutMessage(g); } else { view_button.draw_with_blerb(g,false,submode); if ( submode.equals("EXPORT GRAPHIC") || submode.equals("EXPORT ROTATEGRAPHIC") ) { view_button.drawSubOptionMessage1(0,g); try { String data = new String(); String winfo = new String(); if (submode.equals("EXPORT ROTATEGRAPHIC")) { if (!color) { data += "custom=colormode:gray,rotate:1&"; } else { data += "custom=colormode:color,rotate:1&"; } } else { if (!color) { data += "custom=colormode:gray,rotate:0&"; } else { data += "custom=colormode:color,rotate:0&"; } } data += "command=GRAPHIC&"; for (int j = 0; j < number_links; j++) { data += "c"+j+"="+ links[j].getIndex1()+"+"+ links[j].getIndex2()+"&"; } for (int i = number_words - 1; i >= 0; i--) { // Only redraw words that exist inside the // clipping region. if (words[i].word_type.equals("LINKINGWORD")) { winfo = words[i].info(g)+"+n"; } else { winfo = words[i].info(g) + "+w"; } data += "w" + i + "=" + winfo + "&"; } if (disable_string != null) { data += "DISABLE="+disable_string; } if (disable_string != null && gallery != null) { data += "&gallery="+gallery; } // Authentication data for the CGI/Servlet. data += "&mapname="+mapname; data += "&expiration_key="+expiration_key; data += "&sid="+sid; // Cannot trust cookie data to // be available from applet. // CGI/Servlet uniform resource locator. URL url = new URL(document_base+ "/ConceptServerScript.cgi?action="); // Communicate request to server. server_talker.put(url,data); // Output the graphic page to // a new browser window. ac.showDocument(url,new String("_blank")); } catch (MalformedURLException me) { System.err.println("MalformedURLException: " + me); } catch (IOException e) { System.out.println( "unsuccessful attempt at saving data" + e); } submode = ""; if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} } else if (submode.equals("TOGGLE COLOR")) { view_button.drawSubOptionMessage1(1,g); submode = ""; if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} } else if (submode.equals("More Options")) { view_button.drawSubOptionMessage1(1,g); submode = ""; mode = "VIEW"; } else if (submode.equals("Fewer Options")) { view_button.drawSubOptionMessage1(1,g); submode = ""; mode = "VIEW"; } else if ( submode.equals("SMALL") || submode.equals("MEDIUM") || submode.equals("LARGE") || submode.equals("480x300") || submode.equals("768x480") || submode.equals("960x600") || submode.equals("1119x669") || submode.equals("1282x801") || submode.equals("1440x900") ) { // In this submode, notify user that saving is beginning, // and advance to the next submode of saving (SAVE ENACT). // Set this true to force multiple passes through // this function (necessary since SAVE involves // automated displaying). mode_cycle = true; // Determine the map space background color. if (color == true) { g.setColor(Background_Color); } else { g.setColor(Background_Gray); } // Draw map space (boundaried subspace in applet space). g.fillRect(left_space, top_space, space_width, space_height); if (color == true) { g.setColor(Entry_Bg_Color); } else { g.setColor(Entry_Bg_Gray); } g.setFont(font_banner); // Set font. g.drawString(resize_banner_text, left_space+20, top_space+80); // Draw text string. submode = submode+" csENACT"; } else if ( submode.equals(" +3 ") || submode.equals(" +2 ") || submode.equals(" +1 ") || submode.equals(" default ") || submode.equals(" -1 ") ) { // In this submode, notify user that saving is beginning, // and advance to the next submode of saving (SAVE ENACT). // Set this true to force multiple passes through // this function (necessary since SAVE involves // automated displaying). mode_cycle = true; // Determine the map space background color. if (color == true) { g.setColor(Background_Color); } else { g.setColor(Background_Gray); } // Draw map space (boundaried subspace in applet space). g.fillRect(left_space, top_space, space_width, space_height); if (color == true) { g.setColor(Entry_Bg_Color); } else { g.setColor(Entry_Bg_Gray); } g.setFont(font_banner); // Set font. g.drawString(resize_banner_text, left_space+20, top_space+80); // Draw text string. submode = submode+"ENACT"; } else if (submode.indexOf("csENACT",0) != -1) { // Parse out the specified resize dimensions. int csi = submode.indexOf(" csENACT",0); String csstring = new String(); csstring = submode.substring(0,csi); // Convert basic size tags into pixel dimensions. if (csstring.equals("SMALL")) { csstring = "480x300"; } else if (csstring.equals("MEDIUM")) { csstring = "768x480"; } else if (csstring.equals("LARGE")) { csstring = "960x600"; } try { // Holds arguments to CGI post to URI. String data = new String(); // Used to construct information about each "word". String winfo = new String(); data += "command=RESIZE&"; for (int j = 0; j < number_links; j++) { data += "c"+j+"="+ links[j].getIndex1()+"+"+ links[j].getIndex2()+"&"; } for (int i = number_words - 1; i >= 0; i--) { // Only redraw words that exist inside the // clipping region. if (words[i].word_type.equals("LINKINGWORD")) { winfo = words[i].info(g)+"+n"; } else { winfo = words[i].info(g) + "+w"; } data += "w" + i + "=" + winfo + "&"; } if (disable_string != null) { data += "DISABLE="+disable_string; } if (disable_string != null && gallery != null) { data += "&gallery="+gallery; } // Authentication data for the CGI/Servlet. data += "&canvassize="+csstring; data += "&fontsize= "+fontsize_string; data += "&mapname="+mapname; data += "&expiration_key="+expiration_key; data += "&sid="+sid; // Cannot trust cookie data to // be available from applet. // CGI/Servlet uniform resource locator. URL url = new URL(document_base+ "/ConceptServerScript.cgi?action="); server_talker.put(url,data); // The "official" url connection object. ac.showDocument(url); } catch (MalformedURLException me) { System.err.println("MalformedURLException: " + me); } catch (IOException e) { System.out.println( "unsuccessful attempt at "+ "saving data"+e); } submode=""; save_button.drawSubOptionMessage2(0,g); if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} } else if (submode.indexOf("ENACT",0) != -1) { String fs1 = new String(submode); String fs2 = new String(submode); String fa = new String(); String fb = new String(); fa = fs1.substring(1,2); fb = fs2.substring(2,3); // System.out.println("submodeS1: ["+fa+"]"); // System.out.println("submodeS2: ["+fb+"]"); if (fa.equals("+")) { fa = "P"; } else if (fa.equals("-")) { fa = "N"; } else { fa = "default"; fb = ""; } try { String data = new String(); String winfo = new String(); data += "command=RESIZE&"; for (int j = 0; j < number_links; j++) { data += "c"+j+"="+ links[j].getIndex1()+"+"+ links[j].getIndex2()+"&"; } for (int i = number_words - 1; i >= 0; i--) { // Only redraw words that exist inside the // clipping region. if (words[i].word_type.equals("LINKINGWORD")) { winfo = words[i].info(g)+"+n"; } else { winfo = words[i].info(g) + "+w"; } data += "w" + i + "=" + winfo + "&"; } if (disable_string != null) { data += "DISABLE="+disable_string; } if (disable_string != null && gallery != null) { data += "&gallery="+gallery; } // Authentication data for the CGI/Servlet. data += "&canvassize="+canvassize_string; data += "&fontsize= "+fa+fb+" "; data += "&mapname="+mapname; data += "&expiration_key="+expiration_key; data += "&sid="+sid; // Cannot trust cookie data to // be available from applet. // CGI/Servlet uniform resource locator. URL url = new URL(document_base+ "/ConceptServerScript.cgi?action="); server_talker.put(url,data); // The "official" url connection object. // If the user tries to save an applet outside // of user authentication, the page needs to // be reloaded (and the CGI servlet layer // subsequently takes the user through a // login or registration process prior to // the save procedure). if (expiration_key.equals("NA")) { ac.showDocument(url); } } catch (MalformedURLException me) { System.err.println("MalformedURLException: " + me); } catch (IOException e) { System.out.println( "unsuccessful attempt at "+ "saving data"+e); } submode=""; save_button.drawSubOptionMessage2(0,g); if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} } else if (submode.indexOf("resize",0) != -1) { view_button.drawSubOptionMessage1(2,g); submode = ""; if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} } else if (submode.indexOf(" ",0) != -1) { view_button.drawSubOptionMessage1(2,g); submode = ""; if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} } } } else if (mode.equals("SAVE")) { if (!is_disabled(1)) {move_button.draw(g,true);} if (!is_disabled(2)) {add_button.draw(g,true);} if (!is_disabled(7)) {edit_button.draw(g,true);} if (!is_disabled(10)) {view_button.draw(g,true);} if (!is_disabled(16)) {grade_button.draw(g,true);} if (submode.equals("")) { save_button.draw(g,false); save_button.drawPopOut(g); save_button.drawPopOutMessage(g); } else { save_button.draw_with_blerb(g,false,submode); if (submode.equals("SAVE NOW")) { // In this submode, notify user that saving is beginning, // and advance to the next submode of saving (SAVE ENACT). // Set this true to force multiple passes through // this function (necessary since SAVE involves // automated displaying). mode_cycle = true; // Determine the map space background color. if (color == true) { g.setColor(Background_Color); } else { g.setColor(Background_Gray); } // Draw map space (boundaried subspace in applet space). g.fillRect(left_space, top_space, space_width, space_height); if (color == true) { g.setColor(Entry_Bg_Color); } else { g.setColor(Entry_Bg_Gray); } g.setFont(font_banner); // Set font. g.drawString(save_banner_text, left_space+20, top_space+80); // Draw text string. save_button.drawSubOptionMessage1(0,g); submode = "SAVE ENACT"; } else if (submode.equals("SAVE ENACT")) { try { String data = new String(); String winfo = new String(); data += "command=NOW&"; for (int j = 0; j < number_links; j++) { data += "c"+j+"="+ links[j].getIndex1()+"+"+ links[j].getIndex2()+"&"; } for (int i = number_words - 1; i >= 0; i--) { // Only redraw words that exist inside the // clipping region. if (words[i].word_type.equals("LINKINGWORD")) { winfo = words[i].info(g)+"+n"; } else { winfo = words[i].info(g) + "+w"; } data += "w" + i + "=" + winfo + "&"; } if (disable_string != null) { data += "DISABLE="+disable_string; } if (disable_string != null && gallery != null) { data += "&gallery="+gallery; } // Authentication data for the CGI/Servlet. data += "&mapname="+mapname; data += "&expiration_key="+expiration_key; data += "&sid="+sid; // Cannot trust cookie data to // be available from applet. // CGI/Servlet uniform resource locator. URL url = new URL(document_base+ "/ConceptServerScript.cgi?action="); server_talker.put(url,data); // The "official" url connection object. // If the user tries to save an applet outside // of user authentication, the page needs to // be reloaded (and the CGI servlet layer // subsequently takes the user through a // login or registration process prior to // the save procedure). if (expiration_key.equals("NA")) { ac.showDocument(url); } } catch (MalformedURLException me) { System.err.println("MalformedURLException: " + me); } catch (IOException e) { System.out.println( "unsuccessful attempt at saving data" + e); } submode=""; save_button.drawSubOptionMessage2(0,g); if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} } else if (submode.equals("EXPORT DATA")) { save_button.drawSubOptionMessage1(1,g); try { String data = new String(); String winfo = new String(); data += "command=EXPORT&"; for (int j = 0; j < number_links; j++) { data+="c"+j+"="+ links[j].getIndex1()+"+"+ links[j].getIndex2()+"&"; } for (int i = number_words - 1; i >= 0; i--) { // Only redraw the word if it exists inside the clipping region. if (words[i].word_type.equals("LINKINGWORD")) { winfo = words[i].info(g)+"+n"; } else { winfo = words[i].info(g)+"+w"; } data += "w"+i+"="+winfo+"&"; } if (disable_string != null) { data += "DISABLE="+disable_string; } URL url = new URL( "http://hobbes.lite.msu.edu/concept/CC_CGI/CC_Server.cgi?"+ data); // URL url=new URL(getDocumentBase(),"../CC_CGI/CC_Server.cgi?"+data); ac.showDocument(url,new String("_blank")); } catch (MalformedURLException me) { System.err.println("MalformedURLException: " + me); } catch (Exception e) { System.out.println("unsuccessful invocation of making GIF"); } submode=""; if (!is_disabled(1)) {mode="MOVE";} else {mode="";} } } } else if (mode.equals("GRADE")) { if (!is_disabled(1)) {move_button.draw(g,true);} if (!is_disabled(2)) {add_button.draw(g,true);} if (!is_disabled(7)) {edit_button.draw(g,true);} if (!is_disabled(10)) {view_button.draw(g,true);} if (!is_disabled(13)) {save_button.draw(g,true);} if (submode.equals("")) { grade_button.draw(g,false); grade_button.drawPopOut(g); grade_button.drawPopOutMessage(g); } else { grade_button.draw_with_blerb(g,false,submode); if (submode.equals("SUBMIT")) { grade_button.drawSubOptionMessage1(0,g); try { String data = new String(); String winfo = new String(); data += "command=SUBMITNOW&gallery="+gallery+"&"; for (int j = 0; j < number_links; j++) { data += "c"+j+"="+ links[j].getIndex1()+"+"+ links[j].getIndex2()+"&"; } for (int i = number_words - 1; i >= 0; i--) { // Only redraw words that exist inside // clipping region. if (words[i].word_type.equals("LINKINGWORD")) { winfo = words[i].info(g)+"+n"; } else { winfo = words[i].info(g)+"+w"; } data += "w"+i+"="+winfo+"&"; } if (disable_string != null) { data += "DISABLE="+disable_string; } // Authentication data for the CGI/Servlet. data += "&mapname="+mapname; data += "&expiration_key="+expiration_key; data += "&sid="+sid; // Cannot trust cookie data to // be available from applet. // CGI/Servlet uniform resource locator. // URL url = new URL(document_base+ // "/ConceptServerScript.cgi?action=&testval=123"); URL url = new URL(document_base+ "/ConceptServerScript.cgi?action="); // Communicate request to server. server_talker.put(url,data); // Output a response page to // the same browser window. ac.showDocument(url); } catch (MalformedURLException me) { System.err.println("MalformedURLException: " + me); } catch (Exception e) { System.out.println( "unsuccessful invocation of making image"); } submode = ""; if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} } else if (submode.equals("SHOW ROBOGRADER")) { // In this submode, notify user that saving is beginning, // and advance to the next submode of saving (SAVE ENACT). // Set this true to force multiple passes through // this function (necessary since SAVE involves // automated displaying). mode_cycle = true; // Determine the map space background color. if (color == true) { g.setColor(Background_Color); } else { g.setColor(Background_Gray); } // Draw map space (boundaried subspace in applet space). g.fillRect(left_space, top_space, space_width, space_height); if (color == true) { g.setColor(Entry_Bg_Color); } else { g.setColor(Entry_Bg_Gray); } g.setFont(font_banner); // Set font. g.drawString(robograder_banner_text, left_space+20, top_space+80); // Draw text string. save_button.drawSubOptionMessage1(0,g); submode = "ENACT ROBOGRADER"; } else if (submode.equals("ENACT ROBOGRADER")) { try { String data = new String(); String winfo = new String(); data += "command=NOW&"; for (int j = 0; j < number_links; j++) { data += "c"+j+"="+ links[j].getIndex1()+"+"+ links[j].getIndex2()+"&"; } for (int i = number_words - 1; i >= 0; i--) { // Only redraw words that exist inside the // clipping region. if (words[i].word_type.equals("LINKINGWORD")) { winfo = words[i].info(g)+"+n"; } else { winfo = words[i].info(g) + "+w"; } data += "w" + i + "=" + winfo + "&"; } if (disable_string != null) { data += "DISABLE="+disable_string; } if (disable_string != null && gallery != null) { data += "&gallery="+gallery; } // Authentication data for the CGI/Servlet. data += "&mapname="+mapname; data += "&expiration_key="+expiration_key; data += "&sid="+sid; // Cannot trust cookie data to // be available from applet. // CGI/Servlet uniform resource locator. URL url = new URL(document_base+ "/robograder.cgi?action="); BufferedReader br = server_talker.put_and_get(url,data); // Variable that holds data returned from servlet. String receive_data = null; int string_index; String element_string; String idx_string; String value_string; int idx; int value; robo.clear_tables(); while ( (receive_data = br.readLine()) != null) { try { string_index = receive_data.indexOf(" ",0); element_string = receive_data.substring(0,1); idx_string = receive_data.substring(1,string_index); value_string = receive_data.substring(string_index+1, receive_data.length()); /* System.out.println("VALS:'" +idx_string+"' '"+value_string+ "'");*/ idx = Integer.parseInt(idx_string); value = Integer.parseInt(value_string); if (element_string.equals("w")) { robo.word_table(idx,value); } else if (element_string.equals("l")) { robo.link_table(idx,value); } } catch (Exception e) {} } // If the user tries to save an applet outside // of user authentication, the page needs to // be reloaded (and the CGI servlet layer // subsequently takes the user through a // login or registration process prior to // the save procedure). /* if (expiration_key.equals("NA")) { getAppletContext().showDocument(url); } */ } catch (MalformedURLException me) { System.err.println("MalformedURLException: " + me); } catch (IOException e) { System.out.println( "unsuccessful attempt at saving data" + e); } g.setColor(Color.black); g.setFont(small_font_button); /* g.drawString("ROBOGRADER",5,top_space+175); g.drawString("NOT YET",5,top_space+190); g.drawString("IMPLEMENTED",5,top_space+205); */ g.drawString("ROBOGRADER",5,top_space+220); /* g.drawString("NOT YET",5,top_space+235); g.drawString("IMPLEMENTED",5,top_space+250); */ // if (!is_disabled(1)) {mode="MOVE";} else {mode="";} } } } // Disable the text entry box if the applet is not in add or edit mode. if (!(mode.equals("ADD") || mode.equals("EDIT")) || ((mode.equals("ADD") && !(submode.equals("CONCEPT WORD") || submode.equals("LINKING WORD"))) && text_entry_box.isEditable()) || ((mode.equals("EDIT") && !(submode.equals("EDIT WORD") && event_counter != 1) && text_entry_box.isEditable()) ) ) { text_entry_box.setText(""); text_entry_box.setEditable(false); text_entry_box.setVisible(false); this.remove(text_entry_box); if (color == true) { g.setColor(Entry_Bg_Color); } else { g.setColor(Entry_Bg_Gray); } g.drawRect(0,top_space+160,left_space-1,100); // 0,top_space+190,button_width,35 } // A brief description of the software inside the bottom applet space. if (color == true) { g.setColor(Footer_Fg_Color); } else { g.setColor(Footer_Fg_Gray); } g.setFont(font_message); g.drawString("C-TOOLS - Copyright 2001-2007 Michigan State University"+ " Board of Trustees", left_space+10,top_space+space_height+15); } // END push_information_everywhere /** * Coordinates push_information_everywhere invocation. * Standard applet method. Should try and use screen buffer if available. * This method invokes the push_information_everywhere method. * (push_information_everywhere combines painting with a number of other * network and internal state transactions). */ public void paint(Graphics g) { if (temp_screen != null && !(mode.equals("ADD") && (submode.equals("CONCEPT WORD") || submode.equals("LINKING WORD"))) && !(mode.equals("EDIT") && (submode.equals("EDIT WORD"))) ) { // Can use buffer. push_information_everywhere(temp_screen, g.getClipBounds()); g.drawImage(temp_screen_image, 0, 0, this); if (mode_cycle) { push_information_everywhere(temp_screen, g.getClipBounds()); g.drawImage(temp_screen_image, 0, 0, this); push_information_everywhere(temp_screen, g.getClipBounds()); g.drawImage(temp_screen_image, 0, 0, this); } } else { // Cannot use buffer. push_information_everywhere(g, g.getClipBounds()); if (mode_cycle) { push_information_everywhere(g, g.getClipBounds()); push_information_everywhere(g, g.getClipBounds()); } } } // END paint /** * Cleans up memory. * Standard applet method. Dispose of buffered screen memory if it exists. */ public void destroy() { if (temp_screen != null) { temp_screen.dispose(); // Dispose of buffered screen memory. } } // END destroy /** * Whenever the applet needs to update. * Standard applet method. Simply call the paint method. */ public void update(Graphics g) { paint(g); } // END update /** * Whenever an event occurs for an interface object. * ActionListener method. Currently, no events for any objects * are handled, since there are a few browser compatibility issues * with AWT object events. */ public void actionPerformed(ActionEvent event) { String action_command = event.getActionCommand(); return; // If an event occurred for an unknown AWT object. } public void mouseMoved(MouseEvent e) {} /** * What to do when mouse is in motion. * Note: selected areas of the applet are redrawn only when the interface * is in "MOVE" mode. */ public void mouseDragged(MouseEvent e) { // Where is the mouse? int x = e.getX(); // x coordinate of mouse. int y = e.getY(); // y coordinate of mouse. // If a word is being moved around, then interactively repaint the // canvas. if (selected_word && mode.equals("MOVE")) { repaint (words[0].X, words[0].Y, words[0].width, words[0].height); words[0].X = Math.max (left_space+1, Math.min (x - words[0].dx, left_space+space_width - 1 - words[0].width)); words[0].Y = Math.max (top_space+1, Math.min (y - words[0].dy, top_space+space_height - 1 - words[0].height)); words[0].set_center(); repaint (words[0].X, words[0].Y, words[0].width, words[0].height); } else if (selected_image && mode.equals("MOVE")) { repaint (image_x,image_y, image_width,image_height); image_x = Math.max(left_space+1, Math.min(left_space+space_width-1-image_width, x) ); image_y = Math.max(top_space+1, Math.min(top_space+space_height-image_height-1, y) ); repaint (image_x,image_y, image_width,image_height); } return; } // END mouseDragged /** * Nothing happens. */ public void mouseClicked(MouseEvent e) { // System.out.println("mouse clicked"); } // END mouseClicked /** * Nothing happens. */ public void mouseEntered(MouseEvent e) { // System.out.println("mouse entered"); } // END mouseEntered /** * Nothing happens. */ public void mouseExited(MouseEvent e) { // System.out.println("mouse exited"); } // END mouseExited /** * What to do when mouse button is released. * Note: redraw the entire applet. Also, record that no word is * selected. */ public void mouseReleased (MouseEvent e) { // Where is the mouse? int x = e.getX(); // x coordinate of mouse. int y = e.getY(); // y coordinate of mouse. //System.out.println("DEBUG mouse released"); mousedown = false; // Record action (the mouse button is unpressed). // Area-specific redrawing (deprecated). // repaint(left_space,0,space_width+right_space,applet_height); // repaint(0,0,left_space,top_space+125); repaint(0,0,applet_width,applet_height); // Repaint entire applet. // If a word is being moved, the submode should be blank. if (mode.equals("MOVE")) { submode = ""; } // Are they dragging and dropping onto a link? if (selected_word) { for (int j = 0; j < number_links; j++) { if (links[j].getTargetArea().hit_query(x,y)) { int temp_index2 = links[j].getIndex2(); // If not linking to same word (otherwise, // drag-and-dropping produces many self-referential // links. if ( (temp_index2 != 0) && (links[j].getIndex1() != 0) ) { links[j].setValue(links[j].getIndex1(),0); links[number_links].setValue(0,temp_index2); number_links++; } } } } selected_word = false; // Record action (a word is not selected). selected_image = false; return; } // END mouseReleased /** * What to do when mouse button is pressed. * Note: determine the object that was hit based upon the mouse pointer * coordinates. Based on the number of possibilities, this is a lengthy * method. */ public void mousePressed(MouseEvent e) { // ---------------------------------------------------- Method variables. // Where is the mouse? int x = e.getX(); // x coordinate of mouse. int y = e.getY(); // y coordinate of mouse. int j2; // Additional loop iterator. MoveableWord temp; // For swapping (when resorting the words list). int templink_idx1; // Temporary link, index #1. int templink_idx2; // Temporary link, index #2. int current_word = 0; // Current word; index of the array "words". mousedown = true; // Record action. // What menu or action button, if any, was selected. // The y coordinate is evaluated for its position in // "button_height" units to determine the menu button that // was pressed. // "add to map" action button? if ((mode.equals("ADD")) && (submode.equals("CONCEPT WORD") || submode.equals("LINKING WORD")) && text_entry_button.getTargetArea().hit_query(x,y)) { int row_place = top_space+(int)(space_height/2); int col_place = left_space; int col_offset = (int)((space_width-50)/5); int row1yA; int row1yB; int row2yA; int row2yB; MoveableWord word2add = new MoveableWord(new String(text_entry_box.getText()), "CONCEPT"); row1yA = row_place-word2add.height-5; row1yB = row_place-5; row2yA = row_place+5; row2yB = row_place+word2add.height+5; int col1yA = col_place+col_offset*(1-1); int col2yA = col_place+col_offset*(2-1); int col3yA = col_place+col_offset*(3-1); int col4yA = col_place+col_offset*(4-1); int col5yA = col_place+col_offset*(5-1); int Xnewloc = left_space+space_width-100; // Pot. X loc, new word. // Potential Y location for new word. int Ynewloc1 = row1yA; int Ynewloc2 = row2yA; int Ynewloc = Ynewloc1; int rowtry = 0; int coltry1 = 0; int coltry2 = 0; int coltry3 = 0; int coltry4 = 0; int coltry5 = 0; if (number_words < 100) { // while (coltry < 100) { j2 = number_words-1; while(j2 >= 0) // Run through list of words. { if ( ( (words[j2].X>=col1yA) && (words[j2].X<= (col1yA+col_offset)) ) || ( ((words[j2].X+words[j2].width)>=col1yA) && ((words[j2].X+words[j2].width)<= (col1yA+col_offset)) ) ) { if ( ( (words[j2].Y>=row1yA) && (words[j2].Y<= (row1yA+word2add.height)) ) || ( ((words[j2].Y+words[j2].height)>=row1yA) && ((words[j2].Y+words[j2].height)<= (row1yA+word2add.height)) ) ) { coltry1++; rowtry--; } if ( ( (words[j2].Y>=row2yA) && (words[j2].Y<= (row2yA+word2add.height)) ) || ( ((words[j2].Y+words[j2].height)>=row2yA) && ((words[j2].Y+words[j2].height)<= (row2yA+word2add.height)) ) ) { coltry1++; rowtry++; } } if ( ( (words[j2].X>=col2yA) && (words[j2].X<= (col2yA+col_offset)) ) || ( ((words[j2].X+words[j2].width)>=col2yA) && ((words[j2].X+words[j2].width)<= (col2yA+col_offset)) ) ) { if ( ( (words[j2].Y>=row1yA) && (words[j2].Y<= (row1yA+word2add.height)) ) || ( ((words[j2].Y+words[j2].height)>=row1yA) && ((words[j2].Y+words[j2].height)<= (row1yA+word2add.height)) ) ) { coltry2++; rowtry--; } if ( ( (words[j2].Y>=row2yA) && (words[j2].Y<= (row2yA+word2add.height)) ) || ( ((words[j2].Y+words[j2].height)>=row2yA) && ((words[j2].Y+words[j2].height)<= (row2yA+word2add.height)) ) ) { coltry2++; rowtry++; } } if ( ( (words[j2].X>=col3yA) && (words[j2].X<= (col3yA+col_offset)) ) || ( ((words[j2].X+words[j2].width)>=col3yA) && ((words[j2].X+words[j2].width)<= (col3yA+col_offset)) ) ) { if ( ( (words[j2].Y>=row1yA) && (words[j2].Y<= (row1yA+word2add.height)) ) || ( ((words[j2].Y+words[j2].height)>=row1yA) && ((words[j2].Y+words[j2].height)<= (row1yA+word2add.height)) ) ) { coltry3++; rowtry--; } if ( ( (words[j2].Y>=row2yA) && (words[j2].Y<= (row2yA+word2add.height)) ) || ( ((words[j2].Y+words[j2].height)>=row2yA) && ((words[j2].Y+words[j2].height)<= (row2yA+word2add.height)) ) ) { coltry3++; rowtry++; } } if ( ( (words[j2].X>=col4yA) && (words[j2].X<= (col4yA+col_offset)) ) || ( ((words[j2].X+words[j2].width)>=col4yA) && ((words[j2].X+words[j2].width)<= (col4yA+col_offset)) ) ) { if ( ( (words[j2].Y>=row1yA) && (words[j2].Y<= (row1yA+word2add.height)) ) || ( ((words[j2].Y+words[j2].height)>=row1yA) && ((words[j2].Y+words[j2].height)<= (row1yA+word2add.height)) ) ) { coltry4++; rowtry--; } if ( ( (words[j2].Y>=row2yA) && (words[j2].Y<= (row2yA+word2add.height)) ) || ( ((words[j2].Y+words[j2].height)>=row2yA) && ((words[j2].Y+words[j2].height)<= (row2yA+word2add.height)) ) ) { coltry4++; rowtry++; } } if ( ( (words[j2].X>=col5yA) && (words[j2].X<= (col5yA+col_offset)) ) || ( ((words[j2].X+words[j2].width)>=col5yA) && ((words[j2].X+words[j2].width)<= (col5yA+col_offset)) ) ) { if ( ( (words[j2].Y>=row1yA) && (words[j2].Y<= (row1yA+word2add.height)) ) || ( ((words[j2].Y+words[j2].height)>=row1yA) && ((words[j2].Y+words[j2].height)<= (row1yA+word2add.height)) ) ) { coltry5++; rowtry--; } if ( ( (words[j2].Y>=row2yA) && (words[j2].Y<= (row2yA+word2add.height)) ) || ( ((words[j2].Y+words[j2].height)>=row2yA) && ((words[j2].Y+words[j2].height)<= (row2yA+word2add.height)) ) ) { coltry5++; rowtry++; } } j2--; } } } if (rowtry<0) { Ynewloc = Ynewloc2+(int)(Math.random()*5.0)*3; } else { Ynewloc = Ynewloc1-(int)(Math.random()*5.0)*3; } if ( (coltry1 <= coltry2) && (coltry1 <= coltry3) && (coltry1 <= coltry4) && (coltry1 <= coltry5) ) { Xnewloc = (int)(Math.random()*(float)(col_offset/3))*3+col1yA; } else if ( (coltry2 < coltry1) && (coltry2 < coltry3) && (coltry2 < coltry4) && (coltry2 < coltry5) ) { Xnewloc = (int)(Math.random()*(float)(col_offset)/3)*3+col2yA; } else if ( (coltry3 <=coltry1) && (coltry3 <=coltry2) && (coltry3 <=coltry4) && (coltry3 <=coltry5) ) { Xnewloc = (int)(Math.random()*(float)(col_offset)/3)*3+col3yA; } else if ( (coltry4 < coltry2) && (coltry4 < coltry3) && (coltry4 < coltry1) && (coltry4 < coltry5) ) { Xnewloc = (int)(Math.random()*(float)(col_offset)/3)*3+col4yA; } else if ( (coltry5 <=coltry2) && (coltry5 <=coltry3) && (coltry5 <=coltry4) && (coltry5 <=coltry1) ) { Xnewloc = (int)(Math.random()*(float)(col_offset)/3)*3+col5yA; } else { Xnewloc = (int)(Math.random()*(float)(space_width-50))+ left_space; } if (number_words < 100) { j2 = number_words-1; while(j2 >= 0) { // This discover-free-space clause is not perfect, // but I am trying to avoid a slow sorting routine // or hash table. This is at least an improvement. if ((words[j2].Y>130) && (words[j2].Y<170)) { if ((words[j2].X<=Xnewloc) && ((words[j2].X+words[j2].width)>=Xnewloc) ) { // Xnewloc = words[j2].X-30; } } words[j2+1] = words[j2]; j2--; } number_words++; for (int j = 0; j < number_links; j++) { links[j].incrementIndex1(); links[j].incrementIndex2(); } if (mode.equals("ADD") && submode.equals("CONCEPT WORD")) { words[0] = new MoveableWord(new String(text_entry_box.getText()), "CONCEPT"); } else if (mode.equals("ADD") && submode.equals("LINKING WORD")) { words[0] = new MoveableWord(new String(text_entry_box.getText()), "LINKINGWORD"); } // Define coordinates of word (in such a way as to minimize // overlapping; see the processing of Xnewloc and Ynewloc // above). if ((words[0].X+words[0].width)>(left_space+space_width)) { Xnewloc = left_space+space_width-words[0].width-10; } if (Xnewloc<(left_space+10)) { Xnewloc = left_space+10; } words[0].X = Xnewloc; words[0].Y = Ynewloc; // Immediately draw word. repaint(words[0].X, words[0].Y, words[0].width, words[0].height); words[0].set_center(); } event_counter = 1; // Reset event counter. // To be on the safe (browser-compatible) side, redraw applet. repaint(0, 0, applet_width, applet_height); return; } // "change word" action button? else if (mode.equals("EDIT") && submode.equals("EDIT WORD") && event_counter ==