// 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 == 3 && text_entry_button.getTargetArea().hit_query(x,y)) { words[0].changeText(new String(text_entry_box.getText())); // Immediately draw word. repaint(words[0].X, words[0].Y, words[0].width, words[0].height); event_counter = 1; // Reset event counter. // To be on the safe (browser-compatible) side, redraw applet. repaint(0, 0, applet_width, applet_height); return; } else if ((!is_disabled(1)) && move_button.getTargetArea().hit_query(x,y)) { mode = "MOVE"; submode = "ON"; event_counter = 1; repaint(0, 0, applet_width, applet_height); return; } else if ((!is_disabled(2)) && add_button.getTargetArea().hit_query(x,y)) { /* if (mode!=2) { event_counter=1; } */ mode = "ADD"; submode = ""; repaint(0, 0, applet_width, applet_height); return; } else if ((!is_disabled(7)) && edit_button.getTargetArea().hit_query(x,y)) { mode = "EDIT"; submode = ""; repaint(0, 0, applet_width, applet_height); event_counter = 1; return; } else if ((!is_disabled(10)) && view_button.getTargetArea().hit_query(x,y)) { mode = "VIEW"; submode = ""; repaint(0, 0, applet_width, applet_height); event_counter = 1; return; } else if ((!is_disabled(13)) && save_button.getTargetArea().hit_query(x,y)) { mode = "SAVE"; submode = ""; repaint(0, 0, applet_width, applet_height); event_counter = 1; return; } else if ((!is_disabled(16)) && grade_button.getTargetArea().hit_query(x,y)) { mode = "GRADE"; submode = ""; repaint(0, 0, applet_width, applet_height); event_counter = 1; return; } if (mode.equals("EDIT") && submode.equals("DELETE LINES")) { int nlinks = number_links; for (int k = 0; k < nlinks; k++) { if (links[k].getTargetArea().hit_query(x,y)) { // Put the selected link at the top of the list // for subsequent easier removal. templink_idx1 = links[k].getIndex1(); templink_idx2 = links[k].getIndex2(); for (int k2 = k; k2 > 0; k2--) { links[k2].setValue(links[k2-1].getIndex1(), links[k2-1].getIndex2()); } links[0].setValue(templink_idx1,templink_idx2); // Deleting link. int k2 = 1; while(k2 < number_links) { links[k2-1].setValue(links[k2].getIndex1(), links[k2].getIndex2()); k2++; } number_links--; // "Delete link" mission accomplished. repaint(0, 0, applet_width, applet_height); return; } } } // "mode"-dependent evaluation of SubOption targets. // Determine if any of the SubOptions have been selected // by the mouse pointer. if (mode.equals("ADD") && submode.equals("")) { if ((add_button.getSubOptionTargetArea(0)).hit_query(x,y)) { submode = "CONCEPT WORD"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if ((add_button.getSubOptionTargetArea(1)).hit_query(x,y)) { submode = "LINKING WORD"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if ((add_button.getSubOptionTargetArea(2)).hit_query(x,y)) { submode = "CONNECTING LINE"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} return; } else if (mode.equals("EDIT") && submode.equals("")) { if ((edit_button.getSubOptionTargetArea(0)).hit_query(x,y)) { submode = "DELETE WORD"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if ((edit_button.getSubOptionTargetArea(1)).hit_query(x,y)) { submode = "DELETE LINES"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if ((edit_button.getSubOptionTargetArea(2)).hit_query(x,y)) { submode = "EDIT WORD"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} return; } else if (mode.equals("VIEW") && submode.equals("")) { /* if ((view_button.getSubOptionTargetArea(0)).hit_query(x,y)) { submode = "EXPORT GRAPHIC"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if ((view_button.getSubOptionTargetArea(1)).hit_query(x,y)) { submode = "TOGGLE COLOR"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); }*/ if ((view_button.getSubOptionTargetArea(0,1)).hit_query(x,y)) { submode = "EXPORT GRAPHIC"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if ((view_button.getSubOptionTargetArea(0,2)).hit_query(x,y)) { submode = "EXPORT ROTATEGRAPHIC"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if ((view_button.getSubOptionTargetArea(0,3)).hit_query(x,y)) { submode = "TOGGLE COLOR"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("basic") && (view_button.getSubOptionTargetArea(2,1)).hit_query(x,y)) { submode = "More Options"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("basic") && (view_button.getSubOptionTargetArea(1,7)).hit_query(x,y)) { submode = "SMALL"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("basic") && (view_button.getSubOptionTargetArea(1,8)).hit_query(x,y)) { submode = "MEDIUM"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("basic") && (view_button.getSubOptionTargetArea(1,9)).hit_query(x,y)) { submode = "LARGE"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(2,1)).hit_query(x,y)) { submode = "Fewer Options"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(1,1)).hit_query(x,y)) { submode = "480x300"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(1,2)).hit_query(x,y)) { submode = "768x480"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(1,3)).hit_query(x,y)) { submode = "960x600"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(1,4)).hit_query(x,y)) { submode = "1119x669"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(1,5)).hit_query(x,y)) { submode = "1282x801"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(1,6)).hit_query(x,y)) { submode = "1440x900"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(2,1)).hit_query(x,y)) { submode = " -1 "; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(2,2)).hit_query(x,y)) { submode = " -1 "; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(2,3)).hit_query(x,y)) { submode = " default "; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(2,4)).hit_query(x,y)) { submode = " +1 "; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(2,5)).hit_query(x,y)) { submode = " +2 "; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (MenuButton.mode.equals("advanced") && (view_button.getSubOptionTargetArea(2,6)).hit_query(x,y)) { submode = " +3 "; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} return; } else if (mode.equals("SAVE") && submode.equals("")) { if ((save_button.getSubOptionTargetArea(0)).hit_query(x,y)) { submode = "SAVE NOW"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if ((save_button.getSubOptionTargetArea(1)).hit_query(x,y)) { submode = "RECOVER"; event_counter = 1; repaint (0, top_space, applet_width, space_height+bottom_space); } else if ((save_button.getSubOptionTargetArea(2)).hit_query(x,y)) { submode = "EXPORT DATA"; event_counter = 1; repaint (0, top_space, applet_width, space_height+bottom_space); } else if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} return; } else if (mode.equals("GRADE") && submode.equals("")) { if ((grade_button.getSubOptionTargetArea(0)).hit_query(x,y)) { submode = "SUBMIT"; event_counter = 1; repaint(0, top_space, applet_width, space_height+bottom_space); } else if ((grade_button.getSubOptionTargetArea(1)).hit_query(x,y)) { submode = "SHOW ROBOGRADER"; event_counter = 1; repaint (0, top_space, applet_width, space_height+bottom_space); } else if (!is_disabled(1)) {mode = "MOVE";} else {mode = "";} return; } // END long conditional // Check to see if a word was clicked on, and which word. if (!(mode.equals("EDIT") && submode.equals("EDIT WORD") && event_counter>1)) { for (int i = number_words - 1; i >= 0; i--) { if (words[i].mouse_inside(x, y)) // Is it clicked on? { current_word = i; // The word that was clicked on. getAppletContext().showStatus(words[current_word].word); selected_word = true; // Record that a word was clicked on. } } if (!selected_word) { /* if ( image_x < x && x < image_x+image_width && image_y < y && y < image_y+image_height ) { selected_image = true; } */ } // END for } if (selected_word) // If a word was clicked on. { // Put the selected word in the front of the list to ensure that // it will be redrawn on top of the other words. for (int j = 0; j < number_links; j++) { if (links[j].getIndex1() < current_word) { links[j].incrementIndex1(); } else if (links[j].getIndex1() == current_word) { links[j].setValue(0,links[j].getIndex2()); } if (links[j].getIndex2() < current_word) { links[j].incrementIndex2(); } else if (links[j].getIndex2() == current_word) { links[j].setValue(links[j].getIndex1(),0); } } if (mode.equals("ADD") && submode.equals("CONNECTING LINE")) { // If adding a link. if (event_counter == 2) { // Never exceed 100 links. // Never link to the same word. if (number_links < 100) { // Do not duplicate an existing link. int uniqlink = 0; for (int i = 0; i < number_links; i++) { if ((links[i].getIndex1() == 1) && (links[i].getIndex2() == 0)) { uniqlink++; } } if (uniqlink == 0) { links[number_links].setValue(1,0); number_links++; } } event_counter = 1; } else { event_counter = 2; } } temp = words[current_word]; for (int j = current_word; j > 0; j--) { words[j] = words[j-1]; } words[0] = temp; // Process arrays based on the mode and submode of the interface. if (mode.equals("EDIT") && (submode.equals("DELETE WORD") || submode.equals("DELETE LINES"))) { // If deleting a word or deleting links. for (int j = (number_links-1); j >= 0; j--) { if (links[j].getIndex1() != 0 && links[j].getIndex2() == 0) { j2 = j+1; while (j2 < number_links) { links[j2-1].setValue(links[j2].getIndex1(), links[j2].getIndex2()); j2++; } number_links--; } else if (links[j].getIndex1() == 0 && links[j].getIndex2() != 0) { j2 = j+1; while (j2 < number_links) { links[j2-1].setValue(links[j2].getIndex1(), links[j2].getIndex2()); j2++; } number_links--; } } } if (mode.equals("EDIT") && submode.equals("DELETE WORD")) { // If deleting word. j2 = 1; while(j2 < number_words) { words[j2-1] = words[j2]; j2++; } number_words--; for (int j = 0; j < number_links; j++) { links[j].decrementIndex1(); links[j].decrementIndex2(); } } if (mode.equals("EDIT") && submode.equals("EDIT WORD")) { // If altering the text of a word. if (event_counter == 1) { event_counter = 2; } } /* if (mode.equals("COPY")) { // if copying j2 = number_words-1; while(j2 >= 0) { words[j2+1] = words[j2]; j2--; } number_words++; for (int j = 0; j < number_links; j++) { links[j].incrementIndex1(); links[j].incrementIndex2(); } words[0] = new MoveableWord(new String(words[1].word),words[1].word_type); words[0].width=words[1].width; words[0].height=words[1].height; words[0].ascent=words[1].ascent; words[0].X = (int)(Math.random() * (float)(space_width - words[0].width) ); words[0].Y = (int)(Math.random() * (float)(space_height - words[0].height) )+top_space; words[0].set_center(); words[0].fg_color=words[1].fg_color; words[0].bg_color=words[1].bg_color; }*/ repaint (words[0].X, words[0].Y, words[0].width, words[0].height); // To be on the safe (browser-compatible) side, redraw applet. repaint(0, 0, applet_width, applet_height); } // END conditional } // END mousePressed /** * Is a given feature number disabled?
* In order to condense the feature list, I am indexing them as numbers. * This method mimics a hash table. Should probably use a real hash table, * but I seem to recall browser incompatibility with this.... */ public boolean is_disabled(int num) { String tmp=new String("r"+num+"r"); // A small substring pattern match. // Does the small substring occur inside the disable_string? if (disable_string!=null && disable_string.indexOf(tmp)!=-1) { return true; } else { return false; } } // END is_disabled } // END ConceptWebClient /** * Implements "magnetic rectangles". */ class MoveableWord { // --------------------------------------------------------- Class variables. /** x offset of text inside moveable word rectangle. */ static int xoff; /** y offset of text inside moveable word rectangle. */ static int yoff; /** Start with color mode (not gray mode). */ static boolean color = true; /** Foreground color of concept words (can be color or gray mode). */ static Color conceptword_fg; /** Background color of concept words (can be color or gray mode). */ static Color conceptword_bg; /** Foreground color of linking words (can be color or gray mode). */ static Color linkingword_fg; /** Background color of linking words (can be color or gray mode). */ static Color linkingword_bg; /** Foreground color of concept, color-mode. */ static Color conceptword_fg_colormode; /** Background color of concept, color-mode. */ static Color conceptword_bg_colormode; /** Foreground color of linking, color-mode. */ static Color linkingword_fg_colormode; /** Background color of linking, color-mode. */ static Color linkingword_bg_colormode; /** Foreground color of concept, gray-mode. */ static Color conceptword_fg_graymode; /** Background color of concept, gray-mode. */ static Color conceptword_bg_graymode; /** Foreground color of linking, gray-mode. */ static Color linkingword_fg_graymode; /** Background color of linking, gray-mode. */ static Color linkingword_bg_graymode; /** Foreground color of concept border, gray-mode. */ static Color conceptword_border_fg_graymode; /** Foreground color of linking, gray-mode. */ static Color linkingword_border_fg_graymode; /** Font metrics of concept words. */ static FontMetrics conceptword_fm; /** Font metrics of linking words. */ static FontMetrics linkingword_fm; /** Font of concept words. */ static Font conceptword_font; /** Font of linking words. */ static Font linkingword_font; /** Padding inside the rectangle. */ static final int padX = 6, padY = 4; // Upper left corner of the moveable word rectangle. /** Top left x coordinate of the moveable word rectangle. */ int X = 0; /** Top left y coordinate of the moveable word rectangle. */ int Y = 0; // Offset for dragging (these coordinates are internal to the word // rectangle). /** x coordinate of where the word was clicked on. */ int dx; /** y coordinate of where the word was clicked on. */ int dy; // Moveable word dimensions. /** Width of the moveable word. */ int width; /** Height of the moveable word. */ int height; /** Font height of the moveable word. */ int ascent; /** x coordinate of the center point of the word. */ int Xc; /** y coordinate of the center point of the word. */ int Yc; /** Text of the moveable word. */ String word; /** Whether the word is a concept word or a linking word. */ String word_type; /** * Constructor. Set the text and type of the moveable word. * @param s The text for the moveable word. * @param wtype The type of moveable word (concept or linking). */ MoveableWord(String s, String wtype) { FontMetrics fm; // Font measurement variable. word = s; // The text for the moveable word. word_type = wtype; // The type of moveable word (concept or linking). // Set font measurements dependent on word_type. if (word_type.equals("CONCEPT")) { fm = conceptword_fm; } else { fm = linkingword_fm; } // Determine the dimensions. // Find the total height of the moveable word. // (padY pixels are added to the top and bottom, // for an "ad hoc beautification adjustment".) height = fm.getHeight() + padY; ascent = fm.getAscent(); // Find out how long the moveable word needs to be, given the number // of letters in the moveable word. // (Again, padX pixels are added as a minor tweaking adjustment.) width = (fm.stringWidth(word) + padX); } // END MoveableWord constructor /** * Force colormode to be on. */ static void colormode_on() { color = true; conceptword_bg = conceptword_bg_colormode; conceptword_fg = conceptword_fg_colormode; linkingword_bg = linkingword_bg_colormode; linkingword_fg = linkingword_fg_colormode; } // END colormode_on /** * Switch between color and black-and-white. */ static void color_toggle() { if (color == true) // Color mode, so switch to black and white mode. { color = false; conceptword_bg = conceptword_bg_graymode; conceptword_fg = conceptword_fg_graymode; linkingword_bg = linkingword_bg_graymode; linkingword_fg = linkingword_fg_graymode; } else // Black and white mode, so switch to color mode. { colormode_on(); } } // END color_toggle /** * Set parameters for concept words. * Set fonts, coordinates, and colors for concept words. * @param xo The x offset at which to position text inside rectangle. * @param yo The y offset at which to position text inside rectangle. * @param fnt The font of the text. * @param fm The geometric dimension characteristics of the text. * @param fg_c The foreground color of the text, color-mode. * @param bg_c The background color of the text, color-mode. * @param fg_g The foreground color of the text, gray-mode. * @param bg_g The background color of the text, gray-mode. * @param brd_fg_g The border foreground color of the rectangle gray-mode. */ static void conceptword_configure(int xo, int yo, Font fnt, FontMetrics fm, Color fg_c, Color bg_c, Color fg_g, Color bg_g, Color brd_fg_g) { conceptword_font = fnt; // Set the font of concept words. conceptword_fm = fm; // Set the font metrics of concept words. conceptword_fg = fg_c; // Set the foreground color concept words. conceptword_bg = bg_c; // Set the background color of concept words. conceptword_fg_colormode = fg_c; //Set the color-mode foreground color. conceptword_bg_colormode = bg_c; //Set the color-mode background color. conceptword_fg_graymode = fg_g; // Set the gray-mode foreground color. conceptword_bg_graymode = bg_g; // Set the gray-mode background color. conceptword_border_fg_graymode = brd_fg_g; // Set gray-mode bkgd color. xoff = xo; yoff = yo; // Offset of text appears inside word rectangle. } // END conceptword_configure /** * Set parameters for linking words. * Set fonts, coordinates, and colors for linking words. * @param xo The x offset at which to position text inside rectangle. * @param yo The y offset at which to position text inside rectangle. * @param fnt The font of the text. * @param fm The geometric dimension characteristics of the text. * @param fg_c The foreground color of the text, color-mode. * @param bg_c The background color of the text, color-mode. * @param fg_g The foreground color of the text, gray-mode. * @param bg_g The background color of the text, gray-mode. * @param brd_fg_g The border foreground color of the rectangle gray-mode. */ static void linkingword_configure(int xo, int yo, Font fnt, FontMetrics fm, Color fg_c, Color bg_c, Color fg_g, Color bg_g, Color brd_fg_g) { linkingword_font = fnt; // Set the font of linking words. linkingword_fm = fm; // Set the font metrics of linking words. linkingword_fg = fg_c; // Set the foreground color of linking words. linkingword_bg = bg_c; // Set the background color of linking words. linkingword_fg_colormode = fg_c; // Set the colormode foreground color. linkingword_bg_colormode = bg_c; // Set the colormode background color. linkingword_fg_graymode = fg_g; // Set the gray-mode foreground color. linkingword_bg_graymode = bg_g; // Set the gray-mode background color. linkingword_border_fg_graymode = brd_fg_g; // Set gray-mode bkgd color. xoff=xo; yoff=yo; // Offset of text that appears inside word rectangle. } // END linkingword_configure /** * Set center based on location, width, and height. * Note: probably want to remove the integer return type here. */ void set_center() { Xc = X + width/2; // Calculate the x coordinate middle point. Yc = Y + height/2; // Calculate the y coordinate middle point. } // END set_center /** * Mouse position versus word boundaries. * Is the current mouse position within the word rectangle boundaries? * @param x_mouse * @param y_mouse * @return boolean; True if the current mouse position is inside the * word rectangle boundaries. False, otherwise. */ boolean mouse_inside (int x_mouse, int y_mouse) { boolean status = false; // Assume false unless proven otherwise. if (x_mouse >= X && (x_mouse <= (X + width)) && y_mouse >= Y && (y_mouse <= (Y + height))) { status = true; } // Set the offset (coordinates within the moveable word rectangle). dx = x_mouse-X; dy = y_mouse-Y; // True if x and y position are within the bounds of the rectangle. return (status); } // END mouse_inside /** * Draw the moveable word with robograding enhancement. * @param robo the robograding object. * @param g the graphics instance upon which to draw */ void draw (Robograde robo, int i, Graphics g) { // Draw the word. this.draw(g); // Draw robograding. robo.word_scribble(g,robo.word_table(i),X,Y,X+width,Y+height); } /** * Draw the moveable word. Call the necessary graphics routines * @param g Graphics instance. */ void draw (Graphics g) { Color foreground_color; // Foreground color. Color background_color; // Background color. // Set the correct colors and fonts depending on word type. if (word_type.equals("CONCEPT")) // If a concept word. { foreground_color = conceptword_fg; background_color = conceptword_bg; g.setFont(conceptword_font); } else // If a linking word. { foreground_color = linkingword_fg; background_color = linkingword_bg; g.setFont(linkingword_font); } // Draw the background of the word. g.setColor(background_color); g.fill3DRect (X, Y, width, height, true); if (word_type.equals("CONCEPT") && color == false) { g.setColor(conceptword_border_fg_graymode); g.drawRect (X, Y, width, height); } else if (word_type.equals("LINKINGWORD") && color == false) { g.setColor(linkingword_border_fg_graymode); g.drawRect (X, Y, width, height); } // Draw the word. g.setColor(foreground_color); g.drawString(word, X + padX / 2, Y + ascent + padY / 2); // g.drawString("location", X + padX / 2, height+Y + ascent + padY / 2); } // END draw /** * Is word inside clipping region? * Does the clipping area contain the word rectangle boundaries? */ boolean inside_clip(int clipx, int clipy, int clipwidth, int clipheight) { boolean status = false; // Assume false unless proven otherwise. // If the right-hand side of the word rectangle is greater than // the left-hand side of the clipping area, AND // the left-hand side of the word rectangle is less than the // right-hand side of the clipping area, AND // the bottom of the word rectangle is greater than the top // of the clipping area, AND // the top of the word rectangle is less than the bottom of // the clipping area, then should return true. if (((X + width) > clipx) && (X < (clipx + clipwidth)) && ((Y + height) > clipy) && (Y < (clipy + clipheight))) { status = true; } return (status); } // END inside_clip /** * Construct URL-ified word information. * @param g Graphics instance. */ String info(Graphics g) { String text = new String(); text += (X-xoff) + "+" + (Y-yoff) + "+" + width + "+" + height + "+" + (X-xoff+padX/2) + "+" + (Y-yoff+ascent+padY/2) + "+" + URLEncoder.encode(word); return text; } // END info /** * Construct URL-ified word information. * @param new_text New text for the word. */ public void changeText(String new_text) { word = new_text; // Set font measurements dependent on word_type. FontMetrics fm; // Font measurements. if (word_type.equals("CONCEPT")) { fm = conceptword_fm; } else { fm = linkingword_fm; } width = (fm.stringWidth(word) + padX); set_center(); } // END changeText } // END MoveableWord /** * Ordered pair structure by which one MoveableWord is attached to another * Moveable word.
* Word #1 and word #2 are to be graphically connected with an arrowed line. */ class Link { // --------------------------------------------------------- Class variables. /** The index number of MoveableWord #1. */ private int t1 = 0; /** The index number of MoveableWord #2. */ private int t2 = 0; /** The target area of the link (square surrounding arrowhead). */ private TargetArea target_area; /** Start with color mode (not black-and-white). */ private static boolean color = true; // Configuration variables. /** Length of arrowhead along connecting line. */ private static int arrowhead_length; /** Width of arrowhead along connecting line. */ private static int arrowhead_width; /** Width of line thickening for the link. */ private static int linkthickener_width; /** Foreground color of link. */ private static Color link_fg; /** Foreground color of link, color-mode. */ private static Color link_fg_colormode; /** Foreground color of link, gray-mode. */ private static Color link_fg_graymode; /** Foreground color of link target box, color-mode. */ private static Color link_targetbox_fg_colormode; /** Foreground color of link target box, gray-mode. */ private static Color link_targetbox_fg_graymode; // These static variables are only used for the draw subroutine. /** The link's directional indicator. */ private static Polygon arrowhead = new Polygon(); /** Make the beginning part of the link thick. */ private static Polygon linkthickener = new Polygon(); // The arrow tip is at xm,ym. /** X-coordinate of point in between word #1 and word #2. */ private static int xm; /** Y-coordinate of point in between word #1 and word #2. */ private static int ym; /** X-coordinate of arrow base. */ private static float x2; /** Y-coordinate of arrow base. */ private static float y2; /** y versus x. */ private static float slope; /** 90 degrees (-1/m) to slope. */ private static float inverse_slope; /** Arrowhead going up, down, left or right? */ private static int afactor; /** Quadrants I+IV -OR- II+III. */ private static float hfactor; /** Quadrants I+II -OR- III+IV. */ private static float vfactor; /** * Constructor. Nothing happens. */ Link() { target_area = new TargetArea(); } // END Link constructor /** * Increment index number of the word that defines the * beginning of the link. */ public void incrementIndex1() { t1++; } /** * Increment index number of the word that defines the * end of the link. */ public void incrementIndex2() { t2++; } /** * Decrement index number of the word that defines the * beginning of the link. */ public void decrementIndex1() { t1--; } /** * Decrement index number of the word that defines the * end of the link. */ public void decrementIndex2() { t2--; } /** * Return the index number of the word that defines the * beginning of the link. */ public int getIndex1() { return t1; } /** * Return the index number of the word that defines the * end of the link. */ public int getIndex2() { return t2; } /** * Get the target area object associated with the link. */ public TargetArea getTargetArea() { return target_area; } /** * Set concept map ordered pair value which defines a link. */ public void setValue(int word1_index,int word2_index) { t1 = word1_index; // Set the first word (from which the arrow cometh). t2 = word2_index; // Set the second word (to which the arrow leadeth). } /** * Set class static variables. */ static void configure(int arrowhead_l, int arrowhead_w, int linkthickener_w, Color foreground_colormode, Color foreground_graymode, Color targetbox_foreground_colormode, Color targetbox_foreground_graymode) { arrowhead_length = arrowhead_l; // Length of arrowhead. arrowhead_width = arrowhead_w; // Width of arrowhead. linkthickener_width = linkthickener_w; // Thickening width for link. arrowhead.npoints = 3; // It takes 3 points to make the triangle arrow. arrowhead.xpoints = new int[3]; // Define memory usage. arrowhead.ypoints = new int[3]; // Define memory usage. linkthickener.npoints = 4; // It takes 4 points to make a rectangle. linkthickener.xpoints = new int[4]; // Define memory usage. linkthickener.ypoints = new int[4]; // Define memory usage. link_fg = foreground_colormode; link_fg_colormode = foreground_colormode; link_fg_graymode = foreground_graymode; link_targetbox_fg_colormode = targetbox_foreground_colormode; link_targetbox_fg_graymode = targetbox_foreground_graymode; } // END configure /** * Force colormode to be on. */ static void colormode_on() { color = true; link_fg = link_fg_colormode; } // END colormode_on /** * Flip between color and gray modes. * Only one color values is treated: on. */ public static void color_toggle() { if (color == true) // Color mode, so switch to black and white mode. { color = false; link_fg = link_fg_graymode; } else // Gray mode, so switch to color mode. { colormode_on(); } } // END color_toggle /** * Draw line with arrowhead along with robograding enhancement. */ public void draw ( Robograde robo, int idx, Graphics g, MoveableWord word1, MoveableWord word2, boolean show_target ) { g.setColor(link_fg); this.draw(g,word1,word2,show_target); robo.link_scribble(g,robo.link_table(idx),word1,word2); } // END draw /** * Draw line with arrowhead.
* The arrowhead is placed in the line like this:
*

     *BEFORE (just the line):      t1word ----------- t2word
     *AFTER  (line and arrowhead): t1word ----->----- t2word
     *
*/ void draw( Graphics g, MoveableWord word1, MoveableWord word2, boolean show_target ) { g.setColor(link_fg); // Draw the line. g.drawLine(word1.Xc,word1.Yc,word2.Xc,word2.Yc); // Draw the arrowhead and thicken the first part of the line. // Calculate the middle of the connecting line. xm = (word1.Xc+word2.Xc)/2; ym = (word1.Yc+word2.Yc)/2; // Now, a conditional statement. // Draw arrowhead and line-thickening based on three possibilities: // vertical line, horizontal line, or diagonal line. if (xm-word1.Xc == 0) // If this is a vertical line. { if (ym > word1.Yc) {afactor = 1;} // arrowhead up. else {afactor = -1;} // arrowhead down. arrowhead.xpoints[0] = xm; arrowhead.ypoints[0] = ym; arrowhead.xpoints[1] = xm-afactor*arrowhead_width; arrowhead.ypoints[1] = ym-afactor*arrowhead_length; arrowhead.xpoints[2] = xm+afactor*arrowhead_width; arrowhead.ypoints[2] = ym-afactor*arrowhead_length; g.fillPolygon(arrowhead); // Draw vertical pointed arrowhead. linkthickener.xpoints[0] = xm-afactor*linkthickener_width; linkthickener.ypoints[0] = ym-afactor*1; linkthickener.xpoints[1] = xm+afactor*linkthickener_width; linkthickener.ypoints[1] = ym-afactor*1; linkthickener.xpoints[3] = word1.Xc-afactor*linkthickener_width; linkthickener.ypoints[3] = word1.Yc-afactor*1; linkthickener.xpoints[2] = word1.Xc+afactor*linkthickener_width; linkthickener.ypoints[2] = word1.Yc-afactor*1; g.fillPolygon(linkthickener); // THICKEN FIRST PART OF LINK. } else if (ym-word1.Yc == 0) // If this is a horizontal line. { if (xm > word1.Xc) {afactor = 1;} // arrowhead to the right. else {afactor = -1;} // arrowhead to the left. arrowhead.xpoints[0] = xm; arrowhead.ypoints[0] = ym; arrowhead.xpoints[1] = xm-afactor*arrowhead_length; arrowhead.ypoints[1] = ym-afactor*arrowhead_width; arrowhead.xpoints[2] = xm-afactor*arrowhead_length; arrowhead.ypoints[2] = ym+afactor*arrowhead_width; g.fillPolygon(arrowhead); // Draw horizontal pointed arrowhead. linkthickener.xpoints[0] = xm-afactor*1; linkthickener.ypoints[0] = ym-afactor*linkthickener_width; linkthickener.xpoints[1] = xm-afactor*1; linkthickener.ypoints[1] = ym+afactor*linkthickener_width; linkthickener.xpoints[3] = word1.Xc-afactor*1; linkthickener.ypoints[3] = word1.Yc-afactor*linkthickener_width; linkthickener.xpoints[2] = word1.Xc-afactor*1; linkthickener.ypoints[2] = word1.Yc+afactor*linkthickener_width; g.fillPolygon(linkthickener); // THICKEN FIRST PART OF LINK. } else // If this is a diagonal line. { // Length-wise direction of arrowhead. slope = (float)( ((float)word1.Yc - ym) / ((float)word1.Xc - xm) ); // Width-wise direction of arrowhead. inverse_slope = (float)( -1.0 / slope ); // To determine the direction, compare middle with word 1. hfactor = -1; // Horizontal comparison, rightwards=-1 if (xm < word1.Xc) {hfactor = 1;} // leftwards=1. vfactor = 1; // Vertical comparison, downwards=1. if (ym < word1.Yc) {vfactor = -1;} // upwards=-1. arrowhead.xpoints[0] = xm; arrowhead.ypoints[0] = ym; // The length of arrowhead should run from xm,ym to x2,y2. x2 = (float)((float)xm + (hfactor * Math.sqrt(arrowhead_length * arrowhead_length / (slope * slope + 1.0) ) ) ); y2 = (float)((float)ym - (vfactor * Math.sqrt(arrowhead_length * arrowhead_length / (inverse_slope * inverse_slope + 1.0) ) ) ); arrowhead.xpoints[1] = (int)(x2 + (hfactor * Math.sqrt(arrowhead_width * arrowhead_width / (inverse_slope * inverse_slope + 1.0) ) ) ); arrowhead.ypoints[1] = (int)(y2 + vfactor * (Math.sqrt(arrowhead_width * arrowhead_width / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); arrowhead.xpoints[2] = (int)(x2 - (hfactor * Math.sqrt(arrowhead_width * arrowhead_width / (inverse_slope * inverse_slope + 1.0) ) ) ); arrowhead.ypoints[2] = (int)(y2 - vfactor * (Math.sqrt(arrowhead_width * arrowhead_width / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); g.fillPolygon(arrowhead); // DRAW ARROWHEAD. linkthickener.xpoints[0] = (int)(x2 + (hfactor * Math.sqrt(linkthickener_width * linkthickener_width / (inverse_slope * inverse_slope + 1.0) ) ) ); linkthickener.ypoints[0] = (int)(y2 + vfactor * (Math.sqrt(linkthickener_width * linkthickener_width / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); linkthickener.xpoints[1] = (int)(x2 - (hfactor * Math.sqrt(linkthickener_width * linkthickener_width / (inverse_slope * inverse_slope + 1.0) ) ) ); linkthickener.ypoints[1] = (int)(y2 - vfactor * (Math.sqrt(linkthickener_width * linkthickener_width / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); linkthickener.xpoints[3] = (int)(word1.Xc + (hfactor * Math.sqrt(linkthickener_width * linkthickener_width / (inverse_slope * inverse_slope + 1.0) ) ) ); linkthickener.ypoints[3] = (int)(word1.Yc + vfactor * (Math.sqrt(linkthickener_width * linkthickener_width / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); linkthickener.xpoints[2] = (int)(word1.Xc - (hfactor * Math.sqrt(linkthickener_width * linkthickener_width / (inverse_slope * inverse_slope + 1.0) ) ) ); linkthickener.ypoints[2] = (int)(word1.Yc - vfactor * (Math.sqrt(linkthickener_width * linkthickener_width / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); g.fillPolygon(linkthickener); // THICKEN FIRST PART OF LINK. } // Determine the target box to draw around the link. int x1 = arrowhead.xpoints[0]; if (arrowhead.xpoints[0] >= arrowhead.xpoints[1] && arrowhead.xpoints[2] >= arrowhead.xpoints[1]) { x1 = arrowhead.xpoints[1]; } if (arrowhead.xpoints[0] >= arrowhead.xpoints[2] && arrowhead.xpoints[1] >= arrowhead.xpoints[2]) { x1 = arrowhead.xpoints[2]; } int x2 = arrowhead.xpoints[0]-x1; if (arrowhead.xpoints[0] <= arrowhead.xpoints[1] && arrowhead.xpoints[2] <= arrowhead.xpoints[1]) { x2 = arrowhead.xpoints[1]-x1; } if (arrowhead.xpoints[0] <= arrowhead.xpoints[2] && arrowhead.xpoints[1] <= arrowhead.xpoints[2]) { x2 = arrowhead.xpoints[2]-x1; } int y1 = arrowhead.ypoints[0]; if (arrowhead.ypoints[0] >= arrowhead.ypoints[1] && arrowhead.ypoints[2] >= arrowhead.ypoints[1]) { y1 = arrowhead.ypoints[1]; } if (arrowhead.ypoints[0] >= arrowhead.ypoints[2] && arrowhead.ypoints[1] >= arrowhead.ypoints[2]) { y1 = arrowhead.ypoints[2]; } int y2 = arrowhead.ypoints[0]-y1; if (arrowhead.ypoints[0] <= arrowhead.ypoints[1] && arrowhead.ypoints[2] <= arrowhead.ypoints[1]) { y2 = arrowhead.ypoints[1]-y1; } if (arrowhead.ypoints[0] <= arrowhead.ypoints[2] && arrowhead.ypoints[1] <= arrowhead.ypoints[2]) { y2 = arrowhead.ypoints[2]-y1; } int padding = 3; x1 -= padding; x2 += padding; y1 -= padding; y2 += padding; if (show_target == true) { if (color == true) { g.setColor(Color.pink); } else { g.setColor(Color.black); } g.drawRect(x1,y1,x2,y2); target_area.sethit(x1,y1,x2,y2); } } // END draw } // END Link /** * A suite of functions needed for "robograding"; * a means for human-to-computer learning. */ class Robograde { /** Color mode. */ private static boolean color = true; /** Foreground color of "incorrect" scribbling. */ static Color incorrect_fg; /** Foreground color of "neutral" scribbling. */ static Color neutral_fg; /** Foreground color of "correct" scribbling. */ static Color correct_fg; /** Foreground color of "incorrect" scribbling, colormode. */ static Color incorrect_fg_colormode; /** Foreground color of "neutral" scribbling, colormode. */ static Color neutral_fg_colormode; /** Foreground color of "correct" scribbling, colormode. */ static Color correct_fg_colormode; /** Foreground color of "incorrect" scribbling, graymode. */ static Color incorrect_fg_graymode; /** Foreground color of "neutral" scribbling, graymode. */ static Color neutral_fg_graymode; /** Foreground color of "correct" scribbling, graymode. */ static Color correct_fg_graymode; /** List of scribblings to apply to words. */ int word_scribble_list[]=new int[200]; /** List of scribblings to apply to connecting links. */ int link_scribble_list[]=new int[200]; /** * Constructor. Nothing happens. */ Robograde() { for (int j = 0; j < 200; j++) { link_scribble_list[j] = 0; word_scribble_list[j] = 0; } // END for } // END Robograde constructor /** * Configure colors. */ public static void configure (Color inc_fg_c, Color inc_fg_g, Color neu_fg_c, Color neu_fg_g, Color cor_fg_c, Color cor_fg_g) { incorrect_fg = inc_fg_c; neutral_fg = neu_fg_c; correct_fg = cor_fg_c; incorrect_fg_colormode = inc_fg_c; neutral_fg_colormode = neu_fg_c; correct_fg_colormode = cor_fg_c; incorrect_fg_graymode = inc_fg_g; neutral_fg_graymode = neu_fg_g; correct_fg_graymode = cor_fg_g; } /** * Force colormode to be on. */ static void colormode_on() { color = true; incorrect_fg = incorrect_fg_colormode; neutral_fg = neutral_fg_colormode; correct_fg = correct_fg_colormode; } // END colormode_on /** * Flip between color and gray modes. */ static void color_toggle() { if (color == true) // Color mode, so switch to black and white mode. { color = false; incorrect_fg = incorrect_fg_graymode; neutral_fg = neutral_fg_graymode; correct_fg = correct_fg_graymode; } else // Gray mode, so switch to color mode. { colormode_on(); } } // END color_toggle /** * Clear scribbling directives. */ void clear_tables() { for (int j = 0; j < 200; j++) { link_scribble_list[j] = 0; word_scribble_list[j] = 0; } } // END clear_tables /** * Set an entry inside a link scribbling table. */ void link_table(int idx, int value) { link_scribble_list[idx] = value; } // link_table /** * Return an entry inside a link scribbling table. */ int link_table(int idx) { return link_scribble_list[idx]; } // END link_table /** * Set an entry inside a word scribbling table. */ void word_table(int idx, int value) { word_scribble_list[idx] = value; } // END word_table /** * Return an entry inside a word scribbling table. */ int word_table(int idx) { return word_scribble_list[idx]; } // END word_table /** * "Scribble" robograding feedback directly on top of a * concept or linking word. * @param grade the grade, which implies style of scribbling * @param x1 top left x coordinate * @param y1 top left y coordinate * @param x2 bottom right x coordinate * @param y2 bottom right y coordinate */ void word_scribble(Graphics g, int grade, int x1, int y1, int x2, int y2) { // The scribbling is conditional based upon the grade score. int yi; if (grade == -2) // Draw red X's. { g.setColor(incorrect_fg); for (int xi = x1; xi < x2-12; xi += 15) { g.drawLine(xi+0,y2+3,xi+10+0,y1-3); g.drawLine(xi+1,y2+3,xi+10+1,y1-3); g.drawLine(xi+2,y2+3,xi+10+2,y1-3); } for (int xi = x1+10; xi-10 < x2-12; xi += 15) { g.drawLine(xi+0,y2+3,xi-10+0,y1-3); g.drawLine(xi+1,y2+3,xi-10+1,y1-3); g.drawLine(xi+2,y2+3,xi-10+2,y1-3); } } else if (grade == -1) // Draw red slashes. { g.setColor(incorrect_fg); for (int xi = x1; xi < x2-8; xi += 10) { g.drawLine(xi+0,y2+3,xi+5+0,y1-3); g.drawLine(xi+1,y2+3,xi+5+1,y1-3); g.drawLine(xi+2,y2+3,xi+5+2,y1-3); } } else if (grade == 0) // Draw yellow question marks. { g.setColor(neutral_fg); g.drawLine(x1-5,y1-5,x2+5,y1-5); g.drawLine(x1-5,y1-4,x2+5,y1-4); g.drawLine(x1-5,y1-6,x2+5,y1-6); g.drawLine(x1-5,y2+5,x2+5,y2+5); g.drawLine(x1-5,y2+4,x2+5,y2+4); g.drawLine(x1-5,y2+6,x2+5,y2+6); } else if (grade == 1) // Draw green haloes. { g.setColor(correct_fg); g.drawRect(x1-5,y1-5,x2+9-x1,y2+9-y1); } else if (grade == 2) // Draw green double-haloes. { g.setColor(correct_fg); g.drawRect(x1-5,y1-5,x2+9-x1,y2+9-y1); g.drawRect(x1-10,y1-10,x2+19-x1,y2+19-y1); } } // END word_scribble /** * "Scribble" robograding feedback directly on top of a * connecting link. * @param g graphics instance * @param grade the grade, which implies style of scribbling * @param word1 the originating word of the link * @param word2 the destination word of the link */ void link_scribble(Graphics g, int grade, MoveableWord word1, MoveableWord word2) { /** Polygon coordinates. */ int npoints = 4; int[] xpoints = new int[4]; int[] ypoints = new int[4]; int[] xpoints2 = new int[4]; int[] ypoints2 = new int[4]; int xm; int ym; float x2; float y2; float x3; float y3; int afactor; float slope; float inverse_slope; int hfactor; int vfactor; int linkbox_width = 10; int linkbox_length = 20; int linkbox_width2 = 15; int linkbox_length2 = 25; // Calculate the middle of the connecting line. xm = (word1.Xc+word2.Xc)/2; ym = (word1.Yc+word2.Yc)/2; // Now, a conditional statement. // Draw arrowhead and line-thickening based on three possibilities: // vertical line, horizontal line, or diagonal line. if (xm-word1.Xc == 0) // If this is a vertical line. { if (ym > word1.Yc) {afactor = 1;} // arrowhead up. else {afactor = -1;} // arrowhead down. xpoints[0] = xm-afactor*linkbox_width; ypoints[0] = ym-afactor*linkbox_length; xpoints[1] = xm-afactor*linkbox_width; ypoints[1] = ym+afactor*linkbox_length; xpoints[2] = xm+afactor*linkbox_width; ypoints[2] = ym+afactor*linkbox_length; xpoints[3] = xm+afactor*linkbox_width; ypoints[3] = ym-afactor*linkbox_length; xpoints2[0] = xm-afactor*linkbox_width2; ypoints2[0] = ym-afactor*linkbox_length2; xpoints2[1] = xm-afactor*linkbox_width2; ypoints2[1] = ym+afactor*linkbox_length2; xpoints2[2] = xm+afactor*linkbox_width2; ypoints2[2] = ym+afactor*linkbox_length2; xpoints2[3] = xm+afactor*linkbox_width2; ypoints2[3] = ym-afactor*linkbox_length2; } else if (ym-word1.Yc == 0) // If this is a horizontal line. { if (xm > word1.Xc) {afactor = 1;} // arrowhead to the right. else {afactor = -1;} // arrowhead to the left. xpoints[0] = xm-afactor*linkbox_length; ypoints[0] = ym-afactor*linkbox_width; xpoints[1] = xm-afactor*linkbox_length; ypoints[1] = ym+afactor*linkbox_width; xpoints[2] = xm+afactor*linkbox_length; ypoints[2] = ym+afactor*linkbox_width; xpoints[3] = xm+afactor*linkbox_length; ypoints[3] = ym-afactor*linkbox_width; xpoints2[0] = xm-afactor*linkbox_length2; ypoints2[0] = ym-afactor*linkbox_width2; xpoints2[1] = xm-afactor*linkbox_length2; ypoints2[1] = ym+afactor*linkbox_width2; xpoints2[2] = xm+afactor*linkbox_length2; ypoints2[2] = ym+afactor*linkbox_width2; xpoints2[3] = xm+afactor*linkbox_length2; ypoints2[3] = ym-afactor*linkbox_width2; } else // If this is a diagonal line. { // Length-wise direction of arrowhead. slope = (float)( ((float)word1.Yc - ym) / ((float)word1.Xc - xm) ); // Width-wise direction of arrowhead. inverse_slope = (float)( -1.0 / slope ); // To determine the direction, compare middle with word 1. hfactor = -1; // Horizontal comparison, rightwards=-1 if (xm < word1.Xc) {hfactor = 1;} // leftwards=1. vfactor = 1; // Vertical comparison, downwards=1. if (ym < word1.Yc) {vfactor = -1;} // upwards=-1. // The length of arrowhead should run from xm,ym to x2,y2. x2 = (float)((float)xm + (hfactor * Math.sqrt(linkbox_length * linkbox_length / (slope * slope + 1.0) ) ) ); y2 = (float)((float)ym - (vfactor * Math.sqrt(linkbox_length * linkbox_length / (inverse_slope * inverse_slope + 1.0) ) ) ); // The length of arrowhead should run from xm,ym to x2,y2. x3 = (float)((float)xm - (hfactor * Math.sqrt(linkbox_length * linkbox_length / (slope * slope + 1.0) ) ) ); y3 = (float)((float)ym + (vfactor * Math.sqrt(linkbox_length * linkbox_length / (inverse_slope * inverse_slope + 1.0) ) ) ); xpoints[0] = (int)(x2 + (hfactor * Math.sqrt(linkbox_width * linkbox_width / (inverse_slope * inverse_slope + 1.0) ) ) ); ypoints[0] = (int)(y2 + vfactor * (Math.sqrt(linkbox_width * linkbox_width / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); xpoints[1] = (int)(x2 - (hfactor * Math.sqrt(linkbox_width * linkbox_width / (inverse_slope * inverse_slope + 1.0) ) ) ); ypoints[1] = (int)(y2 - vfactor * (Math.sqrt(linkbox_width * linkbox_width / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); xpoints[3] = (int)(x3 + (hfactor * Math.sqrt(linkbox_width * linkbox_width / (inverse_slope * inverse_slope + 1.0) ) ) ); ypoints[3] = (int)(y3 + vfactor * (Math.sqrt(linkbox_width * linkbox_width / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); xpoints[2] = (int)(x3 - (hfactor * Math.sqrt(linkbox_width * linkbox_width / (inverse_slope * inverse_slope + 1.0) ) ) ); ypoints[2] = (int)(y3 - vfactor * (Math.sqrt(linkbox_width * linkbox_width / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); // The length of arrowhead should run from xm,ym to x2,y2. x2 = (float)((float)xm + (hfactor * Math.sqrt(linkbox_length2 * linkbox_length2 / (slope * slope + 1.0) ) ) ); y2 = (float)((float)ym - (vfactor * Math.sqrt(linkbox_length2 * linkbox_length2 / (inverse_slope * inverse_slope + 1.0) ) ) ); // The length of arrowhead should run from xm,ym to x2,y2. x3 = (float)((float)xm - (hfactor * Math.sqrt(linkbox_length2 * linkbox_length2 / (slope * slope + 1.0) ) ) ); y3 = (float)((float)ym + (vfactor * Math.sqrt(linkbox_length2 * linkbox_length2 / (inverse_slope * inverse_slope + 1.0) ) ) ); xpoints2[0] = (int)(x2 + (hfactor * Math.sqrt(linkbox_width2 * linkbox_width2 / (inverse_slope * inverse_slope + 1.0) ) ) ); ypoints2[0] = (int)(y2 + vfactor * (Math.sqrt(linkbox_width2 * linkbox_width2 / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); xpoints2[1] = (int)(x2 - (hfactor * Math.sqrt(linkbox_width2 * linkbox_width2 / (inverse_slope * inverse_slope + 1.0) ) ) ); ypoints2[1] = (int)(y2 - vfactor * (Math.sqrt(linkbox_width2 * linkbox_width2 / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); xpoints2[3] = (int)(x3 + (hfactor * Math.sqrt(linkbox_width2 * linkbox_width2 / (inverse_slope * inverse_slope + 1.0) ) ) ); ypoints2[3] = (int)(y3 + vfactor * (Math.sqrt(linkbox_width2 * linkbox_width2 / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); xpoints2[2] = (int)(x3 - (hfactor * Math.sqrt(linkbox_width2 * linkbox_width2 / (inverse_slope * inverse_slope + 1.0) ) ) ); ypoints2[2] = (int)(y3 - vfactor * (Math.sqrt(linkbox_width2 * linkbox_width2 / (1.0 + 1.0 / (inverse_slope * inverse_slope)) ) ) ); } // The scribbling is conditional based upon the grade score. if (grade == -2) { g.setColor(incorrect_fg); g.drawLine(xpoints[0],ypoints[0],xpoints[2],ypoints[2]); g.drawLine(xpoints[1],ypoints[1],xpoints[3],ypoints[3]); g.drawLine(xpoints[0]+1,ypoints[0],xpoints[2]+1,ypoints[2]); g.drawLine(xpoints[1]+1,ypoints[1],xpoints[3]+1,ypoints[3]); g.drawLine(xpoints[0],ypoints[0]+1,xpoints[2],ypoints[2]+1); g.drawLine(xpoints[1],ypoints[1]+1,xpoints[3],ypoints[3]+1); } else if (grade == -1) { g.setColor(incorrect_fg); g.drawLine(xpoints[0],ypoints[0],xpoints[2],ypoints[2]); g.drawLine(xpoints[0]+1,ypoints[0],xpoints[2]+1,ypoints[2]); g.drawLine(xpoints[0],ypoints[0]+1,xpoints[2],ypoints[2]+1); } else if (grade == 0) { g.setColor(neutral_fg); g.drawLine(xpoints[0],ypoints[0],xpoints[3],ypoints[3]); g.drawLine(xpoints[0]+1,ypoints[0],xpoints[3]+1,ypoints[3]); g.drawLine(xpoints[0],ypoints[0]+1,xpoints[3],ypoints[3]+1); g.drawLine(xpoints[2],ypoints[2],xpoints[1],ypoints[1]); g.drawLine(xpoints[2]+1,ypoints[2],xpoints[1]+1,ypoints[1]); g.drawLine(xpoints[2],ypoints[2]+1,xpoints[1],ypoints[1]+1); } else if (grade == 1) { g.setColor(correct_fg); g.drawPolygon(xpoints,ypoints,npoints); // Draw linkbox. } else if (grade == 2) { g.setColor(correct_fg); g.drawPolygon(xpoints,ypoints,npoints); // Draw linkbox. g.drawPolygon(xpoints2,ypoints2,npoints); // Draw linkbox. } } // END link_scribble } // END Robograde /** * A menu button that can be clicked on; * menu buttons appear on the left side of the applet. */ class MenuButton { // --------------------------------------------------------- Class variables. /** The bubble that appears when a menu button is hit. * This bubble contains additional options as well as * explanatory text. */ private BubbleMenuHelp help; /** 'basic' or 'advanced' */ public static String mode; /** The message that appears when a menu button is pressed. * Usage of this variable is currently deprecated. */ private Message message; /** The target area of the menu button. */ private TargetArea target_area; /** The width of the menu button. */ private static int width=0; /** The height of the menu button. */ private static int height=0; // Working color-values of the menu button. /** The foreground color when a menu button is selected. */ private static Color fgon; /** The foreground color when button is not selected. */ private static Color fgoff; /** The background color of the menu button. */ private static Color bg; // Needed to support color toggling between color versus black-and-white. /** Stores the color value for "foreground on". */ private static Color fgon_colormode; /** Stores the color value for "foreground off". */ private static Color fgoff_colormode; /** Stores the color value for background. */ private static Color bg_colormode; /** Stores the graymode value for "foreground on". */ private static Color fgon_graymode; /** Stores the graymode value for "foreground off". */ private static Color fgoff_graymode; /** Stores the graymode value for background. */ private static Color bg_graymode; // Fonts for the menu button. /** The font of the menu button text. */ private static Font font; /** The font metrics for the menu button text. */ private static FontMetrics font_metrics; /** The text offset on the menu button. */ private static int text_offset = 0; /** The small font of text that may or may not * be present on the menu button (originally meant * to help implement the * MenuButton::draw_with_blerb method). */ private static Font smallfont; // The color toggle. /** Whether or not menu buttons should be drawn * with color. Start out in color mode. */ private static boolean color = true; /** Top left x coordinate of text. */ private int tx = 0; /** Top left y coordinate of text. */ private int ty = 0; /** Top left x coordinate of button. */ private int bx = 0; /** Top left y coordinate of button. */ private int by = 0; /** The text that is placed on the menu button. */ String text; /** * Set the primary button text. * Constructed with the text that is placed on the menu button. * @param s The button label text. * @param top_left_x Absolute x pixel coordinate of the top left corner. * @param top_left_y Absolute y pixel coordinate of the top left corner. */ MenuButton(String s,int top_left_x,int top_left_y) { text = s; // Set the text to the string argument. bx = top_left_x; by = top_left_y; ty = by+15; tx = 0+text_offset+(width/2 - font_metrics.stringWidth(s)/2); target_area = new TargetArea(); target_area.sethit(bx,by,width,height); } // END MenuButton constructor /** * Get the target area for a suboption. * @param idx The index number of the suboption. */ public TargetArea getSubOptionTargetArea(int idx) { return help.getTargetArea(idx); } /** * Get the target area for a suboption. * @param idx The index number of the suboption. * @param subidx Subindex number of suboption (for canvas size selection). */ public TargetArea getSubOptionTargetArea(int idx, int subidx) { return help.getTargetArea(idx,subidx); } /** * Get the target area object associated with the menu button. */ public TargetArea getTargetArea() { return target_area; } /** * Draw a SubOption's first indexed message. * @param idx The index number of the suboption. * @param g Graphics instance. */ public void drawSubOptionMessage1(int idx, Graphics g) { help.drawSubOptionMessage1(idx,g); } /** * Draw a SubOption's second indexed message. * @param idx The index number of the suboption. * @param g Graphics instance. */ public void drawSubOptionMessage2(int idx, Graphics g) { help.drawSubOptionMessage2(idx,g); } /** * Define the overall pop-out objects. * @param bmh The BubbleMenuHelp object. * @param msg A message object (deprecated). */ public void setPopOut(BubbleMenuHelp bmh, Message msg) { help = bmh; // Set the pop-out window when the button is pressed. help.setMessage(msg); // Set the message associated with the pop-out. } /** * Define the overall pop-out objects. * @param bmh The BubbleMenuHelp object. * @param msg A message object (deprecated). */ public static void setMode(String m) { mode = m; } /** * Define the overall pop-out objects. * @param g Graphics instance. */ public void drawPopOut(Graphics g) { help.draw(g,mode); } /** * Define the overall pop-out objects. * @param g Graphics instance. */ public void drawPopOutMessage(Graphics g) { help.drawMessage(g); } /** * Set class variables. * This initializes static variables that will apply to all of the menu * buttons. * @param w Width. * @param h Height. * @param fnt Font. * @param smlfnt Secondary smaller font (deprecated). * @param fnt_mtrcs Metrics associated with the font. * @param txt_off Left space text offset. * @param fgon_c Colormode foreground color when button is selected. * @param fgoff_c Colormode foreground color when button is not selected. * @param bg_c Colormode background color when button is selected. * @param fgon_g Graymode foreground color when button is selected. * @param fgoff_g Graymode foreground color when button is not selected. * @param bg_g Graymode background color when button is selected. */ public static void configure(int w, int h, Font fnt, Font smlfnt, FontMetrics fnt_mtrcs, int txt_off, Color fgon_c, Color fgoff_c, Color bg_c, Color fgon_g, Color fgoff_g, Color bg_g ) { fgon = fgon_c; // Foreground color when menu button is selected. fgoff = fgoff_c; // Foreground color when menu button is not selected. bg = bg_c; // Background color of menu button. fgon_colormode = fgon_c; // Color-mode foreground color of menu button. fgoff_colormode = fgoff_c; // Color-mode foreground, not selected. bg_colormode = bg_c; // Gray-mode background color of menu button. fgon_graymode = fgon_g; // Gray-mode foreground color of menu button. fgoff_graymode = fgoff_g; // Gray-mode foreground, not selected. bg_graymode = bg_g; // Color-mode background color of menu button. font = fnt; // Font of menu button. smallfont = smlfnt; // Small status text font of menu button (not used) font_metrics = fnt_mtrcs; // Font metrics of menu button text. text_offset = txt_off; // Left-space text offset (pixels). width = w; // Width of menu button. height = h; // Height of menu button. } // END configure /** * Insert SizeSubOption with one instructive message. * @param mb1 The mini-button to hit to get the SubOption. * @param mb2 The mini-button to hit to get the SubOption. * @param mb3 The mini-button to hit to get the SubOption. * @param mb4 The mini-button to hit to get the SubOption. * @param mb5 The mini-button to hit to get the SubOption. * @param mb6 The mini-button to hit to get the SubOption. * @param canvassize_string The current canvas size. * @param comment The comment shown next to button. * @param m The message shown when a SubOption is selected. * @param a Boolean toggle as to whether the SubOption is shown and * whether it can be selected. */ void addSizeSubOption( String mb1, String mb2, String mb3, String mb4, String mb5, String mb6, String canvassize_string, String comment, Message m, boolean a) { help.add_size(mb1,mb2,mb3,mb4,mb5,mb6, canvassize_string, comment, m, a); } // END addSizeSubOption /** * Insert SizeSubOption with one instructive message. * @param mb1 The mini-button to hit to get the SubOption. * @param mb2 The mini-button to hit to get the SubOption. * @param mb3 The mini-button to hit to get the SubOption. * @param mb4 The mini-button to hit to get the SubOption. * @param mb5 The mini-button to hit to get the SubOption. * @param mb6 The mini-button to hit to get the SubOption. * @param mb7 The mini-button to hit to get the SubOption. * @param mb8 The mini-button to hit to get the SubOption. * @param mb9 The mini-button to hit to get the SubOption. * @param mb10 The mini-button to hit to get the SubOption. * @param canvassize_string The current canvas size. * @param comment The comment shown next to button. * @param m The message shown when a SubOption is selected. * @param a Boolean toggle as to whether the SubOption is shown and * whether it can be selected. */ void addComplexSizeSubOption( String mb1, String mb2, String mb3, String mb4, String mb5, String mb6, String mb7, String mb8, String mb9, String mb10, String canvassize_string, String comment, Message m, boolean a) { help.add_complexsize(mb1,mb2,mb3,mb4,mb5,mb6,mb7,mb8,mb9,mb10, canvassize_string, comment, m, a); } // END addSizeSubOption /** * Insert SizeSubOption with one instructive message. * @param mb1 The mini-button to hit to get Print Preview Landscape. * @param mb2 The mini-button to hit to get Print Preview Portrait. * @param canvassize_string The current canvas size. * @param comment The comment shown next to button. * @param m The message shown when a SubOption is selected. * @param a Boolean toggle as to whether the SubOption is shown and * whether it can be selected. */ void addPrintSubOption( String mb1, String mb2, String mb3, String comment, Message m, boolean a) { help.add_print(mb1,mb2,mb3, comment, m, a); } // END addPrintSubOption /** * Insert SubOption with one instructive message. * @param button The button to hit to get the SubOption. * @param comment The comment shown next to button. * @param m The message shown when a SubOption is selected. * @param a Boolean toggle as to whether the SubOption is shown and * whether it can be selected. */ void addSubOption(String button, String comment, Message m, boolean a) { help.add(button, comment, m, a); } // END addSubOption /** * Insert SubOption with two instructive messages. * @param button The button to hit to get the SubOption. * @param comment The comment shown next to button. * @param m1 The message shown when a SubOption is selected. * @param m2 The message shown when a SubOption is selected (used for * secondary instructions, such as those with connecting links). * @param a Boolean toggle as to whether the SubOption is shown and * whether it can be selected. */ void addSubOption(String button, String comment, Message m1, Message m2, boolean a) { help.add(button, comment, m1, m2, a); } // END addSubOption /** * Force colormode to be on. */ static void colormode_on() { color = true; fgon = fgon_colormode; fgoff = fgoff_colormode; bg = bg_colormode; } // END colormode_on /** * Flip between color and gray modes. * Three color values are treated: background, foreground (on; when * something is selected), and foreground (off; when something is not * selected). */ static void color_toggle() { if (color == true) // Color mode, so switch to black and white mode. { color = false; fgon = fgon_graymode; fgoff = fgoff_graymode; bg = bg_graymode; } else // Gray mode, so switch to color mode. { colormode_on(); } } // END color_toggle /** * Draw the menu button. * Make the menu button look like it should be up or down depending * on whether it has been pressed. */ void draw(Graphics g, boolean up) { g.setFont(font); // Set the font. if (up == true) // If menu button should look like it is released "up". { g.setColor(bg); g.fill3DRect(bx, by, width, height, up); g.setColor(fgon); g.drawString(text, tx, ty); } else // If menu button should look like it is pressed "down". { g.setColor(bg); g.fill3DRect(bx, by, width, height, up); g.setColor(fgoff); g.drawString(text, tx+4, ty+2); } } // END draw /** * Draw the menu button when suboption selected. * Ordinarily, this just calls the draw method. However, this * method exists to support customized rendering of the menu button * depending on the suboption which is selected. * @param g Graphics instance upon which to draw. * @param up Whether or not the button is pressed. * @param blerb The little text to draw in addition. */ void draw_with_blerb(Graphics g, boolean up, String blerb) { this.draw(g,up); // Draw the menu button. return; /* g.setFont(smallfont); if (up == true) { g.setColor(bg); g.fill3DRect(bx, by, width, height, up); g.setColor(fgon); g.drawString(blerb, tx, ty); } else { g.setColor(bg); g.fill3DRect(bx, by, width, height, up); g.setColor(fgoff); g.drawString(blerb, tx+4, ty+2); }*/ } // END draw_with_blerb } // END MenuButton /** * An action button that can be clicked on; * action buttons can appear anywhere. * This substitutes for AWT and ActionListener; these appear to memory-overrun * and introduce problems on mozilla and linux systems. */ class ActionButton { // --------------------------------------------------------- Class variables. /** The width of the action button. */ private static int width = 0; /** The height of the action button. */ private static int height = 0; /** The target area of the menu button. */ private TargetArea target_area; // Working color-values of the action button. /** The foreground color when action button is not selected. */ private static Color fgon; /** The foreground color when button is selected. */ private static Color fgoff; /** The background color of the action button. */ private static Color bg; // Needed to support color toggling between color versus black-and-white. /** Stores the color value for "foreground on". */ private static Color fgon_colormode; /** Stores the color value for "foreground off". */ private static Color fgoff_colormode; /** Stores the color value for background. */ private static Color bg_colormode; /** Stores the graymode value for "foreground on". */ private static Color fgon_graymode; /** Stores the graymode value for "foreground off". */ private static Color fgoff_graymode; /** Stores the graymode value for background. */ private static Color bg_graymode; // Fonts for the action button. /** The font of the action button text. */ private static Font font; /** The font metrics for the menu button text. */ private static FontMetrics font_metrics; /** The text offset on the menu button. */ private static int text_offset = 0; /** The small font of text that may or may not * be present on the action button (originally meant * to help implement the * MenuButton::draw_with_blerb method). */ private static Font smallfont; // The color toggle. /** Whether or not action buttons should be drawn * with color. Start out in color mode. */ private static boolean color = true; /** Top left x coordinate of text. */ private int tx = 0; /** Top left y coordinate of text. */ private int ty = 0; /** Top left x coordinate of button. */ private int bx = 0; /** Top left y coordinate of button. */ private int by = 0; /** The text that is placed on the action button. */ String text; /** * Set the primary button text. * Constructed with the text that is placed on the action button. */ ActionButton(String s, int top_left_x, int top_left_y) { text = s; // Set the text to the string argument. bx = top_left_x; by = top_left_y; ty = by+15; tx = 0+text_offset+(width/2-font_metrics.stringWidth(s)/2); target_area = new TargetArea(); target_area.sethit(bx,by,width,height); } // END ActionButton constructor /** * Set class variables. * This initializes static variables that will apply to all of the menu * buttons. * @param w Width. * @param h Height. * @param fnt Font. * @param smlfnt Secondary smaller font (deprecated). * @param fnt_mtrcs Metrics associated with the font. * @param txt_off Left space text offset. * @param fgon_c Colormode foreground color when button is not selected. * @param fgoff_c Colormode foreground color when button is selected. * @param bg_c Colormode background color. * @param fgon_g Graymode foreground color when button is not selected. * @param fgoff_g Graymode foreground color when button is selected. * @param bg_g Graymode background color. */ static void configure(int w, int h, Font fnt, Font smlfnt, FontMetrics fnt_mtrcs, int txt_off, Color fgon_c, Color fgoff_c, Color bg_c, Color fgon_g, Color fgoff_g, Color bg_g ) { fgon = fgon_c; // Foreground color when action button is selected. fgoff = fgoff_c; // Foreground color when action button not selected. bg = bg_c; // Background color of action button. fgon_colormode = fgon_c; // Color-mode foreground color, action button. fgoff_colormode = fgoff_c; // Color-mode foreground color not selected. bg_colormode = bg_c; // Color-mode background color of action button. fgon_graymode = fgon_g; // Gray-mode foreground color, action button. fgoff_graymode = fgoff_g; // Gray-mode foreground color, not selected. bg_graymode = bg_g; // Gray-mode background color of action button. font = fnt; // Font of action button. smallfont = smlfnt; // Small status text font (not used). font_metrics = fnt_mtrcs; // Font metrics of menu button text. text_offset = txt_off; // Left-space text offset (pixels). width = w; // Width of action button. height = h; // Height of action button. } // END configure /** * Get the target area object associated with the action button. */ public TargetArea getTargetArea() { return target_area; } /** * Force colormode to be on. */ static void colormode_on() { color = true; fgon = fgon_colormode; fgoff = fgoff_colormode; bg = bg_colormode; } // END colormode_on /** * Flip between color and gray modes. * Three color values are treated: background, foreground (on; when * something is not selected), and foreground (off; when something is * selected). */ static void color_toggle() { if (color == true) // Color mode, so switch to black and white mode. { color = false; fgon = fgon_graymode; fgoff = fgoff_graymode; bg = bg_graymode; } else // Gray mode, so switch to color mode. { colormode_on(); } } // END color_toggle /** * Change the text of the button. * @param new_text The new text for the button. */ public void changeText(String new_text) { text = new_text; } // END changeText /** * Draw the action button. * Make the action button look like it should be up or down depending * on whether it has been pressed. */ public void draw(Graphics g, boolean up) { g.setFont(font); // Set the font. if (up == true) // What action button should be when released "up". { g.setColor(bg); g.fill3DRect(bx, by, width, height, up); g.setColor(fgon); g.drawString(text, tx, ty); } else // If action button should look like it is pressed "down". { g.setColor(bg); g.fill3DRect(bx, by, width, height, up); g.setColor(fgoff); g.drawString(text, tx+4, ty+2); } } // END draw /** * Draw the action button when suboption selected. * Ordinarily, this just calls the draw method. However, this * method exists to support customized rendering of the action button * depending on the suboption which is selected. * @param g graphics instance * @param up boolean, whether to look like it is or is not pressed. * @param blerb deprecated additional little text to button */ void draw_with_blerb(Graphics g, boolean up, String blerb) { this.draw(g,up); // Draw the action button. return; /* g.setFont(smallfont); if (up == true) { g.setColor(bg); g.fill3DRect(bx, by, width, height, up); g.setColor(fgon); g.drawString(blerb, tx, ty); } else { g.setColor(bg); g.fill3DRect(bx, by, width, height, up); g.setColor(fgoff); g.drawString(blerb, tx+4, ty+2); }*/ } // END draw_with_blerb } // END ActionButton /** * This class appears on the screen as a "bubble"; a filled-in rectangle * with relevant information (the "menu") and options (the "help"). * Shows list of actions (SubOptions) whenever a action button is pressed; * brief help text is displayed for each SubOption. */ class BubbleMenuHelp { // --------------------------------------------------------- Class variables. public static String advanced_text; public static String basic_text; /** Horizontal padding on the bubble. */ private static final int padX = 6; /** Vertical padding on the bubble. */ private static final int padY = 4; /** Whether or not bubble should be drawn * with color. Start out in color mode. */ private static boolean color = true; /** Top left x coordinate for the bubble. It needs to be * placed to the right of the menu choices. */ private static final int X = 70; /** Top left y coordinate for calculating bubble location. */ private int Y = 0; // Offsets (not used). /** (not currently used) */ private int dx; /** (not currently used) */ private int dy; /** Height of the bubble. */ private static int width; /** Width of the bubble. */ private int height; /** The height of the font. */ private static int ascent; /** (deprecated; not used) */ private Message message; /** The y coordinate bubble location relative to Y. */ private int yoff; /** Adjustment value for SubOption y coordinates. */ private int y2; /** The header (big label) for the bubble. */ private String header; /** Stores the suboptions. */ private Vector v = new Vector(3,1); /** Iterator for the vector of suboptions. */ private Enumeration vEnum; /** Font. */ private static Font font; /** Font dimensions. */ private static FontMetrics fm; /** SubOption font. */ private static Font bfont; /** SubOption font dimensions. */ private static FontMetrics bfm; /** SubOption superscript font. */ private static Font bfontsup; /** SubOption superscript font dimensions. */ private static FontMetrics bfmsup; // Extra variables for canvas size mini-buttons. int mbsw; int subwidth0; int subwidth1; int subwidth2; int subwidth3; int subwidth4; int subwidth5; int subwidth6; /** Width of a SubOption button choice. */ int subwidth; /** Height of a SubOption button choice. */ int subheight; /** Temporary variable to hold SubOption data. */ SubOption opt; /** Border color of bubble. */ static Color border_color; /** Foreground color of bubble (e.g. text). */ static Color fg_color; /** Background color of bubble. */ static Color bg_color; /** Foreground color of SubOption inside bubble. */ static Color subfg_color; /** Background color of SubOption inside bubble. */ static Color subbg_color; /** Color-mode border color of bubble. */ static Color border_colormode; /** Color-mode foreground color of bubble. */ static Color fg_colormode; /** Color-mode background color of bubble. */ static Color bg_colormode; /** Color-mode foreground color of SubOption. */ static Color subfg_colormode; /** Color-mode background color of SubOption. */ static Color subbg_colormode; /** Gray-mode border color of bubble. */ static Color border_graymode; /** Gray-mode foreground color of bubble. */ static Color fg_graymode; /** Gray-mode background color of bubble. */ static Color bg_graymode; /** Gray-mode foreground color of SubOption. */ static Color subfg_graymode; /** Gray-mode background color of SubOption. */ static Color subbg_graymode; /** Highlight color of SubOption. */ static Color highlight_color; /** Color-mode highlight color of SubOption. */ static Color highlight_colormode; /** Gray-mode highlight color of SubOption. */ static Color highlight_graymode; /** Text pattern to specify highlighted SubOption. */ static String highlight_textpattern; /** Trademark string (TM). */ static String trademark; /** Polygon coordinates. */ int xpoints[] = {0,0,0,0}; /** Polygon coordinates. */ int ypoints[] = {0,0,0,0}; /** Whether to draw a "link" (graphical polygon). */ boolean link = true; /** The maximum width of a SubOption for this bubble. * (This will determine the width of the entire bubble.) */ int maxwidth = 0; /** * Construct dimensions and header text. * @param s Header text displayed for the bubble. * @param h Height of the bubble. * @param yo Y coordinate location. * @param lnk Whether or not a polygon link should be drawn. */ BubbleMenuHelp(String s, int h, int yo, boolean lnk) { header = s; // Set the header text displayed for the bubble. height = h; // Set the height of the bubble. yoff = yo; // Set the y coordinate location. link = lnk; // Whether a polygon link should be drawn // (unrelated to concept map link). } // END BubbleMenuHelp constructor /** * Get the target area for an indexed suboption. * @param idx The index number of the suboption. */ public TargetArea getTargetArea(int idx) { return ((SubOption)v.elementAt(idx)).getTargetArea(); } /** * Get the target area for an indexed, subindexed suboption. * Used for canvas size selection. * @param idx The index number of the suboption. */ public TargetArea getTargetArea(int idx, int subidx) { return ((SubOption)v.elementAt(idx)).getTargetArea(subidx); } /** * Draw message #1 associated with an indexed SubOption. */ public void drawSubOptionMessage1(int idx, Graphics g) { ((SubOption)v.elementAt(idx)).drawMessage1(g); } /** * Draw message #2 associated with an indexed SubOption. */ public void drawSubOptionMessage2(int idx, Graphics g) { ((SubOption)v.elementAt(idx)).drawMessage2(g); } /** * Force colormode to be on. */ static void colormode_on() { color = true; fg_color = fg_colormode; bg_color = bg_colormode; subfg_color = subfg_colormode; subbg_color = subbg_colormode; border_color = border_colormode; highlight_color = highlight_colormode; } // END colormode_on /** * Switch between colormode and graymode. */ static void color_toggle() { if (color == true) // Color mode, so switch to black and white mode. { color = false; fg_color = fg_graymode; bg_color = bg_graymode; subfg_color = subfg_graymode; subbg_color = subbg_graymode; border_color = border_graymode; highlight_color = highlight_graymode; } else // Gray mode, so switch to color mode. { colormode_on(); } } // END color_toggle /** * Configures colors and fonts. * @param bfnt SubOption font. * @param bfmet SubOption font metrics. * @param bfntsup SubOption superscript font. * @param bfmetsup SubOption superscript font metrics. * @param fnt General font. * @param fmet General font metrics. * @param bwidth Width, in pixels, of the bubble menu. * @param fg_c Foreground color, colormode. * @param bg_c Background color, colormode. * @param fg_g Foreground color, graymode. * @param bg_g Background color, graymode. * @param sfg_c SubOption foreground color, colormode. * @param sbg_c SubOption background color, colormode. * @param sfg_g SubOption foreground color, graymode. * @param sbg_g SubOption background color, graymode. * @param brd_c The bubble border color, colormode. * @param brd_g The bubble border color, graymode. * @param hlt_c The bubble highlight color, colormode. * @param hlt_g The bubble highlight color, graymode. * @param hlt_tp The bubble highlight text pattern. */ static void configure( Font bfnt, FontMetrics bfmet, Font bfntsup, FontMetrics bfmetsup, Font fnt, FontMetrics fmet, int bwidth, Color fg_c, Color bg_c, Color fg_g, Color bg_g, Color sfg_c, Color sbg_c, Color sfg_g, Color sbg_g, Color brd_c, Color brd_g, Color hlt_c, Color hlt_g, String hlt_tp) { fm = fmet; // Set font metrics. font = fnt; // Set font. bfm = bfmet; // Set the SubOption font metrics. bfont = bfnt; // Set the SubOption font. bfmsup = bfmetsup; // Set the SubOption superscript font metrics. bfontsup = bfntsup; // Set the SubOption superscript font. width = bwidth; // Set the width of the bubble. fg_color = fg_c; // Set the foreground color. bg_color = bg_c; // Set the background color. subfg_color = sfg_c; // Set the SubOption foreground color. subbg_color = sbg_c; // Set the SubOption background color. border_color = brd_c; // Set the bubble border color. highlight_color = hlt_c; // Set the highlight of suboption color. fg_colormode = fg_c; // Set the color-mode foreground color. bg_colormode = bg_c; // Set the color-mode background color. subfg_colormode = sfg_c; // Set the color-mode SubOption foreground. subbg_colormode = sbg_c; // Set the color-mode SubOption background. fg_graymode = fg_g; // Set the gray-mode foreground color. bg_graymode = bg_g; // Set the gray-mode background color. subfg_graymode = sfg_g; // Set the gray-mode SubOption foreground. subbg_graymode = sbg_g; // Set the gray-mode SubOption background. border_colormode = brd_c; // Set the colormode bubble border color. border_graymode = brd_g; // Set the graymode bubble border color. highlight_colormode = hlt_c; // Set the colormode SubOption highlight. highlight_graymode = hlt_g; // Set the graymode SubOption highlight. highlight_textpattern = hlt_tp; // Set the textpattern to highlight. ascent = fmet.getAscent(); // Get the height of the font. trademark = new String("TM"); advanced_text = new String("More Options"); basic_text = new String("Fewer Options"); } // END configure /** * Set the message associated with the BubbleMenuHelp object. * @param msg Message associated with the BubbleMenuHelp object. */ void setMessage(Message msg) { message = msg; // Set associated message. } /** * Draw the message associated with the BubbleMenuHelp object. * @param g Graphics instance. */ void drawMessage(Graphics g) { message.draw(g); // Set associated message. } /** * Insert SubOption with one instructive message. * @param button The button to hit to get the SubOption. * @param comment The comment shown next to button. * @param m The message shown when a SubOption is selected. * @param a Boolean toggle as to whether the SubOption is shown and * whether it can be selected. */ void add(String button, String comment, Message m, boolean a) { v.addElement(new SubOption(button,comment,m,a)); // Add to vector. } // END add /** * Insert SubOption with one instructive message. * @param button The button to hit to get the SubOption. * @param comment The comment shown next to button. * @param m The message shown when a SubOption is selected. * @param a Boolean toggle as to whether the SubOption is shown and * whether it can be selected. */ void add_size( String mb1, String mb2, String mb3, String mb4, String mb5, String mb6, String canvassize_string, String comment, Message m, boolean a) { v.addElement(new SubOption(mb1, mb2, mb3, mb4, mb5, mb6, canvassize_string, comment,m,a)); // Add to vector. } // END add_size /** * Insert SubOption with one instructive message. * @param button The button to hit to get the SubOption. * @param comment The comment shown next to button. * @param m The message shown when a SubOption is selected. * @param a Boolean toggle as to whether the SubOption is shown and * whether it can be selected. */ void add_complexsize( String mb1, String mb2, String mb3, String mb4, String mb5, String mb6, String mb7, String mb8, String mb9, String mb10, String canvassize_string, String comment, Message m, boolean a) { v.addElement(new SubOption( mb1, mb2, mb3, mb4, mb5, mb6, mb7, mb8, mb9, mb10, canvassize_string, comment,m,a)); // Add to vector. } // END add_size /** * Insert SubOption with one instructive message. * @param button The button to hit to get the SubOption. * @param comment The comment shown next to button. * @param m The message shown when a SubOption is selected. * @param a Boolean toggle as to whether the SubOption is shown and * whether it can be selected. */ void add_print( String mb1, String mb2, String mb3, String comment, Message m, boolean a) { v.addElement(new SubOption(mb1, mb2, mb3, comment,m,a)); // Add to vector. } // END add_print /** * Insert SubOption with two instructive messages. * @param button The button to hit to get the SubOption. * @param comment The comment shown next to button. * @param m1 The message shown when a SubOption is selected. * @param m2 The message shown when a SubOption is selected (used for * secondary instructions, such as those with connecting links). * @param a Boolean toggle as to whether the SubOption is shown and * whether it can be selected. */ void add(String button, String comment, Message m1, Message m2, boolean a) { v.addElement(new SubOption(button,comment,m1,m2,a)); // Add to vector. } // END add /** * Draw rectangles, polygons, SubOptions, and text. * @param g Graphics instance in which to draw. */ void draw(Graphics g,String mode) { int extrapad = 0; // Draw the background of the bubble. g.setColor(bg_color); g.fillRect(X+5, Y+yoff, width, height); // Draw border of the bubble. g.setColor(border_color); g.drawRect(X+5,Y+yoff,width,height); // Draw a "link". This is not a concept map link. This is // just a small filled-in polygon which helps attach the bubble // (with the suboptions) to the relevant menu choice. g.setColor(bg_color); xpoints[0] = X; ypoints[0] = Y+yoff+15; // Top left corner. xpoints[1] = X+5; ypoints[1] = Y+yoff+15; // Top right corner. xpoints[2] = X+5; ypoints[2] = Y+yoff+15+25; // Bottom right corner. xpoints[3] = X; ypoints[3] = Y+yoff+15+25; // Bottom left corner. if (link == true) // If a link should be drawn. { g.fillPolygon(xpoints,ypoints,4); // Draw polygon. g.drawLine(xpoints[1],ypoints[1],xpoints[2],ypoints[2]); // Shade. g.setColor(border_color); // Draw "horizontal" lines of link. g.drawLine(xpoints[0],ypoints[0],xpoints[1],ypoints[1]); g.drawLine(xpoints[2],ypoints[2],xpoints[3],ypoints[3]); } // Draw the header text (a big label for the bubble). g.setColor(fg_color); g.setFont(font); // Set color and font. g.drawString(header, X+15 + padX / 2, Y + yoff + ascent + padY / 2); // Calculate maximum width for suboption buttons. vEnum = v.elements(); // Reset the enumeration. while (vEnum.hasMoreElements()) // Run through the vector elements. { opt = (SubOption)vEnum.nextElement(); // Calculate width. if (opt.mb1_text == null) { subwidth = (bfm.stringWidth(opt.getButtonText())+padX); if (opt.getButtonText().equals("SHOW ROBOGRADER")) { extrapad = bfmsup.stringWidth(trademark)+padX; subwidth += extrapad; } if (subwidth > maxwidth) { maxwidth = subwidth; // Set the maximum width. } } } vEnum = v.elements(); // Reset the enumeration. // Initialize and draw the suboptions that should appear inside the // bubble. y2 = -5; while (vEnum.hasMoreElements()) // Loop through all the suboptions. { opt = (SubOption)vEnum.nextElement(); if (opt.active && (opt.mb1_text == null) ) // If SubOption active and not canvas size selector, // then draw+set target { // Determine width of SubOption button. subwidth = (bfm.stringWidth(opt.getButtonText()) + padX); /* subheight = bfm.getHeight() + padY; y2+=subheight+5;*/ // Begin to calculate height of SubOption button. subheight = 25; // Basic height of SubOption button. y2 += subheight; // Adjusted height of SubOption button. g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(X+10, Y+yoff+y2, maxwidth, subheight, true); opt.sethit(X+10, Y+yoff+y2, maxwidth, subheight); // Draw the SubOption button label. g.setFont(bfont); g.setColor(subfg_color); //g.drawString(opt.getButtonText(), X+20 + padX / 2, Y + yoff + y2 + ascent + padY / 2); g.drawString(opt.getButtonText(), X+10 + padX / 2, Y+yoff+y2+15); // Draw superscript "TM" if button text is "SHOW ROBOGRADER". if (opt.getButtonText().equals("SHOW ROBOGRADER")) { g.setFont(bfontsup); g.setColor(subfg_color); g.drawString(trademark, X+10 + maxwidth - extrapad , Y+yoff+y2+10); } // Draw explanatory text for the SubOption button. g.setFont(font); g.setColor(fg_color); g.drawString(opt.getCommentText(), X+10+maxwidth+10 + padX / 2, Y + yoff + y2 + ascent + padY / 2); g.setColor(highlight_color); // Rectangle border color. if (opt.getButtonText().equals(highlight_textpattern)) { g.drawRect(X+10, Y+yoff+y2, maxwidth, subheight); //Border. g.drawRect(X+11, Y+yoff+y2+1, maxwidth-2, subheight-2); // Thicken. g.drawRect(X+12, Y+yoff+y2+2, maxwidth-4, subheight-4); // Thicken. } } // DRAW CANVAS SIZE SUBOPTIONS else if (opt.active && (opt.mb1_text != null) && (opt.mb5_text != null) && (opt.mb9_text != null) ) // If SubOption active and canvas size selector, // then draw+set target { // Begin to calculate height of SubOption button. subheight = 25; // Basic height of SubOption button. y2 += subheight; // Adjusted height of SubOption button. if (mode.equals("basic")) { // Determine width of SubOption buttons. // Draw the SubOption button label. // Draw explanatory text for the SubOption button. mbsw = X+10; g.setFont(font); g.setColor(fg_color); g.drawString(opt.getCommentText(), X + 10 + padX / 2, Y + yoff + y2 + 15); subwidth0 = (fm.stringWidth(opt.getCommentText()) + padX); mbsw = subwidth0+X+5; g.setFont(font); subwidth1 = (fm.stringWidth(opt.getButtonText(7)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth1, subheight-4, true); if (opt.getButtonText(1).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(7), mbsw+10 + padX / 2, Y+yoff+y2+15); // Designate target area. opt.sethit(mbsw+10, Y+yoff+y2, subwidth1, subheight, 7); mbsw += subwidth1+5; g.setFont(font); subwidth2 = (fm.stringWidth(opt.getButtonText(8)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth2, subheight-4, true); if (opt.getButtonText(2).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(8), mbsw+10 + padX / 2, Y+yoff+y2+15); // Designate target area. opt.sethit(mbsw+10, Y+yoff+y2, subwidth2, subheight, 8); mbsw += subwidth2+5; subwidth3 = (fm.stringWidth(opt.getButtonText(9)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth3, subheight-4, true); if (opt.getButtonText(3).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(9), mbsw+10 + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw+10, Y+yoff+y2, subwidth3, subheight, 9); mbsw += subwidth3+5; } else if (mode.equals("advanced")) { // Determine width of SubOption buttons. // Draw the SubOption button label. // Draw explanatory text for the SubOption button. mbsw = X+10; g.setFont(font); g.setColor(fg_color); g.drawString(opt.getCommentText(), X + 10 + padX / 2, Y + yoff + y2 + 15); subwidth0 = (fm.stringWidth(opt.getCommentText()) + padX); mbsw = subwidth0+X+5; g.setFont(font); subwidth1 = (fm.stringWidth(opt.getButtonText(1)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth1, subheight-4, true); if (opt.getButtonText(1).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(1), mbsw+10 + padX / 2, Y+yoff+y2+15); // Designate target area. opt.sethit(mbsw+10, Y+yoff+y2, subwidth1, subheight, 1); mbsw += subwidth1+5; g.setFont(font); subwidth2 = (fm.stringWidth(opt.getButtonText(2)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth2, subheight-4, true); if (opt.getButtonText(2).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(2), mbsw+10 + padX / 2, Y+yoff+y2+15); // Designate target area. opt.sethit(mbsw+10, Y+yoff+y2, subwidth2, subheight, 2); mbsw += subwidth2+5; subwidth3 = (fm.stringWidth(opt.getButtonText(3)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth3, subheight-4, true); if (opt.getButtonText(3).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(3), mbsw+10 + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw+10, Y+yoff+y2, subwidth3, subheight, 3); mbsw += subwidth3+5; subwidth4 = (fm.stringWidth(opt.getButtonText(4)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth4, subheight-4, true); if (opt.getButtonText(4).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(4), mbsw+10 + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw+10, Y+yoff+y2, subwidth4, subheight, 4); mbsw += subwidth4+5; subwidth5 = (fm.stringWidth(opt.getButtonText(5)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth5, subheight-4, true); if (opt.getButtonText(5).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(5), mbsw+10 + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw+10, Y+yoff+y2, subwidth5, subheight, 5); mbsw += subwidth5+5; subwidth6 = (fm.stringWidth(opt.getButtonText(6)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth6, subheight-4, true); if (opt.getButtonText(6).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(6), mbsw+10 + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw+10, Y+yoff+y2, subwidth6, subheight, 6); mbsw += subwidth5+5; } // Designate target area. opt.sethit(X+10, Y+yoff+y2, subwidth1, subheight); } // DRAW FONT SIZE SUBOPTIONS else if (opt.active && (opt.mb1_text != null) && (opt.mb5_text != null) && (opt.mb9_text == null) && (mode.equals("advanced")) ) // If SubOption active and font size selector, // then draw+set target { // Begin to calculate height of SubOption button. subheight = 25; // Basic height of SubOption button. y2 += subheight; // Adjusted height of SubOption button. // Determine width of SubOption buttons. // Draw the SubOption button label. if (opt.getButtonText(1).equals("TOGGLE COLOR")) { /* mbsw = X+12; g.setFont(font); subwidth0 = (fm.stringWidth(opt.getButtonText(1)+" ") + padX); g.setColor(subbg_color); // Background of SubOption button. g.drawRect(mbsw-2, Y+yoff+y2, subwidth0+4, subheight); //Border. g.drawRect(mbsw, Y+yoff+y2+1, subwidth0, subheight-2); // Thicken. g.drawRect(mbsw+2, Y+yoff+y2+2, subwidth0-4, subheight-4); // Thicken. // g.fill3DRect(X+20, Y+yoff+y2+2, subwidth0, subheight-4, true); g.setColor(subbg_color); g.drawString(" "+opt.getButtonText(1)+" ", mbsw + padX / 2, Y+yoff+y2+15); // Designate target area. opt.sethit(mbsw, Y+yoff+y2, subwidth0, subheight, 1); // Draw explanatory text for the SubOption button. mbsw = subwidth0+X+10; */ mbsw = X+10; g.setFont(font); g.setColor(fg_color); g.drawString(opt.getCommentText(), mbsw + padX / 2, Y + yoff + y2 + 15); g.setFont(font); subwidth1 = (fm.stringWidth(opt.getCommentText()) + padX); mbsw += subwidth1-5; } else { // Draw explanatory text for the SubOption button. mbsw = X+10; g.setFont(font); g.setColor(fg_color); g.drawString(opt.getCommentText(), X + 10 + padX / 2, Y + yoff + y2 + 15); subwidth0 = (fm.stringWidth(opt.getCommentText()) + padX); mbsw = subwidth0+X+5; g.setFont(font); subwidth1 = (fm.stringWidth(opt.getButtonText(1)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth1, subheight-4, true); if (opt.getButtonText(1).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(1), mbsw+10 + padX / 2, Y+yoff+y2+15); // Designate target area. opt.sethit(mbsw+10, Y+yoff+y2, subwidth1, subheight, 1); mbsw += subwidth1+5; } g.setFont(font); subwidth2 = (fm.stringWidth(opt.getButtonText(2)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth2, subheight-4, true); if (opt.getButtonText(2).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(2), mbsw+10 + padX / 2, Y+yoff+y2+15); // Designate target area. opt.sethit(mbsw+10, Y+yoff+y2, subwidth2, subheight, 2); mbsw += subwidth2+5; subwidth3 = (fm.stringWidth(opt.getButtonText(3)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth3, subheight-4, true); if (opt.getButtonText(3).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(3), mbsw+10 + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw+10, Y+yoff+y2, subwidth3, subheight, 3); mbsw += subwidth3+5; subwidth4 = (fm.stringWidth(opt.getButtonText(4)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth4, subheight-4, true); if (opt.getButtonText(4).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(4), mbsw+10 + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw+10, Y+yoff+y2, subwidth4, subheight, 4); mbsw += subwidth4+5; subwidth5 = (fm.stringWidth(opt.getButtonText(5)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth5, subheight-4, true); if (opt.getButtonText(5).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(5), mbsw+10 + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw+10, Y+yoff+y2, subwidth5, subheight, 5); mbsw += subwidth5+5; subwidth6 = (fm.stringWidth(opt.getButtonText(6)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw+10, Y+yoff+y2+2, subwidth6, subheight-4, true); if (opt.getButtonText(6).indexOf(opt.canvassize_string,0) != -1) {g.setColor(highlight_color);} else {g.setColor(subfg_color);} g.drawString(opt.getButtonText(6), mbsw+10 + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw+10, Y+yoff+y2, subwidth6, subheight, 6); mbsw += subwidth5+5; // subwidth4 = (fm.stringWidth(basic_text) + padX); mbsw = X+width-10-subwidth4-4; g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw, Y+yoff+y2+2, subwidth4, subheight-4, true); g.setColor(subfg_color); g.drawString(basic_text, mbsw + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw, Y+yoff+y2, subwidth4, subheight, 1); } // DRAW FONT SIZE SUBOPTIONS else if (opt.active && (opt.mb1_text != null) && (opt.mb5_text != null) && (opt.mb9_text == null) && (!mode.equals("advanced")) ) // If SubOption active and font size selector, // then draw+set target { // Begin to calculate height of SubOption button. subheight = 25; // Basic height of SubOption button. y2 += subheight; // Adjusted height of SubOption button. // subwidth4 = (fm.stringWidth(advanced_text) + padX); mbsw = X+width-10-subwidth4-4; g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw, Y+yoff+y2+2, subwidth4, subheight-4, true); g.setColor(subfg_color); g.drawString(advanced_text, mbsw + padX / 2, Y+yoff+y2+15); opt.sethit(mbsw, Y+yoff+y2, subwidth4, subheight, 1); // Designate target area. // opt.sethit(X+10, Y+yoff+y2, subwidth1, subheight, 1); } // DRAW PRINT PREVIEW SUBOPTIONS else if (opt.active && (opt.mb1_text != null) && (opt.mb5_text == null) ) // If SubOption active and print preview selector, // then draw+set target { // Begin to calculate height of SubOption button. subheight = 25; // Basic height of SubOption button. y2 += subheight; // Adjusted height of SubOption button. // Determine width of SubOption buttons. // Draw the SubOption button label. mbsw = X+10; g.setFont(font); g.setColor(fg_color); g.drawString(opt.getCommentText(), mbsw + padX / 2, Y + yoff + y2 + 15); subwidth3 = (fm.stringWidth(opt.getCommentText()) + padX); mbsw = subwidth3+X+15; g.setFont(bfont); subwidth1 = (bfm.stringWidth(opt.getButtonText(1)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw, Y+yoff+y2+2, subwidth1, subheight-4, true); g.setColor(subfg_color); g.drawString(opt.getButtonText(1), mbsw + padX / 2, Y+yoff+y2+15); // Designate target area. opt.sethit(mbsw, Y+yoff+y2, subwidth1, subheight, 1); // Designate target area. opt.sethit(mbsw, Y+yoff+y2, subwidth1, subheight); mbsw += subwidth1+5; subwidth2 = (bfm.stringWidth(opt.getButtonText(2)) + padX); g.setColor(subbg_color); // Background of SubOption button. g.fill3DRect(mbsw, Y+yoff+y2+2, subwidth2, subheight-4, true); g.setColor(subfg_color); g.drawString(opt.getButtonText(2), mbsw + padX / 2, Y+yoff+y2+15); // Designate target area. opt.sethit(mbsw, Y+yoff+y2+2, subwidth2, subheight, 2); g.setFont(font); subwidth3 = (fm.stringWidth(" "+opt.getButtonText(3)+" ") + padX); // mbsw += subwidth2+25; mbsw = X+width-10-subwidth3-4; g.setColor(subbg_color); // Background of SubOption button. g.drawRect(mbsw-2, Y+yoff+y2+2, subwidth3+4, subheight-5); //Border. g.drawRect(mbsw, Y+yoff+y2+2, subwidth3, subheight-5); // Thicken. g.drawRect(mbsw+2, Y+yoff+y2+2, subwidth3-4, subheight-5); // Thicken. // g.fill3DRect(mbsw, Y+yoff+y2+2, subwidth3, subheight-4, true); // g.setColor(subfg_color); g.drawString(" "+opt.getButtonText(3)+" ", mbsw + padX / 2, Y+yoff+y2+15); // Designate target area. opt.sethit(mbsw, Y+yoff+y2+2, subwidth3, subheight-4, 3); // Draw explanatory text for the SubOption button. /* g.setFont(font); g.setColor(fg_color); g.drawString(opt.getCommentText(), mbsw + 10 + padX / 2, Y + yoff + y2 + ascent + padY / 2); */ } else { opt.sethit(0,0,0,0); // Deactivate target area for suboption. } } } // END draw } // END BubbleMenuHelp /** * A choice that is available after a menu button is pressed; usually * there are multiple SubOptions associated with each menu button. */ class SubOption { // --------------------------------------------------------- Class variables. // Temporarily empowering class to handle complex canvas size selection. /** The "mini-buttons" for selecting canvas sizes. */ public String mb1_text; public String mb2_text; public String mb3_text; public String mb4_text; public String mb5_text; public String mb6_text; public String mb7_text; public String mb8_text; public String mb9_text; public String mb10_text; public String canvassize_string; /** Target areas for "mini-buttons" for selecting canvas sizes. */ public TargetArea mb1_target_area; public TargetArea mb2_target_area; public TargetArea mb3_target_area; public TargetArea mb4_target_area; public TargetArea mb5_target_area; public TargetArea mb6_target_area; public TargetArea mb7_target_area; public TargetArea mb8_target_area; public TargetArea mb9_target_area; public TargetArea mb10_target_area; /** The text that appears on the SubOption button. */ private String button_text; /** Explanatory text that appears next to the SubOption * button. */ private String comment_text; /** The first message that should be displayed while carrying * out an action described by SubOption. */ private Message m1; /** If needed, the second message that should be displayed while * carrying out an action described by SubOption. */ private Message m2; /* To explain "m1" and "m2": * A user selects a given SubOption. * The user is then instructed to do something by "m1". * If there is a second step to be performed, then the * "m2" instruction is delivered to the user. * Currently, only the addition of connecting lines * requires two separate instructions (i.e. first "click the first word"; * then second, "click the second word"). */ /** Whether or not this SubOption can be selected. */ public boolean active; /** The region on the screen which should correspond to a mouse action. */ private TargetArea target_area; /** * Constructor (for when only one instruction is needed). * msg1 is provided as an instruction to the user. * @param b Set the text for button. * @param c Set the text for comment. * @param msg1 Set the text for the instruction message. * @param act Whether or not the button should be active on the interface. */ SubOption(String b, String c, Message msg1, boolean act) { button_text = b; // Set the button. comment_text = c; // Set the comment. m1 = msg1; // Set the first message that is displayed. active = act; // Whether it is currently available to be selected. target_area = new TargetArea(); mb1_target_area = new TargetArea(); mb2_target_area = new TargetArea(); mb3_target_area = new TargetArea(); mb4_target_area = new TargetArea(); mb5_target_area = new TargetArea(); mb6_target_area = new TargetArea(); } // END SubOption constructor /** * Constructor (for when only one instruction is needed). * canvas size modification (basic/advanced) * msg1 is provided as an instruction to the user. * @param b Set the text for button. * @param c Set the text for comment. * @param msg1 Set the text for the instruction message. * @param act Whether or not the button should be active on the interface. * 1: scaling=1, 480x300 * 2: scaling=1.6, 768x480 (DEFAULT) * 3: scaling=2, 960x600 * 4: scaling=2.33, 1119x669 * 5: scaling=2.67, 1282x801 * 6: scaling=3, 1440x900 */ SubOption( String b1, String b2, String b3, String b4, String b5, String b6, String b7, String b8, String b9, String b10, String cs_string, String c, Message msg1, boolean act) { mb1_text = b1; // Set mini-button 1. mb2_text = b2; // Set mini-button 2. mb3_text = b3; // Set mini-button 3. mb4_text = b4; // Set mini-button 4. mb5_text = b5; // Set mini-button 5. mb6_text = b6; // Set mini-button 6. mb7_text = b7; // Set mini-button 7. mb8_text = b8; // Set mini-button 8. mb9_text = b9; // Set mini-button 9. mb10_text = b10; // Set mini-button 10. mb1_target_area = new TargetArea(); mb2_target_area = new TargetArea(); mb3_target_area = new TargetArea(); mb4_target_area = new TargetArea(); mb5_target_area = new TargetArea(); mb6_target_area = new TargetArea(); mb7_target_area = new TargetArea(); mb8_target_area = new TargetArea(); mb9_target_area = new TargetArea(); mb10_target_area = new TargetArea(); canvassize_string = cs_string; button_text = mb1_text; comment_text = c; // Set the comment. m1 = msg1; // Set the first message that is displayed. active = act; // Whether it is currently available to be selected. target_area = new TargetArea(); } // END SubOption constructor /** * Constructor (for when only one instruction is needed). * font size modification * msg1 is provided as an instruction to the user. * @param b Set the text for button. * @param c Set the text for comment. * @param msg1 Set the text for the instruction message. * @param act Whether or not the button should be active on the interface. * 1: scaling=1, 480x300 * 2: scaling=1.6, 768x480 (DEFAULT) * 3: scaling=2, 960x600 * 4: scaling=2.33, 1119x669 * 5: scaling=2.67, 1282x801 * 6: scaling=3, 1440x900 */ SubOption( String b1, String b2, String b3, String b4, String b5, String b6, String cs_string, String c, Message msg1, boolean act) { mb1_text = b1; // Set mini-button 1. mb2_text = b2; // Set mini-button 2. mb3_text = b3; // Set mini-button 3. mb4_text = b4; // Set mini-button 4. mb5_text = b5; // Set mini-button 5. mb6_text = b6; // Set mini-button 6. mb1_target_area = new TargetArea(); mb2_target_area = new TargetArea(); mb3_target_area = new TargetArea(); mb4_target_area = new TargetArea(); mb5_target_area = new TargetArea(); mb6_target_area = new TargetArea(); canvassize_string = cs_string; button_text = mb1_text; comment_text = c; // Set the comment. m1 = msg1; // Set the first message that is displayed. active = act; // Whether it is currently available to be selected. target_area = new TargetArea(); } // END SubOption constructor /** * Constructor (for when only one instruction is needed). * canvas size modification * msg1 is provided as an instruction to the user. * @param b Set the text for button. * @param c Set the text for comment. * @param msg1 Set the text for the instruction message. * @param act Whether or not the button should be active on the interface. * 1: print preview landscape * 2: print preview portrait */ SubOption( String b1, String b2, String b3, String c, Message msg1, boolean act) { mb1_text = b1; // Set mini-button 1. mb2_text = b2; // Set mini-button 2. mb3_text = b3; // Set mini-button 2. mb1_target_area = new TargetArea(); mb2_target_area = new TargetArea(); mb3_target_area = new TargetArea(); button_text = mb1_text; comment_text = c; // Set the comment. m1 = msg1; // Set the first message that is displayed. active = act; // Whether it is currently available to be selected. target_area = new TargetArea(); } // END SubOption constructor /** * Constructor (for when two instructions are needed). * First, msg1 is provided as an instruction to the user. * After the user carries out the first action, a second * message, msg2, is delivered to the user. * @param b Set the text for button. * @param c Set the text for comment. * @param msg1 Set the text for the first message. * @param msg2 Set the text for the second message. * @param act Whether or not the button should be active on the interface. */ SubOption(String b, String c, Message msg1, Message msg2, boolean act) { button_text = b; // Set the button. comment_text = c; // Set the comment. m1 = msg1; // Set the first message that is displayed. m2 = msg2; // Set the second message that is displayed while the user // is performing an action. active = act; // Whether it is currently available to be selected. target_area = new TargetArea(); } // END SubOption constructor /** * Get the button text. */ public String getButtonText() { return button_text; } /** * Get mini-button text (for canvas size selection). */ public String getButtonText(int i) { if (i == 1) {return mb1_text;} if (i == 2) {return mb2_text;} if (i == 3) {return mb3_text;} if (i == 4) {return mb4_text;} if (i == 5) {return mb5_text;} if (i == 6) {return mb6_text;} if (i == 7) {return mb7_text;} if (i == 8) {return mb8_text;} if (i == 9) {return mb9_text;} if (i == 10) {return mb10_text;} return button_text; } /** * Get the comment text. */ public String getCommentText() { return comment_text; } /** * Get the target area object associated with the suboption. */ public TargetArea getTargetArea() { return target_area; } /** * Get the target area object associated with the suboption * with mini-options (canvas size selection). * @param i specified minioption */ public TargetArea getTargetArea(int i) { if (i == 1) {return mb1_target_area;} if (i == 2) {return mb2_target_area;} if (i == 3) {return mb3_target_area;} if (i == 4) {return mb4_target_area;} if (i == 5) {return mb5_target_area;} if (i == 6) {return mb6_target_area;} if (i == 7) {return mb7_target_area;} if (i == 8) {return mb8_target_area;} if (i == 9) {return mb9_target_area;} if (i == 10) {return mb10_target_area;} return target_area; } /** Draw the first message associated with the selection of a * SubOption. */ public void drawMessage1(Graphics g) { m1.draw(g); } /** Draw the second message associated with the selection of a * SubOption. */ public void drawMessage2(Graphics g) { m2.draw(g); } /** * Determine the target coordinates for this region. * This method sets variables in order to define the target coordinates * for the mouse arrow being on top of the SubOption. * @param Xloc The top left x coordinate for the target hit area. * @param Yloc The top left y coordinate for the target hit area. * @param width The width of the target hit area. * @param height The height of the target hit area. */ public void sethit(int Xloc, int Yloc, int width, int height) { // Set the top left and dimensional target hit area. target_area.sethit(Xloc,Yloc,width,height); } // END sethit /** * For the canvas size feature. * Determine the target coordinates for this region. * This method sets variables in order to define the target coordinates * for the mouse arrow being on top of the SubOption. * @param Xloc The top left x coordinate for the target hit area. * @param Yloc The top left y coordinate for the target hit area. * @param width The width of the target hit area. * @param height The height of the target hit area. */ public void sethit(int Xloc, int Yloc, int width, int height, int mb) { // Set the top left and dimensional target hit area. if (mb == 1) {mb1_target_area.sethit(Xloc,Yloc,width,height);} if (mb == 2) {mb2_target_area.sethit(Xloc,Yloc,width,height);} if (mb == 3) {mb3_target_area.sethit(Xloc,Yloc,width,height);} if (mb == 4) {mb4_target_area.sethit(Xloc,Yloc,width,height);} if (mb == 5) {mb5_target_area.sethit(Xloc,Yloc,width,height);} if (mb == 6) {mb6_target_area.sethit(Xloc,Yloc,width,height);} if (mb == 7) {mb7_target_area.sethit(Xloc,Yloc,width,height);} if (mb == 8) {mb8_target_area.sethit(Xloc,Yloc,width,height);} if (mb == 9) {mb9_target_area.sethit(Xloc,Yloc,width,height);} if (mb == 10) {mb10_target_area.sethit(Xloc,Yloc,width,height);} } // END sethit } // END SubOption /** * Brief help messages which are displayed; * typically used when SubOptions are selected by the user. * These messages help guide and instruct the user about the action they * are performing. */ class Message { // --------------------------------------------------------- Class variables. /** The message text. */ private String text; /** The font for the message. */ private static Font font; /** The top left x coordinate for the message string. */ private static int text_X; /** The top left y coordinate for the message string. */ private static int text_Y; /** The top left x coordinate for the background. */ private static int back_X; /** The top left y coordinate for the background. */ private static int back_Y; /** The background rectangle height. */ private static int back_height; /** The background rectangle width. */ private static int back_width; /** Color of the text. */ private static Color fg; /** Color of the background. */ private static Color bg; /** Colormode. */ private static boolean color = true; /** Color of the text, colormode. */ private static Color fg_colormode; /** Color of the background, colormode. */ private static Color bg_colormode; /** Color of the text, graymode. */ private static Color fg_graymode; /** Color of the background, graymode. */ private static Color bg_graymode; /** * Constructor: set the text to be displayed. * @param txt The text to be displayed. */ Message(String txt) { text = txt; // Set the text to be displayed. } // END Message constructor /** * Force colormode to be on. */ static void colormode_on() { color = true; fg = fg_colormode; bg = bg_colormode; } // END colormode_on /** * Switch between color and graymode. */ static void color_toggle() { if (color == true) // Color mode, so switch to black and white mode. { color = false; fg = fg_graymode; bg = bg_graymode; } else // Black and white mode, so switch to color mode. { colormode_on(); } } // END color_toggle /** * Initialize values that are common to all messages. */ static void configure(Font fnt, FontMetrics fm, Color fg_c, Color bg_c, Color fg_g, Color bg_g, int text_x, int text_y, int back_x, int back_y, int back_w, int back_h) { font = fnt; // Set the font. fg = fg_c; // Set foreground color. bg = bg_c; // Set background color. fg_colormode = fg_c; // Set foreground color, colormode. bg_colormode = bg_c; // Set background color, colormode. fg_graymode = fg_g; // Set foreground color, graymode. bg_graymode = bg_g; // Set background color, graymode. text_X = text_x; text_Y = text_y; // Set text coordinates. back_X = back_x; back_Y = back_y; // Set top left corner of background. // Background width and height. back_width = back_w; back_height = back_h; } // END configure /** * Call necessary functions of the graphics library. */ void draw(Graphics g) { g.setColor(bg); // Set background (rectangle fill color). g.fillRect(back_X, back_Y, back_width, back_height); // Draw rectangle. g.setColor(fg); // Set foreground (text color). g.setFont(font); // Set font. g.drawString(text, text_X, text_Y); // Draw text string. } // END draw } // END Message /** * Status message which is displayed; * "SAVED"/"AUTOSAVED"/"NOT SAVED". */ class StatusMessage { // --------------------------------------------------------- Class variables. /** The message text. */ private String text; /** The font for the message. */ private static Font font; /** The top left x coordinate for the message string. */ private static int text_X; /** The top left y coordinate for the message string. */ private static int text_Y; /** The top left x coordinate for the background. */ private static int back_X; /** The top left y coordinate for the background. */ private static int back_Y; /** The background rectangle height. */ private static int back_height; /** The background rectangle width. */ private static int back_width; /** Color of the text. */ private static Color fg; /** Color of the background. */ private static Color bg; /** Color of the text. */ private static Color fga; /** Color of the background. */ private static Color bga; /** Colormode. */ private static boolean color = true; /** Color of the text, colormode. */ private static Color fg_colormode; /** Color of the background, colormode. */ private static Color bg_colormode; /** Color of the text, graymode. */ private static Color fg_graymode; /** Color of the background, graymode. */ private static Color bg_graymode; /** Color of the text, colormode. */ private static Color fga_colormode; /** Color of the background, colormode. */ private static Color bga_colormode; /** Color of the text, graymode. */ private static Color fga_graymode; /** Color of the background, graymode. */ private static Color bga_graymode; /** * Constructor: set the text to be displayed. * @param txt The text to be displayed. */ StatusMessage(String txt) { text = txt; // Set the text to be displayed. } // END Message constructor /** * Force colormode to be on. */ static void colormode_on() { color = true; fg = fg_colormode; bg = bg_colormode; } // END colormode_on /** * Switch between color and graymode. */ static void color_toggle() { if (color == true) // Color mode, so switch to black and white mode. { color = false; fg = fg_graymode; bg = bg_graymode; } else // Black and white mode, so switch to color mode. { colormode_on(); } } // END color_toggle /** * Initialize values that are common to all messages. */ static void configure(Font fnt, FontMetrics fm, Color fg_c, Color bg_c, Color fg_g, Color bg_g, Color fga_c, Color bga_c, Color fga_g, Color bga_g, int text_x, int text_y, int back_x, int back_y, int back_w, int back_h) { font = fnt; // Set the font. fg = fg_c; // Set foreground color. bg = bg_c; // Set background color. fg_colormode = fg_c; // Set foreground color, colormode. bg_colormode = bg_c; // Set background color, colormode. fg_graymode = fg_g; // Set foreground color, graymode. bg_graymode = bg_g; // Set background color, graymode. fga = fg_c; // Set foreground alert color. bga = bg_c; // Set background alert color. fga_colormode = fg_c; // Set foreground alert color, colormode. bga_colormode = bg_c; // Set background alert color, colormode. fga_graymode = fg_g; // Set foreground alert color, graymode. bga_graymode = bg_g; // Set background alert color, graymode. text_X = text_x; text_Y = text_y; // Set text coordinates. back_X = back_x; back_Y = back_y; // Set top left corner of background. // Background width and height. back_width = back_w; back_height = back_h; } // END configure /** * Call necessary functions of the graphics library. */ void draw(Graphics g) { g.setColor(bg); // Set background (rectangle fill color). g.fillRect(back_X, back_Y, back_width, back_height); // Draw rectangle. g.setColor(fg); // Set foreground (text color). g.setFont(font); // Set font. g.drawString(text, text_X, text_Y); // Draw text string. } // END draw } // END StatusMessage /** * Structure and testing against a target area. */ class TargetArea { /** The top left x coordinate for the target hit area. */ private int hit_x = 0; /** The width of the target hit area. */ private int hit_w = 0; /** The top left y coordinate for the target hit area. */ private int hit_y = 0; /** The height of the target hit area. */ private int hit_h = 0; /** * Constructor. */ TargetArea() { } // END TargetArea constructor. /** * Determine the target coordinates for this region. * This method sets variables in order to define the target coordinates * for the mouse arrow being on top of the SubOption. * @param Xloc The top left x coordinate for the target hit area. * @param Yloc The top left y coordinate for the target hit area. * @param width The width of the target hit area. * @param height The height of the target hit area. */ public void sethit(int Xloc, int Yloc, int width, int height) { hit_x = Xloc; // Set the top left x coordinate for the target hit area. hit_y = Yloc; // Set the top left y coordinate for the target hit area. hit_w = width; // Set the width of the target hit area. hit_h = height; // Set the height of the target hit area. } // END sethit /** * See whether or not a proposed coordinate falls within the hit area. * @param X The proposed x coordinate. * @param Y The proposed y coordinate. */ public boolean hit_query(int X, int Y) { if ((X >= hit_x) && (X < (hit_w+hit_x)) && (Y >= hit_y) && (Y <= (hit_y+hit_h))) { return true; } else { return false; } } // END hit_query } // END TargetArea /** * A uniform object for talking to a server. * This supports the POST method of passing data * to a specific URL. */ class ServerTalker { /** * Send data to a URL. * @param url Uniform Resource Locator * @param data CGI-formatted data string */ public void put(URL url, String data) { BufferedReader br = put_and_get(url, data); String receive_data = null; try { while ( (receive_data = br.readLine()) != null) { ; } } catch (Exception e) { System.err.println("Error reading buffered input: "+e); } } /** * Send data to a URL and then receive data. * @param url Uniform Resource Locator * @param data CGI-formatted data string * @return BufferedReader; a buffered reader object. */ public BufferedReader put_and_get(URL url, String data) { try { int datalength = data.length(); data += "&datalength="+datalength; // The "official" url connection object. URLConnection url_connection = url.openConnection(); // URL connection specifics. url_connection.setDoOutput(true); url_connection.setDoInput(true); url_connection.setUseCaches(false); url_connection.setDefaultUseCaches(false); // Remind protocol to accept ALL of the data. url_connection.setRequestProperty("CONTENT_LENGTH", "" + data.length()); // This is necessary for CGI.pm ($cgi=new CGI()); url_connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); // Place in the output queue. OutputStream os = url_connection.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(os); osw.write(data); osw.flush(); osw.close(); // AT THIS POINT... the data has not yet been posted // to the server. The strange nature of the // URLConnection class is such that the output stream // data gets passed along when the "getInputStream" // function is called. Strange, but the following // line is definitely needed. InputStream in = url_connection.getInputStream(); // Okay. CGI data is sent to the server now. // Variable that holds data returned from servlet. String receive_data = null; // Doing the buffered input stream thing. InputStreamReader isr = new InputStreamReader(in); BufferedReader br = new BufferedReader(isr); // Note that receive_data should be valid html // to accomodate an Internet Explorer on MS-Windows // glitch (something to do with the cache; receive_data // is presented as a web page when the user hits the // back button). return (br); } catch (MalformedURLException me) { System.err.println("MalformedURLException: " + me); } catch (IOException e) { System.out.println( "Unsuccessful communication with server" + e); } return (null); } } // END ServerTalker