/* * StoJ.java - stella to java conversion program * Copyright 1999-2003 David A. Joiner and the Shodor Edcuation * Foundation, Inc. */ import java.awt.*; import java.applet.Applet; import com.helplets.awt.*; import java.awt.event.*; public class StoJ extends Applet implements Runnable,ActionListener,ItemListener { // Graphic display uses graphPaper class, with modifications LineGraphPaper graphs; AnimatedGraphPaper animation; String gr_title; String gr_depLabel; String gr_type; String gr_auto; // Model class is an extension of Diffeq, with overrides // for problem setup and differential equation calculation Model my_eq; // Model_running is the thread, which runs continously, // try_model tracks actual solution of model Thread model_running; int try_model; int start_model; // User controls contains sliderbar controls for variables // and parameters Panel user_controls; // Text output is given as an option for users to cut // and paste a model solution into Excel or another spreadsheet. GEchoDlg text_out2; // Model controls holds numerical solution and model // run options. Panel model_controls; // graph_key controls what will be displayed on the // graph. Panel graph_key; // Panels to assist in layout, many choices for different layout // possibilities Panel panelKeyModelSwitch; Panel panelGraphSwitch; // add user controls // text field variable names start with tf_ // NumInput variable names start with ni_ // ScrollBar variable names start with sb_ TextField [] tf_varlabel; TextField [] tf_ratelabel; NumSlider [] ns_var; NumSlider [] ns_rate; // user control labels TextField uclabel1; TextField uclabel2; // variables (stocks) and rates (converters) controlled // by scrollbars double [] x_var; double [] x_rate; // add graph_key controls // check_var stores the state of the display boolean // check_colors stores the colors used for display // check_key is a series of panels which are painted to // give a key for the display // autoscale changes the range of display so that all // are displayed from min to max // show_text allows the user to get text output. // ch_trace allows the user to turn tracing on Checkbox [] check_var; Color [] check_colors; Panel [] check_key; Checkbox ch_autoscale; Checkbox ch_trace; Button show_text; // add model controls TextField tf_itlabel; TextField tf_ftlabel; TextField tf_stlabel; TextField tf_imlabel; TextField tf_yminlabel; TextField tf_ymaxlabel; TextField tf_status; NumInput ni_it; NumInput ni_ft; NumInput ni_st; NumInput ni_ymin; NumInput ni_ymax; Choice ch_method; Checkbox ch_adaptive; Button stop_model; double x_it,x_ft,x_st,x_ymin,x_ymax; // CardLayout controls // For the many sliders view, a cardlayout is used to switch back // and forth between display controls and model controls CardLayout cardLayoutKey; Choice choiceCardLayoutKey; CardLayout cardLayoutGraph; Choice choiceCardLayoutGraph; // xtemp is used to create a single array to pass to // graphpaper //double [] xtemp; //int ntemp=0; int redraw=0; int textbox=0; // Display types are // STANDARD - 2 X 2 - graph, user controls, model controls // display controls // LIMITED - 2 X 1 - graph, user controls // MANY_SPLIDERS - 2 left, 1 right - switch between model // and graph controls final static int DISPLAY_STANDARD=0; final static int DISPLAY_LIMITED=1; final static int DISPLAY_MANY_SLIDERS=2; int display_type=DISPLAY_STANDARD; Color bg_color; Color text_bg_color; Color label_bg_color; public void init() { // define model my_eq=new Model(); my_eq.init_problem(0.25); String paramstring; //Check for parameter modifications paramstring = getParameter("GRAPHS_TITLE"); if (paramstring != null) { gr_title = new String(paramstring); } else { gr_title = my_eq.gr_title; } paramstring = getParameter("GRAPHS_DEPLABEL"); if (paramstring != null) { gr_depLabel = new String(paramstring); } else { gr_depLabel = my_eq.gr_depLabel; } paramstring = getParameter("GRAPHS_AUTO"); if (paramstring != null) { gr_auto = new String(paramstring); if (!gr_auto.equalsIgnoreCase("TRUE")) { gr_auto = new String("FALSE"); } } else { gr_auto = new String("FALSE"); } paramstring = getParameter("GRAPHS_TYPE"); if (paramstring != null) { gr_type = new String(paramstring); if (!gr_type.equalsIgnoreCase("Bar")) { gr_type = new String("Line"); } } else { gr_type = new String("Line"); } //Graphs to be allowed - beware, if they allow too // many, an error could result due to too many colors // make sure that the display section cuts it off // appropriately // maybe there needs to be an internal check paramstring = getParameter("GRAPHS_ALLOW"); // This gets a little nasty, since everything is // contained on one string, we have to parse it all // out, and check each occurence. This is a // serious candidate for a subroutine at some point. if (paramstring != null) { String rest = paramstring; String first = null; String arg = null; while (rest!=null) { int index = rest.indexOf(";"); if (index<0) { first = rest; rest = null; } else { first = rest.substring(0,index); rest = rest.substring(index+1,rest.length()); } // loop through all possible labels, and search for // a match (do not ignore case) // If a match occurs, change as appropriate index = first.indexOf(","); if (index>-1) { arg = first.substring(index+1,first.length()); first = first.substring(0,index); } else { arg = new String("true"); } boolean done=false; int imatch=-1; // loop through all of the things which can // be displayed, and check for a match. for(int i=0;i-1) { arg = first.substring(index+1,first.length()); first = first.substring(0,index); } else { arg = new String("true"); } boolean done=false; int imatch=-1; for(int i=0;icomponentHeight) cboxHeight=componentHeight; if (cboxHeight<2) cboxHeight=2; graph_key.add("left="+left+", right="+right+ ", top="+pos+", bottom="+(pos+cboxHeight),graphlabel); pos+=cboxHeight; for(int i=0;icomponentHeight) controlHeight=componentHeight; if (controlHeight<2) controlHeight=2; if (my_eq.it_enable) { model_controls.add("left="+left+", right="+inputBorder+ ", top="+pos+", bottom="+(pos+controlHeight),tf_itlabel); model_controls.add("left="+inputBorder+", right="+right+ ", top="+pos+", bottom="+(pos+controlHeight),ni_it); pos+=controlHeight; } if (my_eq.ft_enable) { model_controls.add("left="+left+", right="+inputBorder+ ", top="+pos+", bottom="+(pos+controlHeight),tf_ftlabel); model_controls.add("left="+inputBorder+", right="+right+ ", top="+pos+", bottom="+(pos+controlHeight),ni_ft); pos+=controlHeight; } if (my_eq.st_enable) { model_controls.add("left="+left+", right="+inputBorder+ ", top="+pos+", bottom="+(pos+controlHeight),tf_stlabel); model_controls.add("left="+inputBorder+", right="+right+ ", top="+pos+", bottom="+(pos+controlHeight),ni_st); pos+=controlHeight; } if (my_eq.imeth_enable) { model_controls.add("left="+left+", right="+inputBorder+ ", top="+pos+", bottom="+(pos+controlHeight),tf_imlabel); model_controls.add("left="+inputBorder+", right="+right+ ", top="+pos+", bottom="+(pos+controlHeight),ch_method); pos+=controlHeight; } if (my_eq.ymin_enable) { model_controls.add("left="+left+", right="+inputBorder+ ", top="+pos+", bottom="+(pos+controlHeight),tf_yminlabel); model_controls.add("left="+inputBorder+", right="+right+ ", top="+pos+", bottom="+(pos+controlHeight),ni_ymin); pos+=controlHeight; } if (my_eq.ymax_enable) { model_controls.add("left="+left+", right="+inputBorder+ ", top="+pos+", bottom="+(pos+controlHeight),tf_ymaxlabel); model_controls.add("left="+inputBorder+", right="+right+ ", top="+pos+", bottom="+(pos+controlHeight),ni_ymax); pos+=controlHeight; } if (my_eq.adap_enable) { model_controls.add("left="+left+", right="+right+ ", top="+pos+", bottom="+(pos+controlHeight),ch_adaptive); pos+=controlHeight; } model_controls.add("left="+left+", right="+right+ ", top="+pos+", bottom="+(pos+controlHeight),tf_status); pos+=controlHeight; cardLayoutGraph = new CardLayout(); choiceCardLayoutGraph = new Choice(); choiceCardLayoutGraph.setBackground(bg_color); choiceCardLayoutGraph.addItem("Line Graph"); choiceCardLayoutGraph.addItem("Bar Graph"); if (gr_type.equalsIgnoreCase("Bar")) { choiceCardLayoutGraph.select(1); } panelGraphSwitch = new Panel(); panelGraphSwitch.setBackground(bg_color); panelGraphSwitch.setLayout(cardLayoutGraph); panelGraphSwitch.add("Line Graph",graphs); panelGraphSwitch.add("Bar Graph",animation); cardLayoutGraph.show(panelGraphSwitch, choiceCardLayoutGraph.getSelectedItem()); // set up basic applet layout if (display_type == DISPLAY_STANDARD) { // standard layout, top panel contains graph and sliders // bottom panel contains controls setLayout(new PercentLayout()); //add("left=0, right=50, top=0, bottom=50",graphs); add("left=0, right=50, top=0, bottom=10",choiceCardLayoutGraph); add("left=0, right=50, top=10, bottom=50",panelGraphSwitch); add("left=50, right=100, top=0, bottom=50",user_controls); add("left=0, right=50, top=50, bottom=100",graph_key); add("left=50, right=100, top=50, bottom=100",model_controls); } else if (display_type == DISPLAY_LIMITED) { // limited layout, do not include controls setLayout(new PercentLayout()); add("left=0, right=50, top=0, bottom=20", choiceCardLayoutGraph); add("left=0, right=50, top=20, bottom=100", panelGraphSwitch); add("left=50, right=100, top=0, bottom=100", user_controls); } else { // many slider layout, graph and controls are on left, sliders are // on right panelKeyModelSwitch = new Panel(); panelKeyModelSwitch.setBackground(bg_color); panelKeyModelSwitch.setLayout(cardLayoutKey); panelKeyModelSwitch.add("Graph Controls",graph_key); panelKeyModelSwitch.add("Model Controls",model_controls); setLayout(new PercentLayout()); add("left=0, right=50, top=0, bottom=10",choiceCardLayoutGraph); add("left=0, right=50, top=10, bottom=50",panelGraphSwitch); add("left=0, right=50, top=50, bottom=60",choiceCardLayoutKey); add("left=0, right=50, top=60, bottom=100", panelKeyModelSwitch); add("left=50, right=100, top=0, bottom=100", user_controls); cardLayoutKey.show(panelKeyModelSwitch,"Graph Controls"); } // initialize arrays and set here x_var=new double[my_eq.n_vars]; x_rate=new double[my_eq.n_rates]; for(int i=0;ixtemp[i]) xmin=xtemp[i]; } if (ch_autoscale.getState()) { if (xmin!=xmax) { //xtemp = new double[my_eq.ntime]; double tempmax=xmax; double tempmin=xmin; xmin = Math.abs(xmin); xmax = Math.abs(xmax); tempmax/=xmax; tempmin/=xmin; if (xmin>xmax) xmax=xmin; for(int i=0;itruemax) truemax=tempmax; if (tempmin50) { labelcount=0; fix_labels(); } tf_status.setText("Program Status: RUNNING"); if(runmode==0) { // if in immediate mode my_eq.solve(x_var,x_rate, x_it,x_ft, x_st, ch_adaptive.getState()); my_eq.try_model=0; redraw=1; tf_status.setText("Program Status: IDLE"); } else { // this will one day be slow mode } } if (redraw==1) { draw_graphs(); } if(textbox==1) { textbox=0; tf_status.setText("Program Status: TEXT"); text_out2.updateText(); text_out2.show(); tf_status.setText("Program Status: IDLE"); } model_running.sleep(50); } catch (Exception e) { e.printStackTrace(); } } } public void itemStateChanged(ItemEvent e) { for (int i=0; i