// File: Visualizer.java // // Author: Francois Coupleux (coupleux@eleve.emn.fr) // // Date: 7-29-1996 // // Description: Applet that allows users to create interactive tutorials accessible through the web. import java.awt.*; import java.util.*; import java.applet.*; import java.net.*; import java.io.*; // Class Visualizer // ---------------- // This class is the principal class. This is the model of the applet. public class Visualizer extends Applet { private WindowController controller; private Parser parser; // init() // ------ // Method which initializes the applet. public void init() { String graphName; int graphWidth , graphHeight; // Desactivates the automatic layout system setLayout(null); // Creates the window controller controller = new WindowController(this); // Creates a parser on the file called tutorialdescription.dat, loads default values and builds the // main menu parser = new Parser(controller , 500 , 450 , this); // Sets the parser of the controller controller.setParser(parser); } // stop() // ------ // Method which stops the applet. public void stop() { controller.killWindows(); controller.receiveMessage(null); } // enableButtons() // --------------- // Method which enables all the buttons of the main menu. public void enableButtons() { Component components[]; int i; // Enables all buttons components = getComponents(); for(i = 0 ; i < components.length ; i++) { if(components[i] instanceof NavigatorButton) { ((NavigatorButton)components[i]).enable(); } } } // receiveMessage() // ---------------- // Method which starts the first window. public void receiveMessage(String nextWindowName) { Component components[]; int i; // Disables all buttons components = getComponents(); for(i = 0 ; i < components.length ; i++) { if(components[i] instanceof NavigatorButton) { ((NavigatorButton)components[i]).disable(); } } controller.handleWindow(parser.parseWindow(nextWindowName , parser.getTitle(nextWindowName) + "/ ")); } } // ************** // * Components * // ************** // Class NavigatorButton // --------------------- // This class describes a button used to navigate to another window. class NavigatorButton extends Button { private Component elementContainingButton; private String nextWindowName; // Constructors // ------------ NavigatorButton(String buttonLabel , String nameOfNextWindow , Color buttonColor , Color labelColor) { Font buttonFont; FontMetrics buttonFontMetrics; int buttonWidth , buttonHeight; // Sets the font used for the label buttonFont = new Font("TimesRoman" , Font.PLAIN , 14); setFont(buttonFont); // Associates the button with the next window nextWindowName = nameOfNextWindow; // Sets colors setBackground(buttonColor); setForeground(labelColor); // Sets the label setLabel(buttonLabel); // Calculates the button's dimensions buttonFontMetrics = getFontMetrics(buttonFont); buttonWidth = buttonFontMetrics.stringWidth(buttonLabel) + 20; buttonHeight = buttonFontMetrics.getHeight() + 10; // Resizes the button resize(buttonWidth , buttonHeight); } NavigatorButton(String buttonLabel , String nameOfNextWindow , Color buttonColor , Color labelColor , Visualizer applet) { this(buttonLabel , nameOfNextWindow , buttonColor , labelColor); elementContainingButton = applet; } // associateWindow() // ----------------- // Method which associates the button to the window it belongs to. public void associateWindow(CustomizableWindow window) { elementContainingButton = window; } // handleEvent() // ------------- // Method which sends the name of the next window. public boolean action(Event event , Object target) { // If the button is associated to a window if(elementContainingButton instanceof CustomizableWindow) { // Sends the message to the window controller ((CustomizableWindow)elementContainingButton).getWindowController().receiveMessage(nextWindowName); } // If the button is associated to the applet (main menu) else { // Sends the message to the applet ((Visualizer)elementContainingButton).receiveMessage(nextWindowName); } return true; } } // Class Title // ----------- // This class describes a component that is used as a title. class Title extends Label { private boolean isCentered; // Constructor // ----------- Title(String content , boolean center , Font font , Color titleColor) { FontMetrics titleFontMetrics; // Set color setForeground(titleColor); // Sets alignment isCentered = center; // Sets font, alignment and text setFont(font); setAlignment(Label.CENTER); setText(content); // Resizes the title titleFontMetrics = getFontMetrics(font); resize(titleFontMetrics.stringWidth(content) , titleFontMetrics.getHeight()); } // isCentered() // ------------ // Method which returns true if the title is centered. public boolean isCentered() { return isCentered; } } // Class NormalTitle // ----------------- // This class describes a title with a 17 font size. class NormalTitle extends Title { NormalTitle(String content , boolean center , Color color) { super(content , center , new Font("TimesRoman" , Font.BOLD , 17) , color); } } // Class MediumTitle // ----------------- // This class describes a title with a 21 font size. class MediumTitle extends Title { MediumTitle(String content , boolean center , Color color) { super(content , center , new Font("TimesRoman" , Font.BOLD , 21) , color); } } // Class LargeTitle // ---------------- // This class describes a title with a 25 font size. class LargeTitle extends Title { LargeTitle(String content , boolean center , Color color) { super(content , center , new Font("TimesRoman" , Font.BOLD , 25) , color); } } // Class Text // ---------- // This class describes a component containing a text. class Text extends Panel { private int panelWidth; // Constructor // ----------- Text(int textWidth , Color textColor) { // Sets the text width panelWidth = textWidth; // Sets color of text setForeground(textColor); // Desactivates the automatic layout system setLayout(null); } // putText() // --------- // Method which splits up the lines of the text in order to display them in the panel. public void putText(Vector lines) { String newLine , lastWord; StringTokenizer stringTokenizer; Font textFont; FontMetrics fontMetrics; Label label; int i , x , y , nbLines , newLineWidth , lastWordWidth , spaceWidth , fontHeight; boolean isItem; // Sets the font textFont = new Font("TimesRoman" , Font.PLAIN , 14); setFont(textFont); // Sets the space width and the font height fontMetrics = getFontMetrics(textFont); spaceWidth = fontMetrics.charWidth(' '); fontHeight = fontMetrics.getHeight(); // Sets the number of lines nbLines = 0; // Sets the vertical position of the first line y = 0; for(i = 0 ; i < lines.size() ; i++) { // Creates a string tokenizer on the current line stringTokenizer = new StringTokenizer((String)lines.elementAt(i) , " "); // Sets the default starting position x = 0; // Initializes the new line newLine = ""; newLineWidth = 0; // The line doesn't contain any item isItem = false; while(stringTokenizer.hasMoreTokens()) { lastWord = stringTokenizer.nextToken(); // If a horizontal space is needed this sets the right starting position if(lastWord.charAt(0) == '_') { x = lastWord.length() * spaceWidth; } // If an item is detected this sets the right starting position and puts a '-' at // the beginning of the line if(lastWord.charAt(0) == '@') { x = lastWord.length() * spaceWidth; isItem = true; lastWord = "-"; } // If it's a simple text or an item if(lastWord.charAt(0) != '_') { lastWordWidth = fontMetrics.stringWidth(lastWord); // If the last word can be added into the new line this adds it if(newLineWidth + spaceWidth + lastWordWidth + x < panelWidth) { newLine = newLine.concat(lastWord + " "); newLineWidth += lastWordWidth + spaceWidth; } // If the last word cannot be added into the new line this changes line else { // Puts the new line in the panel, updates the vertical position and the number of lines label = new Label(newLine , Label.LEFT); add(label); label.reshape(x , y , panelWidth , fontHeight); y += fontHeight; nbLines++; // Creates the new line with the last word newLine = lastWord + " "; newLineWidth = lastWordWidth + spaceWidth; // If no item was detected this sets the starting position to 0 if(! isItem) { x = 0; } } } } // Puts the new line in the panel, updates the vertical position and the number of lines label = new Label(newLine , Label.LEFT); add(label); label.reshape(x , y , panelWidth , fontHeight); y += fontHeight; nbLines++; // Desactivates item isItem = false; } // Resizes the text resize(panelWidth , fontHeight * nbLines); } } // Class Path // ---------- // This class represents a panel displaying the path of the window. class Path extends Text { private Vector lines; // Constructor // ----------- Path(int width , String path , Color color) { // Creates an instance of Text super(width , color); // Defines text to be displayed lines = new Vector(); lines.addElement("Path:"); lines.addElement(path); // Puts text putText(lines); } } // Class Picture // ------------- // This class describes a panel containing an image , a figure number and a one-line caption. class Picture extends Panel { private Image image; // Contructor // ---------- Picture(String imageName , int imageWidth , int imageHeight , String figureNumber , String text , Color textColor, Visualizer visualizer) { Label figureText , caption; Vector lines; Text longCaption; Font font; FontMetrics fontMetrics; int fontHeight , panelHeight; // Sets the image image = visualizer.getImage(visualizer.getDocumentBase() , imageName); // Sets font font = new Font("TimesRoman" , Font.PLAIN , 14); fontMetrics = getFontMetrics(font); fontHeight = fontMetrics.getHeight(); setFont(font); // Sets the color of the text setForeground(textColor); // Desactivates the automatic layout system setLayout(null); // Sets the panel height panelHeight = imageHeight; // If there's a figure number this adds it in the panel and updates the panel height if(figureNumber != null) { figureText = new Label(figureNumber , Label.CENTER); add(figureText); figureText.reshape(0 , imageHeight + 5 , imageWidth , fontHeight); panelHeight += fontHeight + 5; } // If there's a caption if(text != null) { caption = null; longCaption = null; // Puts the caption in the panel if(fontMetrics.stringWidth(text) <= imageWidth) { caption = new Label(text , Label.CENTER); add(caption); } else { longCaption = new Text(imageWidth , textColor); lines = new Vector(); lines.addElement(text); longCaption.putText(lines); add(longCaption); } // If there's a figure number this places the caption after the figure number if(figureNumber != null) { // If the caption is a label if(caption != null) { caption.reshape(0 , imageHeight + fontHeight + 5 , imageWidth , fontHeight); panelHeight += fontHeight; } // If the caption is a text else { longCaption.move(0 , imageHeight + fontHeight + 5); panelHeight += longCaption.size().height; } } // If there's no figure number this places the caption after the image else { // If the caption is a label if(caption != null) { caption.reshape(0 , imageHeight + 5 , imageWidth , fontHeight); panelHeight += fontHeight + 5; } // If the caption is a text else { longCaption.move(0 , imageHeight + 5); panelHeight += longCaption.size().height + 5; } } } // Resizes the panel resize(imageWidth , panelHeight); } // paint() // ------- // Method which displays the image. public void paint(Graphics g) { update(g); } // update() // -------- // Method which displays the image. public void update(Graphics g) { g.drawImage(image , 0 , 0 , this); } // flush() // ------- // Method which flushes the image. public void flush() { image.flush(); } } // Class Navigator // --------------- // This class represents a set of buttons which allow the user to browse in the tutorial. class Navigator extends Panel { private Vector navigatorButtons; private Color buttonColor , labelColor; private int buttonWidth; // Constructor // ----------- Navigator(Color colorButton , Color colorLabel) { navigatorButtons = new Vector(); buttonWidth = 0; buttonColor = colorButton; labelColor = colorLabel; // Desactivates the automatic layout system setLayout(null); } // addButton() // ----------- // Method which adds a button to the navigator. public void addButton(String label , String nextWindowName) { NavigatorButton button; // Adds a button in the navigator button = new NavigatorButton(label , nextWindowName , buttonColor , labelColor); navigatorButtons.addElement(button); add(button); // If this button's width is greater than the current button's width this updates the current button's width if(button.size().width > buttonWidth) { buttonWidth = button.size().width; } } // associateWindow() // ----------------- // Method which associates the navigator to the window it belongs to. public void associateWindow(CustomizableWindow window) { int i; // Associates all the navigator button to the window for(i = 0 ; i < navigatorButtons.size() ; i++) { ((NavigatorButton)navigatorButtons.elementAt(i)).associateWindow(window); } } // normalizeSize() // --------------- // Method which places all the buttons in the navigator. public void normalizeSize() { NavigatorButton currentButton; int i , x , buttonHeight; x = 0; buttonHeight = ((NavigatorButton)navigatorButtons.elementAt(0)).size().height; // Places and resizes all buttons for(i = 0 ; i < navigatorButtons.size() ; i++) { currentButton = (NavigatorButton)navigatorButtons.elementAt(i); currentButton.reshape(x , 0 , buttonWidth , buttonHeight); x += buttonWidth + 10; } // Resizes the navigator resize(buttonWidth * navigatorButtons.size() + 10 * (navigatorButtons.size() - 1) , buttonHeight); } } // Class ParameterInputPanel // ------------------------- // This class describes a component which contains a set of input panels in order to get values. class ParameterInputPanel extends Panel { private Vector parameterNames , parameterUnits , textFields , previousParameterValues; private int textFieldWidth , textWidth; private FontMetrics fontMetrics; private Color textFieldBackgroundColor; // Constructor // ----------- ParameterInputPanel(Color textFieldColor , Color textColor) { Font font; // Sets width textWidth = 0; // Sets colors textFieldBackgroundColor = textFieldColor; setForeground(textColor); // Creates vectors for names, labels, units, text fields and previous values parameterNames = new Vector(); parameterUnits = new Vector(); textFields = new Vector(); previousParameterValues = new Vector(); // Sets font font = new Font("TimesRoman" , Font.PLAIN , 14); fontMetrics = getFontMetrics(font); setFont(font); // Desactivates the automatic layout system setLayout(null); } // addParameterInput() // ------------------- // Method which adds a line in the input panel. public void addParameterInput(String label , String unit) { TextField textField; // Creates a text field with the right color textField = new TextField(); textField.setBackground(textFieldBackgroundColor); // Adds all the elements in their vector parameterNames.addElement(label); textFields.addElement(textField); parameterUnits.addElement(new Label(unit , Label.CENTER)); previousParameterValues.addElement(""); // Updates text's width if(fontMetrics.stringWidth(label) > textWidth) { textWidth = fontMetrics.stringWidth(label); } if(fontMetrics.stringWidth(unit) > textWidth) { textWidth = fontMetrics.stringWidth(unit); } } // normalizeSize() // --------------- // Method which places labels and text fields in the panel. public void normalizeSize() { Label currentName , currentUnit; TextField currentTextField; int i , y , fontHeight; boolean isWestElement; // Sets the font's height fontHeight = fontMetrics.getHeight(); // Sets vertical position for the first line y = 0; // The first element must be located in the left hand part of the panel isWestElement = true; for(i = 0 ; i < textFields.size() ; i++) { // Gets the three elements of the line currentName = new Label((String)parameterNames.elementAt(i) , Label.CENTER); currentTextField = (TextField)textFields.elementAt(i); currentUnit = (Label)parameterUnits.elementAt(i); // Adds the three elements in the panel add(currentName); add(currentTextField); add(currentUnit); // Resizes and places the three elements // If the input panel must be put in the left hand part of the panel if(isWestElement) { currentName.reshape(0 , y + 9 , textWidth , fontHeight); currentTextField.reshape(textWidth + 10 , y , 100 , fontHeight + 18); currentUnit.reshape(textWidth + 120 , y + 9 , textWidth , fontHeight); isWestElement = false; } // If the input panel must be put in the right hand part of the panel else { currentName.reshape(2 * textWidth + 140 , y + 9 , textWidth , fontHeight); currentTextField.reshape(3 * textWidth + 150 , y , 100 , fontHeight + 18); currentUnit.reshape(3 * textWidth + 260 , y + 9 , textWidth , fontHeight); // Updates the vertical position for the next line y += fontHeight + 20; isWestElement = true; } } // If the last element is located in the left hand side of the panel if(! isWestElement) { // Updates the vertical position to have the correct panel's size y += fontHeight + 20; } // Resizes the panel resize(4 * textWidth + 260 , y - 2); } // getParameterNames() // ------------------- // Method which returns the names of parameters. public Vector getParameterNames() { return parameterNames; } // getParameterValues() // -------------------- // Method which returns the values of parameters. public Vector getParameterValues() { Vector values; int i; values = new Vector(); for(i = 0 ; i < textFields.size() ; i++) { values.addElement(((TextField)textFields.elementAt(i)).getText()); } return values; } // getPreviousParameterValues() // ---------------------------- // Method which returns the previous values of parameters. public Vector getPreviousParameterValues() { return previousParameterValues; } // setPreviousParameterValue() // --------------------------- // Method which sets the previous value of a parameter. public void setPreviousParameterValue(int i , Object element) { previousParameterValues.setElementAt(element , i); } // getNumberOfElements() // --------------------- // Method which returns the number of elements contained in the vector. public int getNumberOfElements() { return textFields.size(); } } // Class ColorSelector // ------------------- // This class represents a component that allows to choose the color of curves. class ColorSelector extends Panel { private CheckboxGroup checkboxGroup; private Checkbox checkboxes[]; // Constructor // ----------- ColorSelector(Color textColor) { int i; String colors[] = {"Black" , "Light Blue" , "Red" , "Green" , "Dark Blue" , "Grey"}; // Sets displaying parameters for the color selector setLayout(new GridLayout(2 , 3, 0 , 0)); // Sets color and font setForeground(textColor); setFont(new Font("TimesRoman" , Font.PLAIN , 14)); // Creates the checkbox group and checkboxes and places them checkboxGroup = new CheckboxGroup(); checkboxes = new Checkbox[colors.length]; checkboxes[0] = new Checkbox(colors[0] , checkboxGroup , true); add(checkboxes[0]); for(i = 1 ; i < checkboxes.length ; i++) { checkboxes[i] = new Checkbox(colors[i] , checkboxGroup , false); add(checkboxes[i]); } // Resizes the color selector resize(300 , 40); } // getColor() // ---------- // Method which returns the color selected. public char getColor() { char i; String selectedCheckboxLabel; i = 0; selectedCheckboxLabel = checkboxGroup.getCurrent().getLabel(); while(checkboxes[i].getLabel() != selectedCheckboxLabel) { i++; } return (char)(i + '1'); } } // Class OperationPanel // -------------------- // This class represents a component which controls the PV-Wave access (draw a curve and clear the graph). class OperationPanel extends Panel { private PVWaveController pvWaveController; private Button buttonDraw , buttonClear; // Constructor // ----------- OperationPanel(PVWaveController controller , Color buttonColor , Color labelColor) { Font font; FontMetrics fontMetrics; int buttonWidth , buttonHeight; // Associates a PV-Wave controller to the operation panel pvWaveController = controller; // Sets font font = new Font("TimesRoman" , Font.PLAIN , 14); fontMetrics = getFontMetrics(font); setFont(font); // Sets buttons' dimensions buttonWidth = fontMetrics.stringWidth("Clear") + 20; buttonHeight = fontMetrics.getHeight() + 10; // Creates the buttons buttonDraw = new Button("Draw"); buttonClear = new Button("Clear"); buttonClear.disable(); buttonDraw.setBackground(buttonColor); buttonDraw.setForeground(labelColor); buttonDraw.resize(buttonWidth , buttonHeight); buttonClear.setBackground(buttonColor); buttonClear.setForeground(labelColor); buttonClear.resize(buttonWidth , buttonHeight); // Desactivates automatic layout system setLayout(null); // Adds buttons in the panel add(buttonDraw); add(buttonClear); // Moves the buttons buttonDraw.move(0 , 0); buttonClear.move(130 - buttonWidth , 0); // Resizes the operation panel resize(130, buttonHeight); } // enableClear() // ------------- // Method which enables the clear button. public void enableClear() { buttonClear.enable(); } // disableClear() // -------------- // Method which disables the clear button. public void disableClear() { buttonClear.disable(); } // handleEvent() // ------------- // Method which sends a request to the PV-Wave controller. public boolean handleEvent(Event event) { if(event.id == Event.ACTION_EVENT) { // If it's a drawing request the PV-Wave controller draws the curve if(event.target == buttonDraw) { pvWaveController.draw(); } // If it's not a drawing request the PV-Wave controller clears the graph else { pvWaveController.clear(); } return true; } return super.handleEvent(event); } } // ****************** // * WINDOW CLASSES * // ****************** // Class ErrorWindow // ----------------- // This class describes a simple window displaying an error message. class ErrorWindow extends Frame { private Object callingElement; // Constructor // ----------- ErrorWindow(String message , Object element) { Panel messagePanel; Button OKButton; // Sets the calling element callingElement = element; // Activates a border layout system setLayout(new BorderLayout()); // Sets colors setBackground(Color.white); setForeground(Color.red); // Sets font setFont(new Font("TimesRoman" , Font.PLAIN , 14)); // Sets title setTitle("Error Window"); // Creates the button OK OKButton = new Button("OK"); // Creates a panel which will contain the error message messagePanel = new Panel(); messagePanel.setLayout(new BorderLayout()); messagePanel.add("North" , new Label(" ")); messagePanel.add("Center" , new Label(message , Label.CENTER)); messagePanel.add("South" , new Label(" ")); // Places the panel and the button in the window add("Center" , messagePanel); add("South" , OKButton); // Displays the window pack(); show(); } // handleEvent // ----------- // Method which defines operations when the user clicks on the button or when he destroys the window. public boolean handleEvent(Event event) { if((event.id == Event.WINDOW_DESTROY) || ((event.id == Event.ACTION_EVENT) && (event.target instanceof Button))) { // Closes the window dispose(); // Warns the calling element that the error window is killed if(callingElement instanceof Parser) { ((Parser)callingElement).killApplet(); } else if(callingElement instanceof CustomizableWindow) { ((CustomizableWindow)callingElement).killAndGoBack(); } else { ((PVWaveController)callingElement).killErrorWindow(); } return true; } return super.handleEvent(event); } } // Class CustomizableWindow // ------------------------ // This class is the model for all windows in which you can put elements. class CustomizableWindow extends Frame { private WindowController windowController; private Vector components , firstVisibleElementIndexes , lastVisibleElementIndexes; private int contentWidth , buttonWidth , buttonHeight, xGap , yGap , windowIndex; private Button buttonPrevious , buttonNext; private NavigatorButton buttonGoBack; private Path pathPanel; private WindowDescription windowDescription; private ErrorWindow errorWindow; // Constructors // ------------ CustomizableWindow(WindowController controller , Color specialButtonColor , Color specialLabelColor) { Font buttonFont; FontMetrics buttonFontMetrics; // Associates the window with its controller windowController = controller; // There is no error window errorWindow = null; // Sets the index of the first page to be displayed windowIndex = 0; // Creates the previous button and the next button in case of a too high content buttonPrevious = new Button("Previous"); buttonPrevious.disable(); buttonNext = new Button("Next"); buttonFont = new Font("TimesRoman" , Font.PLAIN , 14); buttonFontMetrics = getFontMetrics(buttonFont); buttonWidth = buttonFontMetrics.stringWidth("Previous") + 20; buttonHeight = buttonFontMetrics.getHeight() + 10; buttonPrevious.setFont(buttonFont); buttonNext.setFont(buttonFont); buttonPrevious.setBackground(specialButtonColor); buttonPrevious.setForeground(specialLabelColor); buttonNext.setBackground(specialButtonColor); buttonNext.setForeground(specialLabelColor); buttonPrevious.resize(buttonWidth , buttonHeight); buttonNext.resize(buttonWidth , buttonHeight); // Creates the button to go to the previous window buttonGoBack = new NavigatorButton("Go Back" , "Previous Window" , specialButtonColor , specialLabelColor); buttonGoBack.associateWindow(this); // Sets content's width contentWidth = buttonWidth * 2 + 10; // Desactivates the automatic layout system setLayout(null); } CustomizableWindow(WindowController controller , WindowDescription info) { // Creates an instance of CustomizableWindow by using the previous constructor this(controller , info.getSpecialButtonColor() , info.getSpecialLabelColor()); // Displays the window and its components displayComponents(info); } // displayComponent() // ------------------ // Method which displays the window and its components. public void displayComponents(WindowDescription info) { FontMetrics titleFontMetrics; Color backgroundColor; Component component; int i , maxiContentHeight , contentHeight , componentWidth , componentHeight; // Gets information from the WindowDescription's instance windowDescription = info; xGap = windowDescription.getXGap(); yGap = windowDescription.getYGap(); maxiContentHeight = windowDescription.getMaxContentHeight(); components = windowDescription.getComponents(); // If the width of the window's title + 70 is greater than the content's width titleFontMetrics = getFontMetrics(new Font("Helevtica" , Font.BOLD , 13)); if(titleFontMetrics.stringWidth(windowDescription.getWindowTitle()) + 70 > contentWidth) { // Updates content's width contentWidth = titleFontMetrics.stringWidth(windowDescription.getWindowTitle()) + 70; } // Sets background color setBackground(info.getBackgroundColor()); // Sets window title setTitle(windowDescription.getWindowTitle()); // Creates the two vectors which will contain the indexes of the first element and the last element to be displayed in a same page firstVisibleElementIndexes = new Vector(); lastVisibleElementIndexes = new Vector(); // The first element of the first page is the first element in the list of components firstVisibleElementIndexes.addElement(new Integer(0)); // Splits up the list of components in several pages (if it's necessary) contentHeight = 0; for(i = 0 ; i < components.size() ; i++) { component = (Component)components.elementAt(i); // If the component is a navigator button this associates the button to the window if(component instanceof NavigatorButton) { ((NavigatorButton)component).associateWindow(this); } // If the component is a navigator this associates the navigator to the window and // normalizes the size of the component if(component instanceof Navigator) { ((Navigator)component).associateWindow(this); ((Navigator)component).normalizeSize(); } // If the component is an input panel this normalizes the size of the component if(component instanceof ParameterInputPanel) { ((ParameterInputPanel)component).normalizeSize(); } // Gets component's dimensions componentWidth = component.size().width; componentHeight = component.size().height; // If the current component is too high to be displayed in the current window if(contentHeight + componentHeight + 2 * yGap > maxiContentHeight) { // If the current component's high + 2 * yGap is greater than the maximal content's height -> ERROR if((componentHeight + 2 * yGap > maxiContentHeight) && (errorWindow == null)) { errorWindow = new ErrorWindow("Error during display: A component is too high." , this); break; } // If the current component can be displayed in a page else { // Puts the current component in the next page lastVisibleElementIndexes.addElement(new Integer(i - 1)); firstVisibleElementIndexes.addElement(new Integer(i)); // Updates the content's height contentHeight = componentHeight + yGap; } } // If the current component can be displayed in the current page else { // Updates the content's height contentHeight += componentHeight + yGap; } // If the current component's width + 2 * xGap is greater than the window's width if(componentWidth + 2 * xGap > contentWidth) { // Updates content's width contentWidth = componentWidth + 2* xGap; } } // If there's no error if(errorWindow == null) { // The last component displayed in the last page is the last component of the components list lastVisibleElementIndexes.addElement(new Integer(i - 1)); // Displays the first page display(); } } // display() // --------- // Method which displays the page corresponding to the windowIndex. private void display() { Component component; int i , y , xSpace , xButtonPrevious , xButtonNext , componentWidth , componentHeight; // Removes all components contained in the window removeAll(); // Initializes the vertical position of the first component y = yGap + 45; // Displays all the elements of the current page for(i = ((Integer)firstVisibleElementIndexes.elementAt(windowIndex)).intValue() ; i <= ((Integer)lastVisibleElementIndexes.elementAt(windowIndex)).intValue() ; i++) { component = (Component)components.elementAt(i); // Gets component's dimensions componentWidth = component.size().width; componentHeight = component.size().height; // Puts the component in the window add(component); // If the component is a navigator button this updates the component's width if(component instanceof NavigatorButton) { component.reshape(5 + xGap , y , contentWidth - 2 * xGap , componentHeight); // 5 = border's width } // If the component is a non centered title this puts it in the left hand side of the window else if((component instanceof Title) && (! ((Title)component).isCentered())) { component.move(5 + xGap , y); // 5 = border's width } // If the component is not a navigator button or a title it moves the component in the center of the window else { component.move((contentWidth - componentWidth) / 2 + 5, y); // 5 = border's width } // Updates the vertical position for the next component y += componentHeight + yGap; } // Sets the new vertical position for the next component y += 10; // If there are several pages this adds the panel to browse in pages if(firstVisibleElementIndexes.size() > 1) { // Puts the buttons in the window add(buttonPrevious); add(buttonNext); // Caclulates the horizontal positions of the buttons xSpace = (contentWidth - 2 * (xGap + buttonWidth) - 10) / 2; xButtonPrevious = xGap + xSpace + 5; // 5 = border's width xButtonNext = xButtonPrevious + buttonWidth + 10; // Moves the buttons buttonPrevious.move(xButtonPrevious , y); buttonNext.move(xButtonNext , y); // Updates the vertical position for the path panel y += buttonHeight + 10; } // If the window is not a graph viewer or a legend window if(! (this instanceof GraphViewer || this instanceof LegendWindow)) { // Places the button "Go Back" add(buttonGoBack); buttonGoBack.move((contentWidth - buttonGoBack.size().width) / 2 + 5 , y); // Updates the vertical position for the path panel y += buttonGoBack.size().height + 10; } // Puts the path panel pathPanel = new Path(contentWidth - 4 , windowDescription.getWindowPath() , windowDescription.getForegroundColor()); add(pathPanel); pathPanel.move(7 , y); // Resizes the window resize(contentWidth + 10 , y + pathPanel.size().height + 5); // 5 = border's width , 10 = 2 * border's width // Displays the window pack(); show(); } // getDescription() // ---------------- // Method which returns the description of the window public WindowDescription getDescription() { return windowDescription; } // setPreviousWindowName() // ----------------------- // Method which sets the name of the previous window. public void setPreviousWindowName(String name) { windowDescription.setPreviousWindowName(name); } // getWindowController() // --------------------- // Method which returns the window controller. public WindowController getWindowController() { return windowController; } // kill() // ------ // Method which kills the window and all the associated windows. public void kill() { // If there's an error window this destroys it if(errorWindow != null) { errorWindow.dispose(); } // If the window is a control window this kills the PV-Wave controller if(this instanceof ControlWindow) { ((ControlWindow)this).killPVWaveController(); } // If the window is a graph viewer this kills the control window else if(this instanceof GraphViewer) { ((GraphViewer)this).getControlWindow().kill(); } // If the window is a legend window this kills the control window else if(this instanceof LegendWindow) { ((LegendWindow)this).getControlWindow().kill(); } // Destroys the window dispose(); } // killAndGoBack() // --------------- // Method which kills the window and goes back to the main menu. public void killAndGoBack() { // Kills the window kill(); // Goes back to the main menu if(windowController != null) { windowController.receiveMessage(null); } else { if(this instanceof GraphViewer) { ((GraphViewer)this).getControlWindow().getWindowController().receiveMessage(null); } // If the window is a legend window this kills the control window else if(this instanceof LegendWindow) { ((LegendWindow)this).getControlWindow().getWindowController().receiveMessage(null); } } } // handleEvent // ----------- // Method which manages events of the window. public boolean handleEvent(Event event) { // If the user wants to destroy the window this kills the window and all the associated windows if(event.id == Event.WINDOW_DESTROY) { killAndGoBack(); return true; } // If the user clicks on the previous or on the next button this displays the correct page if((event.id == Event.ACTION_EVENT) && (event.target instanceof Button)) { // If it's previous button if(event.target == buttonPrevious) { // Updates the page index windowIndex--; // Enables the next button buttonNext.enable(); // If the page is the first one this disables the previous button if(windowIndex == 0) { buttonPrevious.disable(); } } // If it's next button else { // Updates the page index windowIndex++; // Enables the previous button buttonPrevious.enable(); // If the page is the last one this disables the next button if(windowIndex == lastVisibleElementIndexes.size() - 1) { buttonNext.disable(); } } // Displays the page display(); return true; } return super.handleEvent(event); } } // Class MenuWindow // ---------------- // This class describes a window containing several navigator buttons to browse in the tutorial. class MenuWindow extends CustomizableWindow { private WindowDescription info; private Color buttonColor , labelColor; // Constructor // ----------- MenuWindow(WindowController controller , String windowName , String windowTitle , String path , Color backgroundColor , Color foregroundColor , Color colorOfButton , Color colorOfLabel , Color specialButtonColor , Color specialLabelColor , int contentHeightLimit) { // Creates an instance of CustomizableWindow super(controller , specialButtonColor , specialLabelColor); // Creates an instance of WindowDescription containing all the information required to describe the window info = new WindowDescription(); info.setWindowName(windowName); info.setWindowTitle(windowTitle); info.setWindowPath(path); info.setBackgroundColor(backgroundColor); info.setForegroundColor(foregroundColor); info.setSpecialButtonColor(specialButtonColor); info.setSpecialLabelColor(specialLabelColor); info.setXGap(0); info.setYGap(0); info.setMaxContentHeight(contentHeightLimit); // Sets colors for buttons buttonColor = colorOfButton; labelColor = colorOfLabel; } // addItem() // --------- // Method which adds a new button in the window. public void addItem(String label , String associatedWindowName) { info.addComponent(new NavigatorButton(label , associatedWindowName , buttonColor , labelColor)); } // display() // --------- // Method which displays the window. public void display() { displayComponents(info); } } // Class GraphViewer // ----------------- // This class describes a window used to display a PV-Wave graph. class GraphViewer extends CustomizableWindow { private WindowDescription info; private ControlWindow controlWindow; private GraphDescription graphDescription; // Constructor // ----------- GraphViewer(ControlWindow window , String path , GraphDescription description) { // Creates an instance of CustomizableWindow super(null , null , null); // Initializes instance variables controlWindow = window; graphDescription = description; // Creates a description of the window info = new WindowDescription(); info.setWindowTitle("Graph Viewer"); info.setWindowPath(path); info.setBackgroundColor(Color.white); info.setXGap(5); info.setYGap(5); info.setMaxContentHeight(graphDescription.getImageHeight() + 10); // Puts the blank image in the window instead of the real graph because there's no data info.addComponent(new Picture("blank.gif" , graphDescription.getImageWidth() , graphDescription.getImageHeight() , null , null , null, graphDescription.getVisualizer())); // Displays the window displayComponents(info); } // updateGraph() // ------------- // Method which updates the graph. public void updateGraph() { ((Picture)info.getComponents().elementAt(0)).flush(); ((Picture)info.getComponents().elementAt(0)).repaint(); } // putRealGraph() // -------------- // Method which puts the real graph in the window instead of the blank image. public void putRealGraph() { String path; // Gets path path = info.getWindowPath(); // Creates a description of the window info = new WindowDescription(); info.setWindowTitle("Graph Viewer"); info.setWindowPath(path); info.setBackgroundColor(Color.white); info.setXGap(5); info.setYGap(5); info.setMaxContentHeight(graphDescription.getImageHeight() + 10); info.addComponent(new Picture("PVWaveGraphs/" + graphDescription.getImageName() , graphDescription.getImageWidth() , graphDescription.getImageHeight() , null , null , null , graphDescription.getVisualizer())); // Displays the window displayComponents(info); } // getControlWindow() // ------------------ // Method which returns the control window which controls the graph viewer. public ControlWindow getControlWindow() { return controlWindow; } } // Class LegendWindow // ------------------ // This class is the model for windows displaying a legend for a graph. class LegendWindow extends CustomizableWindow { private WindowDescription info; private ControlWindow controlWindow; // Constructor // ----------- LegendWindow(ControlWindow window , String path) { // Creates an instance of CustomizableWindow super(null , null , null); // Associates the legend window to its control window controlWindow = window; // Sets information for the window info = new WindowDescription(); info.setWindowTitle("Legend"); info.setWindowPath(path); info.setBackgroundColor(Color.white); info.setXGap(2); info.setYGap(3); info.setMaxContentHeight(506); } // addInfoCurve() // -------------- // Method which adds a new line in the legend window. public void addInfoCurve(String infoCurve , Color color) { Vector lines; Text text; lines = new Vector(); lines.addElement(infoCurve); text = new Text(396 , color); text.putText(lines); info.addComponent(text); } // display() // --------- // Method which displays the window. public void display() { displayComponents(info); } // getControlWindow() // ------------------ // Method which returns the control window that controls the legend window. public ControlWindow getControlWindow() { return controlWindow; } } // Class ControlWindow // ------------------- // This class describes a window which allows the user to enter parameters for the graph. class ControlWindow extends CustomizableWindow { private PVWaveController pvWaveController; private OperationPanel operationPanel; private ColorSelector colorSelector; private WindowDescription info; private ParameterInputPanel parameterInputPanel , boundInputPanel; private Color titleColor , textColor; private int section; // Constructor // ----------- ControlWindow(WindowController controller , String windowName , String windowTitle , String path , Color backgroundColor , Color foregroundColor , Color colorOfTitle , Color textFieldBackgroundColor , Color colorOfText , Color buttonColor , Color buttonLabelColor , Color specialButtonColor , Color specialLabelColor , GraphDescription description , int contentHeightLimit) { // Creates an instance of CustomizableWindow super(controller , specialButtonColor , specialLabelColor); // Sets colors titleColor = colorOfTitle; textColor = colorOfText; // Initializes the index of the current section section = 0; // Puts information about the window info = new WindowDescription(); info.setWindowName(windowName); info.setWindowTitle(windowTitle); info.setWindowPath(path); info.setBackgroundColor(backgroundColor); info.setForegroundColor(foregroundColor); info.setSpecialButtonColor(specialButtonColor); info.setSpecialLabelColor(specialLabelColor); info.setXGap(10); info.setYGap(5); info.setMaxContentHeight(contentHeightLimit); info.addComponent(new MediumTitle("Equation Parameters" , true , Color.black)); // titleColor // Associates a PV-Wave controller pvWaveController = new PVWaveController(this , path , description); // Creates two input panels: one for equation parameters , one for bounds parameterInputPanel = new ParameterInputPanel(textFieldBackgroundColor , textColor); boundInputPanel = new ParameterInputPanel(textFieldBackgroundColor , textColor); // Creates a color selector colorSelector = new ColorSelector(textColor); // Creates an operation panel operationPanel = new OperationPanel(pvWaveController , buttonColor , buttonLabelColor); } // newSection() // ------------ // Method which changes the section. public void newSection() { // If it's the first section this adds the input panel containing equation parameters // and puts the title "Plotting Parameters" if(section == 0) { info.addComponent(parameterInputPanel); info.addComponent(new MediumTitle("Plotting Parameters" , true , titleColor)); } // If it's the second section this adds the input panel containing bounds, puts the color selector, // adds the title "Operations" and adds the operation panel if(section == 1) { info.addComponent(boundInputPanel); info.addComponent(colorSelector); info.addComponent(new MediumTitle("Operations" , true , titleColor)); info.addComponent(operationPanel); } // Updates the section section++; } // addInputPanel() // --------------- // Method which adds an input panel line. public void addInputPanel(String label , String unit) { // If it's the first section this adds the input panel line in the equation parameter input panel if(section == 0) { parameterInputPanel.addParameterInput(label , unit); } // If it's not the first section this adds the input panel line in the bound input panel else { boundInputPanel.addParameterInput(label , unit); } } // display() // --------- // Method which displays the window. public void display() { displayComponents(info); } // killPVWaveController() // ---------------------- // Method which kills the PV-Wave controller. public void killPVWaveController() { pvWaveController.kill(); } // enableClear() // ------------- // Method which enables the clear button of the operation panel. public void enableClear() { operationPanel.enableClear(); } // disableClear() // -------------- // Method which disables the clear button of the operation panel. public void disableClear() { operationPanel.disableClear(); } // getParameterInputPanel() // ------------------------ // Method which returns the input panel containing the equation parameters. public ParameterInputPanel getParameterInputPanel() { return (ParameterInputPanel)info.getComponents().elementAt(1); } // getBoundInputPanel() // -------------------- // Method which returns the input panel containing the bounds. public ParameterInputPanel getBoundInputPanel() { return (ParameterInputPanel)info.getComponents().elementAt(3); } // getColorSelector() // ------------------ // Method which returns the color selector. public ColorSelector getColorSelector() { return (ColorSelector)info.getComponents().elementAt(4); } } // **************** // * Descriptions * // **************** // Class WindowDescription // ----------------------- // This class describes a storing unit for information about a window. class WindowDescription { private String windowName , previousWindowName , windowTitle , windowPath; private Color backgroundColor , foregroundColor , specialButtonColor , specialLabelColor; private Vector components; private int xGap , yGap , maxContentHeight; // Constructor // ----------- WindowDescription() { components = new Vector(); } // setWindowName() // --------------- // Method which sets the window's name. public void setWindowName(String name) { windowName = name; } // setPreviousWindowName() // ----------------------- // Method which sets the name of the previous window. public void setPreviousWindowName(String name) { previousWindowName = name; } // setWindowTitle() // ---------------- // Method which sets the window's title. public void setWindowTitle(String title) { windowTitle = title; } // setWindowPath() // --------------- // Method which sets the window's path. public void setWindowPath(String path) { windowPath = path; } // setBackgroundColor() // -------------------- // Method which sets the background color of the window. public void setBackgroundColor(Color color) { backgroundColor = color; } // setForegroundColor() // -------------------- // Method which sets the foreground color of the window. public void setForegroundColor(Color color) { foregroundColor = color; } // setSpecialButtonColor() // ----------------------- // Method which sets the color of special buttons. public void setSpecialButtonColor(Color color) { specialButtonColor = color; } // setSpecialLabelColor() // ---------------------- // Method which sets the color of the labels used in special buttons. public void setSpecialLabelColor(Color color) { specialLabelColor = color; } // setXGap() // --------- // Method which sets the horizontal gap between the edges of the window and the widest component. public void setXGap(int gap) { xGap = gap; } // setYGap() // --------- // Method which sets the vertical gap between the edges of the window and the hightest component. public void setYGap(int gap) { yGap = gap; } // setMaxContentHeight() // --------------------- // Method which sets the limit height of window's content. public void setMaxContentHeight(int height) { maxContentHeight = height; } // addComponent() // -------------- // Method which adds a component to the description. public void addComponent(Component component) { components.addElement(component); } // getWindowName() // --------------- // Method which returns the window's name. public String getWindowName() { return windowName; } // getPreviousWindowName() // ----------------------- // Method which returns the name of the previous window. public String getPreviousWindowName() { return previousWindowName; } // getWindowTitle() // ---------------- // Method which returns the window's title. public String getWindowTitle() { return windowTitle; } // getWindowPath() // --------------- // Method which returns the window's path. public String getWindowPath() { return windowPath; } // getBackgroundColor() // -------------------- // Method which returns the background color of the window. public Color getBackgroundColor() { return backgroundColor; } // getForegroundColor() // -------------------- // Method which returns the foreground color of the window. public Color getForegroundColor() { return foregroundColor; } // getSpecialButtonColor() // ----------------------- // Method which returns the color of special buttons. public Color getSpecialButtonColor() { return specialButtonColor; } // getSpecialLabelColor() // ---------------------- // Method which returns the color of the labels used in special buttons. public Color getSpecialLabelColor() { return specialLabelColor; } // getXGap() // --------- // Method which returns the horizontal gap between the edges of the window and the widest component. public int getXGap() { return xGap; } // getYGap() // --------- // Method which returns the vertical gap between the edges of the window and the hightest component public int getYGap() { return yGap; } // getMaxContentHeight() // --------------------- // Method which returns the limit height of window's content. public int getMaxContentHeight() { return maxContentHeight; } // getComponents() // --------------- // Method which returns the vector containing all the components. public Vector getComponents() { return components; } } // Class GraphDescription // ---------------------- // This class gives information for a PV-Wave graph. class GraphDescription { String graphTitle, xTitle , yTitle , xVariable , yVariable , imageName; int imageWidth , imageHeight; Visualizer visualizer; Vector equations; // Constructor // ----------- GraphDescription(String title , String xLabel , String yLabel , String x , String y , int width , int height , Visualizer applet) { // Sets instance variables graphTitle = title; xTitle = xLabel; yTitle = yLabel; xVariable = x; yVariable = y; imageWidth = width; imageHeight = height; visualizer = applet; // Creates a vector which will contain the equations to evaluate before plotting equations = new Vector(); } // setImageName() // -------------- // Method which sets the name of the image. public void setImageName(String name) { imageName = name; } // addEquation() // ------------- // Method which adds an equation into the list of equations. public void addEquation(String equation) { equations.addElement(equation); } // getGraphTitle() // --------------- // Method which returns the title of the graph. public String getGraphTitle() { return graphTitle; } // getXTitle() // ----------- // Method which returns the title of the x axis. public String getXTitle() { return xTitle; } // getYTitle() // ----------- // Method which returns the title of the y axis. public String getYTitle() { return yTitle; } // getXVariable() // -------------- // Method which returns the variable used for the x coordinates. public String getXVariable() { return xVariable; } // getYVariable() // -------------- // Method which returns the variable used for the y coordinates. public String getYVariable() { return yVariable; } // getImageName() // -------------- // Method which returns the name of the image. public String getImageName() { return imageName; } // getImageWidth() // --------------- // Method which returns the image's width. public int getImageWidth() { return imageWidth; } // getImageHeight() // ---------------- // Method which returns the image's height. public int getImageHeight() { return imageHeight; } // getVisualizer() // --------------- // Method which returns the applet. public Visualizer getVisualizer() { return visualizer; } // getEquations() // -------------- // Method which returns the list of equations. public Vector getEquations() { return equations; } } // *************** // * Controllers * // *************** // Class WindowController // ---------------------- // This class is in charge of the management of windows. class WindowController { private Visualizer applet; private Parser parser; private CustomizableWindow currentWindow; private Vector windowDescriptions; // Constructor // ----------- WindowController(Visualizer visualizer) { applet = visualizer; windowDescriptions = new Vector(); } // setParser() // ----------- // Method which sets the parser of the window controller. public void setParser(Parser descriptionFileParser) { parser = descriptionFileParser; } // handleWindow() // -------------- // Method which declares the first window to the controller. public void handleWindow(CustomizableWindow window) { currentWindow = window; if(currentWindow != null) { currentWindow.setPreviousWindowName(null); windowDescriptions.addElement(currentWindow.getDescription()); } } // receiveMessage() // ---------------- // Method which manages the display of windows. public void receiveMessage(String nextWindowName) { CustomizableWindow previousWindow; int i; if(nextWindowName != null) { previousWindow = currentWindow; // If the button "Go Back" wasn't pressed if(! nextWindowName.equals("Previous Window")) { // Searches if the window has already been displayed for(i = 0 ; i < windowDescriptions.size() ; i++) { if(((WindowDescription)windowDescriptions.elementAt(i)).getWindowName().equals(nextWindowName)) { break; } } // If it has been displayed if(i != windowDescriptions.size()) { currentWindow = new CustomizableWindow(this , (WindowDescription)windowDescriptions.elementAt(i)); } // If it has not been displayed else { currentWindow = parser.parseWindow(nextWindowName , currentWindow.getDescription().getWindowPath() + parser.getTitle(nextWindowName) + "/ "); currentWindow.setPreviousWindowName(previousWindow.getDescription().getWindowName()); if(! (currentWindow instanceof ControlWindow)) { windowDescriptions.addElement(currentWindow.getDescription()); } } } // If the button "Go Back" was pressed else { // If the window is not the first one if(currentWindow.getDescription().getPreviousWindowName() != null) { for(i = 0 ; i < windowDescriptions.size() ; i++) { if(((WindowDescription)windowDescriptions.elementAt(i)).getWindowName().equals(currentWindow.getDescription().getPreviousWindowName())) { break; } } currentWindow = new CustomizableWindow(this , (WindowDescription)windowDescriptions.elementAt(i)); } // If the window is the first one else { // Enables the main menu applet.enableButtons(); } } // Destroys the window previousWindow.kill(); } // If no window is handled by the controller else { // Enables the main menu applet.enableButtons(); } } // killWindows() // ------------- // Method which kills all the windows associated to the current window. public void killWindows() { if(currentWindow != null) { currentWindow.kill(); } } } // Class PVWaveController // ---------------------- // This class describes the interface with PV-Wave. class PVWaveController { private ControlWindow callingWindow; private GraphViewer graphViewer; private LegendWindow legendWindow; private GraphDescription graphDescription; private String windowPath , id; private ErrorWindow errorWindow; private Color plottingColors[]; private boolean isGoodConnection , isInitialized , isFirstDraw , isRealGraph; private Socket socket; private DataInputStream inputStream; private PrintStream outputStream; // Constructor // ----------- PVWaveController(ControlWindow window , String path , GraphDescription description) { Date date; // Sets the calling window (control window) callingWindow = window; // Sets window's path windowPath = path; // Sets the graph's description graphDescription = description; // Sets the name of the image date = new Date(); id = new StringBuffer().append(date.getHours()).append(date.getMinutes()).append(date.getSeconds()).append(".gif").toString(); graphDescription.setImageName(id); // Sets flags for the plotting isGoodConnection = false; isInitialized = false; isFirstDraw = true; isRealGraph = false; // Sets the palette plottingColors = new Color[6]; plottingColors[0] = new Color(0 , 0 , 0); plottingColors[1] = new Color(43 , 158 , 230); plottingColors[2] = new Color(234 , 25 , 15); plottingColors[3] = new Color(6 , 144 , 38); plottingColors[4] = new Color(0 , 0 , 255); plottingColors[5] = new Color(125 , 125 , 125); // Creates a graph viewer graphViewer = new GraphViewer(callingWindow , windowPath , graphDescription); // There's no legend window , there's no error window legendWindow = null; errorWindow = null; } // disconnect() // ------------ // Method which stops the PV-Wave server. public void disconnect() { if(isGoodConnection) { openConnection(); sendCommand(id , "exit"); closeConnection(); } } // killErrorWindow() // ----------------- // Method which desactivates the error window. public void killErrorWindow() { errorWindow = null; } // kill() // ------ // Method which kills the graph viewer, the legend window, the error window and stops the server. public void kill() { graphViewer.dispose(); if(legendWindow != null) { legendWindow.dispose(); } if(errorWindow != null) { errorWindow.dispose(); } disconnect(); } // checkParameters() // ----------------- // Method which checks if parameters are numbers. private char[] checkParameters(ParameterInputPanel parameterInputPanel) { int i , j; char character; char nbDots[]; Vector parameterValues , parameterNames; // Creates an array that will contain the number of dots of parameters nbDots = new char[parameterInputPanel.getNumberOfElements()]; // Gets parameters' names and values parameterValues = parameterInputPanel.getParameterValues(); parameterNames = parameterInputPanel.getParameterNames(); for(i = 0 ; i < parameterValues.size() ; i++) { // If a parameter is a void parameter -> ERROR if((((String)parameterValues.elementAt(i)).equals("")) && (errorWindow == null)) { errorWindow = new ErrorWindow("Error in the value of '" + (String)parameterNames.elementAt(i) + "': Void parameter." , this); return nbDots; } // Initializes the default number of dots nbDots[i] = 0; for(j = 0 ; j < ((String)parameterValues.elementAt(i)).length() ; j++) { character = ((String)parameterValues.elementAt(i)).charAt(j); if(character == '.') { // If the first or the last character is a dot -> ERROR if((j == 0 || j == ((String)parameterValues.elementAt(i)).length() - 1) && (errorWindow == null)) { errorWindow = new ErrorWindow("Error in the value of '" + (String)parameterNames.elementAt(i) + "': Wrong position for a dot." , this); return nbDots; } // If the first or the last character is not a dot else { // Updates the number of dots of the current parameter nbDots[i]++; // If there are more than 1 dot -> ERROR if((nbDots[i] > 1) && (errorWindow == null)) { errorWindow = new ErrorWindow("Error in the value of '" + (String)parameterNames.elementAt(i) + "': Too many dots." , this); return nbDots; } } } else { // If a '-' is not at the beginning of a parameter -> ERROR if((character == '-') && (j != 0) && (errorWindow == null)) { errorWindow = new ErrorWindow("Error in the value of '" + (String)parameterNames.elementAt(i) + "': Wrong place for '-'." , this); return nbDots; } // If there's a dot after a '-' -> ERROR if((character == '-') && ((String)parameterValues.elementAt(i)).charAt(j+1) == '.' && (errorWindow == null)) { errorWindow = new ErrorWindow("Error in the value of '" + (String)parameterNames.elementAt(i) + "': Wrong place for dot." , this); return nbDots; } // If the character is not a digit or a '-' -> error if((character != '-') && (! Character.isDigit(character)) && (errorWindow == null)) { errorWindow = new ErrorWindow("Error in the value of '" + (String)parameterNames.elementAt(i) + "': Wrong character." , this); return nbDots; } } } } return nbDots; } // openConnection() // ---------------- // Method which opens the connection to the PV-Wave server. private void openConnection() { try { // Opens the connection with the server on port 7000 socket = new Socket("www.jwave.vt.edu" , 7000); // Opens streams outputStream = new PrintStream(socket.getOutputStream()); inputStream = new DataInputStream(socket.getInputStream()); isGoodConnection = true; } catch(IOException exception) { errorWindow = new ErrorWindow("Error in connection to PV-WAVE server: Impossible to connect to the server." , this); } } // closeConnection() // ----------------- // Method which closes the connection to the server. private void closeConnection() { try { outputStream.close(); inputStream.close(); socket.close(); } catch(IOException exception) { errorWindow = new ErrorWindow("Error in connection to PV-WAVE server: Impossible to close the connection to the server." , this); } } // sendCommand() // ------------- // Method which sends a command to PV-Wave. private void sendCommand(String id , String command) { String message; try { outputStream.println(id + "&" + command); while((message = inputStream.readLine()) == null) { ; } System.out.println(message); // If the PV-Wave server sends back a REDRAW message if(message.startsWith("WAVE> PLOT") || message.startsWith("WAVE> OPLOT")) { // If the graph is the blank graph this changes the graph if(! isRealGraph) { graphViewer.putRealGraph(); graphViewer.updateGraph(); isRealGraph = true; } // If the graph is the correct graph this updates it else { graphViewer.updateGraph(); } } } // If an error has occured during the connection -> ERROR catch(Exception exception) { errorWindow = new ErrorWindow("Error in connection to PV-WAVE server: Impossible to connect to the server." , this); } } // clear() // ------- // Method which clears the graph. public void clear() { StringBuffer command; char color; command = new StringBuffer(); color = callingWindow.getColorSelector().getColor(); openConnection(); // If the connection is good this sends the clear command to PV-Wave if(isGoodConnection) { command.append("PLOT,"); command.append(graphDescription.getXVariable()); command.append(','); command.append(graphDescription.getYVariable()); command.append(",/Nodata,Title='"); command.append(graphDescription.getGraphTitle()); command.append("',XTitle='"); command.append(graphDescription.getXTitle()); command.append("',YTitle='"); command.append(graphDescription.getYTitle()); command.append("',Color="); command.append(color); sendCommand(id , command.toString()); closeConnection(); legendWindow.dispose(); callingWindow.disableClear(); isFirstDraw = true; } } // draw() // ------ // Method which draws a curve. public void draw() { Vector parameterNames , parameterValues , previousParameterValues , bounds , previousBounds; String boundVariableName[] = {"first_x_value" , "last_x_value"}; String currentValue; StringBuffer command , infoCurve; int i; char color; char nbDotsOfParameters[] , nbDotsOfBounds[]; boolean isNewParameter , isNewBound; // Checks equation parameters nbDotsOfParameters = new char[callingWindow.getParameterInputPanel().getNumberOfElements()]; nbDotsOfParameters = checkParameters(callingWindow.getParameterInputPanel()); // Checks bounds nbDotsOfBounds = new char[2]; nbDotsOfBounds = checkParameters(callingWindow.getBoundInputPanel()); // Checks the order of bounds bounds = callingWindow.getBoundInputPanel().getParameterValues(); if(errorWindow == null) { if((errorWindow == null) && (new Double((String)bounds.elementAt(0)).doubleValue() >= new Double((String)bounds.elementAt(1)).doubleValue())) { errorWindow = new ErrorWindow("Error in the values of bounds: First x value >= Last x value." , this); } } // Sets the palette, the number for points for the draw, the style of the x and y axis, creates the // vector used to define the clipping area openConnection(); if(errorWindow == null) { // Gets the information we need to plot parameterNames = callingWindow.getParameterInputPanel().getParameterNames(); parameterValues = callingWindow.getParameterInputPanel().getParameterValues(); previousParameterValues = callingWindow.getParameterInputPanel().getPreviousParameterValues(); previousBounds = callingWindow.getBoundInputPanel().getPreviousParameterValues(); color = callingWindow.getColorSelector().getColor(); // There is no new bound isNewBound = false; for(i = 0 ; i < bounds.size() ; i++) { currentValue = (String)bounds.elementAt(i); if(! currentValue.equals((String)previousBounds.elementAt(i))) { // There is a new bound isNewBound = true; // Updates previous bound value callingWindow.getBoundInputPanel().setPreviousParameterValue(i , currentValue); } command = new StringBuffer(); command.append(boundVariableName[i]); command.append('='); command.append(currentValue); // If the bound is not a float number this converts it if(nbDotsOfBounds[i] == 0) { command.append(".0"); } // Sends the command sendCommand(id , command.toString()); } sendCommand(id , "step=(last_x_value-first_x_value)/(nb_points-1)"); command = new StringBuffer(); command.append(graphDescription.getXVariable()); command.append("=DINDGEN(nb_points)"); sendCommand(id , command.toString()); command = new StringBuffer(); command.append(graphDescription.getXVariable()); command.append('='); command.append(graphDescription.getXVariable()); command.append("*step+first_x_value"); sendCommand(id , command.toString()); // There's no new parameter isNewParameter = false; // Creates the line for the legend infoCurve = new StringBuffer(); for(i = 0 ; i < parameterValues.size() ; i++) { currentValue = (String)parameterValues.elementAt(i); if(! currentValue.equals((String)previousParameterValues.elementAt(i))) { // There is a new parameter isNewParameter = true; // Updates previous bound value callingWindow.getParameterInputPanel().setPreviousParameterValue(i , currentValue); } command = new StringBuffer(); command.append((String)parameterNames.elementAt(i)); command.append('='); command.append(currentValue); infoCurve.append((String)parameterNames.elementAt(i)); infoCurve.append('='); infoCurve.append(currentValue); // If the parameter is not a float number this converts it if(nbDotsOfParameters[i] == 0) { command.append(".0"); infoCurve.append(".0"); } if(i != parameterValues.size() - 1) { infoCurve.append(' '); } // Sends the command sendCommand(id , command.toString()); } // Evaluates equations for(i = 0 ; i < graphDescription.getEquations().size() ; i++) { sendCommand(id , (String)graphDescription.getEquations().elementAt(i)); } // If only parameters have changed this adds a curve to the graph if(! isNewBound && isNewParameter && ! isFirstDraw) { command = new StringBuffer(); command.append("OPLOT,"); command.append(graphDescription.getXVariable()); command.append(','); command.append(graphDescription.getYVariable()); command.append(",Clip=clipping_area,Color="); command.append(color); sendCommand(id , command.toString()); } else { // Sets the clipping area for the OPLOT function sendCommand(id , "clipping_area(0)=first_x_value"); sendCommand(id , "clipping_area(2)=last_x_value"); command = new StringBuffer(); command.append("clipping_area(1)=MIN("); command.append(graphDescription.getYVariable()); command.append(')'); sendCommand(id , command.toString()); command = new StringBuffer(); command.append("clipping_area(3)=MAX("); command.append(graphDescription.getYVariable()); command.append(')'); sendCommand(id , command.toString()); sendCommand(id , "PRINT,clipping_area(0)"); sendCommand(id , "PRINT,clipping_area(1)"); sendCommand(id , "PRINT,clipping_area(2)"); sendCommand(id , "PRINT,clipping_area(3)"); command = new StringBuffer(); command.append("PLOT,"); command.append(graphDescription.getXVariable()); command.append(','); command.append(graphDescription.getYVariable()); command.append(",Title='"); command.append(graphDescription.getGraphTitle()); command.append("',XTitle='"); command.append(graphDescription.getXTitle()); command.append("',YTitle='"); command.append(graphDescription.getYTitle()); command.append("',Color="); command.append(color); sendCommand(id , command.toString()); } closeConnection(); // If it's the first draw or if bounds have changed if(isFirstDraw || isNewBound) { if(legendWindow != null) { legendWindow.dispose(); } // Creates a new legend window legendWindow = new LegendWindow(callingWindow , windowPath); // Enables the clear button of the operation panel callingWindow.enableClear(); // This is not the first draw isFirstDraw = false; } // Adds a line to the legend window and displays the window legendWindow.addInfoCurve(infoCurve.toString() , plottingColors[color - '1']); legendWindow.display(); } } } // ********** // * Parser * // ********** // Class Parser // ------------ // This class provides ways to get information from the file which describes the content of the tutorial. class Parser { private Socket socket; private DataInputStream inputStream; private PrintStream outputStream; private WindowController windowController; private DefaultValues defaultValues; private Visualizer applet; private int graphWidth , graphHeight; private boolean isAbleToParse; private ErrorWindow errorWindow; // Constructor // ----------- Parser(WindowController controller , int imageWidth , int imageHeight , Visualizer visualizer) { // Sets the parameters concerning the graph image graphWidth = imageWidth; graphHeight = imageHeight; // Sets the window controller windowController = controller; // Sets the applet applet = visualizer; // It's possible to parse the file isAbleToParse = true; // Gets the default values sendRequest("DEFAULTVALUES"); defaultValues = parseDefaultValues(); // Builds the main menu sendRequest("MAINMENU"); parseMainMenu(); } // sendRequest() // ------------- // Method which sends a request to the server. public void sendRequest(String queryKey) { try { // Opens the connection with the server on port 8000 socket = new Socket("www.jwave.vt.edu" , 8000); // Opens streams outputStream = new PrintStream(socket.getOutputStream()); inputStream = new DataInputStream(socket.getInputStream()); // Sends query key outputStream.println(queryKey); } // If a problem occured catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; } } // getTitle() // ---------- // Method which returns the title of a window. public String getTitle(String windowName) { String windowTitle; try { // Sends the request to the server sendRequest("TITLE " + windowName); // Gets the title windowTitle = inputStream.readLine(); // Closes the connection outputStream.close(); inputStream.close(); socket.close(); return windowTitle; } // If there's a problem catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; return null; } } // killApplet() // voir si on ne peut pas l'executer directement du handle event // ------------ // Method which closes all windows and ends the applet. public void killApplet() { // Destroys the error window errorWindow.dispose(); // Destroys current windows handled by the controller windowController.killWindows(); // Ends the applet System.exit(1); } // parseDefaultValues() // -------------------- // Method which initializes default values used to describe a window. private DefaultValues parseDefaultValues() { String currentLine , keyword; StringTokenizer stringTokenizer; DefaultValues defaultValues; try { if(isAbleToParse) { defaultValues = new DefaultValues(); while((currentLine = inputStream.readLine()) != null) { // If there's no section about default values if(currentLine.equals("Not Found")) { break; } stringTokenizer = new StringTokenizer(currentLine , " "); keyword = stringTokenizer.nextToken(); // Sets default background color if(keyword.equals("BACKGROUNDCOLOR")) { defaultValues.setBackgroundColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets default foreground color else if(keyword.equals("FOREGROUNDCOLOR")) { defaultValues.setForegroundColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets the default color of titles else if(keyword.equals("TITLECOLOR")) { defaultValues.setTitleColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets the default color of texts else if(keyword.equals("TEXTCOLOR")) { defaultValues.setTextColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets the default color of buttons else if(keyword.equals("BUTTONCOLOR")) { defaultValues.setButtonColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets the default color of labels else if(keyword.equals("LABELCOLOR")) { defaultValues.setLabelColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets the default color of special buttons else if(keyword.equals("SPECIALBUTTONCOLOR")) { defaultValues.setSpecialButtonColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets the default color of labels for special buttons else if(keyword.equals("SPECIALLABELCOLOR")) { defaultValues.setSpecialLabelColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets the default color of text fields else if(keyword.equals("TEXTFIELDCOLOR")) { defaultValues.setTextFieldColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets default text's width else if(keyword.equals("TEXTWIDTH")) { defaultValues.setTextWidth(Integer.parseInt(stringTokenizer.nextToken())); } // Sets the default limit of the height of a window's content else if(keyword.equals("MAXCONTENTHEIGHT")) { defaultValues.setMaxContentHeight(Integer.parseInt(stringTokenizer.nextToken())); } // Sets the default horizontal gap else if(keyword.equals("XGAP")) { defaultValues.setXGap(Integer.parseInt(stringTokenizer.nextToken())); } // Sets the default vertical gap else { defaultValues.setYGap(Integer.parseInt(stringTokenizer.nextToken())); } } // Closes the connection outputStream.close(); inputStream.close(); socket.close(); return defaultValues; } return null; } // If there's a problem catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; return null; } } // parseMainMenu() // --------------- // Method which creates the main menu in the web browser according to the information contained in // the file. private void parseMainMenu() { String currentLine , keyword; int i , y , appletWidth , appletHeight , buttonWidth; StringTokenizer stringTokenizer , buttonDescriptionStringTokenizer; Color backgroundColor , buttonColor , labelColor; Title title; Vector navigatorButtons; NavigatorButton button; try { if(isAbleToParse) { backgroundColor = defaultValues.getBackgroundColor(); buttonColor = defaultValues.getButtonColor(); labelColor = defaultValues.getLabelColor(); title = null; button = null; navigatorButtons = new Vector(); // Sets vertical position for the title "Visualizer" y = 5; // Gets applet's dimensions appletWidth = applet.size().width; appletHeight = applet.size().height; // Sets buttons' width buttonWidth = 0; // Puts title in the applet title = new LargeTitle("Visualizer" , true , Color.black); applet.add(title); title.move((appletWidth - title.size().width) / 2 , y); // Updates vertical position for the title defined by the user y += title.size().height + 20; while((currentLine = inputStream.readLine()) != null) { stringTokenizer = new StringTokenizer(currentLine , " "); keyword = stringTokenizer.nextToken(); // Sets background color if(keyword.equals("BACKGROUNDCOLOR")) { backgroundColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets color of buttons else if(keyword.equals("BUTTONCOLOR")) { buttonColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets color of labels else if(keyword.equals("LABELCOLOR")) { labelColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Creates the title else if(keyword.equals("TITLE")) { title = parseTitle(); applet.add(title); title.move((appletWidth - title.size().width) / 2 , y); y += title.size().height + 10; } // Creates a navigator button and stores it in the vector else { buttonDescriptionStringTokenizer = new StringTokenizer(currentLine , "&"); button = new NavigatorButton(buttonDescriptionStringTokenizer.nextToken() , buttonDescriptionStringTokenizer.nextToken() , buttonColor , labelColor , applet); navigatorButtons.addElement(button); if(button.size().width > buttonWidth) { buttonWidth = button.size().width; } } } applet.setBackground(backgroundColor); for(i = 0 ; i < navigatorButtons.size() ; i++) { button = (NavigatorButton)navigatorButtons.elementAt(i); applet.add(button); button.reshape((appletWidth - buttonWidth) / 2 , y , buttonWidth , button.size().height); y += button.size().height; } // Closes the connection outputStream.close(); inputStream.close(); socket.close(); } } // If there's a problem catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; } } // parseWindow() // ------------- // Method which creates a window thanks to the information contained in the description file. public CustomizableWindow parseWindow(String name , String path) { WindowDescription windowDescription; String windowType , currentLine , keyword; StringTokenizer stringTokenizer; int i , maxContentHeight; try { if(isAbleToParse) { // Sends the request to the server sendRequest(name); // Gets the type of the window windowType = inputStream.readLine(); // If the window is a menu window this creates a menu window if(windowType.equals("MENU")) { return parseMenu(path); } // If the window is a plotting system this creates a plotting system else if(windowType.equals("PLOTTINGSYSTEM")) { return parsePlottingSystem(path); } // If the window is a special window this builds it else { windowDescription = new WindowDescription(); windowDescription.setBackgroundColor(defaultValues.getBackgroundColor()); windowDescription.setForegroundColor(defaultValues.getForegroundColor()); windowDescription.setXGap(defaultValues.getXGap()); windowDescription.setYGap(defaultValues.getYGap()); maxContentHeight = defaultValues.getMaxContentHeight(); while((currentLine = inputStream.readLine()) != null) { stringTokenizer = new StringTokenizer(currentLine , " "); keyword = stringTokenizer.nextToken(); // Sets background color if(keyword.equals("BACKGROUNDCOLOR")) { windowDescription.setBackgroundColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets foreground color else if(keyword.equals("FOREGROUNDCOLOR")) { windowDescription.setForegroundColor(new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()))); } // Sets the name of the window else if(keyword.equals("NAME")) { windowDescription.setWindowName(stringTokenizer.nextToken()); } // Sets the title of the window else if(keyword.equals("WINDOWTITLE")) { windowDescription.setWindowTitle(currentLine.substring(12)); } // Sets the limit of the height of window's content else if(keyword.equals("MAXCONTENTHEIGHT")) { maxContentHeight = Integer.parseInt(stringTokenizer.nextToken()); } // Sets the horizontal gap else if(keyword.equals("XGAP")) { windowDescription.setXGap(Integer.parseInt(stringTokenizer.nextToken())); } // Sets the vertical gap else if(keyword.equals("YGAP")) { windowDescription.setYGap(Integer.parseInt(stringTokenizer.nextToken())); } // Adds a title in the window's description else if(keyword.equals("TITLE")) { windowDescription.addComponent(parseTitle()); } // Adds a text in the window's description else if(keyword.equals("TEXT")) { windowDescription.addComponent(parseText()); } // Adds a navigator in the window's description else if(keyword.equals("NAVIGATOR")) { windowDescription.addComponent(parseNavigator()); } // Adds a picture in the window's description else { windowDescription.addComponent(parsePicture()); } } windowDescription.setWindowPath(path); // Closes the connection outputStream.close(); inputStream.close(); socket.close(); windowDescription.setSpecialButtonColor(defaultValues.getSpecialButtonColor()); windowDescription.setSpecialLabelColor(defaultValues.getSpecialLabelColor()); windowDescription.setMaxContentHeight(maxContentHeight); return new CustomizableWindow(windowController , windowDescription); } } return null; } // If there's a problem catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; return null; } } // parseMenu() // ----------- // Method which creates a menu window thanks to the information contained in the description file. private MenuWindow parseMenu(String path) { String currentLine , keyword , windowName , windowTitle; StringTokenizer stringTokenizer , buttonDescriptionStringTokenizer; int maxContentHeight; boolean isFirstButton; Color backgroundColor , foregroundColor , buttonColor , labelColor; MenuWindow menuWindow; try { if(isAbleToParse) { windowName = null; windowTitle = null; backgroundColor = defaultValues.getBackgroundColor(); foregroundColor = defaultValues.getForegroundColor(); buttonColor = defaultValues.getButtonColor(); labelColor = defaultValues.getLabelColor(); maxContentHeight = defaultValues.getMaxContentHeight(); menuWindow = null; isFirstButton = true; while((currentLine = inputStream.readLine()) != null) { stringTokenizer = new StringTokenizer(currentLine , " "); keyword = stringTokenizer.nextToken(); // Sets background color if(keyword.equals("BACKGROUNDCOLOR")) { backgroundColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets foreground color else if(keyword.equals("FOREGROUNDCOLOR")) { foregroundColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets the color of buttons else if(keyword.equals("BUTTONCOLOR")) { buttonColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets color of labels else if(keyword.equals("LABELCOLOR")) { labelColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets window's name else if(keyword.equals("NAME")) { windowName = stringTokenizer.nextToken(); } // Sets window's title else if(keyword.equals("WINDOWTITLE")) { windowTitle = currentLine.substring(12); } // Sets the upper limit of the content's height else if(keyword.equals("MAXCONTENTHEIGHT")) { maxContentHeight = Integer.parseInt(stringTokenizer.nextToken()); } // Creates buttons else { if(isFirstButton) { menuWindow = new MenuWindow(windowController , windowName , windowTitle , path , backgroundColor , foregroundColor , buttonColor , labelColor , defaultValues.getSpecialButtonColor() , defaultValues.getSpecialLabelColor() , maxContentHeight); isFirstButton = false; } buttonDescriptionStringTokenizer = new StringTokenizer(currentLine , "&"); menuWindow.addItem(buttonDescriptionStringTokenizer.nextToken() , buttonDescriptionStringTokenizer.nextToken()); } } menuWindow.display(); // Closes the connection outputStream.close(); inputStream.close(); socket.close(); return menuWindow; } return null; } // If there's a problem catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; return null; } } // parsePlottingSystem() // --------------------- // Method which creates a plotting system (control window + graph viewer + legend window) // thanks to the information contained in the description file. private ControlWindow parsePlottingSystem(String path) { String currentLine , keyword , windowName , windowTitle , graphTitle , xTitle , yTitle , xVariable , yVariable , xUnit; StringTokenizer stringTokenizer; int maxContentHeight; Color backgroundColor , foregroundColor , titleColor , textColor , textFieldColor , buttonColor , labelColor; GraphDescription graphDescription; ControlWindow controlWindow; try { if(isAbleToParse) { windowName = null; windowTitle = null; graphTitle = null; xTitle = null; yTitle = null; xVariable = null; yVariable = null; xUnit = null; backgroundColor = defaultValues.getBackgroundColor(); foregroundColor = defaultValues.getForegroundColor(); titleColor = defaultValues.getTitleColor(); textColor = defaultValues.getTextColor(); textFieldColor = defaultValues.getTextFieldColor(); buttonColor = defaultValues.getButtonColor(); labelColor = defaultValues.getLabelColor(); maxContentHeight = defaultValues.getMaxContentHeight(); graphDescription = null; controlWindow = null; while((currentLine = inputStream.readLine()) != null) { stringTokenizer = new StringTokenizer(currentLine , " "); keyword = stringTokenizer.nextToken(); // Sets background color if(keyword.equals("BACKGROUNDCOLOR")) { backgroundColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets foreground color else if(keyword.equals("FOREGROUNDCOLOR")) { foregroundColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets the color of titles else if(keyword.equals("TITLECOLOR")) { titleColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets the color of texts else if(keyword.equals("TEXTCOLOR")) { textColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets the color of text fields else if(keyword.equals("TEXTFIELDCOLOR")) { textFieldColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets the color of buttons else if(keyword.equals("BUTTONCOLOR")) { buttonColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets the color of labels else if(keyword.equals("LABELCOLOR")) { labelColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets window's name else if(keyword.equals("NAME")) { windowName = stringTokenizer.nextToken(); } // Sets window's title else if(keyword.equals("WINDOWTITLE")) { windowTitle = currentLine.substring(12); } // Sets the limit height for the content of the window else if(keyword.equals("MAXCONTENTHEIGHT")) { maxContentHeight = Integer.parseInt(stringTokenizer.nextToken()); } // Sets graph's title else if(keyword.equals("GRAPHTITLE")) { graphTitle = currentLine.substring(11); } // Sets the title of the x axis else if(keyword.equals("XTITLE")) { xTitle = currentLine.substring(7); } // Sets the title of the y axis else if(keyword.equals("YTITLE")) { yTitle = currentLine.substring(7); } // Sets the variable used for the x axis else if(keyword.equals("XVARIABLE")) { xVariable = stringTokenizer.nextToken(); } // Sets the variable used for the y axis else if(keyword.equals("YVARIABLE")) { yVariable = stringTokenizer.nextToken(); } // Sets the unit of the variable used for the x axis else if(keyword.equals("XVARIABLEUNIT")) { xUnit = stringTokenizer.nextToken(); } // Gets equations else if(keyword.equals("EQUATIONS")) { // Creates a graph description graphDescription = new GraphDescription(graphTitle , xTitle , yTitle , xVariable , yVariable , graphWidth , graphHeight , applet); // Adds equations in the graph description while(! (currentLine = inputStream.readLine()).equals("ENDEQUATIONS")) { graphDescription.addEquation(currentLine); } } // Creates a control window and adds the input panels corresponding to parameters else { controlWindow = new ControlWindow(windowController , windowName , windowTitle , path , backgroundColor , foregroundColor , titleColor , textFieldColor , textColor , buttonColor , labelColor , defaultValues.getSpecialButtonColor() , defaultValues.getSpecialLabelColor() , graphDescription , maxContentHeight); while(! (currentLine = inputStream.readLine()).equals("ENDPARAMETERS")) { stringTokenizer = new StringTokenizer(currentLine , "&"); controlWindow.addInputPanel(stringTokenizer.nextToken() , stringTokenizer.nextToken()); } } } // Puts the panel for bounds controlWindow.newSection(); controlWindow.addInputPanel("First x value" , xUnit); controlWindow.addInputPanel("Last x value" , xUnit); // Puts the operation panel controlWindow.newSection(); // Displays the window controlWindow.display(); // Closes the connection outputStream.close(); inputStream.close(); socket.close(); return controlWindow; } return null; } // If there's a problem catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; return null; } } // parseTitle() // ------------ // Method which creates a title thanks to the information extracted from the file. private Title parseTitle() { String currentLine , keyword , size; boolean isCentered; Color titleColor; StringTokenizer stringTokenizer; Title title; try { if(isAbleToParse) { title = null; isCentered = defaultValues.getTitleAlignment(); titleColor = defaultValues.getTitleColor(); size = defaultValues.getTitleSize(); while(! (currentLine = inputStream.readLine()).equals("ENDTITLE")) { stringTokenizer = new StringTokenizer(currentLine , " "); keyword = stringTokenizer.nextToken(); // Sets title's color if(keyword.equals("TITLECOLOR")) { titleColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets title's alignment else if(keyword.equals("CENTER")) { isCentered = true; } // Sets title's size else if(keyword.equals("TITLESIZE")) { size = stringTokenizer.nextToken(); } // Creates the title else { if(size.equals("NORMAL")) { title = new NormalTitle(currentLine , isCentered , titleColor); } else if(size.equals("MEDIUM")) { title = new MediumTitle(currentLine , isCentered , titleColor); } else { title = new LargeTitle(currentLine , isCentered , titleColor); } } } return title; } return null; } // If there's a problem catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; return null; } } // parseText() // ----------- // Method which creates a text thanks to the information extracted from the file. private Text parseText() { String currentLine , keyword , textLine; Color textColor; int textWidth; StringTokenizer stringTokenizer; Text text; Vector lines; try { if(isAbleToParse) { lines = new Vector(); textColor = defaultValues.getTextColor(); textWidth = defaultValues.getTextWidth(); textLine = ""; while(! (currentLine = inputStream.readLine()).equals("ENDTEXT")) { stringTokenizer = new StringTokenizer(currentLine , " "); keyword = stringTokenizer.nextToken(); // Sets text's color if(keyword.equals("TEXTCOLOR")) { textColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets text's width else if(keyword.equals("TEXTWIDTH")) { textWidth = Integer.parseInt(stringTokenizer.nextToken()); } // Builds the lines of the text else { textLine = textLine.concat(currentLine); if(currentLine.endsWith("$")) { lines.addElement(textLine.substring(0 , textLine.length() - 1)); textLine = ""; } else { textLine = textLine.concat(" "); } } } // Creates the text text = new Text(textWidth , textColor); text.putText(lines); return text; } return null; } // If there's a problem catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; return null; } } // parseNavigator() // ---------------- // Method which creates a navigator thanks to the information extracted from the file. private Navigator parseNavigator() { String currentLine , keyword; boolean isFirstButton; Color buttonColor , labelColor; StringTokenizer stringTokenizer , buttonDescriptionStringTokenizer; Navigator navigator; try { if(isAbleToParse) { isFirstButton = true; navigator = null; buttonColor = defaultValues.getButtonColor(); labelColor = defaultValues.getLabelColor(); while(! (currentLine = inputStream.readLine()).equals("ENDNAVIGATOR")) { stringTokenizer = new StringTokenizer(currentLine , " "); keyword = stringTokenizer.nextToken(); // Sets color of buttons if(keyword.equals("BUTTONCOLOR")) { buttonColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets the color of labels else if(keyword.equals("LABELCOLOR")) { labelColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Creates buttons else { if(isFirstButton) { navigator = new Navigator(buttonColor , labelColor); isFirstButton = false; } buttonDescriptionStringTokenizer = new StringTokenizer(currentLine , "&"); navigator.addButton(buttonDescriptionStringTokenizer.nextToken() , buttonDescriptionStringTokenizer.nextToken()); } } return navigator; } return null; } // If there's a problem catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; return null; } } // parsePicture() // -------------- // Method which creates a picture thanks to the information extracted from the file. private Picture parsePicture() { String currentLine , keyword , imageName , figureNumber , caption; int imageWidth , imageHeight; Color textColor; StringTokenizer stringTokenizer; Picture picture; try { if(isAbleToParse) { imageName = null; imageWidth = 0; imageHeight = 0; figureNumber = null; caption = null; textColor = defaultValues.getTextColor(); while(! (currentLine = inputStream.readLine()).equals("ENDPICTURE")) { stringTokenizer = new StringTokenizer(currentLine , " "); keyword = stringTokenizer.nextToken(); // Sets the color of text if(keyword.equals("TEXTCOLOR")) { textColor = new Color(Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken()) , Integer.parseInt(stringTokenizer.nextToken())); } // Sets image's name else if(keyword.equals("IMAGENAME")) { imageName = stringTokenizer.nextToken(); } // Sets image's width else if(keyword.equals("IMAGEWIDTH")) { imageWidth = Integer.parseInt(stringTokenizer.nextToken()); } // Sets image's height else if(keyword.equals("IMAGEHEIGHT")) { imageHeight = Integer.parseInt(stringTokenizer.nextToken()); } // Sets figure number else if(keyword.equals("FIGURENUMBER")) { figureNumber = currentLine.substring(13); } // Sets caption else { caption = currentLine; } } // Creates and returns the picture return new Picture(imageName , imageWidth , imageHeight , figureNumber , caption , textColor , applet); } return null; } // If there's a problem catch(IOException exception) { errorWindow = new ErrorWindow("Error in parser: Impossible to read the description file." , this); isAbleToParse = false; return null; } } } // Class DefaultValues // ------------------- // This class is a model of object that store the default values of variables used to describe a window. class DefaultValues { private Color backgroundColor , foregroundColor , titleColor , textColor , buttonColor , labelColor , specialButtonColor , specialLabelColor , textFieldColor; private boolean titleAlignment; private String titleSize; private int textWidth , maxContentHeight , xGap , yGap; // Constructor // ----------- DefaultValues() { // Sets the default values backgroundColor = Color.white; foregroundColor = Color.black; titleColor = Color.black; textColor = Color.black; buttonColor = Color.white; labelColor = Color.black; specialButtonColor = Color.white; specialLabelColor = Color.black; textFieldColor = Color.white; titleAlignment = false; titleSize = "NORMAL"; textWidth = 400; maxContentHeight = 700; xGap = 0; yGap = 0; } // setBackgroundColor() // -------------------- // Method which sets the default color of the background of the window. public void setBackgroundColor(Color color) { backgroundColor = color; } // setForegroundColor() // -------------------- // Method which sets the default color of the foreground of the window. public void setForegroundColor(Color color) { foregroundColor = color; } // setTitleColor() // --------------- // Method which sets the default color of titles. public void setTitleColor(Color color) { titleColor = color; } // setTextColor() // --------------- // Method which sets the default color of texts. public void setTextColor(Color color) { textColor = color; } // setButtonColor() // --------------- // Method which sets the default color of buttons. public void setButtonColor(Color color) { buttonColor = color; } // setLabelColor() // --------------- // Method which sets the default color of buttons' labels. public void setLabelColor(Color color) { labelColor = color; } // setSpecialButtonColor() // ----------------------- // Method which sets the default color of special buttons (Previous, Next , Go Back). public void setSpecialButtonColor(Color color) { specialButtonColor = color; } // setSpecialLabelColor() // ---------------------- // Method which sets the default color of special buttons' labels (Previous, Next , Go Back). public void setSpecialLabelColor(Color color) { specialLabelColor = color; } // setTextFieldColor() // ------------------- // Method which sets the default color of text fields. public void setTextFieldColor(Color color) { textFieldColor = color; } // setTitleAlignment() // ------------------- // Method which sets the default alignment of titles. public void setTitleAlignment(boolean isCentered) { titleAlignment = isCentered; } // setTitleSize() // -------------- // Method which sets the default size of titles. public void setTitleSize(String size) { titleSize = size; } // setTextWidth() // -------------- // Method which sets the default texts' width. public void setTextWidth(int width) { textWidth = width; } // setMaxContentHeight() // --------------------- // Method which sets the default limit of the content's height of a window. public void setMaxContentHeight(int height) { maxContentHeight = height; } // setXGap() // --------- // Method which sets the default horizontal gap. public void setXGap(int gap) { xGap = gap; } // setYGap() // --------- // Method which sets the default vertical gap. public void setYGap(int gap) { yGap = gap; } // getBackgroundColor() // -------------------- // Method which returns the default color of the background of the window. public Color getBackgroundColor() { return backgroundColor; } // getForegroundColor() // -------------------- // Method which returns the default color of the foreground of the window. public Color getForegroundColor() { return foregroundColor; } // getTitleColor() // --------------- // Method which returns the default color of titles. public Color getTitleColor() { return titleColor; } // getTextColor() // --------------- // Method which returns the default color of texts. public Color getTextColor() { return textColor; } // getButtonColor() // --------------- // Method which returns the default color of buttons. public Color getButtonColor() { return buttonColor; } // getLabelColor() // --------------- // Method which returns the default color of buttons' labels. public Color getLabelColor() { return labelColor; } // getSpecialButtonColor() // ----------------------- // Method which returns the default color of special buttons (Previous, Next , Go Back). public Color getSpecialButtonColor() { return specialButtonColor; } // getSpecialLabelColor() // ---------------------- // Method which returns the default color of special buttons' labels (Previous, Next , Go Back). public Color getSpecialLabelColor() { return specialLabelColor; } // getTextFieldColor() // ------------------- // Method which returns the default color of text fields. public Color getTextFieldColor() { return textFieldColor; } // getTitleAlignment() // ------------------- // Method which returns the default alignment of titles. public boolean getTitleAlignment() { return titleAlignment; } // getTitleSize() // -------------- // Method which returns the default size of titles. public String getTitleSize() { return titleSize; } // getTextWidth() // -------------- // Method which returns the default texts' width. public int getTextWidth() { return textWidth; } // getMaxContentHeight() // --------------------- // Method which returns the default limit of the content's height of a window. public int getMaxContentHeight() { return maxContentHeight; } // getXGap() // --------- // Method which returns the default horizontal gap. public int getXGap() { return xGap; } // getYGap() // --------- // Method which returns the default vertical gap. public int getYGap() { return yGap; } }